起きたこと
タイトルの通り。
背景
- 以下ステージ構成の CodePipeline を設定した。
- Source
- Build
- Staging
- Approval
- Production
- Source ステージはS3を設定し、CloudWatch Events + CloudTrailによる変更検知を設定した。
- 上記の設定には Terraform を利用した。
調べたこと
- CloudTrailのイベントログ調査
- CloudWatch Eventsの無効化
CloudTrailのイベントログ調査
当然ながらCloudTrailのデータイベントログは取得できているので、パイプライン動作時のイベントログを確認した。すると、1回の PutObject
に対して、CodePipelineのArtifactsバケットへの CopyObject
が2回走っていることがわかった。
{
"Records": [
{
... 略 ...
"eventName": "PutObject",
... 略 ...
},
{
... 略 ...
"eventName": "CopyObject",
... 略 ...
},
{
... 略 ...
"eventName": "CopyObject",
... 略 ...
}
]
}
この結果から、Sourceステージが2重起動していることがわかった。
CloudWatch Eventsの無効化
さらに被疑箇所を特定するため、CW Eventsを無効化した状態でS3バケットにソースを置いてみたところ、CodePipelineが1回だけ起動した。このことから、CW Events以外の方法でCodePipelineが起動していることがわかった。
原因と対処方法
ここまで調べてある程度あたりがついたのでドキュメントを読んでみたら、無事原因がわかった。
原因
原因はSourceステージの設定ミスだった。CodePipelineのSourceステージ(S3)は、以下2種類の方法でソースを検知できる。
- CW Eventsによる検知
- CodePipelineによるポーリング
CodePipelineによるポーリングの有効化/無効化は、PollForSourceChanges
というパラメータで管理している。AWSはCW Eventsによる検知を推奨しているため、AWSコンソールでCodePipelineを作成する場合、 PollForSourceChanges
はデフォルトで false
(無効化) となる。しかし、CLI (Terraform) で設定する場合はデフォルトで true
(有効化) となる。したがって、Terraformで設定する際には明示的に PollForSourceChanges = false
とする必要があった。以下ドキュメント1からの引用。
CLI を使用して作成あるいは更新されたパイプラインでは、このパラメータのデフォルトは true ですが、これは推奨される設定ではありません。代わりに、パイプラインを更新し、推奨される変更検出方法を使用してこのパラメータを false に設定します。詳細については、パイプラインの自動開始に使用される変更検出方法 を参照してください。このパラメータは、明示的に設定されていない場合は表示されません。
対処方法
設定を見直したら案の定 PollForSourceChanges
が抜けていたので、Terraform設定ファイルに以下のように設定を追記した。
resource "aws_codepipeline" "app" {
... 略 ...
stage {
name = "Source"
action {
name = "Source"
category = "Source"
owner = "AWS"
provider = "S3"
version = "1"
output_artifacts = ["MyApp"]
configuration {
S3Bucket = "${aws_s3_bucket.app_src.bucket}"
S3ObjectKey = "app.zip"
### CodePipelineによるPollingでオブジェクトの変更を検知する機能
### CW Eventsによる検知が使えるため非推奨
### CLIで設定する場合は明示的に無効化する必要がある
PollForSourceChanges = "false"
}
}
}
... 略 ...
}
上記を適用したところ、CodePipelineの2重起動は解消された。というわけで、ドキュメントをちゃんと読みましょう案件だった。