Closed24

Self-hosted GitHub Actions runners in AWS CodeBuild を試す

Futa HirakobaFuta Hirakoba

これ

AWS CodeBuild が GitHub Actions をサポート開始
https://aws.amazon.com/jp/about-aws/whats-new/2023/07/aws-codebuild-github-actions/

Set up self-hosted GitHub Actions runners in AWS CodeBuild - AWS CodeBuild
https://docs.aws.amazon.com/codebuild/latest/userguide/action-runner.html

Futa HirakobaFuta Hirakoba
  • CodeBuild プロジェクトを使用して Webhook を設定し、GitHub ACtions ワークフローの yaml を更新して CodeBuild マシン上でホストされているセルフホストランナーを使用できる
  • GitHub への認証は PAT か OAuth App を使う
Futa HirakobaFuta Hirakoba

まとめというかわかったこと

※間違ってることや、こうすればいいよなどがあったらコメントください。

良かった点

  • セットアップは楽
  • ephemeral である
  • 起動時間は EC2、Lambda 共に 1 分程度だった
    • 個人的には十分速い
  • マネージドイメージに加えて Docker カスタムイメージを指定可能
  • jobs.<job_id>.runs-on-<image>-<image-version>-<instance-size> を追記すると、設定不要で様々なアーキテクチャのイメージを使える
  • jobs.<job_id>.container は EC2、Lambda 共に動く

微妙な点

  • 何ができて何ができないかの制約が不明
    • ドキュメント充実させてくれ〜
  • GitHub との接続は PAT か OAuth App のみ
    • 個人に権限が紐づいてしまう
    • GitHub Apps でやれないと業務利用は厳しい気がする
  • リポジトリとプロジェクトを 1:1 でしか紐づけられない
    • Org 全体で一個のプロジェクトとできない
    • リポジトリごとに設定が必要
    • 個別に使う分にはいいが、横展開しようとすると無理ある
  • jobs.<job_id>.services は Lambda で動かない
    • EC2 では動く
  • jobs.<job_id>.services.ports へホストマシンからアクセスできない
    • jobs.<job_id>.container からのアクセスはできる
    • 何か設定が必要?
  • プールできない
    • やる方法ないよね多分?

所感

  • 開発チーム内で使う分にはいいかも
  • イネーブリングチーム的なチームが社内で横展開するにはむずいかなという感じ
    • 「GitHub Apps 使えない」のと、「リポジトリとプロジェクトが1:1対応」の部分が致命的。それ以外はなんとかなりそう
  • まだまだ登場したばっかで様子見感ある
    • インターネット上の知見が少ない
    • 実用始めると色々な問題でそう
  • 今後に期待
Futa HirakobaFuta Hirakoba

前提条件

  • OAuth アプリか PAT を作成する
    • OAuth アプリの場合は CodeBuild コンソール
    • PAT の場合は CodeBuild コンソールか ImportSourceCredential API を使用する
  • CodeBuild を GitHub アカウントに接続する
    • CodeBuild コンソールでソースプロバイダとして GitHub を追加できる
Futa HirakobaFuta Hirakoba

GitHub OAuth アプリを作成する

https://docs.aws.amazon.com/codebuild/latest/userguide/access-tokens.html#oauth-app-github

コンソールを使用して OAuth アプリを使用してプロジェクトを GitHub に接続するには、 プロジェクトを作成するときに次のようにします。

プロジェクト作成時にソースプロバイダで GitHub を指定して、OAuth で接続をやるらしい。


プロジェクト作成


OAuth 確認画面


接続できた

GitHub リポジトリの指定が必要で、Owner 配下すべて、みたいなのができないかもしれない。

Futa HirakobaFuta Hirakoba

ステップ 1: Webhook を使用して CodeBuild プロジェクトを作成する

