コンテンツにスキップ

ci_pipeline pattern

概要

ci_pipeline patternモジュールでは、以下のステップを実現するため、CIパイプラインに必要なリソースを構築します。

  • GitLabリポジトリで管理されたプロジェクトをビルド
  • ビルドされた成果物を、アーティファクトの格納先へ保存

patternを適用することで、CIパイプラインを実行させるための環境およびビルド結果(アーティファクト)の格納先を構築結果として得ることができます。

想定する適用対象環境

ci_pipeline patternは、Delivery環境での使用を想定しています。

依存するpattern

ci_pipeline patternは、事前に以下のpatternが適用されていることを前提としています。

pattern名 利用する情報
network pattern プライベートサブネット

本patternが依存するリソースを他の構築手段で代替する場合は、依存するpatternと入出力リファレンスの内容を参考に、本patternが必要とするリソースを構築してください。

構築されるリソース

このpatternでは、以下のリソースが構築されます。

リソース名 説明
Amazon EC2 ビルドを行う役割を担う、GitLab Runnerを動作させる環境を構築します
Amazon ECR ビルドされたアプリケーションコンテナを格納する、Dockerコンテナレジストリを構築します
Amazon S3 ビルドされた静的リソースファイルを格納する、S3バケットを構築します

モジュールの理解に向けて

ここでは、ci_pipeline patternが想定している環境や使い方、その背景について記載します。

ci_pipeline patternが実現するフロー

ci_pipeline patternを適用することで、以下のフローを実現できます。

  • GitLabリポジトリで管理されたプロジェクトをビルド
  • ビルドされた成果物を、アーティファクトの格納先へ保存

このフローを実現するためには、ci_pipeline pattern単体だけではなく、GltLabリポジトリで管理される設定ファイル等も含めた組み合わせで実現します。

このため、ci_pipeline patternが構築するリソースと、前提事項への理解が重要になります。

前提事項

ci_pipeline patternは、以下の前提事項のもとで利用されることを想定しています。

  • アプリケーション等のソースコードを管理するリポジトリは、GitLabを使用していること
  • GitLabは、SaaS版(gitlab.com)を使用していること(プランは問わない)
  • アプリケーションのビルドは、GitLab Runnerで行うこと
  • GitLabのリポジトリ内に、GitLab Runnerの設定ファイル(.gitlab-ci.yml)が格納されていること
  • GitLab Runnerの実行には、Dockerを使用すること
  • ビルドされたアプリケーションは、コンテナイメージまたは静的リソースファイルのいずれかであること

なぜGitLabなのか? なぜGitLab SaaS版なのか?

ci_pipeline patternによって構築されるリソースには、GitLab自身は含まれません。

SaaS版(gitlab.com)のGitLabではなく、独自のGitLabインスタンスを使用する場合は、利用者自身で構築する必要があります。

VCS ProviderとしてGitLabを採用するのは、Community Editionの存在があるからです。
仮にリポジトリをSaaS版(gitlab.com)に配置できない場合であっても、Community Editionであればオープンソース版として使用できるため、ノウハウの再利用が行いやすくなります。

GitLabのSaaS版(gitlab.com)を前提としているのは、EponaのConceptであるOperation-Lessに則っているからです。

なぜGitLab Runner用にAmazon EC2を構築するのか?

ci_pipeline patternで構築されるリソースには、GitLab Runner用のAmazon EC2が含まれています。

これはAmazon EC2を運用することになるため、SaaS版のGitLabを前提としているEponaのConceptであるOperation-Lessとは直交します。

それでもこの形態としているのは、GitLab SaaS版における以下の理由からです。

  • Free Planでは、CI/CDパイプラインの実行は月あたり2,000分に制限される
  • 月あたり2,000分の制限は、サービスの規模が大きくなると容易に超える時間であり、この時間を節約するためにCIプロセスを変更するようなコストを割くべきではない
  • Shared Runnersは固有の設定ができず、スペックも変更できない

