AWS Protonを使用した本番運用を考える

こんにちは、上野です。

2020年のAWS re:Inventで発表されたAWS Proton、以下のハンズオンを参考に色々触ってみました。(作者の山口さんありがとうございます!)

AWS Proton で ECS Fargate のアプリケーション実行環境を作ってみようハンズオン

これは実際の本番運用で使用できるのでは?という良いポイントがけっこうあったので、まとめてみます。

AWS Protonとは

AWSでは「コンテナおよびサーバーレスアプリケーションのための初のフルマネージドデリバリーサービス」と紹介されています。

私の感想としては、プラットフォーム管理者とアプリケーション開発者の境界線を明確にし、各担当者が管理する範囲をテンプレートおよび世代管理できるサービスです。この管理をAWSマネージドでできるため、負荷を下げながら整理されたデリバリー構成を維持できるようになります。

説明だけでは少しわかりにくので、AWSで用意されているサンプルを元に、実際の構成をみていきましょう。

AWS Protonの構成

AWS Proton(以下Proton)にはECS Fargate、Lambda・DynamoDBのサンプルテンプレートが用意されています。今回はECSサンプルを参考に構成を見ていきます。

テンプレートファイルは以下GitHub上にあります。

github.com

Protonの画面からサンプルを選択してデプロイすることも可能です。

f:id:fu3ak1:20211010234339p:plain

Protonの公式ドキュメントには、以下のように担当者と管理するテンプレートの概要が記載されています。

f:id:fu3ak1:20211010234435p:plain

登場人物としてはプラットフォーム管理者(左側)と、開発者(右側)の2種類です。

テンプレートは、環境(Environment)とサービスの2種類を管理していくことになります。

サンプルの環境テンプレートは以下のとおり、VPC、パブリックサブネット×2、ECSクラスター×1となっています。また、図では省略しますが、タスク実行ロールやセキュリティグループも含まれます。

※ECSクラスター(Fargate用)はVPCに紐づくわけではないですが、便宜上VPC内に書いています。

f:id:fu3ak1:20211011231648p:plain

これをProtonではCloudFormationテンプレートで管理するため、以下の構成になります。

f:id:fu3ak1:20211011235358p:plain

環境上で稼働するサービステンプレートの範囲は以下のとおりです。ECSサービス、タスク定義、ALB、パイプライン等のリソースが含まれます。

テンプレートのファイルとしては、ECSサービスやタスク定義のサービス部分(インスタンス)と、パイプライン部分は分けて管理されます。

f:id:fu3ak1:20211011234743p:plain

環境と同じくProton上のテンプレートで管理するため次のようになります。

f:id:fu3ak1:20211011235338p:plain

Proton経由で作成されるリソース(環境、サービス)をまとめると次のようになります。

f:id:fu3ak1:20211011235642p:plain

Protonも含めると次のとおりです。

f:id:fu3ak1:20211012001028p:plain

テンプレートを登録すればProton側の準備は完了です。

サービステンプレート作成時に指定したリポジトリに、Dockerfileおよびアプリケーションファイルを登録するだけで、パイプラインが実行され、ECS環境にコンテナ(新しいECSタスク)がデプロイされます。

f:id:fu3ak1:20211012214349p:plain

サクッとリリースを試してみたい方は、サンプルアプリケーションがGitHubに用意されています。

github.com

テンプレート管理をするAWSアカウントとは別のAWSアカウントに環境(VPCやECS)をデプロイすることも可能です。(パイプラインはマネジメント側にあります)

f:id:fu3ak1:20211012220931p:plain

Protonを利用してどう運用していくのか

AWS上でアプリケーションが稼働するようになりました。この構成で、プラットフォーム管理者(インフラ管理者)と開発者はどのような役割で、どのリソースを管理していけば良いでしょうか。

案1. サンプル構成のとおり、ECSタスク定義までサービステンプレートで管理

紹介したサンプル構成どおりに管理するとどうなるのか見ていきます。開発者ができるだけAWSリソース(CloudFormationなど)を触らない例となります。

更新対象としては、環境、サービス(インスタンス、パイプライン)、アプリケーション(Dockerfile含む)の3種類となります。

Protonで管理する環境とサービスのテンプレートの更新方法は、次の2種類があります。

  • テンプレートファイル全体を更新する(テンプレートの新バージョン登録→バージョンアップ)
  • パラメータのみ更新する(VPCのCIDRや、ECSタスク稼働数など)

それぞれ以下のとおり役割を割り振ります。

