こんにちは。2019/8月入社SREチームのくぼっきーです。
今回は弊社のCI/CD環境周りをGitLab CI/CDでスマートに!という内容でお送りします。
前提
- AWS × Jenkins × GitLabCE on EC2 な環境
課題
- 業務バッチとCI/CDジョブが混在していて止まってはいけないジョブがどれなのか担当者じゃないとわからない。(仮に把握してもその後ジョブはどんどん生まれていく
- ジョブ間の依存関係がよくわからない。(Jenkinsのpipelineは敷居高い、、、
- Jenkinsのジョブ定義をバージョン管理できていない。いつの間にか動かなくなったなんてこともざらにある。
- 影響範囲を限定するためプロジェクト毎に専用のJenkinsスレーブを立てているが、スレーブノード自体の管理&認知負荷が辛い。(ノード毎にタグ管理とかしたくない、そして分けても過負荷で止まる
- Gitリポジトリとの連携はServer hooks使い始めたけど、ここの作りこみをやっていくと辛い未来が待っている。
GitLab CI/CDの良いとこ
- ☞ 1.の課題解消 止まるとサービス影響のある業務バッチ(Jenkins)と、止まっても直接的にサービス影響が生じないビルド/デプロイジョブ(GitLab CI/CD)とで棲み分けがされていくことが期待できる。
- ☞ 2.の課題解消 ジョブとリポジトリが紐づく & 強制的にパイプライン表現になるので依存関係がわかりやすい。
- ☞ 3&5.の課題解消 Gitリポジトリとの連携が非常にスマートになる。特につくりこまなくても様々な開発フロー要件にフィットさせられる。
- ☞ 4.の課題解消 ジョブ実行ノードをオートスケールアウト・インさせれるので一度作ってしまえば基本的に放置でおk。ジョブ実行基盤をプロジェクト毎に管理することから解放される。
- Jenkinsリモートビルド機能を活用すれば既存Jenkinsジョブを流用しつつ柔軟に開発フローを組むのも簡単。
参考:JenkinsでJobを起動して、終了まで待つシェルスクリプト - スポットインスタンス運用&営業時間内外でインスタンスのアイドリング数を変更出来たりとコスパ最強!!
- その他まだまだ魅力満載\(^_^)/(機能多過ぎで触りきれない
参考:GitLab機能一覧
構成概要
- GitLab:gitリポジトリサーバ。
- GitLab Runnerベースマシン: ジョブ実行制御用ノード。リクエスト数に応じてスポットインスタンスでジョブ実行ノードをスケーリング。
- GitLab Runnerジョブ実行ノード: 実際に処理が実行されるインスタンス。
全体の流れ
※既にGitLabサーバが立っていることを前提としてます
- GitLab Runnerジョブ実行ノード用AMIを用意
- GitLab Runnerベースマシンセットアップ
- CI/CDジョブを実行してみる
※とりあえずCI/CD機能だけ試してみたい!って人はgitlab.comを利用すれば3のステップだけでお試しできます
Let's try
1. GitLab Runnerジョブ実行ノード用のAMIを用意
概要
ベースマシンがジョブ実行ノード起動時に使用するAMIを用意します。起動処理はdocker-machineで行われ、ジョブ実行ノードで自動的にdockerがセットアップされます。
動作要件
- GitLab Runnerベースマシンから、22番ポートを使用してパスフレーズ無し公開鍵認証でsshログイン出来ること
- GitLab Runnerベースマシンから2376番ポートで通信出来ること(docker socket通信で使用)
docker-machineがデフォルトだとubuntuユーザでsshログインしにいくため、今回の検証ではAMIストアパブリックイメージのUbuntu 19.04(ami-0b50bf6a426e13bf9)を利用しました。デフォルトのままであればSSH鍵も自動生成してくれるのでお手軽です。
2. GitLab Runnerベースマシンセットアップ
概要
下記動作要件を満たすコンテナを立ち上げ、GitLab Runnerの設定をします。
動作要件
- GitLabサーバとSSH、HTTP or HTTPS通信が出来ること
docker
コマンドが動作することdocker-machine
コマンドが動作することgitlab-runner
コマンドが動作すること
セットアップ
- 下記のdockerfileを作成し、コンテナを起動します。
Dockerfile
FROM gitlab/gitlab-runner:latest RUN apt update -y && apt install -y \ apt-transport-https \ ca-certificates \ curl \ software-properties-common RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \ add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" RUN apt update -y && apt install docker-ce -y && \ apt-get clean && rm -rf /var/lib/apt/lists/*
docker build -t gitlab-runner-base "Dockerfileを配置したディレクトリ"
docker run -d -t --name gitlab-runner-base -i gitlab-runner-base
- 下記コマンドを環境に合わせパラメーター設定し、実行
各パラメーターはこちらを参考に設定してください https://docs.gitlab.com/ee/ci/runners/README.html
https://docs.gitlab.com/runner/configuration/runner_autoscale_aws/
https://docs.gitlab.com/runner/executors/docker_machine.html
http://docs.docker.jp/machine/drivers/aws.html
※docs.docker.jpのページは記載されてるオプションの一部でスペル間違いがありハマったので、正確なスペルはdocker-machineコマンドのhelpを確認することお勧めします
Command
docker exec -it gitlab-runner-base gitlab-runner register \ --non-interactive \ --name autoscaler \ --limit 10 \ --url https://gitlab.com/ \ --registration-token XXXX \ --executor docker+machine \ --tag-list sample_runner \ --custom_build_dir-enabled \ --docker-image docker:stable \ --docker-privileged \ --docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \ --docker-volumes "/builds:/builds" \ --docker-pull-policy "if-not-present" \ --machine-max-builds 0 \ --machine-idle-nodes 1 \ --machine-idle-time 1800 \ --machine-machine-driver amazonec2 \ --machine-machine-name=runner-default-%s \ --machine-machine-options "amazonec2-ami=ami-0b50bf6a426e13bf9" \ --machine-machine-options "amazonec2-access-key=XXXX" \ --machine-machine-options "amazonec2-secret-key=XXXX" \ --machine-machine-options "amazonec2-instance-type=t2.micro" \ --machine-machine-options "amazonec2-region=ap-northeast-1" \ --machine-machine-options "amazonec2-root-size=16" \ --machine-machine-options "amazonec2-security-group=gitlab-runner" \ --machine-machine-options "amazonec2-ssh-user=ubuntu" \ --machine-machine-options "amazonec2-tags=Name,gitlab-runner" \ --machine-machine-options "amazonec2-vpc-id=vpc-XXXX" \ --machine-machine-options "amazonec2-subnet-id=subnet-XXXX" \ --machine-machine-options "amazonec2-zone=a" \ --machine-machine-options "amazonec2-private-address-only" \ --machine-machine-options "amazonec2-request-spot-instance" \ --machine-machine-options "amazonec2-spot-price=" \ --cache-type s3 \ --cache-path gitlab-runner/cache \ --cache-shared=true \ --cache-s3-server-address s3.amazonaws.com \ --cache-s3-access-key XXXX \ --cache-s3-secret-key XXXX \ --cache-s3-bucket-name "s3bucket_name" \ --cache-s3-bucket-location ap-northeast-1 \ --machine-off-peak-periods "* * * * * sat,sun *" \ --machine-off-peak-periods "* * 0-9,18-23 * * mon-fri *" \ --machine-off-peak-timezone Asia/Tokyo \ --machine-off-peak-idle-count 0 \ --machine-off-peak-idle-time 60
ログを確認し下記のように最終的に "Machine created" と出力されていればOK
Log
# docker logs -f gitlab-runner-base ~~~ ~~~ Configuration loaded builds=0 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 Running pre-create checks... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create Creating machine... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create (runner-39148577-runner-default-1582858635-dce88b79) Launching instance... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create (runner-39148577-runner-default-1582858635-dce88b79) Waiting for spot instance... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 (runner-39148577-runner-default-1582858635-dce88b79) Created spot instance request sir-3mdrb6sg driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 Waiting for machine to be running, this may take a few minutes... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create Detecting operating system of created instance... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create Waiting for SSH to be available... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 Detecting the provisioner... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 Provisioning with ubuntu(systemd)... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 Installing Docker... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create Copying certs to the local machine directory... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create Copying certs to the remote machine... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 Setting Docker configuration on the remote daemon... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 Checking connection to Docker... driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create WARNING: Failed to process runner builds=0 error=failed to update executor: no free machines that can process builds executor=docker+machine runner=39148577 Docker is up and running! driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env runner-39148577-runner-default-1582858635-dce88b79 driver=amazonec2 name=runner-39148577-runner-default-1582858635-dce88b79 operation=create Machine created duration=1m0.152015073s name=runner-39148577-runner-default-1582858635-dce88b79 now=2020-02-28 02:58:15.978711696 +0000 UTC m=+86584.947166950 retries=0
- ジョブ同時実行数を設定
デフォルトではジョブ同時実行数が1となっているため、必要に応じて同時実行数を増やす
docker exec -it gitlab-runner-base bash vi /etc/gitlab-runner/config.toml
先頭行にあるconcurrentの値を希望の数に設定
concurrent = xx
~~~
3. CI/CDジョブを実行してみる
参考:GitLab CI/CD Pipeline Configuration Reference
.gitlab-ci.ymlサンプル
stages: - codecheck - build_container - deploy_feature - e2etest - deploy_develop - deploy_production variables: GIT_CLONE_PATH: ${CI_BUILDS_DIR}/${CI_PROJECT_NAME}/${CI_COMMIT_REF_SLUG} static_code_analysis: stage: codecheck image: docker/compose:latest script: - echo static_code_analysis code_test: stage: codecheck image: docker/compose:latest script: - echo code_test build_container: stage: build_container image: docker:stable script: - echo build_container deploy_feature: stage: deploy_feature image: docker:stable script: - echo deploy_feature environment: name: feature/${CI_COMMIT_REF_SLUG} url: https://${CI_COMMIT_REF_SLUG}.example.com e2etest: stage: e2etest image: docker:stable script: - echo e2etest deploy_develop: stage: deploy_develop image: docker:stable script: - echo deploy_develop only: - develop when: manual environment: name: develop url: https://dev-example.com deploy_production: stage: deploy_production image: docker:stable script: - echo "deploy_production" only: - master when: manual environment: name: production url: https://prd-example.com
GitLabのPipelinesページでパイプラインが実行されてることを確認
MR画面にパイプラインの実行結果が表示&レビュー用環境へのリンクが自動付与(Review Apps機能)されレビュー効率が大幅アップ\(^_^)/
以上!
コメント
本記事上では一部機能にしか触れてませんが、その他機能含め感触としてGitLabとてもおすすめです!
やはりGitLabはリポジトリとCI/CDが同じサービス内で統合されているという点で利点が大きく、CI/CDでやりたいおおよそのことがスマートに実装出来る印象を持ちました。
またプロジェクト管理機能が充実しているので、この点も上手く使いこなせればよりスマートなDevOpsに近づくのではないかと思います。
世の中ではGitHubのほうが人気ですが、今回色々と触ってみたことで個人的にはGitLab推しになりました!ぜひ皆さんもGitLab使ってみてください。
Enjoy develop!
\\『真のユーザーファーストでマーケットを創造する』「ありがとう」で溢れる仲間を募集中です!! //
919.jp