CIパイプラインはアプリケーション固有の事情が持ち込まれやすいため、この構成としています。

また、ci_pipeline patternが前提とするフロー、環境に統合しやすいよう、構築されるAmazon EC2インスタンスには以下の内容が設定・インストールされます。

  • 次の3つのポリシーを含む、IAMインスタンスプロファイル
    • AmazonSSMManagedInstanceCore
    • AmazonEC2ContainerRegistryPowerUser
    • AmazonS3FullAccess
  • セキュリティグループ
    • すべてのインバウンドを遮断
    • アウトバウンドは許可(GitLab SaaS版と通信するため)
  • GitLab Runnerでジョブを実行するための、Docker Engine

ポリシーには、AWS Systems Manager Session Managerを使用する権限も含まれています。
インスタンスにアクセスする必要が出てきた場合は、Session Managerを使用するとよいでしょう。

このためAmazon EC2に指定するAMIとして、デフォルトでSSMエージェントがインストールされているAmazon Linux 2などの利用をお勧めします。

.gitlab-ci.ymlについて

GitLab Runnerで動作させる.gitlab-ci.ymlは、ここまでの前提事項を考慮して、パイプラインのソースおよび成果物の扱いをコントロールする必要があります。

基本的な流れは、GitLab Runner上でDockerイメージを使用したビルドを行い、アーティファクトを保存(Amazon ECRもしくはAmazon S3へ格納)することになります。

具体的な記述例は、Getting Startedを参考にしてください。

また、GitLab CI/CDでコンテナイメージのCDを行う方法については GitLab CI/CDによるアプリケーションのビルド・デプロイガイドをご確認ください。

Pull policy について

上記の通り、GitLab Runnerがジョブを実行する際はDockerイメージを使用します。 このためGitLab Runnerは、.gitlab-ci.ymlで指定されたイメージをコンテナレジストリからダウンロードすることになります。

コンテナレジストリとして有名なのはDocker Hubですが、Docker Hubではコンテナイメージのダウンロード回数制限が課されます。 結果として、Docker Hubから頻繁にCIジョブを実行する環境では、当該の制限によってエラーが発生し得ます。

当該の制限を超えにくくすることを目的に、本patternで構成されるGitLab Runnerでは、デフォルトで「Pull済みのコンテナイメージがない場合にのみダウンロードする」ように設定しています。 逆に、ジョブを実行する毎に無条件でコンテナイメージをダウンロードをさせる挙動にしたい場合は、gitlab_runner_pull_image_alwaystrueに設定してください。

これらの挙動についてはHow pull policies work、および、本ページのgitlab_runner_pull_image_alwaysの説明を参照ください。

Runtime環境とブランチ戦略

開発において、本番環境、ステージング環境等、用途に合わせた稼働環境が複数あり、EponaではこれをRuntime環境と呼んでいます。

CIパイプラインにて生成する成果物と、複数存在するRuntime環境をどのように紐付けて管理するかは、構成管理上のポイントになります。

Eponaでは、ブランチ戦略にGitLab Flowを利用することを想定しています。

そして、環境ごとに存在するブランチから作成される成果物を、どのように分類するかは以下の想定としています。

  • Dockerイメージ
    • ブランチと紐付けて、タグで分類
  • 静的コンテンツ、Lambda関数
    • ブランチと紐付けて、アーティファクトの保存先で分類

具体的な記述例は、Getting Startedを参考にしてください。

Runtime環境からのクロスアカウントアクセス

ci_pipiline patternは既述の通りDelivery環境上に適用することを想定していますが、以下のようなリソースにRuntime環境からアクセスしたい場合があります。

  • ビルドされたコンテナイメージを格納するECR
  • 静的リソースファイルを格納するS3バケット

このようなリソースアクセスには、クロスアカウントの設定が必要となります。
ここでは、このようなクロスアカウントアクセスが必要となるリソースと、Runtime環境からのアクセス許可について記述します。

ECR