更新対象 更新方法 管理場所 担当者
環境 テンプレートファイル更新 Proton プラットフォーム管理者
環境 パラメータ更新 Proton プラットフォーム管理者
サービス テンプレートファイル更新 Proton プラットフォーム管理者
サービス パラメータ更新 Proton 開発者
アプリケーション Git登録、パイプライン Gitリポジトリ 開発者

サービステンプレートの更新も開発者が管理するという案もありますが、今回は開発者があまりAWS環境部分を触らない前提で、プラットフォーム管理者がサービステンプレートを管理する案にしてみました。
公式ドキュメントは、プラットフォーム管理者or開発者となっています)

担当者ごとの管理リソースは次のようになります。

担当者 管理リソース
プラットフォーム管理者 VPC, IGW, サブネット, ECSクラスター,
ECSサービス, ECSタスク定義, ALB, ECR, CI/CDパイプライン, buildspec(パイプライン実行内容)
開発者 Dockerfile, アプリケーション, ECSの一部設定情報(※1)、
パイプラインの一部設定情報(※2)

※1 ポート、タスク数、タスクサイズ、コンテナイメージのURL
※2 Dockerfileのファイル名と場所、unit testコマンド、デプロイ先AWSアカウント

一部設定情報というのは、次のようにProtonの画面からパラメータ値のみ変更して更新できる内容を指しています。

f:id:fu3ak1:20211012215511p:plain

このレベルであれば、CloudFormation等のAWS知識が少ない場合でも、容易に変更できるかと思います。また、ここで変更できる値はテンプレートのSchemaファイル次第なので、開発者で変更可能とする値を、プラットフォーム管理者が調整できます。

全体像は以下のとおりです。

f:id:fu3ak1:20211012221654p:plain

この構成で、プラットフォーム管理者、開発者の役割を分けてリリース管理ができるかと思います。開発者はDockerfile、アプリケーション、Proton画面上から入力するパラメータ値だけ気にすれば良いので、AWSの知識は少なくとも運用可能です。

ただ、2種類の担当者はいずれもProton経由で、ECSサービス、ECSタスクを更新しに行くので、そこに少し不安があります。たとえばプラットフォーム管理者によるECSサービス設定変更で、ECSタスクが動かなくなるなど、お互いの動きを気にする必要が出てきます。

案2. ECSタスク定義とECSサービスは別出し

上野の1案です。使用するツールは基本的にさっきと同じですが、管理する場所と担当を変えます。

さきほどの全体像からProtonの管理対象を変えてみます。変更部分は緑枠部分です。

f:id:fu3ak1:20211012223100p:plain

ECSサービスおよびECSタスク定義を開発者のリポジトリ管理にしています。Protonの場合と同様にCloudFormationを使用してECSの定義も可能ですが、私もよく使用するecspressoなどのデプロイツールも使用可能になります。

また、細かいですがbuildspecも開発者のリポジトリに移します。(Protonサンプルではサービステンプレートに書かれていました)

役割と担当は以下のとおりになります。太字が変更部分です。

更新対象 更新方法 管理場所 担当者
環境 テンプレートファイル更新 Proton プラットフォーム管理者
環境 パラメータ更新 Proton プラットフォーム管理者
サービス テンプレートファイル更新 Proton プラットフォーム管理者
サービス パラメータ更新 Proton プラットフォーム管理者
アプリケーション、
ECSサービス・タスク定義
Git登録、パイプライン Gitリポジトリ 開発者

担当者ごとの管理リソースは次のとおりです。

担当者 管理リソース
プラットフォーム管理者 VPC, IGW, サブネット, ECSクラスター, ALB, ECR, CI/CDパイプライン
開発者 Dockerfile, アプリケーション, ECSサービス, ECSタスク定義, buildspec

個人的にはこの構成のほうが(Protonサンプルの構成よりも)スッキリです。なぜ開発者にECSタスクとサービスの管理を任せるとスッキリなのかというところですが、「同じライフサイクルであれば同じ担当者が管理したほうが良い」と私は考えているからです。

ECS上でアプリケーションが稼働しており、そこに新機能をリリースする場合、ざっくり以下のような流れになります。

コンテナイメージビルド

ECRにイメージ登録

ECSタスク定義に新リビジョン登録

ECSサービスを新リビジョンのタスクで更新

つまり、開発者がアプリリリース=ECSのサービスとタスクも更新するということになるので、これをまるっと開発者で管理したほうが開発もスムーズにできるという考えです。(ECRはリポジトリを最初に用意できればOK)