Futa HirakobaFuta Hirakoba
  1. ソースの選択
    • 「GitHub OAuth アプリを作成する」でやった
  2. 「プライマリソースの Webhook イベント」のイベントの種類に WORKFLOW_JOB_QUEUED を選択
    • この設定をすると、ビルドが GitHub Actions ワークフロージョブイベントによってのみトリガーされるとか
  3. 「環境(Environment)」でサポートする環境イメージとコンピューティングを選択する
    • Lambda 選んだらランタイム選ばされるんだけど、言語固有のものしかなくてどれ選ぶのが汎用的になるか謎
  4. buildspec は無視される(オーバーライドされる)とのこと
    • Buildspec will be ignored when you use CodeBuild to run GitHub Actions workflow jobs. Instead, CodeBuild will override it to use commands that will setup the self-hosted runner.

    • ちゃんと注意書き出て選択できなくなってた
  5. デフォルト値を続行し、「create build project」を選択
    • 1 validation error detected: Value 'codebuild-korosuke613_playground_github_actions_test-service-role' at 'roleName' failed to satisfy constraint: Member must have length less than or equal to 64

    • エラー出た。デフォルトで出てきたロール名だと長すぎてダメってさ
    • codebuild-korosuke613_playground_github_actions_test に修正した
Futa HirakobaFuta Hirakoba

ステップ 2: GitHub Actions ワークフローの YAML を更新する

Futa HirakobaFuta Hirakoba
  • jobs.<job_id>.runs-oncodebuild-<project-name>-${{ github.run_id }}-${{ github.run_attempt }} を指定する
    • codebuild-korosuke613_playground_github_actions_test-${{ github.run_id }}-${{ github.run_attempt }} でいいかな
  • runs-on: codebuild-<project-name>-${{ github.run_id }}-${{ github.run_attempt }}-<image>-<image-version>-<instance-size> で環境設定をオーバーライドできるらしい
Futa HirakobaFuta Hirakoba


動いた

Total duration が 1m4s なので、立ち上がりに 1m くらいかかってそう(Lambda)。
とはいえ十分速い。

デフォルト設定
cat /etc/image-id

image_name="al2023-container-minimal"
image_version="2023"
image_arch="x86_64"
image_file="al2023-container-minimal-2023.2.20231030.1-x86_64"
image_stamp="1b43-4b52"
image_date="20231101224236"
recipe_name="al2023 container-minimal"
recipe_id="220964eb-6acd-049e-d04f-a09b-7db8-0f27-0eb7c841"
-arm-3.0-smallつけたやつ
image_name="al2023-container"
image_version="2023"
image_arch="aarch64"
image_file="al2023-container-2023.3.20240312.0-arm64"
image_stamp="b7f8-3251"
image_date="20240313015236"
recipe_name="al2023 container"
recipe_id="d3afd5de-b11c-9893-0ca3-693c-9b26-d044-fd09cc9b"
Futa HirakobaFuta Hirakoba


CodeBuild のプロジェクト画面

それぞれ期間が「47 秒間」、「1 分間 0 秒間」となっている。
CodeBuild上の実行時間はここ参照するのが良さそう。

ビルドログにはランナー立ち上げのログがある。

Futa HirakobaFuta Hirakoba

ephemeral runner であるため、ジョブ終了後にランナーは登録解除&破棄される。

Futa HirakobaFuta Hirakoba

ちなワークフロー

on:
  pull_request:

jobs:
  hello_world_default:
    runs-on: codebuild-korosuke613_playground_github_actions_test-${{ github.run_id }}-${{ github.run_attempt }}
    steps:
      - run: echo "Hello World!"
      - run: cat /etc/image-id
  hello_world_arm:
    runs-on: codebuild-korosuke613_playground_github_actions_test-${{ github.run_id }}-${{ github.run_attempt }}-arm-3.0-small
    steps:
      - run: echo "Hello World!"
      - run: cat /etc/image-id

https://github.com/korosuke613/playground/pull/56/commits/afdbb53b8105bfd2dfdd0d6f6adcb216fe2c399a

Futa HirakobaFuta Hirakoba

複数リポジトリを同じビルドプロジェクトに紐づけられるか?

https://zenn.dev/link/comments/1f7c254ee0db47

Futa HirakobaFuta Hirakoba

