コンテンツにスキップ

Code兄弟@AWSリソース

はじめに

本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。


01. Code兄弟サービス

Code兄弟サービス

▼ CodePipeline

CodeCommit、CodeBuild、CodeDeploy を連携させて AWS に対する CI/CD パイプラインを作成する。

CodeCommit は、他のコード管理サービスで代用できる。

code-pipeline

▼ CodeCommit

コードをバージョン管理する。

▼ CodeBuild

ビルドフェーズとテストフェーズを実行する。

▼ CodeDeploy

デプロイフェーズを実行する。


02. CodeBuild

buildspec.yml ファイル

▼ Amazon ECSの場合

Amazon ECS のために、CodeBuild の設定する。

ルートディレクトリの直下に配置しておく。

*実装例*

コンテナをビルドする場合を示す。

コミットのハッシュ値でコンテナイメージをプッシュしたい場合、CodeBuild の設計上、latest タグもプッシュしておいたほうがよい。

version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
  preBuild:
    commands:
      # Amazon 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
      # Amazon 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:
      # Amazon ECRにコンテナイメージをプッシュする。
      # コミットハッシュ値のタグの前に、latestタグのコンテナイメージをプッシュしておく。
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      # Amazon 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 バケットからソースコードの圧縮ファイルをプルする。

code-deploy_agent


04. CodeDeploy (Amazon EC2の場合)

利用できるデプロイメント手法

インプレースデプロイ、ブルー/グリーンデプロイメントを利用できる。


インプレースデプロイメント


ブルー/グリーンデプロイメント


04-02. CodeDeploy (AWS Lambdaの場合)

利用できるデプロイメント手法

ブルー/グリーンデプロイメントを利用できる。


04-03. CodeDeploy (Amazon ECSの場合)

利用できるデプロイメント手法

ローリングアップデート、ブルー/グリーンデプロイメントを利用できる。


ローリングアップデート

imagedefinitions.json ファイル

新しいリビジョンの Amazon ECS タスク定義を作成するために、新しいコンテナ名とイメージリポジトリ URL を定義する。

リポジトリへ事前に配置するのではなく、CI/CD パイプライン上で動的に作成するようにしたほうがよい。

[
  {
    "imageUri": "<イメージリポジトリURL>", # <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/<イメージリポジトリ名>:latest
    "name": "<コンテナ名>",
  },
]


ブルー/グリーンデプロイメント

▼ ブルー/グリーンデプロイメントの仕組み

blue-green-deployment

以下の手順でデプロイする。

(1)

Amazon ECR のコンテナイメージを更新

(2)

Amazon ECS タスク定義の新しいリビジョンを作成。

(3)

サービスを更新。

(4)

AWS CodeDeploy によって、Amazon ECS タスク定義を基に、現環境 (Prod ブルー) の Amazon ECS タスクとは別に、新環境 (Test グリーン) が作成される。

ロードバランサーの接続先を、現環境 (Prodブルー) のターゲットグループ (Primaryターゲットグループ) に加えて、新環境 (Testグリーン) にも向ける。

(5)

社内から新環境 (Test グリーン) の ALB に、特定のポート番号でアクセスし、動作を確認する。

(6)

動作確認で問題なければ、Console 画面からの入力で、ロードバランサーの接続先を新環境 (Test グリーン) のみに設定する。

(7)

新環境 (Test グリーン) が新しい現環境としてユーザーに公開される。

(8)

元の現環境 (Prod ブルー) は削除される。

appspec.yml ファイル

ルートディレクトリの直下に配置しておく。仕様として、複数のコンテナをデプロイできない。

Amazon ECS タスク定義名を <TASK_DEFINITION> とすると、taskdef.json ファイルの値を元にして、新しい Amazon ECS タスク定義が自動的に代入される。

version: 0.0

Resources:
  - TargetService:
      # 使用するAWSリソース
      Type: AWS::Amazon ECS::Service
      Properties:
        # 使用するAmazon ECSタスク定義
        TaskDefinition: "<TASK_DEFINITION>"
        # 使用するロードバランサー
        LoadBalancerInfo:
          ContainerName: "<コンテナ名>"
          ContainerPort: "80"
        PlatformVersion: "1.4.0"

imageDetail.json ファイル

新バージョンタグを含むイメージリポジトリ URL を、taskdef.json ファイルの <IMAGE1_NAME> へ代入するために必要である。

これはリポジトリへ事前に配置するのではなく、CI/CD パイプライン上で動的に作成するようにしたほうがよい。

taskdef.json ファイル

デプロイされる Amazon ECS タスク定義を実装し、ルートディレクトリの直下に配置する。

CodeDeploy は、CodeBuild から渡された imageDetail.json ファイルを検知し、Amazon ECR からコンテナイメージを取得する。

このとき、taskdef.json ファイルのコンテナイメージ名を <IMAGE1_NAME> としておくと、imageDetail.json ファイルの値を元にして、新バージョンタグを含むイメージリポジトリ URL が自動的に代入される。

{
  "family": "<Amazon ECSタスク定義名>",
  "requiresCompatibilities": ["FARGATE"],
  "networkMode": "awsvpc",
  "taskRoleArn": "<タスクロールのARN>",
  "executionRoleArn": "<タスク実行ロールのARN>",
  "cpu": "512",
  "memory": "1024",
  "containerDefinitions":
    [
      {
        "name": "<コンテナ名>",
        "image": "<IMAGE1_NAME>",
        "essential": "true",
        "portMappings": [
            {
              # コンテナポート
              "containerPort": 80,
              # Amazon 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 のデプロイの途中、ターゲットグループからインスタンスを切り離すことにより、リクエストのインスタンスへのルーティングを遮断する。

そのため、デプロイ中にユーザーはアプリにリクエストできなくなる。

デプロイが正常に完了次第、ターゲットグループにインスタンスを再登録し、リクエストできる。