ここの考え方は構成や組織の状況によって色々考え方はあると思いますが、私の一案を書いてみました。

いったんまとめ

Protonの構成をECS Fargateサンプルを元に紹介しつつ、担当と役割を決めた運用例を2案書いてみました。

Protonが良いなと思うのは以下の点です。

  • 開発者とプラットフォーム管理者の役割を議論するきっかけになり、設計として担当と役割を強く意識することができる
  • テンプレートのバージョン管理ができ、どの環境でどのテンプレートが稼働しているか一元管理できる

2021年6月にGAされたばかりですが、本番運用でも充分使えるサービスだと思うので、積極的に導入していきたいです。今後の機能拡充にも期待ですね。

今回の記事では具体的な手順は紹介しませんでしたが、最初に紹介したワークショップや、APN Ambassador新井さんの記事などが参考になると思います。

以下、Protonのテンプレートの書き方も気になるぜ!って方は是非どうぞ。

(参考)テンプレートファイルの構成

Protonを使用するにあたっては、テンプレートファイルの書き方も重要になるので参考としてまとめておきます。

テンプレートは現時点でCloudFormationのみ対応しているのですが、素のCloudFormationとはちょっと違います。テンプレートは以下3ファイルで構成されます。

  • ①Infrastructure as code ファイル
    • 元となるCloudFormationテンプレートファイル(yaml)
  • ②Schema ファイル
    • CloudFormationにパラメータとして渡す値を記載するファイル
    • たとえばVPCのCIDRなどを入力できる
    • ここでパラメータとして設定した項目は、Protonの画面上から入力して更新できる
  • ③Manifest ファイル
    • IaCファイル名やrendering_engine(現在Jinjaのみ)とテンプレート言語(現在CloudFormationのみ)を指定する

環境テンプレートのファイル構成は以下のようになります。

 /schema
   schema.yaml
 /infrastructure
   manifest.yaml
   cloudformation.yaml

実際のファイルの中身も少し見ていきましょう。

①IaCファイルは通常のCloudFormationとほぼ同様なのですが、次のようにJinjaというテンプレートエンジンを使用して、パラメータの値を動的に挿入することができます。

ECRリポジトリのポリシーについて、環境アカウント(別のAWSAWSアカウント)がパラメータとして指定されていた場合に許可するといった制御を、ifとforを使用して設定しています。

# ※サンプルテンプレートより一部抜粋※
  ECRRepo:
    Type: AWS::ECR::Repository
    DeletionPolicy: Retain
    {% if pipeline.inputs.environment_account_ids %}
    Properties:
      # This policy allows environment accounts to get the image from ECRRepo in the management account
      RepositoryPolicyText:
        Version: "2012-10-17"
        Statement:
          - Sid: AllowPull
            Effect: Allow
            Principal:
              AWS:
                {% set environment_account_ids = pipeline.inputs.environment_account_ids.split(',') %}
                {% for environment_account_id in environment_account_ids %}
                - "arn:aws:iam::{{environment_account_id}}:root"
                {% endfor %}
            Action:
              - ecr:GetAuthorizationToken
              - ecr:BatchCheckLayerAvailability
              - ecr:GetDownloadUrlForLayer
              - ecr:BatchGetImage
    {% endif %}

CloudFormationをそのまま利用するよりも柔軟な設定ができますね!

②Schemaファイルで指定できるパラメータはCloudFormationのParametersに似ています。
以下はVPC CIDR部分の抜粋です。

# ※サンプルテンプレートより一部抜粋※
      properties:
        vpc_cidr:
          type: string
          description: "This CIDR range for your VPC"
          default: 10.0.0.0/16
          pattern: ([0-9]{1,3}\.){3}[0-9]{1,3}($|/(16|24))

③Manifestファイルは非常にシンプルで、現状では環境テンプレートもサービステンプレートも同じ形になります。

infrastructure:
  templates:
    - file: "cloudformation.yaml"
      rendering_engine: jinja
      template_language: cloudformation

これら3種類のファイルを環境、サービス(インスタンス、パイプライン)ごとに作成することになります。

作成したテンプレートは、tarで圧縮してS3バケットにアップロードし、Proton側からバケット名を指定して登録、更新することになります。(現時点では直接Protonに登録はできないようです)

簡単ですがテンプレートファイルの構成紹介でした。

それでは!

f:id:fu3ak1:20210325095452j:plain

執筆者上野史瑛

Japan APN Ambassador 2020
AWSを中心としたクラウドの導入、最適化を専門に行っています。