背景
とある案件でCI/CD パイプラインをAWS CodePipelineで実装することになったのだが、以下の諸々の制約を解消する連携方法を模索することになった。
- ソース管理にはBitbucketを使用する
- 作成するパイプラインでは複数のAWSサービス(CodeDeployやSSM Automation、CloudFormation)と連携が必要
- 一つのBitbucketリポジトリから起動したいパイプラインの種類が複数ある
関連する各種サービスの仕様は以下の通り。
- CodePiplineのソースとしてはBitbucketはサポートされていない
- CodePipelineのソースとしてS3はサポートされている
- CodeBuildはBitbucketと連携可能
ところが、後になって以下の制約が判明!
- セキュリティ上Bitbucketは特定のIPアドレスの範囲からしかアクセスできない
AWS CodeBuildとしては以下の仕様があるのでIPアドレスの範囲に追加してもらうことを交渉してみる。
- CodeBuildはVPC内で実行することも可能
しかし、お客様がCodeBuildからもBitbucketにアクセスできるようにすることに乗り気でなかったのでBitbucketのパイプライン機能に白羽の矢を立てることになる。
いろいろ調べたところBitbucket Pipelinesの機能で色々と出来ることが判明し、一気に問題は解決の方向へ!
- Bitbucket Pipelinesで特定のブランチへの更新やタグ付けに反応してパイプラインを起動可能
- Bitbucket Pipelinesの他サービスとの連携機能(Pipesと呼ぶ)にはS3へのデプロイ用のPipeもあるのでS3経由でCodePiplineと連携が簡単にできる
これらを踏まえ以下の流れでBitbucketをソースとしたCodePiplineの起動が出来るようになった。
実装の手順
ここでは、実際にBitbucket PipelinesとCodePiplineを構成し連携するための手順を記載する。
CodePiplineの構成
連携用S3バケットの作成
- S3のコンソールからバケットを作成するをクリック
※CodePipeのソースステージで指定するバケットはバージョニングを有効化している必要がある
CodePipelineの作成
-
ソースステージのプロバイダーにAWS S3を選択し、バケットに事前に作成したバケット名を、オブジェクトキーにsource.zipを入力し次に
-
別のウィンドウが開くので、以下の項目を入力してCodePipelineに進む
※デフォルトからの変更点のみ
項目名 | 値 |
---|---|
プロジェクト名 | 任意の名前 |
オペレーティングシステム | Amazon Linux 2 |
ランタイム | Standard |
イメージ | aws/codebuild/amazonlinux2-x86_64-standard:3.0 |
ビルド仕様 | ビルドコマンドの挿入 |
※ビルドコマンドはエディターを開くことで直接編集可能
内容は以下を設定
version: 0.2
phases:
install:
runtime-versions:
python: 3.7
commands:
- ls -R
中身はPython 3.7のランタイムをインストールしたコンテナ上でls コマンドを実行するのみ
Bitbucket Pipelinesで使用するIAMユーザーの作成
-
このユーザーにはアクセス権限がありませんと表示されるが、そのままユーザーの作成
-
以下のJSONのResource内のS3のARNのバケット名を先ほど作成したものに変更してからコピペしたらポリシーの確認をクリック
※以下の太字部分を変更
arn:aws:s3:::bitbucket-sourcecodeとarn:aws:s3:::bitbucket-sourcecode/*
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::bitbucket-sourcecode",
"arn:aws:s3:::bitbucket-sourcecode/*"
]
}
]
}
Bitbucket Pipelinesの構成
Bitbucket リポジトリの作成
Pipelinesの有効化
-
初期の状態だと起動トリガー(ブランチやタグ)を指定していない状態になっている
image: python:3.7.3
pipelines:
default:
- step:
caches:
- pip
script: # Modify the commands below to build your repository.
- pip install -r requirements.txt
- 起動トリガーをmasterブランチに変更があった場合のみにするため以下のように編集する
image: python:3.7.3
pipelines:
branches:
master:
- step:
caches:
- pip
script: # Modify the commands below to build your repository.
- pip install -r requirements.txt
-
さらにエディターの右ペインに使用できるPipeが表示されるので、検索用のテキストエリアにs3を入力し、AWS S3 DeployPipeを表示する
-
コピーされるSnippetは以下の通り
- pipe: atlassian/aws-s3-deploy:0.4.4
variables:
AWS_ACCESS_KEY_ID: '<string>' # Optional if already defined in the context.
AWS_SECRET_ACCESS_KEY: '<string>' # Optional if already defined in the context.
AWS_DEFAULT_REGION: '<string>' # Optional if already defined in the context.
S3_BUCKET: '<string>'
LOCAL_PATH: '<string>'
# CONTENT_ENCODING: '<string>' # Optional.
# ACL: '<string>' # Optional.
# STORAGE_CLASS: '<string>' # Optional.
# CACHE_CONTROL: '<string>' # Optional.
# EXPIRES: '<timestamp>' # Optional.
# DELETE_FLAG: '<boolean>' # Optional.
# EXTRA_ARGS: '<string>' # Optional.
# DEBUG: '<boolean>' # Optional.
- このSnippetも参考にしつつ設定した最終的な実装は以下の通り
- この内容でCommit fileをクリックする
# This is a sample build configuration for Python.
# Check our guides at https://confluence.atlassian.com/x/x4UWN for more examples.
# Only use spaces to indent your .yml configuration.
# -----
# You can specify a custom docker image from Docker Hub as your build environment.
image: python:3.7.3
pipelines:
branches:
master:
- step:
caches:
- pip
script: # Modify the commands below to build your repository.
- apt update && apt install -y zip
- zip -r source.zip * -x "./.git/*"
- mkdir to_s3
- cp source.zip ./to_s3
- pipe: atlassian/aws-s3-deploy:0.4.4
variables:
AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID # Optional if already defined in the context.
AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY # Optional if already defined in the context.
AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION # Optional if already defined in the context.
S3_BUCKET: 'bitbucket-sourcecode'
LOCAL_PATH: './to_s3'
39c4-4b67ef4143a0.png)
-
処理は以下の通り
- zipコマンドのインストール
- .gitディレクトリ以外の内容をsource.zipに圧縮
- to_s3ディレクトリにsource.zipをコピー
- aws-s3-deployのパイプを以下の変数で実行
- AWS_ACCESS_KEY_ID:環境変数AWS_ACCESS_KEY_IDから取得
- AWS_SECRET_ACCESS_KEY:環境変数AWS_SECRET_ACCESS_KEYから取得
- AWS_DEFAULT_REGION:環境変数AWS_DEFAULT_REGIONから取得
- S3_BUCKET:前の手順で作成したS3バケット名
- LOCAL_PATH: source.zipをコピーしたto_s3ディレクトリを指定
-
設定した内容がbitbucket-pipelines.ymlとしてmasterブランチに登録される
-
masterブランチへの変更があったとみなされすぐに初回のPipelineが起動するが環境変数の設定をしていないため初回は以下のように失敗する
環境変数へAWS認証情報を設定
-
Repository settingsメニューを選択し、PIPELINESセクションのRepository variablesを選択
-
以下の環境変数を作成する
- securedをチェックすると値をmaskして保管できるのでシークレットアクセスキーはmaskすると良い
変数名 | 値 |
---|---|
AWS_ACCESS_KEY_ID | IAMユーザーの作成時にコピーした値 |
AWS_SECRET_ACCESS_KEY | IAMユーザーの作成時にコピーした値 |
AWS_DEFAULT_REGION | ap-northeast-1 |
実行
masterブランチへの変更
-
Bitbucketのリポジトリのソースメニューを選択し、右上のリポジトリのドロップダウンメニューからファイルを追加を選択
-
#2として今コミットした内容でパイプラインが起動しているのでStatusのIn Progressを選択し、Pipelineを開く
-
Bitbucket Pipelineが完了するとAWS CodePipelineが起動しているはずなのでCodePipelineのコンソールを開くと初回は失敗していたSourceステージをクリアして先に進んだことが分かる
-
Buildステージの詳細をクリックするとCodeBuildのログが参照できる
所感
- Good
- 環境に依存する設定ファイルの配布などをBitbucket側で吸収しておくことで、AWS CodePipelineは環境に依存する処理が不要になった
- パイプラインのトリガーをbitbucket-pipelines.yamlのみで管理できるため見通しが良い
- CodeBuildでBitbucketのファイルを取得する構成にする場合はパイプラインの数分CodeBuildのプロジェクトが必要なので、作成するリソースを少なくすることが出来た
- Bad