コンテナイメージを格納したECRには、以下のAWSリソースがアクセスします。

  • public_traffic_container_service patternで構築されるAmazon Elastic Container Service(ECS)
  • cd_pipeline_backend patternで構成されるAWS CodePipeline

したがってこれらのpatternと組み合わせる際は、当該ECRのリポジトリポリシーを用いて、 Runtime環境からのアクセスを許可する必要があります。

クロスアカウントを行うための設定は、以下のようにポリシーを定義して行います。

# Runtime環境からクロスアカウントでPull Accessを可能にするポリシー
data "aws_iam_policy_document" "cross_account_pull_policy" {
  statement {
    actions = [
      "ecr:GetDownloadUrlForLayer",
      "ecr:BatchCheckLayerAvailability",
      "ecr:BatchGetImage"
    ]
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::[Runtime環境のAWSアカウントID]:root"]
    }
  }
}

このポリシーのci_pipeline patternモジュールへの指定方法は、サンプルコードに記載しています。

S3バケット

フロンドエンド用にビルドした静的コンテンツの場合

Eponaでは、ci_pipeline patternでビルドした静的コンテンツをcd_pipeline_frontend pattern によりRuntime環境のS3バケットにデプロイできます。 この静的コンテンツは、ci_pipeline patternstatic_resource_bucketsで指定したS3バケットに 配置するようにGitLab CI/CDを構成してください。

ℹ️
cd_pipeline_frontend patternではアーティファクトの取得元(source_bucket_name)を 指定する必要があります。その際はstatic_resource_bucketsのバケット名を指定してください。

アーティファクトを格納したS3バケットへは、以下のAWSリソースがアクセスします。

  • cd_pipeline_frontend patternで構成されるAWS CodePipeline

したがってこれらのpatternと組み合わせる際は、当該S3バケットのバケットポリシーを用いて、 Runtime環境からのアクセスを許可する必要があります。

クロスアカウントを行うためのバケットポリシーの設定は、本パターンを適用することで以下のポリシーが自動的に設定されます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::${Runtime環境のAWSアカウントID}:root"
            },
            "Action": [
                "s3:GetObject",
                "s3:GetObjectVersion"
            ],
            "Resource": "${作成されるS3バケットのARN}/*"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::${Runtime環境のAWSアカウントID}:root"
            },
            "Action": "s3:ListBucket",
            "Resource": "${作成されるS3バケットのARN}"
        }
    ]
}
Lambda関数の場合

ci_pipeline patternでビルドしたLambda関数のソース等を cd_pipeline_lambda pattern によりRuntime環境のS3バケットにデプロイできます。 これらのファイル群は、ci_pipeline patternstatic_resource_bucketsで指定したS3バケットに 配置するようにGitLab CI/CDを構成してください。

基本的な流れはフロンドエンド用にビルドした静的コンテンツの場合と同じです。

上記以外の(jarファイルなどの)アーティファクトの場合

ci_pipeline patternでjarファイルなどのアーティファクトをビルドしたあと、利用者にて個別にデプロイ(たとえばEC2など)したい場合もあるでしょう。その場合、アーティファクトはartifact_bucketsに配置してください。

アーティファクトを格納したS3バケットには、フロンドエンド用にビルドした静的コンテンツの場合と同様のバケットポリシーが設定されます。アクセスを許可するアカウントIDは利用者の環境に応じて設定してください。

実際の利用やカスタマイズに向けて

ここまで記載してきたとおり、ci_pipeline patternの利用には、patternが想定するフローや前提事項への理解が必要になります。
ソースコードリポジトリからのビルドやアーティファクトの格納などは、利用者側で.gitlab-ci.ymlを記述して実現することになるからです。

また、カスタマイズについてもこれらの前提事項の理解が必要です。
ci_pipeline patternの内容が、要件等に合わない場合は、利用者側で独自にCIパイプラインを構築することになります。

