GitLab Runnerを活用したCI/CD自動化の実践

はじめに

GitLab Runnerは、GitLab CI/CDと連携してパイプラインでジョブを実行するアプリケーションです。GitLab CI/CDを利用した継続的インテグレーションと継続的デプロイメントの自動化には不可欠と言えるでしょう。

CI/CDの自動化ツールは、Gitlab CI/CD以外にも様々な有名ツールが存在します。

  • GitHub Actions
  • CircleCI
  • Jenkins
  • AWS CodePipeline

これらのツールを活用し、CI/CDを自動化することで開発プロセスの効率化と品質向上が期待できます。

こんにちは。
デザインシステム室の森口です。

弊社では一部のプロジェクトにおいてAWS CodePipelineを使用していますが、大半は自動化できておらず、手動でのデプロイを行っています。
今回は既存プロジェクトのリプレイスを行う際に、デプロイフローについても見直しを行いましたので、事例を紹介いたします。

Gitlab Runnerの構成

まず、今回使用するGitlab Runnerですが、Jobの監視と実際のJob処理に使用するインスタンスを分けており、処理に使用するインスタンスは自動起動する様に設定しています。

Jobの監視を行なっているRunnerは、Jobが作成されるとAWS AutoScalingGroup内にJob用のEC2インスタンスを作成します。
このAutoScalingGroupは最小インスタンス数を0で指定しているため、Jobが存在しない場合はインスタンスが存在しない状態となります。

監視RunnerはGitlabインスタンスと同じインスタンス上で稼働しており、Job用インスタンスは必要に応じて稼働させることができるため、稼働コストを抑えることができています。

自動化の概要

今回作成したCI/CDパイプラインは、マージリクエスト作成時、所定のブランチへのマージ時にプロセスを実行します。

マージリクエスト作成時はSASTのみ走りますが、マージ時は以下の条件に沿って実行します。
developmentブランチはfeatureブランチをマージするブランチ、mainは本番環境でチェックアウトしているブランチと考えてください。

SASTとは:
静的アプリケーションセキュリティテストの略。アプリケーションを実行せずにコードを静的に解析することで脆弱性を自動的に探すテスト方法です。

対象ブランチがdevelopmentの場合

1. SAST

対象ブランチがmainの場合

1. SAST
2. イメージの作成(ビルド)とレジストリへのプッシュ
4. 本番環境への自動デプロイ

.gitlab-ci.ymlの設定

.gitlab-ci.ymlに定義している内容の主な箇所を以下に載せています。
(Kanikoのscriptはかなり省略しています。)

Kanikoとは:
Kanikoは、Googleが開発したオープンソースツールで、特権を持たない環境でコンテナイメージをビルドするために使用されます。

stages:
- test
- build
- update-ecs

# セキュリティスキャン関連の設定
sast:
  stage: test
include:
  - template: Security/SAST.gitlab-ci.yml

# Kanikoを使用したイメージのビルド
kaniko-build:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:v1.14.0-debug
    entrypoint: [""]
  script:
	  - イメージのビルド
	  - GitLab container registryへのプッシュ
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: always
      exists:
        - Containerfile
        - Dockerfile

update-ecs-service:
  stage: update-ecs
  image: 
    name: amazon/aws-cli:latest
    entrypoint: [""]
  script:
    - >
      aws ecs update-service 
      --cluster "$AWS_ECS_CLUSTER" 
      --service "$AWS_ECS_SERVICE" 
      --force-new-deployment
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      when: always
  variables:
    AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
    AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
    AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
    AWS_ECS_CLUSTER: $AWS_ECS_CLUSTER
    AWS_ECS_SERVICE: $AWS_ECS_SERVICE

本番環境へのデプロイですが、リプレイスの際に本番環境をオンプレ(EC2を利用はしていましたが…)からECSへ移したため、Gitlab container registryの最新イメージを使用したECSのサービス更新でデプロイを行っています。

課題と解決策

現状の課題としては以下が挙げられます。

1. テストを行えていない
2. デプロイ前の動作検証環境が整っていない

テストに関しては、そもそものテストコードが不足していることも要因ではありますが、CI/CDとしては以下を自動化したいと考えています。

1. RSpecやCapybaraによるテストの実施
2. Rubocopによるコードチェック

動作検証環境については、本番と同じイメージを検証で利用できなければ意味がありません。
そのため、developmentとmainの間にstagingを用意し、stagingへのマージ時にビルドを行い、最新のイメージを元にstaging環境を作成、利用できると良いと考えています。

■CI/CDパイプラインのイメージ
– developmentへのマージでは、SAST、testのみ実施
– developmentからstagingへのマージではSAST、test、imageのbuildを実施
– stagingからmainへのマージでは、stagingで作成したimageを使用してecs環境の更新のみを行う

検証環境は常時使用するわけではないため、必要に応じて作成・停止ができることが望ましいと考えています。そのため、CI/CDパイプラインを活用して、環境の作成、起動、停止を自動または半自動で運用できるようにしたいと思います。

まとめ

今回のCI/CD自動化により、デプロイミスの低減(ssh接続しなくて良い…)、作業効率化が実現できたと思います。
テストが不完全であるため品質向上の余地が残されていますが、この経験を活かして他のプロジェクトへの導入を進めていきたいと考えています。

現在デザイン・システム室では、新しいメンバーを募集しています。
少しでも興味を持たれた方は、ぜひご応募ください