Amazon Web Services ブログ

AWS Organizations を利用したマルチアカウント環境での Amazon ECR リポジトリの共有

この記事は Sharing Amazon ECR repositories with multiple accounts using AWS Organizations を翻訳したものです。

お客様は AWS 上でセキュリティの向上と職務の分離を行うためマルチアカウントの導入を進めています。Amazon Elastic Container Registry (ECR) のような一部の AWS サービスは、管理のオーバーヘッドを減らし可視性を高めるために、単一のインスタンスをアカウント間で共有できるスケーラビリティをサポートしています。AWS アカウントは、アカウント番号やその他のアカウント固有のメタデータが頻繁に生成される弾力性のあるリソースとなっているため、手間の掛からない自動化されたアプローチを採用する必要があります。いくつかのアップデートを行うことで、AWS Organizations を活用したマルチアカウント環境での ECR リポジトリへのきめ細かなアクセス制御が可能になります。

AWS Organizations はお客様の AWS アカウントを論理的に分離し、かつ関連するグループを作成することを可能にしました。階層内の各組織単位 (OU) には、数百から数千ものアカウントを含めることができます。Organizations には多くのカスタマイズ機能があるため、お客様はアカウント間でリソースを共有することがより正確になり、ニーズの増加に合わせた拡張が容易になります。ECR のコンテナイメージはアーティファクトの一例です。コンテナイメージは管理を容易にするために集中型のアーキテクチャでホストされる一方で、標準化と効率化のために多くのアカウント間で共有されます。AWS Organizations の OU と ECR のリポジトリポリシーを組み合わせることで、これらのニーズを満たすソリューションが実現できます。

OU は IAM ポリシーの “principal” として使用することはできませんが、AWS グローバル条件コンテキストキーの Condition として指定することができます。IAM のこの機能には様々な特徴がありますが、ここでは呼び出し元が OU 内のアカウントである場合の、クロスアカウントリクエストに含まれるメタデータの一部に注目してみましょう。“aws:PrincipalOrgPaths” という Condition は、リクエストの対象となるリソースが完全に異なる OU 内の別のアカウントにあるような場合でもアクセスポリシーに含めることができます。ここで、 CI/CD パイプラインに含まれるエンタープライズ規模の重要コンポーネントを提供する共有サービスアカウントについて考えてみましょう。これらは開発アカウントと本番アカウントが分離されているため、セキュリティ保護が容易です。AWS CodeCommit のようなバージョン管理システムは、AWS CodeBuild のようなビルドシステムと統合する堅牢な方法を採用しています。開発者はリポジトリへのコミットやブランチ間のプルリクエストを作成するだけでパイプラインが起動し、アカウント間でオーケストレーションされたこれらのリソースを使用して、アプリケーションのアーティファクトをビルドしてデプロイします。お客様の課題を解決するという AWS の取り組みによって、マルチアカウントでの課題解決に有効なアーキテクチャが、単一の AWS アカウントのサービスで簡単に実装できるようになりました。ここでは、これらの機能がどのように集約されているかを説明します。

ソリューション概要

このブログでは、マルチアカウントで共有の ECR から Amazon Elastic Container Service (ECS) クラスターへの Blue/Green デプロイメントを実行する例を紹介します。これらの機能は、Elastic Kubernetes Service (EKS) を使用するお客様にも役立ちます。また AWS CodeDeploy と AWS CloudFormation を使用して、アプリケーションをサポートするのに必要なインフラストラクチャをオーケストレーションします。ここではシンプルな “hello world” アプリを対象とします。以下のアーキテクチャ図は、サンプルの共有サービスと開発 OU 全体の AWS リソースを示しています。これらについて詳しく説明していきます。