たとえば、GitLab RunnerはSaaS版が提供するShared Runnerを使いたい場合が考えられます。GitLab Runnerがどうしても採用できない場合もあるでしょう。

Eponaでは、ci_pipeline patternにより構築され、CIパイプラインの実行結果として保存されたアーティファクトを元に、後続のデプロイメントパイプラインが動作することになります。

よって、CIパイプラインとCDパイプラインをつなぐインターフェース、つまりアーティファクトの格納先が重要です。

ci_pipiline patternは、単体で利用するものではありません。ソースコードリポジトリに含まれる内容や、その前提になっているブランチ戦略などを理解して、周辺リソースと協調して使うものです。

開発やデプロイのやり方、スピードにCIパイプラインは大きな影響を及ぼすことになるため、これらの背景、設計思想についてはぜひ理解するようにしてください。

GitLab Runnerのregistration tokenについて

ci_pipiline patterngitlab_runner_registration_tokenには、GitLabのregistration tokenを指定する必要があります。

registration tokenは、GitLabのリポジトリまたはグループのCI/CDに関する設定から取得でき、GitLabに対してGitLab Runnerを登録する際に利用されます。

このregistration tokenは、限られた人が参照できるべき情報になります。.tfファイルにハードコードするのではなく、Terraform実行時に都度入力、またはアクセスする人が限られる.tfvarsファイルで管理するなどの方法を取るようにしてください。

サンプルコード

ci_pipeline patternを使用したサンプルコードを、以下に記載します。

# 最新のAmazon Linux 2のAMIを取得するためのデータソース
data "aws_ami" "recent_amazon_linux_2" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-2.0.*-x86_64-gp2"]
  }

  filter {
    name   = "state"
    values = ["available"]
  }
}

# Runtime環境からクロスアカウントでPull Accessを可能にするポリシー
data "aws_iam_policy_document" "cross_account_pull_policy" {
  statement {
    actions = [
      "ecr:GetDownloadUrlForLayer",
      "ecr:BatchCheckLayerAvailability",
      "ecr:BatchGetImage"
    ]
    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::[Runtime環境のAWSアカウントID]:root"]
    }
  }
}

# ci_pipeline patternの適用
module "ci_pipeline" {
  source = "git::https://gitlab.com/eponas/epona.git//modules/aws/patterns/ci_pipeline?ref=v0.2.6"

  name = "epona-gitlab-runner"

  tags = {
    # 任意のタグ
    Environment        = "delivery"
    ManagedBy          = "epona"
  }

  vpc_id = data.terraform_remote_state.production_network.outputs.network.vpc_id

  static_resource_buckets = [{
    bucket_name        = "frontend-static-resource"
    force_destroy      = false
    runtime_account_id = "${Runtime環境のAWSアカウントID}"
  }]

  container_image_repositories = [{
    name                 = "backend-application"
    image_tag_mutability = "MUTABLE"

    repository_policy    = data.aws_iam_policy_document.cross_account_pull_policy.json  # Runtime環境からのクロスアカウントでのアクセスを許可
  }]

  ci_runner_ami                    = data.aws_ami.recent_amazon_linux_2.image_id
  ci_runner_instance_type          = "t3.medium"
  ci_runner_root_block_volume_size = "100"
  ci_runner_subnet                 = data.terraform_remote_state.delivery_network.outputs.network.private_subnets[0]

  gitlab_runner_registration_token = var.gitlab_runner_registration_token
}

関連するpattern

ci_pipeline patternに関連するpatternを、以下に記載します。

