Contents
前提条件と最小権限の IAM ロール設計
Jenkins が AWS の各サービス(CodeBuild・CodeDeploy・S3・ECR など)にアクセスする際は、最小権限の原則 に従ってロールを作成します。過剰なポリシーは攻撃対象が増えるだけでなく、監査やコンプライアンスでも指摘されやすくなるため必ず避けましょう。
最小権限ポリシー例
以下の JSON は Jenkins 用 IAM ロールに付与する 最小限の許可 をまとめたものです。
- 必要なサービスごとに Sid で区切り、Action と Resource を限定しています。
- SSM Parameter Store や Secrets Manager からは 読み取り のみ許可し、書き込みは除外しています。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
{ "Version": "2012-10-17", "Statement": [ { "Sid": "CodeBuildAccess", "Effect": "Allow", "Action": [ "codebuild:StartBuild", "codebuild:BatchGetBuilds" ], "Resource": "arn:aws:codebuild:*:${aws_account_id}:project/${codebuild_project_name}" }, { "Sid": "CodeDeployAccess", "Effect": "Allow", "Action": [ "codedeploy:RegisterApplicationRevision", "codedeploy:GetDeploymentConfig", "codedeploy:CreateDeployment" ], "Resource": "arn:aws:codedeploy:*:${aws_account_id}:deploymentgroup/${application_name}/${deployment_group}" }, { "Sid": "S3ArtifactsAccess", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject" ], "Resource": "arn:aws:s3:::${artifact_bucket}/*" }, { "Sid": "ECRRepositoryAccess", "Effect": "Allow", "Action": [ "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:CompleteLayerUpload", "ecr:InitiateLayerUpload", "ecr:PutImage", "ecr:UploadLayerPart" ], "Resource": "arn:aws:ecr:*:${aws_account_id}:repository/${ecr_repository}" }, { "Sid": "ParameterStoreReadOnly", "Effect": "Allow", "Action": [ "ssm:GetParameters", "secretsmanager:GetSecretValue" ], "Resource": [ "arn:aws:ssm:*:${aws_account_id}:parameter/${jenkins_secret_path}*", "arn:aws:secretsmanager:*:${aws_account_id}:secret:${jenkins_secret_name}" ] } ] } |
ポイント
このロールは EC2 インスタンスや ECS/Fargate タスクに インスタンスプロファイル / タスクロール としてアタッチし、Jenkins は AWS SDK のデフォルト認証フローで自動的に権限を取得します。クレデンシャル情報を Secrets Manager に格納するような一時キーの管理は不要です。
AWS 上に Jenkins 環境を構築する方法
Jenkins を AWS にデプロイする代表的な選択肢として EC2(ベアメタル) と ECS/Fargate(コンテナ) の 2 パターンがあります。どちらも Terraform または CloudFormation でコード化でき、再利用性と可搬性が高くなります。
EC2 インスタンスでのセットアップ
EC2 上に Jenkins を構築すれば、プラグインやカスタムツールのインストールがフルコントロールできます。以下は Free Tier 対応 (t2.micro) の最小構成例です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
resource "aws_instance" "jenkins" { ami = data.aws_ami.amazon_linux.id instance_type = "t2.micro" # Free Tier 利用時の推奨タイプ subnet_id = aws_subnet.private_a.id vpc_security_group_ids = [aws_security_group.jenkins_sg.id] iam_instance_profile = aws_iam_instance_profile.jenkins_profile.name # ロールを付与 user_data = <<-EOF #!/bin/bash yum update -y amazon-linux-extras install java-openjdk11 -y wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key yum install jenkins -y systemctl enable jenkins systemctl start jenkins EOF tags = { Name = "Jenkins-Server" } } |
補足
本番環境では CPU・メモリ要件に合わせてt3.mediumやm5.large等へスケールアウトしてください。インスタンスサイズを変更した場合でも、IAM ロールとセキュリティグループは同一です。
ECS/Fargate でのコンテナ型デプロイ
Fargate はサーバレスなコンテナ実行基盤であり、インフラ管理が不要です。公式 Jenkins イメージ public.ecr.aws/jenkins/jenkins:lts を利用した CloudFormation テンプレート抜粋を示します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
Resources: JenkinsCluster: Type: AWS::ECS::Cluster JenkinsTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - FARGATE Cpu: '1024' # 1 vCPU Memory: '2048' # 2 GB RAM NetworkMode: awsvpc ExecutionRoleArn: !GetAtt JenkinsExecutionRole.Arn # タスク実行ロール TaskRoleArn: !GetAtt JenkinsTaskRole.Arn # アプリ側ロール(最小権限) ContainerDefinitions: - Name: jenkins Image: public.ecr.aws/jenkins/jenkins:lts PortMappings: - ContainerPort: 8080 Protocol: tcp LogConfiguration: LogDriver: awslogs Options: awslogs-group: /ecs/jenkins awslogs-region: !Ref AWS::Region awslogs-stream-prefix: jenkins JenkinsService: Type: AWS::ECS::Service Properties: Cluster: !Ref JenkinsCluster DesiredCount: 1 LaunchType: FARGATE TaskDefinition: !Ref JenkinsTaskDefinition NetworkConfiguration: AwsvpcConfiguration: Subnets: - !Ref PrivateSubnetA SecurityGroups: - !Ref JenkinsSecurityGroup |
ポイント
-ExecutionRoleArnはコンテナイメージ取得や CloudWatch Logs への書き込みに必要です。
-TaskRoleArnが実際に Jenkins ジョブが利用する権限を保持し、ここに最小権限ポリシー(上記 JSON)をアタッチします。
Jenkins と AWS 認証情報・ソース管理の安全な連携
Jenkins のビルドジョブが AWS リソースへアクセスするときは 認証情報を平文で保存しない ことが最重要です。AWS が提供するロールベースの認証フローと、Jenkins 標準プラグインの組み合わせで安全に実装できます。
IAM ロール/インスタンスプロファイルを利用した認証情報管理
- EC2:
aws_iam_instance_profileでアタッチしたロールが自動的に一時クレデンシャルを提供します。Jenkins のCredentials Pluginは「Amazon Web Services Credentials」タイプで “Default credential provider chain” を選択すれば、環境変数やプロファイルではなくインスタンスロールから取得できます。 - ECS/Fargate:タスク定義の
TaskRoleArnが同様に一時クレデンシャルを供給します。コンテナ内部でaws sts get-caller-identityを実行すれば、正しくロールが適用されていることを確認できます。
注意
Secrets Manager に AccessKey/SecretKey を格納して Jenkins から取得するパターンは推奨しません。キーのローテーションや漏洩リスクが増大します。代わりに ロールベース認証 を徹底してください。
Jenkinsfile 内での利用例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
pipeline { agent any environment { AWS_DEFAULT_REGION = 'ap-northeast-1' } stages { stage('Validate IAM Role') { steps { // インスタンスロール/タスクロールから自動取得されるクレデンシャルを使用 withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', credentialsId: 'aws-iam-role', // プラグイン側で「Default provider chain」を選択 accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { sh ''' aws sts get-caller-identity ''' } } } } } |
GitHub / GitLab Webhook 設定手順
Git リポジトリの変更を検知して Jenkins パイプラインを自動起動させる設定です。以下は GitHub を例にした流れですが、GitLab でも同様の項目があります。
- Jenkins 側
- 「新規ジョブ > パイプライン」作成 → SCM に Git、リポジトリ URL とブランチを設定。
-
「ビルドトリガー」で “GitHub hook trigger for GITScm polling” を有効化。
-
GitHub 側(
Settings > Webhooks) - Payload URL:
https://<jenkins-host>/github-webhook/ - Content type:
application/json -
Secret: Jenkins で設定した Webhook secret と同一にし、プラグインの「Validate webhook payload」オプションをオン。
-
イベント選択
- 「Just the push event」または「Pull request events」をチェックして保存。
ベストプラクティス:Webhook のシークレットは必ず Secrets Manager に保管し、Jenkins 起動時に環境変数として注入します。これによりコードリポジトリ側に平文が残りません。
Pipeline as Code 実装ガイド(Jenkinsfile サンプル)
Jenkins のパイプラインは Jenkinsfile でコード化し、バージョン管理下に置くことで変更履歴とレビューを一元化できます。以下では「ビルド → デプロイ → 後処理」の典型フローを示します。
ビルドステージ:CodeBuild の呼び出し例
Jenkins は AWS CLI を使って CodeBuild プロジェクトを起動し、実際のコンパイルや Docker イメージ作成は AWS 側で完結させます。これにより Jenkins サーバーへの負荷が軽減されます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
stage('Build') { steps { script { def project = env.CODEBUILD_PROJECT ?: 'my-codebuild-project' withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', credentialsId: 'aws-iam-role', accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { sh """ aws codebuild start-build \\ --project-name ${project} \\ --environment-variables-override name=BRANCH,value=${env.GIT_BRANCH},type=PLAINTEXT """ } } } } |
ポイント
-CODEBUILD_PROJECTは環境変数で外部化し、ステージング/本番で同一 Jenkinsfile を使い回せます。
- ビルドの進捗は CodeBuild の CloudWatch Logs で確認できるので、Jenkins 側では開始コマンドだけを管理します。
デプロイステージ:CodeDeploy と SAM CLI
CodeDeploy(EC2/ECS 向け)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
stage('Deploy to EC2') { steps { script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', credentialsId: 'aws-iam-role', accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { sh ''' aws deploy create-deployment \ --application-name MyApp \ --deployment-group-name ProdDG \ --revision revisionType=S3,bucket=${DEPLOY_BUCKET},key=${ARTIFACT_KEY} \ --deployment-config-name CodeDeployDefault.AllAtOnce \ --description "Jenkins triggered deployment" ''' } } } } |
SAM CLI(サーバーレス)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
stage('Deploy SAM (Canary)') { steps { script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', credentialsId: 'aws-iam-role', accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { sh ''' sam deploy \ --stack-name my-sam-app \ --s3-bucket ${SAM_BUCKET} \ --parameter-overrides Stage=prod \ --capabilities CAPABILITY_IAM \ --region ${AWS_DEFAULT_REGION} \ --no-fail-on-empty-changeset \ --config-file samconfig.toml ''' } } } } |
補足:
samconfig.tomlにdeployment_type = "canary10percent5minutes"を記載すると、デプロイ時に自動でカナリアリリースが適用されます。
オプションフロー:App2Container での自動コンテナ化
レガシーアプリでも AWS App2Container (A2C) を使えば Dockerfile の手書きなしでコンテナイメージを生成できます。以下は Jenkins から A2C CLI を呼び出すサンプルです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
stage('App2Container') { steps { script { withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', credentialsId: 'aws-iam-role', accessKeyVariable: 'AWS_ACCESS_KEY_ID', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) { sh ''' # A2C CLI インストール curl -O https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip unzip awscli-exe-linux-x86_64.zip sudo ./aws/install # ソースディレクトリで変換実行 a2c-cli generate \ --source-dir /var/lib/jenkins/workspace/${JOB_NAME} \ --runtime java11 \ --output-dir /tmp/a2c-output # ECR にプッシュ $(aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | docker login --username AWS --password-stdin ${ECR_REGISTRY}) docker build -t ${ECR_REPO}:$BUILD_NUMBER /tmp/a2c-output docker push ${ECR_REPO}:$BUILD_NUMBER # ECS サービスをロールアウト更新 aws ecs update-service \ --cluster my-cluster \ --service my-service \ --force-new-deployment ''' } } } } |
ポイント:A2C は IAM ロールで実行するため、事前に
AmazonApp2ContainerFullAccess相当の権限をタスクロールへ付与してください。
運用ベストプラクティスとトラブルシュート
パイプラインが本番環境で安定稼働するように、失敗時の自動ロールバック・通知、ステージング環境の IaC 管理、可観測性の確保 の 3 本柱を整備します。
失敗時のロールバックと Slack / SNS 通知
post ブロックでビルド結果に応じたアクションを定義し、失敗したら自動で CodeDeploy を停止し、Slack と SNS に即時通知します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
post { failure { script { // デプロイ中断(CodeDeploy のロールバック) sh ''' aws deploy stop-deployment \ --deployment-id ${DEPLOYMENT_ID} \ --auto-rollback-enabled ''' // Slack 通知 slackSend channel: '#ci-cd-alerts', color: 'danger', message: "❌ Jenkins パイプライン失敗 - Job:${env.JOB_NAME} #${env.BUILD_NUMBER}" // SNS でも通知(オプション) sh ''' aws sns publish \ --topic-arn ${SNS_TOPIC_ARN} \ --message "Jenkins pipeline failed: ${env.JOB_NAME} #${env.BUILD_NUMBER}" ''' } } success { slackSend channel: '#ci-cd-alerts', color: 'good', message: "✅ Jenkins パイプライン成功 - Job:${env.JOB_NAME} #${env.BUILD_NUMBER}" } } |
ベストプラクティス:通知メッセージに ジョブ名・ビルド番号・失敗理由(
currentBuild.resultなど)を含めると、トラブルシュートが高速化します。
ステージング環境の IaC 管理(Terraform / CloudFormation)
ステージングと本番は 同一コードベース で管理し、変数だけ切り替えてデプロイします。以下は Terraform のモジュール構成例です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
module "vpc" { source = "terraform-aws-modules/vpc/aws" name = "ci-cd-${var.environment}" cidr = var.vpc_cidr azs = ["ap-northeast-1a", "ap-northeast-1c"] private_subnets = ["10.0.1.0/24", "10.0.2.0/24"] } module "jenkins" { source = "./modules/jenkins" vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_subnets instance_type = var.jenkins_instance_type iam_role_name = var.jenkins_iam_role environment = var.environment } |
var.environmentに staging または production を設定するだけで、VPC・サブネット・EC2/ ECS のリソースが自動的に切り替わります。- 本番環境への適用前には必ず
terraform plan -out=plan.outで差分を確認し、承認後にterraform apply "plan.out"を実行します。
監視・ログ集約:CloudWatch アラーム と OpenSearch(旧 ELK)
CloudWatch アラーム例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Resources: BuildFailureAlarm: Type: AWS::CloudWatch::Alarm Properties: AlarmName: "Jenkins-CodeBuild-Failure" MetricName: "FailedBuilds" Namespace: "AWS/CodeBuild" Statistic: Sum Period: 300 # 5 分間隔で集計 EvaluationPeriods: 1 Threshold: 1 ComparisonOperator: GreaterThanOrEqualToThreshold AlarmActions: - !Ref SnsTopicForAlerts |
- アラームが発火したら SNS → Slack に自動転送し、担当者へ即時通知します。
OpenSearch(ELK)へのログ集約フロー
- Jenkins と CodeBuild のログは
aws logsへ出力(デフォルト)。 - Kinesis Firehose を作成し、CloudWatch Logs ストリームを Amazon OpenSearch Service に配信。
- Kibana ダッシュボードで以下の指標を可視化:
- ビルド実行時間・失敗率
- デプロイ成功/ロールバック回数
- Jenkins のシステムエラーログ
ポイント:検索クエリに
@timestampフィールドを使い、過去 30 日分のトレンド分析を自動化すると、異常検知が容易になります。
記事まとめ
- 最小権限 IAM:EC2/ECS のインスタンスロール/タスクロールに JSON ポリシーを付与し、一時キーは一切使用しない。
- Jenkins 環境構築:Free Tier 用
t2.micro(EC2)と Fargate の両パターンを Terraform/CloudFormation でコード化。 - 認証情報管理:Secrets Manager にキー保存は廃止し、ロールベース認証+Credentials Plugin のデフォルトプロバイダーを利用。
- Pipeline as Code:Jenkinsfile で
CodeBuild起動 →CodeDeploy / SAMデプロイ → 必要に応じてApp2Containerを組み込むフローを実装。 - 運用ベストプラクティス:失敗時自動ロールバックと Slack/SNS 通知、ステージング環境の IaC 管理、CloudWatch + OpenSearch による可観測性確保。
これらの手順とコード例をそのままプロジェクトに取り込めば、 安全・スケーラブルな Jenkins‑AWS CI/CD パイプライン が迅速に構築できます。まずは Free Tier の t2.micro で動作確認し、要件に合わせてインスタンスタイプやポリシーを拡張していくことを推奨します。