17日目: コンテナ時代のCI/CD:ECS/EKSへのデプロイパイプライン
はじめに:コンテナ技術とCI/CDの蜜月
皆さん、こんにちは!👋 昨日は、CI/CDパイプラインの信頼性を高める「Immutable Infrastructure」と「AMI」について学びました。このImmutable Infrastructureの考え方をさらに推し進め、現代のインフラ管理手法として主流となっているのがコンテナ技術です。
コンテナは、アプリケーションとその依存関係を一つの独立したパッケージにまとめることで、開発環境から本番環境まで、どこでも一貫した動作を保証します。これはまさにCI/CDの目指す「一貫性と信頼性」を、アプリケーションの実行環境レベルで実現するものです。
本記事では、このコンテナ技術とCI/CDを組み合わせ、AWS ECS (Elastic Container Service) および AWS EKS (Elastic Kubernetes Service) へのデプロイパイプラインを構築する方法を解説します。
1. コンテナのCI/CDワークフロー
コンテナを使ったCI/CDの基本的な流れは、これまでのEC2インスタンスへのデプロイと似ていますが、いくつかの重要な違いがあります。
- ソースコードの変更: 開発者がコードを更新し、CodeCommitにプッシュします。
- ビルド: CodeBuildがコードを取得し、アプリケーションをコンパイルするだけでなく、そのアプリケーションを含むDockerイメージを構築します。
- プッシュ: 構築したDockerイメージを、Amazon ECR (Elastic Container Registry) というコンテナレジストリにプッシュします。
- デプロイ: CodePipelineがECRへの新しいイメージのプッシュを検知し、ECSまたはEKSにデプロイします。このデプロイは、新しいイメージで既存のコンテナを更新するプロセスとなります。
このワークフローの中心となるのが、DockerイメージのビルドとECRへのプッシュです。
2. AWS CodeBuildでのDockerイメージのビルドとECRへのプッシュ
CodeBuildは、Dockerイメージのビルドをネイティブにサポートしています。buildspec.ymlに数行のコマンドを追加するだけで、このプロセスを自動化できます。
buildspec.ymlの修正
CodeBuildプロジェクトに、以下のbuildspec.ymlを設定します。
version: 0.2
# AWS CodeBuildにDockerのビルドを許可する設定
# この設定を有効にするには、CodeBuildプロジェクトの設定で特権モードを有効にする必要があります。
env:
variables:
AWS_DEFAULT_REGION: "ap-northeast-1"
REPOSITORY_URI: "xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-python-app"
phases:
pre_build:
commands:
# Dockerにログイン
- echo "Logging in to Amazon ECR..."
- aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $REPOSITORY_URI
build:
commands:
# Dockerイメージをビルド
- echo "Building the Docker image..."
- docker build -t my-python-app .
# ECRにプッシュするために、イメージにタグ付け
- docker tag my-python-app:latest $REPOSITORY_URI:latest
post_build:
commands:
# ECRにイメージをプッシュ
- echo "Pushing the Docker image to ECR..."
- docker push $REPOSITORY_URI:latest
このbuildspec.ymlでは、以下の処理を行っています。
-
pre_buildフェーズ: AWS CLIを使ってECRに認証情報を取得し、Dockerにログインします。 -
buildフェーズ:docker buildコマンドで、リポジトリにあるDockerfileを基にDockerイメージを構築します。その後、ECRにプッシュするためのタグを付けます。 -
post_buildフェーズ: 構築したイメージをdocker pushコマンドでECRにアップロードします。
注意点: CodeBuildでDockerイメージをビルドするには、プロジェクト設定で「特権モード」を有効にする必要があります。
3. AWS ECS/EKSへのデプロイ
DockerイメージがECRにプッシュされたら、CodePipelineを使ってECSまたはEKSにデプロイします。
ECSへのデプロイ
ECSにデプロイする場合、CodePipelineのデプロイステージで「Amazon ECS」を選択します。
-
デプロイプロバイダー:
Amazon ECS - クラスター名: デプロイ先のECSクラスター名を選択
- サービス名: 更新するECSサービス名を選択
-
イメージ定義ファイル: CodeBuildのビルド成果物として生成される
imagedefinitions.jsonを指定します。
imagedefinitions.jsonは、以下のような形式で、どのコンテナイメージをどのコンテナにデプロイするかを定義します。
[
{
"name": "my-python-app-container",
"imageUri": "xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-python-app:latest"
}
]
CodeBuildのbuildspec.ymlで、このファイルを生成するように設定することで、CodePipelineが自動的にECSサービスのタスク定義を更新し、新しいコンテナをデプロイします。
EKS (Kubernetes) へのデプロイ
EKSにデプロイする場合、CodePipelineは直接EKSを操作するデプロイプロバイダーを持っていません。代わりに、CodeBuildやサードパーティのツール(例: FluxCD, ArgoCD)をデプロイステージで利用します。
一般的には、以下のような流れでデプロイします。
-
CodeBuildでマニフェストファイルを更新: CodeBuildで、デプロイ対象の
k8sマニフェストファイル(Deployment, Serviceなど)のイメージタグを、新しいイメージのタグに書き換えます。 -
EKSにデプロイ:
kubectlコマンドを使い、更新されたマニフェストファイルをEKSクラスターに適用します。
# buildspec.yml (EKSデプロイの例)
# ...
phases:
post_build:
commands:
# マニフェストファイルのイメージタグを更新
- sed -i "s|latest|$CODEBUILD_RESOLVED_SOURCE_VERSION|" k8s/deployment.yml
# kubectlを使ってEKSにデプロイ
- kubectl apply -f k8s/deployment.yml
この例では、kubectlコマンドを実行するために、CodeBuild環境に適切なIAMロールとkubeconfigを設定しておく必要があります。
まとめ:コンテナ時代のCI/CD
本日は、コンテナ技術をCI/CDパイプラインに組み込む方法を学びました。
- コンテナCI/CDワークフロー: ソースコードの変更をトリガーに、Dockerイメージをビルドし、ECRにプッシュ、そしてECSやEKSにデプロイする一連の流れを理解しました。
-
CodeBuild:
buildspec.ymlを使い、DockerイメージのビルドとECRへのプッシュを自動化できることを確認しました。 -
ECS/EKSへのデプロイ: CodePipelineと
imagedefinitions.jsonを使ってECSにデプロイする方法、およびkubectlを使ってEKSにデプロイする一般的なアプローチを解説しました。
コンテナは、現代のアプリケーション開発とデプロイメントの標準となっています。コンテナベースのCI/CDパイプラインを構築することで、アプリケーションのポータビリティ(可搬性)とデプロイの一貫性が向上し、よりスケーラブルで信頼性の高いシステムを構築できるようになります。
次回は、CI/CDパイプラインの概念をさらに一歩進め、サーバーレスアプリケーションへのデプロイについて解説します。お楽しみに!