pattern名 説明
cd_pipeline_backend_trigger pattern ci_pipeline patternによってAmazon ECRへのコンテナイメージPushされたことをトリガーに、バックエンド向けのデプロイメントパイプラインを起動できるようになります
cd_pipeline_backend pattern cd_pipeline_backend_trigger patternによるイベントをもとに、AWS Fargateクラスターへのデプロイを行うパイプラインを起動します
cd_pipeline_frontend_trigger pattern ci_pipeline patternによってAmazon S3へ静的リソースファイルがPushされたことをトリガーに、フロントエンド向けのデプロイメントパイプラインを起動できるようになります
cd_pipeline_frontend pattern cd_pipeline_frontend_trigger patternによるイベントをもとに、Runtime環境のAmazon S3へのデプロイを行うパイプラインを起動します
cd_pipeline_lambda_trigger ci_pipeline patternによってAmazon S3へLambda関数のソースファイル等がPushされたことをトリガーに、Lambda関数向けのデプロイメントパイプラインを起動できるようになります
cd_pipeline_lambda cd_pipeline_lambda_trigger patternによるイベントをもとに、Runtime環境のLambda関数へのデプロイを行うパイプラインを起動します

入出力リファレンス

Requirements

Name Version
terraform ~> 0.14.10
aws >= 3.37.0, < 4.0.0

Inputs

Name Description Type Default Required
ci_runner_ami GitLab Runnerを稼働させるEC2インスタンスインスタンスのAMI string n/a yes
ci_runner_instance_type GitLab Runnerを稼働させるEC2インスタンスのインスタンスタイプ string n/a yes
ci_runner_root_block_volume_size GitLab Runnerを稼働させるEC2インスタンスの、ルートデバイスボリュームのサイズ string n/a yes
ci_runner_subnet GitLab Runnerを稼働させるEC2インスタンスを配置する、サブネットのID string n/a yes
name GitLab Runnerに関するリソースに対して、共通的に付与する名前 string n/a yes
vpc_id このモジュールで作成するリソースが配置される、VPCのID string n/a yes
artifact_buckets ビルドしたアーティファクトを配置するバケットに関する設定を指定する(bucket_name, force_destroy, runtime_account_id)。このバケットに出力されたアーティファクトは、利用者自身でデプロイする list(map(any)) [] no
ci_runner_cloud_init_script GitLab Runnerを稼働させるEC2インスタンスの構築時に適用する、Cloud Initスクリプト。GitLab RunnerおよびCIで必要なパッケージのインストールなどに使用する string null no
ci_runner_security_groups GitLab Runnerを稼働させるEC2インスタンスに適用する、セキュリティグループID list(string) [] no
container_image_repositories 作成するECRに関する設定を指定する(name, image_scan_on_push, image_tag_mutability, lifecycle_policy, repository_policy) list(map(any)) [] no
gitlab_runner_gitlab_url GitLab Runnerのアクセス先となる、GitLabのURL string "https://gitlab.com" no
gitlab_runner_pull_image_always GitLab RunnerがCIジョブでコンテナイメージを取得する際に常に最新のイメージを利用するかどうかのフラグ。
値がtrueである場合、pull_policyalwaysが設定され、コンテナイメージは常に最新のイメージをpullする。
false(もしくはデフォルト値)を指定した場合、pull_policyalwaysが設定され、ローカルにイメージがある場合はローカルイメージを利用する。
pull_policyの詳細は、How pull policies workを参照してください。
bool false no
gitlab_runner_registration_token GitLab RunnerのGitLabに登録するためのトークン。ci_runner_cloud_init_scriptを指定する場合は不要 string null no
static_resource_buckets 静的リソースを配置するS3バケットに関する設定を指定する(bucket_name, force_destroy, runtime_account_id)。このバケットに出力された静的リソースは、cd_pipeline_frontendでのデプロイ対象とする list(map(any)) [] no
tags このモジュールで作成されるリソースに付与するタグ map(string) {} no

Outputs

Name Description
container_image_repository_arns ECRリポジトリの名前とARNのマップ
container_image_repository_urls ECRリポジトリの名前とURLのマップ
s3_ci_bucket_arns S3バケットの名前とARNのマップ

※ このドキュメントはクリエイティブコモンズ(Creative Commons) 4.0 の「表示—継承」に準拠しています。

※ このドキュメントに記載されている会社名、製品名は、各社の登録商標または商標です。

© 2021 TIS Inc.