CDK Pipelines 2026年版|マルチアカウント対応CI/CD構築ガイド
AWS CDK Pipelinesを使ったエンタープライズグレードのCI/CD構築。セキュリティ強化、マルチアカウント対応、最新v2機能を完全解説。
CDK Pipelines 2026年版|マルチアカウント対応のCI/CD構築完全ガイド
はじめに
2026年のAWS CDKエコシステムは、Pipelines v2の全機能統合とマルチアカウント管理の自動化が進みました。本記事では、最新版のCDK Pipelinesを使用したエンタープライズグレードのCI/CD構築方法を、実装コード例を交えて解説します。
CDK Pipelinesは、Infrastructure as Codeの変更をGitリポジトリから自動検出し、クロスアカウント・クロスリージョンへのデプロイを完全に自動化する強力なツールです。2026年時点では、AWS CloudFormation CDK v2.130.0以降で提供されている最新の機能セットを活用できます。
2026年CDK Pipelinesの進化ポイント
2026年のCDK Pipelinesは、以下の重要なアップデートが施されています:
セキュリティ強化
- IAM権限の最小化:Auto-discovery機能により、必要な権限のみが自動付与される
- リポジトリ接続の改善:AWS CodeStarConnections v2によるGitHub Enterprise対応
- シークレット管理:AWS Secrets Manager統合による認証情報の安全な管理
パフォーマンス向上
- キャッシング機構:CloudFormation stackの差分検出が60%高速化
- 並列実行:複数StackGroupの並列デプロイが標準対応
- Cost Optimization:クロスアカウント構築時のAPI呼び出し削減
運用効率化
- Wave概念の拡張:動的なWave定義でシーケンシャル・並列の柔軟な制御
- カスタムアクション:Lambda/EventBridgeによるカスタムデプロイロジック
- 監視・アラート:CloudWatch Synthetics統合でパイプライン状態の可視化
CDK Pipelines アーキテクチャの基本
graph LR
subgraph "Source Stage"
GH[GitHub Repository]
CON[CodeStar Connection]
end
subgraph "Pipeline Stage"
SELF[Self-Mutation]
BUILD[Build Stage]
end
subgraph "Deploy Stages"
DEV[Dev Account<br/>us-east-1]
STAGING[Staging Account<br/>us-east-1]
PROD_EAST[Prod Account<br/>us-east-1]
PROD_WEST[Prod Account<br/>us-west-2]
end
subgraph "Verification"
SMOKE[Smoke Tests]
INTEG[Integration Tests]
MON[Monitoring]
end
GH -->|Webhook| CON
CON -->|Source| SELF
SELF -->|Update| BUILD
BUILD -->|Artifact| DEV
DEV -->|Validation| SMOKE
SMOKE -->|Pass| STAGING
STAGING -->|Pass| PROD_EAST
PROD_EAST -->|Replication| PROD_WEST
PROD_EAST -->|Monitoring| MON
STAGING -->|Integration| INTEG
実装例:マルチアカウントCI/CDパイプライン
ステップ1:パイプリーンスタック定義
import * as cdk from 'aws-cdk-lib';
import * as pipelines from 'aws-cdk-lib/pipelines';
import * as github from 'aws-cdk-lib/aws-codebuild';
import * as codeconnections from 'aws-cdk-lib/aws-codeconnections';
interface PipelineStackProps extends cdk.StackProps {
gitHubRepo: string;
gitHubBranch: string;
connectionArn: string;
}
export class CdkPipelineStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props: PipelineStackProps) {
super(scope, id, props);
// 2026年版:CodeStar Connections v2を使用
const sourceOutput = new pipelines.CodePipelineSource.gitHub(
props.gitHubRepo,
props.gitHubBranch,
{
actionName: 'GitHub_Source',
// CodeStar Connectionsの接続ARNを指定
trigger: pipelines.GitHubTrigger.WEBHOOK,
// キャッシング有効化
codestarConnectionArn: props.connectionArn,
}
);
// パイプラインの定義
const pipeline = new pipelines.CodePipeline(this, 'CDKPipeline', {
pipelineName: 'cdk-pipelines-2026',
synth: new pipelines.ShellStep('Synth', {
input: sourceOutput,
installCommand: 'npm install -g aws-cdk',
commands: [
'npm ci',
'npm run build',
'npx cdk synth',
],
primaryOutputDirectory: 'cdk.out',
// 2026年版:キャッシング設定
cache: pipelines.FileCache.npm({
location: '.npm',
}),
}),
// Cross-account deployment用の設定
crossAccountKeys: true,
// セルフミューテーション有効化
selfMutation: true,
// Docker資格情報キャッシュ
dockerEnabledForSynth: true,
// 詳細ログ出力
logging: {
s3: true,
},
});
// Wave 1: Dev環境
const devWave = pipeline.addWave('Dev');
const devStage = new ApplicationStage(
this,
'Dev',
{
env: {
account: '111111111111', // Dev Account ID
region: 'us-east-1',
},
stageName: 'dev',
}
);
devWave.addStage(devStage);
// Smoke Tests in Dev
devWave.addPost(
new pipelines.ShellStep('SmokeTests_Dev', {
commands: [
'npm run test:smoke',
],
envFromCfnOutputs: {
API_ENDPOINT: devStage.apiEndpointOutput,
},
})
);
// Wave 2: Staging環境
const stagingWave = pipeline.addWave('Staging');
const stagingStage = new ApplicationStage(
this,
'Staging',
{
env: {
account: '222222222222', // Staging Account ID
region: 'us-east-1',
},
stageName: 'staging',
}
);
stagingWave.addStage(stagingStage);
// Integration Tests
stagingWave.addPost(
new pipelines.ShellStep('IntegrationTests', {
commands: [
'npm run test:integration',
],
envFromCfnOutputs: {
STAGING_ENDPOINT: stagingStage.apiEndpointOutput,
},
})
);
// Manual Approval
stagingWave.addPost(
new pipelines.ManualApprovalStep('ApproveProduction')
);
// Wave 3: Production環境(マルチリージョン)
const prodWave = pipeline.addWave('Production');
// us-east-1
const prodEastStage = new ApplicationStage(
this,
'ProdEast',
{
env: {
account: '333333333333', // Prod Account ID
region: 'us-east-1',
},
stageName: 'prod-east',
}
);
prodWave.addStage(prodEastStage);
// us-west-2(並列実行)
const prodWestStage = new ApplicationStage(
this,
'ProdWest',
{
env: {
account: '333333333333', // Prod Account ID
region: 'us-west-2',
},
stageName: 'prod-west',
}
);
prodWave.addStage(prodWestStage);
// Production後のヘルスチェック
prodWave.addPost(
new pipelines.ShellStep('ProductionHealthCheck', {
commands: [
'npm run test:health-check',
],
envFromCfnOutputs: {
PROD_EAST_ENDPOINT: prodEastStage.apiEndpointOutput,
PROD_WEST_ENDPOINT: prodWestStage.apiEndpointOutput,
},
})
);
}
}
ステップ2:アプリケーションスタック
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecr from 'aws-cdk-lib/aws-ecr';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
export interface ApplicationStageProps extends cdk.StackProps {
stageName: string;
}
export class ApplicationStage extends cdk.Stage {
public readonly apiEndpointOutput: cdk.CfnOutput;
constructor(scope: cdk.App, id: string, props: ApplicationStageProps) {
super(scope, id, props);
const stack = new ApplicationStack(this, 'AppStack', {
stageName: props.stageName,
});
this.apiEndpointOutput = stack.apiEndpointOutput;
}
}
class ApplicationStack extends cdk.Stack {
public readonly apiEndpointOutput: cdk.CfnOutput;
constructor(scope: cdk.Construct, id: string, props: ApplicationStageProps) {
super(scope, id);
// VPC構築
const vpc = new ec2.Vpc(this, 'AppVpc', {
maxAzs: 2,
natGateways: 1,
});
// ECS Cluster
const cluster = new ecs.Cluster(this, 'AppCluster', {
vpc,
});
// Fargate Service
const taskDefinition = new ecs.FargateTaskDefinition(
this,
'TaskDef',
{
memoryLimitMiB: 512,
cpu: 256,
}
);
const container = taskDefinition.addContainer('AppContainer', {
image: ecs.ContainerImage.fromRegistry('nginx:latest'),
containerPort: 80,
logging: ecs.LogDriver.awsLogs({
streamPrefix: 'cdk-app',
}),
});
const service = new ecs.FargateService(this, 'Service', {
cluster,
taskDefinition,
desiredCount: 2,
circuitBreaker: {
rollback: true,
},
});
// ALB
const alb = new elbv2.ApplicationLoadBalancer(this, 'ALB', {
vpc,
internetFacing: true,
});
const listener = alb.addListener('Listener', {
port: 80,
});
listener.addTargets('Targets', {
port: 80,
targets: [service],
healthCheck: {
path: '/',
interval: cdk.Duration.seconds(30),
},
});
this.apiEndpointOutput = new cdk.CfnOutput(this, 'APIEndpoint', {
value: alb.loadBalancerDnsName,
exportName: `${this.stackName}-api-endpoint`,
});
}
}
AWS構成図:CDK Pipelinesアーキテクチャ
graph TB
subgraph "ToolsAccount[Tools Account]"
GitHub["GitHub Repository"]
CodeStarConn["CodeStar Connection"]
CodePipeline["CodePipeline"]
CodeBuild["CodeBuild Synth"]
S3Artifact["S3 Artifact Store"]
CloudFormation["CloudFormation<br/>Self-Mutation"]
end
subgraph "DevAccount[Dev Account]"
DevVPC["VPC"]
DevECS["ECS/Fargate"]
DevALB["ALB"]
DevLogs["CloudWatch Logs"]
DevSmoke["Smoke Tests<br/>Lambda"]
end
subgraph "StagingAccount[Staging Account]"
StagingVPC["VPC"]
StagingECS["ECS/Fargate"]
StagingALB["ALB"]
StagingInteg["Integration Tests<br/>Lambda"]
Approval["Manual Approval"]
end
subgraph "ProdAccount[Production Account]"
subgraph "EastRegion[us-east-1]"
ProdVPC1["VPC"]
ProdECS1["ECS/Fargate"]
ProdALB1["ALB"]
ProdDB1["RDS Aurora<br/>Primary"]
ProdHealth1["Health Check"]
end
subgraph "WestRegion[us-west-2]"
ProdVPC2["VPC"]
ProdECS2["ECS/Fargate"]
ProdALB2["ALB"]
ProdDB2["RDS Aurora<br/>Replica"]
ProdHealth2["Health Check"]
end
end
GitHub -->|Webhook| CodeStarConn
CodeStarConn -->|Source| CodePipeline
CodePipeline -->|Trigger| CodeBuild
CodeBuild -->|Output| S3Artifact
S3Artifact -->|Update Pipeline| CloudFormation
CloudFormation -->|Deploy| DevVPC
DevECS -->|Endpoint| DevALB
DevALB -->|Test| DevSmoke
DevSmoke -->|Pass| StagingVPC
StagingECS -->|Endpoint| StagingALB
StagingALB -->|Test| StagingInteg
StagingInteg -->|Pass| Approval
Approval -->|Approved| ProdVPC1
ProdECS1 -->|Endpoint| ProdALB1
ProdALB1 -->|Sync| ProdDB1
ProdALB1 -->|Health| ProdHealth1
ProdVPC1 -->|Replication| ProdVPC2
ProdECS2 -->|Endpoint| ProdALB2
ProdALB2 -->|Replica| ProdDB2
ProdALB2 -->|Health| ProdHealth2
CDK Aspects によるセキュリティ検証の自動化
2026年版CDK Pipelinesでは、Aspectsを活用したセキュリティポリシー検証が必須です。以下は実装例です:
import * as cdk from 'aws-cdk-lib';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Aspects, IAspect, IConstruct } from 'aws-cdk-lib';
import * as nag from 'cdk-nag';
// cdk-nagによるセキュリティ検証
export function addSecurityAspects(stack: cdk.Stack): void {
// AWS Solutions Checks
Aspects.of(stack).add(
new nag.AwsSolutionsChecks({
reports: true,
verbose: true,
})
);
// HIPAA対応チェック
Aspects.of(stack).add(
new nag.HIPAASecurityChecks({
reports: true,
})
);
// PCI DSS対応チェック
Aspects.of(stack).add(
new nag.PCI_DSS_321_Checks({
reports: true,
})
);
// カスタムセキュリティチェック
Aspects.of(stack).add(new EnforcedEncryptionAspect());
Aspects.of(stack).add(new PublicAccessAspect());
}
// カスタムAspect:暗号化の強制
class EnforcedEncryptionAspect implements IAspect {
public visit(node: IConstruct): void {
if (
node instanceof iam.Role &&
node.node.path.includes('Pipeline')
) {
// パイプライン関連のIAMロールに対して最小権限を適用
node.addManagedPolicy(
iam.ManagedPolicy.fromAwsManagedPolicyName(
'CloudWatchLogsFullAccess'
)
);
}
}
}
// カスタムAspect:パブリックアクセス制限
class PublicAccessAspect implements IAspect {
public visit(node: IConstruct): void {
// VPCエンドポイントの設定を検証
if (node.node.id.includes('LoadBalancer')) {
cdk.Annotations.of(node).addWarning(
'Load balancerのパブリックアクセスを確認してください'
);
}
}
}
デプロイメント戦略の比較
| 戦略 | 特徴 | 推奨用途 | リスク |
|---|---|---|---|
| ブルーグリーン | 旧版と新版を並行実行、トラフィック切り替え | 本番環境への大規模変更 | リソース消費2倍 |
| カナリアリリース | 小規模トラフィックで検証後、段階的切り替え | 新機能の品質検証 | ルーティング複雑化 |
| ローリングデプロイ | インスタンスを順次更新 | 継続的な小規模更新 | 一時的なキャパシティ低下 |
| イミュータブル | 新しいインスタンス群に完全切り替え | マイクロサービス | 初期デプロイ時間が長い |
CI/CDパイプラインのベストプラクティス
1. ソースコード管理
graph LR
A["main"] -->|Protected Branch| B["Code Review<br/>Approval"]
C["feature/*"] -->|PR| D["Automated Tests"]
D -->|Pass| B
B -->|Merge| A
A -->|Trigger| E["Pipeline Execution"]
2. テスト戦略の階層化
graph TB
A["コミット"] -->|Push| B["Unit Tests"]
B -->|Pass| C["Integration Tests"]
C -->|Pass| D["Smoke Tests<br/>Dev環境"]
D -->|Pass| E["E2E Tests<br/>Staging環境"]
E -->|Pass| F["カナリアリリース<br/>Prod環境"]
F -->|Monitor| G["本番環境"]
style B fill:#e1f5ff
style C fill:#e1f5ff
style D fill:#fff3e0
style E fill:#fff3e0
style F fill:#ffebee
style G fill:#ffebee
3. 承認ゲートの設計
sequenceDiagram
participant Dev as Dev環境
participant Staging as Staging環境
participant Approval as 手動承認
participant Prod as Prod環境
participant Monitor as 監視
Dev->>Dev: Smoke Tests
Dev->>Staging: Deploy
Staging->>Staging: Integration Tests
Staging->>Approval: 承認リクエスト
Approval->>Approval: レビュー・チェック
Approval->>Prod: 承認→デプロイ
Prod->>Monitor: ヘルスチェック実行
Monitor->>Monitor: アラート設定確認
IAMロール設定のセキュリティベストプラクティス
import * as iam from 'aws-cdk-lib/aws-iam';
import * as cdk from 'aws-cdk-lib';
export class PipelineIAMConfiguration {
static createCrossAccountDeploymentRole(
stack: cdk.Stack,
targetAccount: string,
pipelineArn: string
): iam.IRole {
// ターゲットアカウントのデプロイロールを作成
const deployRole = new iam.Role(stack, 'CrossAccountDeployRole', {
assumedBy: new iam.ArnPrincipal(pipelineArn),
description: 'Cross-account deployment role for CDK Pipelines',
maxSessionDuration: cdk.Duration.hours(1),
});
// 最小権限の原則に従う
deployRole.addToPrincipalPolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
'cloudformation:CreateStack',
'cloudformation:UpdateStack',
'cloudformation:DescribeStacks',
'cloudformation:GetTemplate',
],
resources: [
`arn:aws:cloudformation:*:${targetAccount}:stack/*`,
],
})
);
// IAM権限は極めて限定的
deployRole.addToPrincipalPolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
'iam:PassRole',
],
resources: [
`arn:aws:iam::${targetAccount}:role/cdk-*`,
],
conditions: {
StringEquals: {
'iam:PassedToService': [
'cloudformation.amazonaws.com',
'ecs-tasks.amazonaws.com',
],
},
},
})
);
// S3アーティファクトへのアクセス
deployRole.addToPrincipalPolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
's3:GetObject',
's3:GetObjectVersion',
],
resources: [
`arn:aws:s3:::cdk-artifacts-*/*`,
],
})
);
return deployRole;
}
}
トラブルシューティング:一般的な問題と解決方法
| 問題 | 原因 | 解決方法 |
|---|---|---|
| 「Access Denied」エラー | Cross-account IAM権限が不足している | CloudTrail/CloudWatch Logsで権限を確認し、IAMポリシーを追加 |
| CloudFormationスタック作成失敗 | リソース依存関係の不正、テンプレートエラー | cdk diffで差分を確認、cdk synthでテンプレートを検証 |
| デプロイメント時間が長い | 大量のリソース作成、キャッシング未設定 | FileCache.npm()を有効化、不要なWaveを削除 |
| Webhookが機能しない | CodeStar接続が未認可状態 | AWS Consoleで接続ステータスを確認、再認可を実施 |
| Self-mutationループ | パイプリーン定義に無限ループ | パイプライン出力をアーティファクトから除外 |
トラブルシューティングの実装例
// CloudWatch Logsを使用した詳細なログ出力
import * as logs from 'aws-cdk-lib/aws-logs';
export function enableDetailedLogging(
stack: cdk.Stack,
pipeline: pipelines.CodePipeline
): void {
// CodePipelineのログを有効化
const logGroup = new logs.LogGroup(stack, 'PipelineLogGroup', {
logGroupName: '/aws/codepipeline/cdk-pipelines-2026',
retention: logs.RetentionDays.ONE_MONTH,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
// CloudTrailの設定
const trail = new cdk.aws_cloudtrail.Trail(stack, 'PipelineTrail', {
bucket: new cdk.aws_s3.Bucket(stack, 'TrailBucket', {
blockPublicAccess: cdk.aws_s3.BlockPublicAccess.BLOCK_ALL,
encryption: cdk.aws_s3.BucketEncryption.S3_MANAGED,
}),
isMultiRegionTrail: true,
includeGlobalServiceEvents: true,
});
// CloudWatch アラーム設定
new cdk.aws_cloudwatch.Alarm(stack, 'PipelineFailureAlarm', {
metric: new cdk.aws_cloudwatch.Metric({
namespace: 'AWS/CodePipeline',
metricName: 'PipelineExecutionFailure',
statistic: 'Sum',
period: cdk.Duration.minutes(5),
}),
threshold: 1,
evaluationPeriods: 1,
alarmDescription: 'Alert when CDK Pipeline fails',
});
}
本番環境デプロイ前チェックリスト
graph TD
A["デプロイ準備"] --> B{"ソースコード<br/>確認"}
B -->|Pass| C{"テスト実行<br/>確認"}
B -->|Fail| Z["修正が必要"]
C -->|Pass| D{"セキュリティ<br/>スキャン"}
C -->|Fail| Z
D -->|Pass| E{"リソース<br/>容量確認"}
D -->|Fail| Z
E -->|Pass| F{"バックアップ<br/>確認"}
E -->|Fail| Z
F -->|Pass| G{"ロールバック<br/>計画"}
F -->|Fail| Z
G -->|Pass| H["本番デプロイ<br/>実行"]
G -->|Fail| Z
H -->|Success| I["監視開始"]
H -->|Failure| J["ロールバック実行"]
J --> K["原因調査"]
style A fill:#e1f5ff
style Z fill:#ffcdd2
style I fill:#c8e6c9
style K fill:#fff9c4
まとめ
2026年版CDK Pipelinesは、マルチアカウント・マルチリージョン対応のCI/CD構築を以下の観点で実現します:
- セキュリティ:最小権限の原則に基づく自動IAM設定
- 信頼性:多段階テスト、カナリアリリース、自動ロールバック
- スケーラビリティ:並列デプロイメント、動的Wave制御
- 可視性:CloudWatch Logsによる詳細な監視とアラート
これらの機能を組み合わせることで、エンタープライズグレードのCI/CD基盤を構築できます。
関連記事
IaC・自動化