Open9
CDK Pipelinesの調査メモ
- original APIとmodern APIがある
- original API:
CdkPipelineコンストラクタ - modern API:
CodePipelineコンストラクタ
- original API:
- modern APIのほうが、デフォルトがいい感じ、拡張性に優れている、並列デプロイのサポート、複数のsynth inputsをサポート、CodeBuildをより制御できる
- なるべくmodern APIに移行してね、とのこと
- マイグレーションガイド aws-cdk/ORIGINAL_API.md at master · aws/aws-cdk
At a glance
- アプリのCDを開始するには、まず
Stageのサブクラスを作る- コンストラクタ内でアプリケーションのStackをインスタンス化する
-
CodePipelineのインスタンスを作って、作りたい環境の分だけpipeline.addStage(stage)する -
self-mutating- StackやStageを書き換えると自身(Pipeline)を書き換えて、変更を反映する
- (そりゃそうやろと思ったが、
self-mutatingみたいな名前つけるほどのことなのかよく理解できていない)
CDK Versioning
prereleaseの機能を使うので、以下の設定をcdk.jsonに追記する
{
// ...
"context": {
"@aws-cdk/core:newStyleStackSynthesis": true
}
}
Provisioning the pipeline
-
cdk deployの前に必ずgit commit&git pushすること -
cdk deploy PipelineStack- 1度目だけ管理者権限が必要。それ以降は不要なので、すぐ管理者権限を取り除いたほうがいい
Working on the pipeline
- self-mutation機能はパイプライン開発の邪魔になることもあるので、
selfMutation: falseでself-mutatingを無効化できるので、開発時に使ってね、とのこと。
Defining the pipeline
Synth and sources
-
CodePipelineコンストラクタは、synthパラメタを引数に取る-
cdk synth後のcdk.outディレクトリに吐かれるコンテンツを生成するためのもの
-
-
ShellStepコンストラクタ-
commandsに出力するためのコマンドを配列で書く - cdkのディレクトリがリポジトリの直下にない場合は、
commandsでcd ディレクトリしつつ、primaryOutputDirectoryにcdk.outのパスを別途指定する
-
CodePipeline Sources
- ソースの置き場所を指定。
CodePipelineクラスのファクトリメソッドを使う
// connectionを使う例(推奨)
// AWSコンソールで認証する
CodePipelineSource.connection('org/repo', 'branch', {
connectionArn: 'arn:aws:codestar-connections:us-east-1:222222222222:connection/7d2469ff-514a-4e4f-9003-5ca4a43cdc41',
});
// Githubで発行したトークンを使う
// トークンはrepo, admin:repo_hookスコープを持っている必要がある
CodePipelineSource.gitHub('org/repo', 'branch', {
// This is optional
authentication: SecretValue.secretsManager('my-token'),
});
Additional inputs
-
additionalInputsに追加の入力を指定できる- ShellStep or CodePipelineSource
- (CDKのコードと、アプリケーションのコードを分離する、みたいなことができちゃう感じ?)
CDK application deployments
-
Stageの追加-
Stage: ターゲットとなる環境にデプロイされる対象
-
-
pipeline.addState(Stage)で追加できる
// Do this as many times as necessary with any account and region
// Account and region may different from the pipeline's.
pipeline.addStage(new MyApplicationStage(this, 'Prod', {
env: {
account: '123456789012',
region: 'eu-west-1',
}
}));
- デプロイ先環境が別アカウントの場合、そのアカウントのbootstrapが事前に必要
Deploying in parallel
- デフォルトでは各Stageは直列にデプロイされる
- 並列でデプロイしたい場合は、
addWaveを使う
const europeWave = pipeline.addWave('Europe');
europeWave.addStage(new MyApplicationStage(this, 'Ireland', {
env: { region: 'eu-west-1' }
}));
europeWave.addStage(new MyApplicationStage(this, 'Germany', {
env: { region: 'eu-central-1' }
}));
Deploying to other accounts / encrypting the Artifact Bucket
- 別リージョン・アカウントへの透過的に実行するけど、
CodePipelineコンストラクタにcrossAccountKeys: trueを付ける必要がある- artifact bucketの暗号化を有効にする設定
- (鍵の生成等は勝手にやってくれる感じ?)
Validation
-
addStage,addWaveのpre,postオプション- stage, waveの前後で任意のアクションを実行できる
- Validationを追加するのに使うといい
-
ManualApprovalStepをpreに置くことで、手動による承認ステップを挟むことができる
Using CloudFormation Stack Outputs in approvals
- CloudFormation Stackの出力を承認時に利用可能
-
ShellStepのenvFromCfnOutputsで指定できる
class MyApplicationStage extends Stage {
public readonly loadBalancerAddress: CfnOutput;
// ...
}
const lbApp = new MyApplicationStage(this, 'MyApp', { /* ... */ });
pipeline.addStage(lbApp, {
post: [
new ShellStep('HitEndpoint', {
envFromCfnOutputs: {
// Make the load balancer address available as $URL inside the commands
URL: lbApp.loadBalancerAddress,
},
commands: ['curl -Ssf $URL'],
});
],
});
Running scripts compiled during the synth step
- synthの出力をstageのpre/postで使う方法について
- synthの出力だけじゃなくて、他のビルドステップの出力を利用できる
const synth = new ShellStep('Synth', { /* ... */ });
const pipeline = new CodePipeline(this, 'Pipeline', { synth });
pipeline.addStage(/* ... */, {
post: [
new ShellStep('Approve', {
// Use the contents of the 'integ' directory from the synth step as the input
input: synth.addOutputDirectory('integ'),
commands: ['cd integ && ./run.sh'],
}),
],
});
ちょっと長くなったので、この後は分割して投稿する
Customizing CodeBuild Projects
- CDK pipelinesは
ShellStepごとにCodeBuildのプロジェクトを生成している -
CdeBuildStepコンストラクタを使えば、より細かく設定できる - また、
CodePipeineのcodeBuildDefaultsにCodeBuildのデフォルト値を設定できる
Arbitrary CodePipeline actions
-
Stepを継承、ICodePipelineActionFactoryを実装すれば、独自のCodePipelineアクションを定義できる
CDK Environment Bootstrapping
- environment(環境) = account + region
- 最低2つの環境: Pipelineがプロビジョンされる環境、アプリケーションがデプロイされる環境
- 2つの環境が同一ということもある
- 分けるのが推奨
- 環境は、bootstrapが必要
- 2つの環境が別の場合、両方にbootstrapが必要 & trust releationshipの追加が必要
- CDK PipelineはクロスアカウントのCI/CDに対応しているモダンなbootstrapが必要
-
cdk.jsonに"@aws-cdk/core:newStyleStackSynthesis": trueがあり、cdk.jsonと同一ディレクトリでcdk bootstrapする場合は、自動的にモダンなものにスイッチする - そうでない場合、
CDK_NEW_BOOTSTRAP=1をつけて、cdk bootstrapする
-
# アカウント = 111111111111, region = us-east-1のbootstrap
$ env CDK_NEW_BOOTSTRAP=1 npx cdk bootstrap \
[--profile admin-profile-1] \
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \
aws://111111111111/us-east-1
アプリケーションのデプロイ先の別の環境をbootstrapする場合、--trustにPipelineのアカウントを指定
# アカウント = 222222222222, region = us-east-1のbootstrap
# アカウント = 111111111111のPipelineからデプロイするので--trust 111111111111を付けている
$ env CDK_NEW_BOOTSTRAP=1 npx cdk bootstrap \
[--profile admin-profile-2] \
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \
--trust 11111111111 \
aws://222222222222/us-east-2
Vpc.fromLookup()等のlookupしたい場合は、--trust-for-lookup Pipelineのアカウントを付ける
$ env CDK_NEW_BOOTSTRAP=1 npx cdk bootstrap \
[--profile admin-profile-2] \
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \
--trust-for-lookup 11111111111 \
aws://222222222222/us-east-2
-
--trust付ける場合、Pipeline側のアカウントはデプロイ先のアカウントに対して--cloudformation-execution-policiesで指定した権限を持つことになるので、注意 - 管理者権限はbootstrap時、最初のPipelineのデプロイ時だけ使用して、あとは使わない
- AdministratorAccessの利用について
- PipelineのAdministratorAccessはすべてのAWSリソースをデプロイ可能にするために付けている
- CDKのコード全てが信頼できる状態じゃないと、変なリソースをデプロイされたりするので、依存関係はちゃんと管理する。また、適切なポリシーでAdministratorAccessを利用する
- CDK実行ロールにパーミッションバウンダリーを実装すること
Context Lookups
- 有効なAZの数、Route53 Hosted Zone IDなど、
cdk synth時に自動で調べる cdk bootstrap --trust-for-lookup=<account>
Security Considerations
Confirm permissions broadening
- stageのデプロイ前に
cdk diffで新たにIAM権限の付与等が行われていないか確認したい -
ConfirmPermissionsBroadeningをstageのpreに挟む-
cdk diffの結果、何も無ければ自動でOK - なにかあれば、マニュアルの承認が必要
-
const stage = new MyApplicationStage(this, 'MyApplication');
pipeline.addStage(stage, {
pre: [
new ConfirmPermissionsBroadening('Check', { stage }),
],
});
SNSトピックを付けることもできる
import * as sns from '@aws-cdk/aws-sns';
import * as subscriptions from '@aws-cdk/aws-sns-subscriptions';
import * as pipelines from '@aws-cdk/pipelines';
const topic = new sns.Topic(this, 'SecurityChangesTopic');
topic.addSubscription(new subscriptions.EmailSubscription('test@email.com'));
const stage = new MyApplicationStage(this, 'MyApplication');
pipeline.addStage(stage, {
pre: [
new ConfirmPermissionsBroadening('Check', {
stage,
notificationTopic: topic,
}),
],
});
ここまでの疑問点
-
--trustを付けた場合の適切な--cloudformation-execution-policiesのポリシーはなに?- 結局管理者権限にならない?それかPowerUserみたいなやつをつければいいのかな?
- Permission Boundaryってなに?