Code兄弟@AWSリソース¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. Code兄弟サービス¶
Code兄弟サービス¶
▼ CodePipeline¶
CodeCommit、CodeBuild、CodeDeploy、を連携させてAWSに対するCI/CDパイプラインを作成する。
CodeCommitは、他のコード管理サービスで代用できる。
▼ CodeCommit¶
コードをバージョン管理する。
▼ CodeBuild¶
ビルドフェーズとテストフェーズを実行する。
▼ CodeDeploy¶
デプロイフェーズを実行する。
02. CodeBuild¶
buildspec.yml
ファイル¶
▼ AWS ECSの場合¶
AWS ECSのために、CodeBuildの設定を実行する。
ルートディレクトリの直下に配置しておく。
*実装例*
コンテナをビルドする場合を示す。
コミットのハッシュ値でコンテナイメージをプッシュしたい場合、CodeBuildの設計上、latest
タグもプッシュしておいた方が良い。
version: 0.2
phases:
install:
runtime-versions:
docker: 18
preBuild:
commands:
# AWS ECRにログイン
- 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
# AWS ECRのURLをCodeBuildの環境変数から作成
- REPOSITORY_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${IMAGE_REPO_NAME}
# バージョンタグはコミットのハッシュ値を使用
- COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
# ハッシュ値だけでなく、プレフィクスに日付をつけてもよい。
- IMAGE_TAG=${COMMIT_HASH:=latest}
build:
commands:
# タグ付けしてイメージをビルド
- docker build -t $REPOSITORY_URI:latest .
- docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
postBuild:
commands:
# AWS ECRにコンテナイメージをプッシュする。
# コミットハッシュ値のタグの前に、latestタグのコンテナイメージをプッシュしておく。
- docker push $REPOSITORY_URI:latest
- docker push $REPOSITORY_URI:$IMAGE_TAG
# AWS ECRにあるデプロイ先のコンテナイメージの情報 (imageDetail.json)
- printf '[{"name":"hello-world","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
# デプロイ対象とするビルドのアーティファクト
artifacts:
files: imageDetail.json
03. CodeDeploy (オンプレミスのサーバーの場合)¶
利用できるデプロイメント手法¶
インプレースデプロイメントを利用できる。
インプレースデプロイメント¶
▼ CodeDeployエージェント¶
オンプレミスサーバーにCodeDeployエージェントをインストールし、CodeDeployエージェントにサーバー情報を登録する必要がある。
CodeDeployとCodeDeployエージェントは通信し、CodeDeployエージェントがS3バケットからソースコードの圧縮ファイルをプルする。
04. CodeDeploy (EC2の場合)¶
利用できるデプロイメント手法¶
インプレースデプロイ、ブルー/グリーンデプロイメント、を利用できる。
インプレースデプロイメント¶
ブルー/グリーンデプロイメント¶
04-02. CodeDeploy (AWS Lambdaの場合)¶
利用できるデプロイメント手法¶
ブルー/グリーンデプロイメント、を利用できる。
04-03. CodeDeploy (AWS ECSの場合)¶
利用できるデプロイメント手法¶
ローリングアップデート、ブルー/グリーンデプロイメント、を利用できる。
ローリングアップデート¶
▼ imagedefinitions.json
ファイル¶
新しいリビジョン番号のAWS ECSタスク定義を作成するために、新しいコンテナ名とイメージリポジトリURLを定義する。
リポジトリに事前に配置するのではなく、CI/CDパイプライン上で動的に作成するようにした方が良い。
[
{
"imageUri": "<イメージリポジトリURL>", # <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/<イメージリポジトリ名>:latest
"name": "<コンテナ名>",
},
]
ブルー/グリーンデプロイメント¶
▼ ブルー/グリーンデプロイメントの仕組み¶
以下の手順でデプロイする。
(1)
-
AWS ECRのコンテナイメージを更新
(2)
-
AWS ECSタスク定義の新しいリビジョンを作成。
(3)
-
サービスを更新。
(4)
-
CodeDeployによって、AWS ECSタスク定義を基に、現環境 (Prodブルー) のAWS ECSタスクとは別に、新環境 (Testグリーン) が作成される。
ロードバランサーの接続先を、現環境 (Prodブルー) のターゲットグループ (Primaryターゲットグループ) に加えて、新環境 (Testグリーン) にも向ける。
(5)
-
社内から新環境 (Testグリーン) のALBに、特定のポート番号でアクセスし、動作を確認する。
(6)
-
動作確認で問題なければ、Console画面からの入力で、ロードバランサーの接続先を新環境 (Testグリーン) のみに設定する。
(7)
-
新環境 (Testグリーン) が新しい現環境としてユーザーに公開される。
(8)
-
元の現環境 (Prodブルー) は削除される。
▼ appspec.yml
ファイル¶
ルートディレクトリの直下に配置しておく。仕様として、複数のコンテナをデプロイできない。
AWS ECSタスク定義名を<TASK_DEFINITION>
とすると、taskdef.json
ファイルの値を元にして、新しいAWS ECSタスク定義が自動的に代入される。
version: 0.0
Resources:
- TargetService:
# 使用するAWSリソース
Type: AWS::AWS ECS::Service
Properties:
# 使用するAWS ECSタスク定義
TaskDefinition: "<TASK_DEFINITION>"
# 使用するロードバランサー
LoadBalancerInfo:
ContainerName: "<コンテナ名>"
ContainerPort: "80"
PlatformVersion: "1.4.0"
▼ imageDetail.json
ファイル¶
新バージョンタグを含むイメージリポジトリURLを、taskdef.json
ファイルの <IMAGE1_NAME>
に代入するために必要である。
これはリポジトリに事前に配置するのではなく、CI/CDパイプライン上で動的に作成するようにした方が良い。
▼ taskdef.json
ファイル¶
デプロイされるAWS ECSタスク定義を実装し、ルートディレクトリの直下に配置する。
CodeDeployは、CodeBuildから渡されたimageDetail.json
ファイルを検知し、AWS ECRからコンテナイメージを取得する。
この時、taskdef.json
ファイルのコンテナイメージ名を<IMAGE1_NAME>
としておくと、imageDetail.json
ファイルの値を元にして、新バージョンタグを含むイメージリポジトリURLが自動的に代入される。
{
"family": "<AWS ECSタスク定義名>",
"requiresCompatibilities": ["FARGATE"],
"networkMode": "awsvpc",
"taskRoleArn": "<タスクロールのARN>",
"executionRoleArn": "<タスク実行ロールのARN>",
"cpu": "512",
"memory": "1024",
"containerDefinitions":
[
{
"name": "<コンテナ名>",
"image": "<IMAGE1_NAME>",
"essential": "true",
"portMappings": [
{
# コンテナポート
"containerPort": 80,
# AWS ECSのホストのポート
"hostPort": 80,
"protocol": "tcp",
},
],
"secrets": [
# データ永続化用のDBの接続情報
{"name": "DB_HOST", "valueFrom": "/ecs/DB_HOST"},
{"name": "DB_DATABASE", "valueFrom": "/ecs/DB_DATABASE"},
{"name": "DB_PASSWORD", "valueFrom": "/ecs/DB_PASSWORD"},
{"name": "DB_USERNAME", "valueFrom": "/ecs/DB_USERNAME"},
# セッションキャッシュ用のインメモリDBの接続情報
{"name": "REDIS_HOST", "valueFrom": "/ecs/REDIS_HOST"},
{"name": "REDIS_PASSWORD", "valueFrom": "/ecs/REDIS_PASSWORD"},
{"name": "REDIS_PORT", "valueFrom": "/ecs/REDIS_PORT"},
],
"logConfiguration": {
# ログドライバー
"logDriver": "awslogs",
"options": {
"awslogs-group": "<ログストリーム名>",
# スタックトレースのログを紐付けられるように、日付で区切るようにする。
"awslogs-datetime-format": "\\[%Y-%m-%d %H:%M:%S\\]",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "<ログストリーム名の接頭辞>",
},
},
},
],
}
04-04. CodeDeployと他のAWSリソースとの連携¶
AutoScaling¶
ALB、ELB、NLB¶
▼ インプレースデプロイメントの場合¶
CodeDeployのデプロイの途中、ターゲットグループからインスタンスを切り離すことにより、リクエストのインスタンスへのルーティングを遮断する。
そのため、デプロイ中にユーザーはアプリにリクエストできなくなる。
デプロイが正常に完了次第、ターゲットグループにインスタンスを再登録し、リクエストできる。