株式会社ネットワールドのエンジニアがお届けする技術情報ブログです。
各製品のエキスパートたちが旬なトピックをご紹介します。

GitとCI/CDに関する知識ゼロのSEが、EC2インスタンスでGitLab RunnerのAuto Scalingを試すだけ

皆様こんにちは。SEの小池と申します。

私は今まで、GitLabのRunnerをローカルでDokcer Composeを使ってコンテナで起動させておりました。
理由はそれが一番消したり作成したりするのが簡単だったからです・・・。

コンテナでRunnerを起動すると作成や削除や停止が容易なのでとても便利なのですが、GitLabを本格的に運用している現場では、CI/CDパイプラインを実行するRunnerをAuto Scalingさせたい・・・といったご要望があるかと存じます。

というわけで今回は、Docker Machineを使ってAWS EC2でRunnerをAuto Scalingする方法をご紹介します。

本記事の対象の方

  • AWS EC2でGitLab RunnerのAuto Scalingをお試しなさりたい方。

今回のブログのゴール

このブログのゴールはこちらです。


今回のゴール
  • GitLabでDocker Machineを使ってRunnerをAWS EC2インスタンスでAuto Scalingする。

このブログをお読みいただくにあたっての事前ご連絡事項

  • 本記事はSelf-Managed版 GitLab Community Edition 15.4.1 における仕様をベースに記載しております。それ以外のエディションやバージョンではこの記事に記載の通りではない可能性がございます。また、SaaS版であるGitLab.comは本記事の対象外です。
  • 本記事は前提条件があります (こちら) 。こちらの前提条件となるAWSのVPC、サブネット、セキュリティグループやインターネットゲートウェイ 等の作成方法は省略しております。
  • 本記事では、S3を使ったキャッシュの設定をしますが、本ブログ内でその動作検証はしておりません。
  • 本記事では、EC2のオンデマンドインスタンスを用います (スポットインスタンスではありません) 。課金額にご注意ください。
  • 本記事のGitLabのGUIは日本語にローカライズした状態で掲載しております。それ以外の言語をご利用の方は適宜読み替えてください。
  • 本記事はGitやCI/CDに関する知識ゼロのSEによるなんちゃって記事です。GitLabのディープな使用法についてはGitLabの公式オンラインドキュメント (こちら) をご参照ください。

前提

このブログではGitLab RunnerをAWS EC2インスタンスでAuto Scalingします。
このブログに記載された手順は、既に以下のリソースがAWSにある前提となります。
参考 : Autoscaling GitLab Runner on AWS EC2 - AWS credentials, Autoscaling GitLab Runner on AWS EC2 - AWS security groups

前提
  • 必須 : 以下を満たすAWS IAMユーザー。
    • 必須 : アクセスキーIDとシークレットアクセスキーがある。
    • 必須 : 権限 AmazonEC2FullAccess を持っている。
    • 任意 : 権限 AmazonS3FullAccess を持っている。
  • 必須 : Runner用のEC2インスタンスを展開するVPCとサブネット。
  • 必須 : 上記VPCに適用されたセキュリティグループ。
  • 任意 : Runnerに用いるAMI。
  • 任意 : インターネットゲートウェイとNATゲートウェイ。

実現するシナリオ

今回は以下のご要件があると仮定し、これを満たすように設定を進めていきます。
開発経験ゼロの筆者によるご都合主義的な要件なので、「開発現場じゃあり得ねーよ!」な内容でもお許しください。