このチュートリアルでは 2 つのコンテナイメージを作成します。1 つは “hello world” アプリケーションの Blue バージョン、もう 1 つは Green バージョンです。これらのコンテナイメージは OU に属する共有サービスアカウントにある Amazon ECR のリポジトリにプッシュされます。ECR のリポジトリポリシーは Condition の “aws:PrincipalOrgPaths” を使用して設定され、開発 OU に属するすべての開発アカウントに読み取りアクセスを提供します。新しい開発アカウントが作成され開発 OU に追加されると、ECR リポジトリへのアクセスが自動的に付与されます。新しいアカウントが ECR リポジトリにアクセスしようとすると、AWS はリクエストの呼び出し元であるアカウントの OU がポリシーで指定されたものと一致するかどうかを確認します。開発アカウントでは CloudFormation テンプレートを使用して “hello world” アプリケーションの Blue バージョンを AWS Fargate 上で動作する ECS サービスにデプロイします。その後、CloudFormation スタックを更新して同じアプリケーションの Green バージョンをデプロイします。

ソリューションチュートリアル

前提条件

このソリューションを進めるには、以下の前提条件を満たす必要があります。

  • 共有サービスと開発用の OU を持つ AWS Organizations 環境。新たに作成されたアカウントは必要に応じて割り当てられますが、このソリューションでは各 OU に 1 つずつ割り当てられます。
  • Docker と AWS CLI がインストールされたローカルまたはクラウドベースの開発環境。詳細については AWS CLI の使用開始を参照してください。
  • このブログ内で使用する “aws ecr get-login-password” コマンドが利用可能なバージョンについてはこちらを参照してください。

Step 1: ソースコードをローカル環境にダウンロードする

このソリューションを実装するためのソースコードは amzon-ecr-orgpath-sample GitHub リポジトリからローカルの開発環境にダウンロードするか、以下のコマンドを使用してクローンします。

git clone https://github.com/aws-samples/amazon-ecr-orgpath-sample.git

ソースコードに含まれるファイル

  • cft-service-ecr-repo.yaml – 共有サービスアカウントに必要なすべてのリソースをデプロイするための CloudFormation テンプレート
  • cft-dev-codeploybluegreen-create.yaml – 開発アカウントの Amazon ECS に “hello world” の最初のバージョン (Blue) をデプロイする CloudFormation テンプレート
  • cft-dev-codeploybluegreen-update.yaml – “hello world” の 2 つ目のバージョン (Green) を開発アカウントの Amazon ECS にデプロイするための CloudFormation テンプレート
  • Dockerfile.blue – シンプルな hello world ウェブアプリの バージョン 1 (Blue バージョン) を構築するためのサンプル Dockerfile
  • Dockerfile.green – シンプルな hello world ウェブアプリの バージョン 2 (Green バージョン) を構築するためのサンプル Dockerfile

Step 2: 共有サービスアカウントで Amazon ECR リポジトリをプロビジョニングするための AWS CloudFormation スタックを作成する

共有サービスアカウントの AWS マネジメントコンソールにある AWS CloudFormation のページで、”スタックの作成” を選択します。テンプレートの選択セクションの “テンプレートの指定” で、 “テンプレートファイルのアップロード” を選択します。”ファイルの選択” を選択して、cft-service-ecr-repo.yaml ファイルをアップロードし “次へ” を選択します。詳細はステップ 3: スタックの作成を参照してください。

”スタックの詳細を指定” 画面で以下のフィールドに値を入力します。

  • スタックの名前: スタックの名前を入力します。
  • DevOrgUnitID: 開発環境の AWS Organizations の Unit ID を入力します。
  • OrgID: AWS Organizational Unit ID を入力します。

作成ページで IAM リソースの作成を確認するメッセージが表示されたら “作成” を選択します。スタック作成の進捗状況を確認するには CloudFormation スタックの “イベント” タブを確認します。CloudFormation スタックの作成が完了し、そのスタックの “リソース” タブを表示するとマネジメントコンソール上からリソースが作成されたことを確認できます。

このスタックは、共有サービスアカウントに Amazon ECR リポジトリ demoecshwapp-ecr-repo をプロビジョニングします。スタックの出力は ECR リポジトリの URI で、これは後続のステップでコンテナイメージのプッシュとプルの操作に使用されます。URI の形式は次のとおりです。