リポジトリ指定時に owner で止めてみる

  • korosuke613/
  • korosuke613

を指定したが、いづれも保存に失敗

リポジトリ指定時にワイルドカードを指定

  • korosuke613/*

を指定し、保存したが、実行されず

Futa HirakobaFuta Hirakoba

Docker の機能は使えるか on Lambda

Futa HirakobaFuta Hirakoba

servicescontainer でやってみる。

❯ git --no-pager diff HEAD^
diff --git a/.github/workflows/codebuild-runner.yaml b/.github/workflows/codebuild-runner.yaml
index 347e9ab..1a85c44 100644
--- a/.github/workflows/codebuild-runner.yaml
+++ b/.github/workflows/codebuild-runner.yaml
@@ -4,11 +4,18 @@ on:
 jobs:
   hello_world_default:
     runs-on: codebuild-korosuke613_playground_github_actions_test-${{ github.run_id }}-${{ github.run_attempt }}
+    services:
+      nginx:
+        image: nginx
+        ports:
+          - 8080:80
     steps:
       - run: echo "Hello World!"
       - run: cat /etc/image-id
+      - run: curl http://localhost:8080
   hello_world_arm:
     runs-on: codebuild-korosuke613_playground_github_actions_test-${{ github.run_id }}-${{ github.run_attempt }}-arm-3.0-small
+    container: ubuntu
     steps:
       - run: echo "Hello World!"
       - run: cat /etc/image-id
Futa HirakobaFuta Hirakoba

jobs.<job_id>.services を指定

Set up job 時に Error: docker: command not found エラーが出てしまった。

jobs.<job_id>.contaienr を指定

なんとうまく ubuntu イメージ上で動いた。
(その後のステップで失敗してるのは無視して良い)

Futa HirakobaFuta Hirakoba

jobs.<job_id>.servicesjobs.<job_id>.container の両方を指定

もしやと思いやってみる。

❯ git --no-pager diff HEAD^
diff --git a/.github/workflows/codebuild-runner.yaml b/.github/workflows/codebuild-runner.yaml
index 1a85c44..96a3fec 100644
--- a/.github/workflows/codebuild-runner.yaml
+++ b/.github/workflows/codebuild-runner.yaml
@@ -9,13 +9,8 @@ jobs:
         image: nginx
         ports:
           - 8080:80
-    steps:
-      - run: echo "Hello World!"
-      - run: cat /etc/image-id
-      - run: curl http://localhost:8080
-  hello_world_arm:
-    runs-on: codebuild-korosuke613_playground_github_actions_test-${{ github.run_id }}-${{ github.run_attempt }}-arm-3.0-small
     container: ubuntu
     steps:
       - run: echo "Hello World!"
-      - run: cat /etc/image-id
+      - run: cat /etc/os-release
+      - run: curl http://localhost:8080


Error: docker: command not found

ダメだった。

Futa HirakobaFuta Hirakoba

Docker の機能は使えるか on EC2

https://zenn.dev/link/comments/295b53d0902611 の EC2 版

Futa HirakobaFuta Hirakoba

jobs.<job_id>.servicesjobs.<job_id>.container の両方を指定

これと同じワークフロー動かす。 https://zenn.dev/link/comments/e5bf548a496853


動いた!が、ubuntu コンテナには curl 入っておらず

ちゃんとインストールする
❯ git --no-pager diff HEAD^
diff --git a/.github/workflows/codebuild-runner.yaml b/.github/workflows/codebuild-runner.yaml
index 96a3fec..761d78d 100644
--- a/.github/workflows/codebuild-runner.yaml
+++ b/.github/workflows/codebuild-runner.yaml
@@ -13,4 +13,5 @@ jobs:
     steps:
       - run: echo "Hello World!"
       - run: cat /etc/os-release
+      - run: apt-get update && apt-get install -y curl
       - run: curl http://localhost:8080

まさかのサービスコンテナ起動時にレートリミット!めんどくさ!

Starting nginx service container
  /usr/local/bin/docker pull nginx
  Using default tag: latest
  latest: Pulling from library/nginx
  toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit
  Warning: Docker pull failed with exit code 1, back off 8.341 seconds before retry.
  /usr/local/bin/docker pull nginx
  Using default tag: latest
  Error response from daemon: toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit
  Warning: Docker pull failed with exit code 1, back off 9.637 seconds before retry.
  /usr/local/bin/docker pull nginx
  Using default tag: latest
  latest: Pulling from library/nginx
  toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit
  Error: Docker pull failed with exit code 1

しゃーないので ECR Public の nginx を指定する。

nginxのイメージを ECR のものに
❯ git --no-pager diff HEAD^
diff --git a/.github/workflows/codebuild-runner.yaml b/.github/workflows/codebuild-runner.yaml
index 761d78d..334a658 100644
--- a/.github/workflows/codebuild-runner.yaml
+++ b/.github/workflows/codebuild-runner.yaml
@@ -6,7 +6,7 @@ jobs:
     runs-on: codebuild-korosuke613_playground_github_actions_test-${{ github.run_id }}-${{ github.run_attempt }}
     services:
       nginx:
-        image: nginx
+        image: public.ecr.aws/nginx/nginx:latest
         ports:
           - 8080:80
     container: ubuntu

この場合 AWS 内のサービスからの pull になるが、自動でレートリミット無視されるのかはよくわかってない。


localhostでつながらんのだった

その後色々やった。

on:
  pull_request:

jobs:
  services-and-container:
    runs-on: codebuild-korosuke613_playground_github_actions_test-${{ github.run_id }}-${{ github.run_attempt }}
    services:
      nginx:
        image: public.ecr.aws/nginx/nginx:latest
    container: public.ecr.aws/ubuntu/ubuntu:latest
    steps:
      - run: apt-get update && apt-get install -y curl
      - run: curl --retry 5 --retry-delay 1 --retry-all-errors http://nginx

  services:
    runs-on: codebuild-korosuke613_playground_github_actions_test-${{ github.run_id }}-${{ github.run_attempt }}
    services:
      nginx:
        image: public.ecr.aws/nginx/nginx:latest
        ports:
          - 8080:80
    steps:
      - run: curl --retry 5 --retry-delay 1 --retry-all-errors http://localhost:${{ job.services.nginx.ports[80] }}

  normal:
    runs-on: ubuntu-latest
    services:
      nginx:
        image: public.ecr.aws/nginx/nginx:latest
        ports:
          - 8080:80
    steps:
      - run: curl --retry 5 --retry-delay 1 --retry-all-errors http://localhost:${{ job.services.nginx.ports[80] }}
  • container と services の併用: 疎通可能✅
  • services のみ: ホストから疎通できず❌
    • 比較用に ubuntu-latest で同じことをやってそっちはうまく行った
    • 何か特別な設定がいるのか??

services のみ

curl --retry 5 --retry-delay 1 --retry-all-errors http://localhost:8080
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (7) Failed to connect to localhost port 8080 after 0 ms: Couldn't connect to server
Warning: Problem (retrying all errors). Will retry in 1 seconds. 5 retries 
Warning: left.

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (7) Failed to connect to localhost port 8080 after 0 ms: Couldn't connect to server
Warning: Problem (retrying all errors). Will retry in 1 seconds. 4 retries 
Warning: left.

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (7) Failed to connect to localhost port 8080 after 0 ms: Couldn't connect to server
Warning: Problem (retrying all errors). Will retry in 1 seconds. 3 retries 
Warning: left.

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (7) Failed to connect to localhost port 8080 after 0 ms: Couldn't connect to server
Warning: Problem (retrying all errors). Will retry in 1 seconds. 2 retries 
Warning: left.

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (7) Failed to connect to localhost port 8080 after 0 ms: Couldn't connect to server
Warning: Problem (retrying all errors). Will retry in 1 seconds. 1 retries 
Warning: left.

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (7) Failed to connect to localhost port 8080 after 0 ms: Couldn't connect to server
Error: Process completed with exit code 7.
このスクラップは19日前にクローズされました