【実現するご要件】
  • 共用Runnerとして登録する。
  • Runnerマネージャーは1台とし、AWS EC2で作成する。
  • CI/CDパイプラインの実行状態に応じ、子Runner用 EC2インスタンスをAuto Scalingさせる
  • 子Runner用 EC2インスタンスは、常時2個を稼働させておく。
  • 子Runner用 EC2インスタンスがAuto Scalingで増加する際は1個ずつ増やし、最大6個までとする。
  • 子Runner用 EC2インスタンス1個につき1ジョブを実行する。最大同時実行ジョブ数は6とする。
  • ジョブが長時間になる可能性があるため、子Runner用 EC2インスタンスはオンデマンドで作成する。
  • ジョブを実行していない子Runner用 EC2インスタンスは、待機時間が5分を超えたら順次削除する。
  • 構成イメージ

    前述した実現する要件を考慮し、今回の構成イメージはこんな感じとなります。
    というか本当は環境作ってから要件を後付けで考・・・なんでもありません。

    このブログでは、Runnerマネージャーのエクゼキューターをdocker+machineにします。
    これにより、Auto Scalingは全てRunnerマネージャーで制御することとなり、AWS側のAuto Scaling機能などは使用せず、シンプルな構成となります。
    セキュリティグループの要件についてはこちらをご参照ください。

    実装と実行

    ここからは実際にAWS EC2インスタンスを使ってRunnerをAuto Scalingさせる設定をしていきます。

    Step1 : Runnerマネージャーとなるマシンの作成

    RunnerマネージャーとなるマシンをEC2で用意し、そこへ以下を実施します。
    参考 : Autoscaling GitLab Runner on AWS EC2 | GitLab

    1. Docker Engineのインストール (こちら)
    2. Docker Machineのインストール (こちら)
    3. GitLab Runnerのインストール (こちら)
    4. GitLab Runnerの登録 (こちら)

    先述のシナリオに従い、今回はマネージャーをAWS EC2インスタンスで構成します。
    今回は検証用の環境であり、且つ、「Runner マネージャーはジョブを実行しないので小さいインスタンスサイズでよい」旨がGitLab Docsに記載されていたので、AWS EC2インスタンスサイズはt3.small、イメージはUbuntu Server 20.04 LTS (AMI-ID: ami-09b18720cb71042df) を用いました。(2022/10/04時点。)
    参考 : Autoscaling GitLab Runner on AWS EC2 | GitLab

    Docker Engineのインストール

    まずは、Runnerマネージャー用 EC2インスタンスにDocker Engineをインストールします。
    公式Webページから対応するOSへのインストール手順をご参照ください。
    参考 : Docker Engine のインストール | Docker ドキュメント

    Docker Machineのインストール

    次にRunnerマネージャー用 EC2インスタンスにDocker Machineをインストールします。
    Docker Machineは既に公式では廃止が決定しているのですが、GitLab社がフォークして今でもちょっとだけメンテナンスをしてくれているので、それをインストールします。
    参考 : GitLab.org / Ops Sub-Department / docker-machine · GitLab

    上記の参考URLの [Deployment] > [Releases] を開くと、バイナリをダウンロードできるリンクがあります。
    この中から、今回使うバージョン (こだわりが無ければ最新Ver) と、今回作成したRunnerマネージャーにあうバイナリをファイル名を確認します。
    このブログでは例として、2022/10/04時点で最新のv0.16.2-gitlab.18を使い、そのバージョンのbinary: Linux amd64のファイル名を確認します。
    下図の通り、ファイル名はdocker-machine-Linux-x86_64でした。

    次にインストールコマンドを確認します。
    2022/10/04時点ではこちらにインストールコマンドが載っているので、これを実行します。

    最初のコマンドは、バージョンとファイル名を変更する必要があります。
    バージョンとファイル名は前の手順で確認したものに置き換えます。

    # curl -O "https://gitlab-docker-machine-downloads.s3.amazonaws.com/<バージョン>/<ファイル名>"
    

    このブログだと、使用するバージョンは最新のv0.16.2-gitlab.18、ファイル名はdocker-machine-Linux-x86_64なので以下の通りとなります。

    # curl -O "https://gitlab-docker-machine-downloads.s3.amazonaws.com/v0.16.2-gitlab.18/docker-machine-Linux-x86_64"
    

    ダウンロードしたバイナリを、/user/local/bin/にコピーします。

    # cp <curlで取得したファイル名> /usr/local/bin/docker-machine
    

    このブログの場合は以下のようになります。

    # cp docker-machine-Linux-x86_64 /usr/local/bin/docker-machine
    

    /usr/local/bin/にコピーしたバイナリのパーミッションを変更します。

    # chmod +x /usr/local/bin/docker-machine
    

    GitLab Runnerのインストール

    次に、GitLab Runnerをインストールします。
    このブログでは例としてUbuntuに、リポジトリを使ってインストールします。
    参考 : Install GitLab Runner using the official GitLab repositories | GitLab

    以下のコマンドで公式のGitLabリポジトリを追加します。(以下のコマンドはUbuntuの場合です。)

    # curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
    

    続けて、以下のコマンドで最新バージョンのRunnerをインストールします。

    # apt-get install gitlab-runner
    

    GitLab Runnerの登録

    最後に、RunnerマネージャーにインストールしたGitLab Runnerを、GitLabに共有Runnerとして登録します。

    まずは登録に必要なTokenを確認します。
    GitLabに管理者権限を有するユーザーでサインインし、左上のメニューから [管理者] を開きます。

    [概要] > [Runner] > [Register an instance runner] をクリックし、Registration tokenをコピーします。
    コピーしたトークンはどこかにメモしておきます。

    登録に必要なURLを確認します。
    サインインページに使っているURLの/users/sign_inを削除した文字列をメモしておきます。

    Runnerの登録コマンドをRunnerマネージャーで実行します。
    RunnerマネージャーとなるEC2インスタンスにサインインし、以下のコマンドを実行します。
    (登録は対話式でも可能ですが、ブログの尺の都合上、全部コマンドオプションで指定する方法で行きます。)
    参考 : Registering runners - One-line registration command | GitLab

    # gitlab-runner register \
      --non-interactive \
      --url "<確認したURL>" \
      --registration-token "<確認したToken>" \
      --executor "docker+machine" \
      --docker-image <デフォルトイメージ 例)alpine:latest> \
      --description "docker+machine" \
      --run-untagged="true" \
      --locked="false" \
      --access-level="not_protected"
    

    仮に、URLがhttps://gitlab.example.com、トークンがabcdefghijklmn123456だった場合、以下の通りとなります。

    # gitlab-runner register \
      --non-interactive \
      --url "https://gitlab.example.com" \
      --registration-token "abcdefghijklmn123456" \
      --executor "docker+machine" \
      --docker-image alpine:latest \
      --description "docker+machine" \
      --run-untagged="true" \
      --locked="false" \
      --access-level="not_protected"
    

    GitLabでプライベートCAで発行した証明書を使っている場合 等は、Runnerマネージャーの任意の場所にルート証明書を配置し、オプション--tls-ca-fileでそのルート証明書のフルパスを指定してください。
    ルート証明書のフルパスが/etc/gitlab-runner/certs/private-ca.crtの場合は以下の通りとなります。

    # gitlab-runner register \
      --tls-ca-file=/etc/gitlab-runner/certs/private-ca.crt \
      --non-interactive \
      --url "https://gitlab.example.com" \
      --registration-token "abcdefghijklmn123456" \
      --executor "docker+machine" \
      --docker-image alpine:latest \
      --description "docker+machine" \
      --run-untagged="true" \
      --locked="false" \
      --access-level="not_protected"
    

    以下のような出力で終わることを確認します。

    Runtime platform                                    arch=amd64 os=linux pid=24003 revision=43b2dc3d version=15.4.0
    Running in system-mode.
    
    Registering runner... succeeded                     runner=<任意文字列>
    Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
    
    Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"
    

    GitLabインスタンス側からRunnerが正常に登録されていることを確認します。
    GitLabに管理者権限を有するユーザーでサインインし、左上のメニューから [管理者] を開きます。

    [概要] > [Runner] を開き、先ほど登録したRunnerが表示されていることを確認します。
    なお、この時点ではステータスはnever contactedになっていますが、問題ありません。

    以上で、Runnerマネージャーとなるマシンの作成は完了です。

    Step2 : RunnerマネージャーとAuto Scaling関連の設定

    このステップではRunnerマネージャーに、AWS VPCのサブネット上に子Runner用 EC2インスタンスを生成する設定をします。

    設定前に、以下のコマンドでRunnerのサービスを停止しておきます。
    止めておかないと、設定のミスの有無にかかわらず設定ファイルが保存され次第、Runnerマネージャーは子Runner用 EC2インスタンスの生成を実行してしまうためです。

    # gitlab-runner stop
    

    このステップで必要になる情報は以下の通りです。事前にご用意ください。

    • AWSのアクセスキーIDとシークレットアクセスキー。
    • 子Runner用 EC2インスタンスを展開するVPCのIDとサブネットのID。
    • 子Runner用 EC2インスタンスに適用するセキュリティグループ名。 (IDではありませんのでご注意ください。)
    • 子Runner用 EC2インスタンスを展開するリージョンとアベイラビリティゾーン。
    • (任意) 子Runner用 EC2インスタンスのサイズ。
    • (任意) 子Runner用 EC2インスタンスに使うAMIのID。
    • (任意) キャッシュ用に使うS3バケット名とそのリージョン。

    Runnerマネージャーのファイル/etc/gitlab-runner/config.tomlを編集していきます。
    まず、一行目のconcurrentの数値を変更します。
    この値はこのRunnerマネージャーで同時に実行できるジョブの数を制限します。
    今回は以下の要件を満たすためにこの値を6に変更します。
    参考 : Advanced configuration - The global section | GitLab

    【実現するご要件 (抜粋) 】
  • 子Runner用 EC2インスタンス1個につき1ジョブを実行する。最大同時実行ジョブ数は6とする。
  • concurrent = 6
    check_interval = 0
    
    ~以下略~
    

    次に [[runners]] セクションにlimitを追加します。
    この値は生成される子Runner用 EC2インスタンス数の上限です。
    今回は以下の要件を満たすためにこの値を6にします。
    参考 : Advanced configuration - The [[runners]] section | GitLab

    【実現するご要件 (抜粋) 】
  • 子Runner用 EC2インスタンスがAuto Scalingで増加する際は1個ずつ増やし、最大6個までとする。
  • concurrent = 6
    check_interval = 0
    
    [session_server]
      session_timeout = 1800
    
    [[runners]]
      name = "docker+machine"
      url = "https://gitlab.example.com"
      id = 1
      token = "abcdefghijklmn123456"
      token_obtained_at = 2022-10-04T07:34:53Z
      token_expires_at = 0001-01-01T00:00:00Z
      tls-ca-file = "/etc/gitlab-runner/certs/private-ca.crt"
      executor = "docker+machine"
      limit = 6
    
    ~以下略~
    

    GitLabでDocker Machineを使ってEC2インスタンスにRunner用マシンをAuto Scalingする場合、キャッシュ先をS3にすることが推奨されています。
    このブログでは動作検証はしませんが、一応設定だけしておきます。
    [runners.cache]セクションにTypeSharedPathを指定します。(下記サンプルの18~20行目。)
    PathはS3バケットのプレフィックスへのパスを記載します。
    参考 : Advanced configuration - The [runners.cache] section | GitLab

    concurrent = 6
    check_interval = 0
    
    [session_server]
      session_timeout = 1800
    
    [[runners]]
      name = "docker+machine"
      url = "https://gitlab.example.com"
      id = 1
      token = "abcdefghijklmn123456"
      token_obtained_at = 2022-10-04T07:34:53Z
      token_expires_at = 0001-01-01T00:00:00Z
      tls-ca-file = "/etc/gitlab-runner/certs/private-ca.crt"
      executor = "docker+machine"
      limit = 6
      [runners.cache]
        Type = "s3"
        Shared = true
        Path = "path/to/prefix"
    
    ~以下略~
    

    キャッシュに使うS3バケット設定を続けます。
    [runners.cache.s3]セクションに、以下の項目を記載します。
    参考 : Autoscaling GitLab Runner on AWS EC2 - The runners.cache section, Autoscaling GitLab Runner on AWS EC2 - AWS credentials

    表1. [runners.cache.s3] セクションに追記する設定値
    設定値
    ServerAddress 固定値。s3.amazonaws.com
    AccessKey 検証に使うIAMユーザーのアクセスキーID。
    ポリシーAmazonS3FullAccessが割り当てられていること。
    SecretKey 検証に使うIAMユーザーのシークレットアクセスキー。
    BucketName S3バケット名。存在しない場合は新規作成となる。
    BucketLocation S3バケットのリージョン。任意の値を設定。
    例) アジアパシフィック (東京)なら ap-northeast-1

    concurrent = 6
    check_interval = 0
    
    [session_server]
      session_timeout = 1800
    
    [[runners]]
      name = "docker+machine"
      url = "https://gitlab.example.com"
      id = 1
      token = "abcdefghijklmn123456"
      token_obtained_at = 2022-10-04T07:34:53Z
      token_expires_at = 0001-01-01T00:00:00Z
      tls-ca-file = "/etc/gitlab-runner/certs/private-ca.crt"
      executor = "docker+machine"
      limit = 6
      [runners.cache]
        Type = "s3"
        Shared = true
        Path = "path/to/prefix"
        [runners.cache.s3]
          ServerAddress = "s3.amazonaws.com"
          AccessKey = "ABCDEFGHIJKLMNOPQRST"
          SecretKey = "ABCDEFGhijklmnOPQRSTUvwzxzy123456789000"
          BucketName = "gitlab-runners-cache"
          BucketLocation = "ap-northeast-1"
    
    ~以下略~
    

    セクション[runners.docker]にあるvolumesは削除します。
    参考 : Advanced configuration - The [runners.docker] section | GitLab

    concurrent = 6
    check_interval = 0
    
    [session_server]
      session_timeout = 1800
    
    [[runners]]
      name = "docker+machine"
      url = "https://gitlab.example.com"
      id = 1
      token = "abcdefghijklmn123456"
      token_obtained_at = 2022-10-04T07:34:53Z
      token_expires_at = 0001-01-01T00:00:00Z
      tls-ca-file = "/etc/gitlab-runner/certs/private-ca.crt"
      executor = "docker+machine"
      limit = 6
      [runners.cache]
        Type = "s3"
        Shared = true
        Path = "path/to/prefix"
        [runners.cache.s3]
          ServerAddress = "s3.amazonaws.com"
          AccessKey = "ABCDEFGHIJKLMNOPQRST"
          SecretKey = "ABCDEFGhijklmnOPQRSTUvwzxzy123456789000"
          BucketName = "gitlab-runners-cache"
          BucketLocation = "ap-northeast-1"
      [runners.docker]
        tls_verify = false
        image = "ruby:3.1.2"
        privileged = true
        disable_entrypoint_overwrite = false
        oom_kill_disable = false
        disable_cache = true
    
    ~以下略~
    

    セクション[runners.machine]で以下の項目を編集します。
    一部の項目はデフォルトでは存在しない設定値なので、その場合は追記してください。
    参考 : Advanced configuration - The [runners.machine] section | GitLab

    表2. [runners.machine] セクションに追記する設定値
    設定値
    IdleCount ジョブを実行していない (アイドル状態) の子Runner起動数。
    今回のブログの場合は 2を設定する。
    IdleTime ジョブを実行していない (アイドル状態) の子Runnerを削除するまでの待機時間 (秒)。
    今回のブログの場合は 300を設定する。
    MaxGrowthRate ジョブを実行していない (アイドル状態) の子Runner起動数が設定値IdleCountに満たない場合、この設定値の台数ずつマシンをプロビジョニングしていく。
    今回のブログの場合は 1を設定する。
    MachineDriver 固定値。amazonec2
    MachineName プロビジョニングする子Runnerのインスタンス名。任意に指定。
    このブログではgitlab-docker-machine-%sとしているが、この場合は "runner-<RunnerマネージャーのRunnerID>-gitlab-docker-machine-<エポック秒>-<ランダム文字列>" となる。
    MachineOptions 後述の 表3. [runners.machine] セクションの設定値 MachineOptions に指定する値 参照

    表3. [runners.machine] セクションの設定値 MachineOptions に指定する値
    設定値
    amazonec2-access-key 検証に使うIAMユーザーのアクセスキーID。
    ポリシーAmazonEC2FullAccessが割り当てられていること。
    amazonec2-secret-key 検証に使うIAMユーザーのシークレットアクセスキー。
    amazonec2-region 子Runnerを作成するリージョン。VPCに依存する。
    例) アジアパシフィック (東京)なら ap-northeast-1
    amazonec2-vpc-id 子Runnerを作成するVPCのID。
    例) vpc-aaaaaaaaaaaaaaaaa
    amazonec2-subnet-id 子Runnerを作成するサブネットのID。
    例) subnet-bbbbbbbbbbbbbbbbb
    amazonec2-zone 子Runnerを作成するアベイラビリティゾーン。
    ap-northeast-1c なら c、ap-northeast-1a なら aといった感じに指定する。
    amazonec2-ami EC2インスタンスのAMIのID。任意指定。
    指定しない場合は Ubuntu のイメージが使用される。
    amazonec2-use-private-address trueにすると、Docker MachinesのプライベートIPアドレスを利用しつつ、パブリックIPアドレスを作成する。
    amazonec2-tags EC2インスタンスのタグ。任意指定。
    A,aaa,B,bbbと指定すると、タグ名Aに値aaa、タグ名Bに値bbbが設定される。
    amazonec2-security-group セキュリティグループ名。IDではないので注意。こちらの要件を満たしていること。
    amazonec2-instance-type 子Runnerのインスタンスタイプ。ジョブの内容によってサイズを検討する。

    上記の設定をすることで、以下の要件を満たすことができます。

    【実現するご要件 (抜粋) 】
  • 子Runner用 EC2インスタンスは、常時2個を稼働させておく。
  • 子Runner用 EC2インスタンスがAuto Scalingで増加する際は1個ずつ増やし、最大6個までとする。
  • ジョブを実行していない子Runner用 EC2インスタンスは、待機時間が5分を超えたら順次削除する。
  • concurrent = 6
    check_interval = 0
    
    [session_server]
      session_timeout = 1800
    
    [[runners]]
      name = "docker+machine"
      url = "https://gitlab.example.com"
      id = 1
      token = "abcdefghijklmn123456"
      token_obtained_at = 2022-10-04T07:34:53Z
      token_expires_at = 0001-01-01T00:00:00Z
      tls-ca-file = "/etc/gitlab-runner/certs/private-ca.crt"
      executor = "docker+machine"
      limit = 6
      [runners.cache]
        Type = "s3"
        Shared = true
        Path = "path/to/prefix"
        [runners.cache.s3]
          ServerAddress = "s3.amazonaws.com"
          AccessKey = "ABCDEFGHIJKLMNOPQRST"
          SecretKey = "ABCDEFGhijklmnOPQRSTUvwzxzy123456789000"
          BucketName = "gitlab-runners-cache"
          BucketLocation = "ap-northeast-1"
      [runners.docker]
        tls_verify = false
        image = "ruby:3.1.2"
        privileged = true
        disable_entrypoint_overwrite = false
        oom_kill_disable = false
        disable_cache = true
      [runners.machine]
        IdleCount = 2
        IdleTime = 300
        MaxGrowthRate = 1
        MachineDriver = "amazonec2"
        MachineName = "gitlab-docker-machine-%s"
        MachineOptions = [
          "amazonec2-access-key=ABCDEFGHIJKLMNOPQRST",
          "amazonec2-secret-key=ABCDEFGhijklmnOPQRSTUvwzxzy123456789000",
          "amazonec2-region=ap-northeast-1",
          "amazonec2-vpc-id=vpc-aaaaaaaaaaaaaaaaa",
          "amazonec2-subnet-id=subnet-bbbbbbbbbbbbbbbbb",
          "amazonec2-zone=c",
          "amazonec2-ami=ami-ccccccccccccccccc",
          "amazonec2-use-private-address=true",
          "amazonec2-tags=runner-manager-name,gitlab-aws-autoscaler,gitlab,true,gitlab-runner-autoscale,true",
          "amazonec2-security-group=SecurityGroupName",
          "amazonec2-instance-type=t3.medium",
        ]
    

    これらは必要最低限の設定となります。
    これ以外にも設定値は存在しますので、必要に応じて追記/編集してください。
    参考 : Autoscaling GitLab Runner on AWS EC2 - Configuring the runner | GitLab

    編集が終了したら、ファイル/etc/gitlab-runner/config.tomlを保存して閉じます。

    Step3 : Runnerマネージャーの起動とRunner用EC2インスタンスの確認

    Runnerマネージャーの設定が終わったら、以下のコマンドでRunnerを起動します。

    # gitlab-runner start
    

    Runnerを起動後、5分程度で常時起動分の子Runner用 EC2インスタンス (このブログの場合は2台) が起動します。
    AWSのコンソール, API, CLI等でご確認いただけます。

    また、以下のDocker Machineのコマンドでも、子Runner用 EC2インスタンスの起動を確認することができます。

    # docker-machine ls
    
    docker-machine ls で表示されるステータス
    筆者の検証において、Docker Machineが子Runner用 EC2インスタンスを起動している途中においては、docker-machine lsのステータスがErrorになるケースが多々ありましたが、しばらくするとRunningになりました。
    ステータスがErrorでもしばらくそのまま放置するとRunningになる可能性が有るので、5分程度は様子見をしてください。

    なお、この時点でGitLab側から見たRunnerのステータスもOnlineになっています。

    Step4 : 検証用CI/CDパイプラインの作成と実行

    このステップでは、今回作成したRunnerが要件通りAuto Scalingすることを確認できるCI/CDパイプラインを作成します。

    まずは検証用の空のプロジェクトを作成します。
    空のプロジェクト作成方法については以下のブログに記載しております。
    blogs.networld.co.jp

    空のプロジェクトを作成したら、[CI/CD] > [Editor] をクリックします。

    [Configure pipeline] をクリックします。

    テンプレートが自動入力されますが、それらは全て削除します。

    検証用パイプラインを構成します。
    同時実行ジョブが最大6であることを確認したいので、単純に10分スリープするジョブを10個作成します。

    stages:
        - multijobs
    
    job01:
        stage: multijobs
        script:
            - echo "RunnerのAuto Scalingテスト用ジョブ01"
            - sleep 600
    
    job02:
        stage: multijobs
        script:
            - echo "RunnerのAuto Scalingテスト用ジョブ02"
            - sleep 600
    
    job03:
        stage: multijobs
        script:
            - echo "RunnerのAuto Scalingテスト用ジョブ03"
            - sleep 600
    
    job04:
        stage: multijobs
        script:
            - echo "RunnerのAuto Scalingテスト用ジョブ04"
            - sleep 600
    
    job05:
        stage: multijobs
        script:
            - echo "RunnerのAuto Scalingテスト用ジョブ05"
            - sleep 600
    
    job06:
        stage: multijobs
        script:
            - echo "RunnerのAuto Scalingテスト用ジョブ06"
            - sleep 600
    
    job07:
        stage: multijobs
        script:
            - echo "RunnerのAuto Scalingテスト用ジョブ07"
            - sleep 600
    
    job08:
        stage: multijobs
        script:
            - echo "RunnerのAuto Scalingテスト用ジョブ08"
            - sleep 600
    
    job09:
        stage: multijobs
        script:
            - echo "RunnerのAuto Scalingテスト用ジョブ09"
            - sleep 600
    
    job10:
        stage: multijobs
        script:
            - echo "RunnerのAuto Scalingテスト用ジョブ10"
            - sleep 600
    

    任意にコミットメッセージを設定し、[Commit changes] をクリックします。

    コミット後、しばらくすると画面上部にCI/CDパイプラインが実行され始めた旨のメッセージが表示されるので、[View pipeline] をクリックします。

    CI/CDパイプラインのジョブ実行状態の画面に遷移します。
    このブログでは子Runner用 EC2インスタンスは常時2台起動にしているため、この時点で即時で開始されるジョブは2個であることがわかります。

    このまま後述の動作確認を行います。

    動作確認

    ここからは前の手順で準備した環境を使って、CI/CDパイプライン実行時に子Runner用 EC2インスタンスがAuto Scalingにより増台され、終了して一定期間待機後に最低アイドリング台数だけ残して削除されることを確認します。
    なお、前の手順でCI/CDパイプラインが既に開始されているので、間を開けずに動作確認をします。

    確認箇所1 : 検証用CI/CDパイプラインの実行状態確認

    前の手順で表示している、CI/CDパイプラインのジョブの実行状態画面は自動で更新されないので、F5キーなどで画面を更新しながら確認してください。
    常時起動している子Runner用 EC2インスタンスが2台なので、最初は2つのジョブが同時実行されますが、しばらくすると同時実行ジョブ数が3つ、4つ・・・と徐々に増えていくことが確認できるはずです。
    下図は既に同時に4つのジョブを実行し始めている図です。

    本ブログの例では、子Runner用 EC2インスタンスを最大6台と定義しているため、同時実行ジョブ数が最大6で止まることを確認してください。
    下図は6つのジョブが同時実行されている図です。

    この画面を更新しながら、後述の手順で子Runner用 EC2インスタンスが増えていっている様子も確認しましょう。

    確認箇所2 : Runner用EC2インスタンスの増大の確認

    CI/CDパイプラインが開始されると、子Runner用 EC2インスタンス台数が増え始めます。
    この環境では子Runner用 EC2インスタンスの増加数は1台ずつとしたので、それをAWSのコンソールやAPI, CLIなどから確認します。
    下図は4台目の子Runner用 EC2インスタンスを起動している途中の状態の図です。

    本ブログの例では、子Runner用 EC2インスタンスを最大6台と定義しているため、子Runner用 EC2インスタンスは最大6台で止まることを確認してください。
    下図は子Runner用 EC2インスタンスが6台 (Max台数) 起動している状態の図です。

    展開した子Runner用 EC2インスタンスの数は、Runnerマネージャーから以下のコマンドを実行することでも確認できます。

    # docker-machine ls
    

    下図は4台目の子Runner用 EC2インスタンスを起動している途中の状態の図です。

    下図は子Runner用 EC2インスタンスが6台 (Max台数) 起動している状態の図です。

    確認箇所3 : Runner用EC2インスタンスの減少の確認

    本ブログでは子Runner用 EC2インスタンスにおいてアイドル状態が5分継続した場合、常時起動の2台を除き、それらのインスタンスを削除する設定をしています。

    CI/CDパイプラインのジョブjob08が終了したあたりで、子Runner用 EC2インスタンス数の減少が始まると思います。
    AWSのコンソールやAPI, CLIなどで減少の様子を確認します。
    下図は既に6台あった子Runner用 EC2インスタンスが4台まで減少している図です。
    (なお、この図には写っておりませんが、削除された子Runner用 EC2インスタンスのステータスはシャットダウンです。停止ではありません。)

    同様に、Runnerマネージャーからdocker-machineコマンドで子Runner用 EC2インスタンスの減少を確認することができます。
    下図は6台あった子Runner用 EC2インスタンスのうち、2台の停止が行われている最中の図です。

    CI/CDパイプラインのジョブjob10が終了してから5分以上経過したら、子Runner用 EC2インスタンスの台数を確認してください。
    最終的に子Runner用 EC2インスタンスが常時起動の2台だけ残っているはずです。

    キャッシュに設定したS3バケットの手動削除
    Runnerマネージャーのファイル/etc/gitlab-runner/config.tomlでS3バケットをキャッシュに設定した場合は、バケットが自動生成されています。
    本検証が終了したら、このS3バケットは手動で削除してください。

    以上で今回の検証は全て終了となります。

    【余談】筆者の遭遇したエラー

    筆者の環境で、CI/CDのジョブ実行時に以下のエラーが出ました。

    fatal: unable to access 'https://<GitLabのFQDN>/<検証用のグループ>/<検証用のプロジェクト>.git/': Could not resolve host: gitlab.example.com
    Cleaning up project directory and file based variables00:01
    ERROR: Job failed: exit code 1
    

    子Runner用 EC2インスタンス上で起動したコンテナで、GitLabの名前解決ができないという事象です。

    筆者はDNSを作るのが面倒だったので以下の2つの設定をして事象を回避しました。
    参考 : The Docker executor - Legacy container links | GitLab

    • 子Runner用 EC2インスタンスで使うAMIの/etc/hostsにGitLabのFQDNとIPを追記する。
    • Runnerマネージャーの設定ファイル/etc/gitlab-runner/config.toml[runners.docker]セクションに、network_mode = "host"を追記する。

    最後に

    この度はGitもCI/CDもよくわかっていないど素人SEによるGitLab検証ブログをお読みいただき、誠にありがとうございます。
    このブログの目標は以下のとおりでしたが、皆さまはいかがでしたでしょうか。


    今回のゴール
    • GitLabでDocker Machineを使ってRunnerをAWS EC2インスタンスでAuto Scalingする。

    Docker Machineを使ってGitLab RunnerをパブリッククラウドでAuto Scalingさせる方法はかなり昔から実装されていた模様で、Docker Machineが現状 (2022/10/04時点) 廃止されていてもなお、GitLabでサポートされるRunnerの展開方法です。
    他にもRunnerをAuto Scalingさせる方法はたくさんあるかと存じますが、とりあえず今回はこのレガシー的な実装方法をご紹介いたしました。
    この記事がGitLabを触り始めた方の一助となれば幸いにございます。


    GitLabに関するお問い合わせは、以下のフォームからお願い致します。
    GitLab製品 お問い合わせ

    今までのGitLabの検証ブログはこちらです。
    GitLab カテゴリーの記事一覧 - ネットワールド らぼ

    GitLab操作デモ動画 (基本編) を作ってみました。(音声の録音は自宅でiPhoneのボイスメモ使うという超低クオリティですが…。)
    つたない内容ではありますが、ご興味がおありでしたら是非ご視聴いただければと存じます。


    www.youtube.com