{aws-account-id}.dkr.{aws-region}.amazonaws.com/demoecshwapp-ecr-repo

また、このスタックでは以下のように読み取り専用の ECR リポジトリのポリシーを定義しています。Organization ID と開発 OU の IDが Condtion の “aws:PrincipalOrgPaths” に渡され、開発 OU のすべてのアカウントが共有サービスアカウントの ECR リポジトリからコンテナイメージをプルできるようになっています。

{
  “Version”: “2012-10-17”,
  “Statement”: [
    {
      “Sid”: “AllowPull”,
      “Effect”: “Allow”,
      “Principal”: “*”,
      “Action”: [
        “ecr:BatchCheckLayerAvailability”,
        “ecr:BatchGetImage”,
        “ecr:DescribeImages”,
        “ecr:DescribeRepositories”,
        “ecr:GetDownloadUrlForLayer”
      ],
      “Condition”: {
        “ForAnyValue:StringLike”: {
          “aws:PrincipalOrgPaths”: “o-xxxxxxxxxx/*/ou-xxxx-xxxxxxxx/*”
        }
      }
    }
  ]
}

Step 3: hello world の Docker イメージを作成し、共有サービスアカウントの ECR リポジトリにコンテナイメージをプッシュする

ローカルの開発環境にて、Dockerfile.blue と Docketfile.green が置かれているディレクトリに移動します。シェルで以下の環境変数を設定します。{aws-account-id} と {aws-region} を、あなたの AWS アカウント ID の番号と、ECR レジストリのエンドポイントがある AWS リージョンに置き換えます。または Step 2 で作成したスタックの出力値をコピーして、変数 REPOURI の値に貼り付けるだけでも OK です。

REPOURI={aws-account-id}.dkr.{aws-region}.amazonaws.com/demoecshwapp-ecr-repo
AWS_REGION={aws-region}

Docker クライアントで ECR に ログインします。

aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${REPOURI}

ここで、hello world アプリケーションの Blue バージョンと Green バージョンの 2 つの Docker イメージをビルドし、デモ用にそれぞれ Blue と Green のタグを付けます。両方のコンテナイメージを Amazon ECR にプッシュします。

docker build -t ${REPOURI}:blue -f Dockerfile.blue .
docker push ${REPOURI}:blue
docker build -t ${REPOURI}:green -f Dockerfile.green .
docker push ${REPOURI}:green

Amazon ECR にプッシュされたコンテナイメージは “aws ecr” コマンドで確認できます。

aws ecr describe-images --repository-name demoecshwapp-ecr-repo --region ${AWS_REGION}

Step 4: 開発アカウントの AWS Fargate に hello world の Blue バージョンをデプロイするための AWS CloudFormation スタックを作成する

cft-dev-codeploybluegreen-create.yaml ファイルに対して、Step 2 で説明したスタック作成プロセスを繰り返します。“スタックの詳細を指定” ページで、以下の値を入力します。

  • ImageUri: “hello world” Blue バージョンのコンテナイメージの URI を入力します。(例 {aws-account-id}.dkr.{aws-region}.amazonaws.com/demoecshwapp-ecr-repo:blue)
  • Subnet1: 開発アカウントのパブリックサブネットを選択します。
  • Subnet2: 開発アカウントのパブリックサブネットを選択します。
  • VPC: 開発アカウントの VPC を選択します。

このスタックでは以下のリソースを作成します。これらのリソースには Blue および Green のアプリケーション環境に共通のリソースと、Blue に特化した ECS タスクの関連リソースが含まれます

  • Application Load Balancer
  • Application Load Balancer のリスナーとリスナールール
  • Application Load Balancer の 2 つのターゲットグループ (Blue 環境用と Green 環境用)
  • Amazon ECS クラスター
  • Blue 環境のコンテナイメージを使用した Amazon ECS タスク定義
  • Blue 環境のリソースを定義した Amazon ECS タスクセット
  • Blue 環境のリソースを定義した Amazon ECS プライマリタスクセット
  • 2 つのセキュリティグループ。1 つは Application Load Balancer 用、1 つは ECS サービス用
  • ECS タスク実行のための IAM ロール

スタックテンプレートには、AWS:CodeDeployBlueGreen トランスフォームを呼び出す Transform セクションと、トラフィックルーティング設定を定義する AWS:CodeDeployBlueGreen フックを呼び出す Hook セクションが含まれています。詳細については、AWS CloudFormation を使用した CodeDeploy による ECS Blue/Green のデプロイメントの実行を参照してください。

スタックの作成が完了したら、スタックの出力タブにある “Application Load Balancer DNS name” をクリックします。Web ページに “Hello World! (Blue)” と表示されれば、アプリケーションが AWS Fargate に正常にデプロイされています。

Step 5: AWS CloudFormation スタックを更新して、開発アカウントの AWS Fargate に hello world Green バージョンをデプロイする

開発アカウントの AWS マネジメントコンソールの AWS CloudFormation ページにて、Step 4 で作成したスタックを選択します。“更新” をクリックし “既存テンプレートを置き換える” を選択します。”テンプレートファイルのアップロード” を選択して、cft-dev-codeploybluegreen-update.yaml ファイルをアップロードし、”次へ” を選択します。”スタックの詳細を指定” ページでは、パラメータ ImageUri 以外の既存の値は変更しません。パラメータ ImageUri については、入力値の Blue を Green に置き換えることで Green でタグ付けされた docker イメージがデプロイされます。サンプルでは、{aws-account-id}.dkr.{aws-region}.amazonaws.com/demoecshwapp-ecr-repo:green を入力しています。その後、”次へ” をクリックし、レビューページでIAM リソースの作成を確認し “スタックの更新” を選択します。

CloudFormation テンプレート cft-dev-codeploybluegreen-update.yaml が、更新前のテンプレート cft-dev-codeploybluegreen-create.yaml と比較して唯一異なる点は、ECS タスク定義リソースのメモリが 512 から 1024 に増加したことです。この変更によって引き起こされるスタックの更新により、Blue/Green デプロイメントが実行されます。Green 環境は、Green とタグ付けされたコンテナイメージを使用して作成されます。ECS は CloudFormation テンプレートに定義された Green のターゲットグループのヘルスチェックに基づいて、新しいデプロイメントが正常に動作しているかどうかを判断します。トラフィックが Green スタックにルーティングされる前の段階でエラーが発生した場合、CloudFormation はデプロイメントが開始される前の状態にロールバックします。デプロイメントの CloudFormation テンプレートのフックセクションにある TrafficRoutingConfig の “Type” プロパティでは、トラフィックが Green スタックにルーティングされる方法を定義することができ、この例では “AllAtOnce” というオプションが使用されています。Blue 環境は、“TerminationWaitTimeInMinutes” プロパティで指定された待機時間に達した後に削除されます。

スタックのアップデートが完了したら、スタックの出力タブにある Application Load Balancer DNS name をクリックするか、Step 4 でアクセスした Web ページを更新します。Web ページに “Hello World! (Green)” というメッセージ表示されれば、アプリケーションが Green のバージョンで正常に更新されています。

後片付け

このブログで作成したリソースを片付けるために、共有サービスアカウントと開発アカウントで作成したスタックを削除します。

まとめ

このブログでは、IAM ポリシーの Condition “aws:PrincipalOrgPaths” を使って、AWS Organizations OU と ECR リポジトリポリシーを組み合わせた例を紹介しました。開発アカウントのシンプルな ECS hello world アプリケーションの Blue/Green デプロイメントでは、共有サービス OU の アカウントから Docker イメージをプルしています。OU レベルでアクセスが設定されているため、同じ OU に属するすべての開発アカウントは、追加の設定手順をすることなく別のアカウントのコンテナイメージをプルすることができます。この機能を CI/CD パイプラインに組み込むことでアカウントをまたいだアクセスをよりシンプルに、管理しやすく、安全に行うことができます。

翻訳はソリューションアーキテクト加治が担当しました。原文はこちらです。