CDK(Python)でCodePipelineを作ってECSにデプロイしてみた
こんにちは、soraです。
今回は、CDK(Python)でCodePipelineを作ってECSにデプロイしてみたことについて書いていきます。
CDKのPythonコードメインで説明し、CodePipelineとはみたいな各サービスの説明は割愛します。
また、とりあえず動くものを作ることを目的としているため、ログ取得の有効化などはしていません。
今回やってみること
今回の構成は以下です。
CodeCommitリポジトリのコミットをトリガーとしてCodePipelineが動いて、ECSにデプロイする構成です。
CodeCommit・ECR・ECSは既に存在している状態として、他の部分をCDK(Python)で作っていきます。
環境
Cloud9上に構築した開発環境でCDK(Python)を使って構築します。
(.venv) $ python --version Python 3.7.16 (.venv) $ cdk --version 2.63.0 (build 7f4e35e)
やってみた
それでは実装してテストしていきます。
app.py
基本的には、スタックを呼び出しているだけです。
import aws_cdk as cdk from test_python.aws_cdk_cicd_stack import AwsCdkCicdStack env = cdk.Environment(account="<AWSのアカウントID>", region="ap-northeast-1") app = cdk.App() AwsCdkCicdStack(app, "aws-cdk-cicd", env=env) app.synth()
aws_cdk_cicd_stack.py
メインのコードです。
アーティファクト用のS3は、指定せずに自動で新しく作成されるものを使用します。
デプロイ前の既存のリソースを呼び出す部分は、型に気を付けないとエラーにはまります。(私は少しはまりました)
from constructs import Construct from aws_cdk import( Stack, RemovalPolicy, aws_iam as iam, aws_codebuild as codebuild, aws_codecommit as codecommit, aws_codepipeline as codepipeline, aws_codepipeline_actions as codepipeline_actions, aws_ecs as ecs, aws_ec2 as ec2 ) class AwsCdkCicdStack(Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: super().__init__(scope, construct_id, **kwargs) # CodePipelineの作成 # S3(artifact_bucket)は指定せずに新しく作成 pipeline = codepipeline.Pipeline(self, "Pipeline", pipeline_name = "cicd_codepipeline" ) # ============ source stage start ============= # 既存のCodeCommitリポジトリを取得 repository_arn = "<CodeCommitのARN>" repository = codecommit.Repository.from_repository_arn(self, "cicd-repository", repository_arn) # ソースアーティファクトの指定 source_output=codepipeline.Artifact("source_artifact") # CodeCommitからソースを取得するアクションを定義 source_action=codepipeline_actions.CodeCommitSourceAction( repository=repository, branch="develop", action_name="Source-CodeCommit", output=source_output, # デフォルト値のため、なくても良い trigger=codepipeline_actions.CodeCommitTrigger.EVENTS ) # CodePipelineにソースステージの追加 pipeline.add_stage( stage_name="Source", actions=[source_action] ) # ============ source stage end ============== # ============ build stage start ============= # CodeBuild用のロール作成 build_role=iam.Role(self, "Role", role_name="codebuild-role", assumed_by=iam.ServicePrincipal("codebuild.amazonaws.com") ) # CodeCommitへの読み込み権限・ECRへの書き込み権限の追加 build_role.add_managed_policy(iam.ManagedPolicy.from_aws_managed_policy_name("AWSCodeCommitReadOnly")) build_role.add_managed_policy(iam.ManagedPolicy.from_aws_managed_policy_name("AmazonEC2ContainerRegistryPowerUser")) # CodeBuildの作成 build_project = codebuild.PipelineProject(self, "cicd-build", project_name="cicd_build", # Dockerイメージを構築するための特権付与 environment=codebuild.BuildEnvironment(privileged=True), role=build_role ) # ビルドアーティファクトの指定 build_output = codepipeline.Artifact("build_output") # CodeBuild build_action = codepipeline_actions.CodeBuildAction( action_name="Build-CodeBuild", project=build_project, input=source_output, outputs=[build_output] ) # CodePipelineにビルドステージの追加 pipeline.add_stage( stage_name="Build", actions=[build_action] ) # ============ build stage end =============== # ============ deploy stage start ============ # 既存のECSクラスターの取得 ecs_cluster=ecs.Cluster.from_cluster_arn(self, "cicd-cluster", cluster_arn="<ECSクラスターのARN>" ) # 既存のECSサービスの取得 cicd_fargate=ecs.FargateService.from_fargate_service_attributes(self, "cicd-fargate", cluster=ecs_cluster, service_arn="<ECSサービスのARN>" ) # ECSへのデプロイアクション deploy_ecs = codepipeline_actions.EcsDeployAction( action_name="Deploy-ECS", service = cicd_fargate, input=build_output ) # CodePipelineにデプロイステージの追加 pipeline.add_stage( stage_name="Deploy", actions=[deploy_ecs] ) # ============ deploy stage end ==============
その他のファイル
CodeCommitのリポジトリ内のファイルは以下です。
ブランチ名はdevelopとして、Dockerfileとbuildspec.ymlを配置しています。
Dockerfile(1行)はnginxを拾ってきているだけです。
buildspec.ymlでの出力するjsonファイルの指定について、デプロイ方法によって異なります。
buildspec.yml
version: 0.2 env: variables: AWS_DEFAULT_REGION: ap-northeast-1 AWS_ACCOUNT_ID: <AWSアカウントのID> IMAGE_REPO_NAME: <ECRのリポジトリ名> IMAGE_TAG: latest phases: build: commands: - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com - docker build --no-cache -t $IMAGE_REPO_NAME:$IMAGE_TAG . - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG - printf '[{"name":"nginx","imageUri":"%s"}]' $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG > imagedefinitions.json artifacts: files: imagedefinitions.json
Dockerfile
FROM nginx:latest
実行
ソースコードができたため、差分を確認した後に実行します。
# (不要な場合は省略)仮想環境への切り替え $ source .venv/bin/activate # 実行時の差分確認 (.venv) $ cdk diff # 実行 (.venv) $ cdk deploy
テスト
CodePipelineが作成されて、正常に完了していることを確認します。
画像は取れていませんが、ECSのサービスを確認するとリビジョンも上がっています。
参考にしたサイト
AWS CDK Python Reference
AWS CDKをデプロイするCodepipelineをCDK(Python)で構築する
最後に
今回は、CDK(Python)でCodePipelineを作ってECSにデプロイしてみたことについて紹介しました。
参考になれば幸いです。