2019.01.26

【AWS】AWS Batchを最小構成で構築するCloudformationテンプレート

概要

AWS Batchを最小構成で構築するCloudformationテンプレートを作成しました。
構築したAWSスタックとCloudformationテンプレートについて解説します。
テンプレートやデモ用のDockerリポジトリは、GithubやDockerHubで公開していますので、AWS Batchを構築する際のベーステンプレートとしてお使い頂けるかと思います。

もくじ

  • 構築したAWSスタック
  • 事前準備
  • Cloudformationテンプレート
  • Cloudformationスタック作成
  • 作成されたスタックの確認
  • ジョブの動作確認
  • まとめ

AWSリソース構成

AWS構成図

2019 01 26 1

構成の概要

AWS Batchは、以下のAWSリソースで構成されています。

  • コンピューティング環境(Compute Environment)
  • ジョブキュー(Job Queue)
  • ジョブ定義(Job Definition)

それぞれ簡単に解説していきます。

コンピューティング環境

ジョブ実行環境としてのECS

ジョブを動かす実行環境を定義します。

そもそもジョブとは、コンテナとして起動し実行されるものですが、このコンテナを起動・実行するためのマシンが必要です。
この環境を用意するために、AWS Batchのコンピューティング環境では、ECS(Elastic Container Service)が使用されています。
この後説明する、CloudformationテンプレートでAWS Batch環境を構築すると、ECSクラスターも構築されていることがコンソールから確認できます。

ECSクラスタに必要なVPC環境

ECSクラスターが作成され、ジョブが開始された際にはクラスター内でコンテナインスタンスが立ち上がり、ジョブ処理が完了すると自動的にインスタンスも削除されます。
ECSクラスターでコンテナインスタンスを管理する際に、コンテナインスタンスを配置するサブネットや適用するセキュリティグループが必要です。

VPCの構成については後述します。
VPC用のサンプルCloudformationテンプレートを用意しましたので、後ほど紹介します。

ジョブキューから取り出して実行される

後述するジョブキュー内のジョブを取り出して、コンピューティング環境の設定に基づいてジョブ(コンテナ)を実行します。

ジョブキュー

コンピューティング環境で実行するジョブを登録するキューです。
登録されているジョブは紐づけられているコンピューティング環境で順次実行されていきます。

ジョブ定義

ジョブ定義を元にして、ジョブキューへジョブを登録できます。
ジョブ定義では、コンテナで使用するリソースやコマンド、環境変数など、コンテナへのパラメータを指定できます。

IAM Role

Cloudformationで構築する際には、必ずと言っていいほど登場し、意識する必要があるIAM Roleです。
上記構成図にも記載していますが、今回は以下のIAM Roleが登場します。

Batch Service Role

Compute Environmentが実行環境を構築する際に、AWS APIを呼び出すために必要なIAM Roleです。
AWS管理ポリシー「AWSBatchServiceRole」の権限が付与されていれば十分です。

Instance Role

ECSによって起動されるEC2インスタンス(コンテナインスタンス)に付与するIAM Roleです。
AWS管理ポリシー「AmazonEC2ContainerServiceforEC2Role」の権限を指定すれば十分で、追加で権限が必要となった場合でも Instance Roleではなく、後述のJob Roleに付与することがAWSで推奨されています。

Job Role

ECSコンテナインスタンス内に起動するジョブコンテナ(タスクコンテナ)へ付与する IAM Roleです。

VPC環境

AWS Batchは、ジョブを実行するコンテナインスタンスが起動するVPC環境を予め設定しておく必要があります。

今回は以下のリソースを構築しています。

- VPC
    - CIDRブロック: 10.0.0.0/16
- パブリックサブネット
    - AZ-A: 10.0.1.0/24
    - AZ-C: 10.0.2.0/24
- インターネットゲートウェイ
    - 上記パブリックサブネットとルートテーブルで紐付け
- セキュリティグループ
    - 全IP・全ポートを解放

これらのリソースがわからない場合でも問題ありません。

今回は上記のうち、インスタンスを配置するサブネットと適用するセキュリティグループを、コンピューティング環境に設定する必要があります。

事前準備

VPC環境のスタック作成

上記で説明したVPC環境のCloudformationテンプレートを用意しています。
https://github.com/YoshinoriSatoh/cloudformation-templates/blob/master/batch/vpc.yaml

Cloudformationスタックの作成手順については、以下の記事を参照して下さい。
https://yoshinori-satoh.com/starting_cloudformation/

Cloudformationテンプレート

AWS Batchを構成するテンプレートは、以下からダウンロードしてください。
https://github.com/YoshinoriSatoh/cloudformation-templates/blob/master/batch/vpc.yaml

こちらも、Cloudformationスタックの作成手順については、以下の記事を参照して下さい。
https://yoshinori-satoh.com/starting_cloudformation/

テンプレートを部分ごとに解説していきます。

コンピューティング環境関連

コンピューティング環境関連で、以下のリソースを定義しています。

  • コンピューティング環境
  • コンピューティング環境に付与するService Role
  • コンテナインスタンスに付与するInstance Roleと、それを内包するInstance Profile

template.yaml

ComputeEnvironment:
  Type: AWS::Batch::ComputeEnvironment
  Properties:
    Type: MANAGED
    ServiceRole: !Ref ServiceRole
    State: ENABLED
    ComputeResources:
      Subnets: !Ref SubnetIds
      SecurityGroupIds: !Ref SecurityGroupIds
      Type: EC2
      MinvCpus: 0
      MaxvCpus: 2
      InstanceRole: !Ref InstanceProfile
      InstanceTypes:
        - m5.large
      Tags: { "Name": "AWS Batch Instance" }

Type

起動するコンテナインスタンスをAWSにお任せするか、自分でAMIとして登録したものを使用するかを選択できます。
ここではMANAGEDにしています。
私の経験上、起動するコンテナイメージが巨大なものを使用する場合には、UNMANAGEDにしてブロックデバイス等を調整する必要がありました。
イメージが小さいや特殊な要件がなければ、MANAGEDで問題ないと思います。

ComputeResources

コンテナインスタンスの設定です。 配置するサブネットやセキュリティグループ、vcpu数、インスタンスタイプ、そしてInstanceRoleを設定します。

ServiceRole

コンピューティング環境に付与するServiceRoleです。
AWS::IAM:Roleのリソースとして別途定義し、!Refで参照しています。

template.yaml

ServiceRole:
  Type: AWS::IAM::Role
  Properties:
    AssumeRolePolicyDocument:
      Version: 2012-10-17
      Statement:
        - Effect: Allow
          Principal:
            Service: batch.amazonaws.com
          Action: sts:AssumeRole
    ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AWSBatchServiceRole

ロールの内容は、「"batch.amazonaws.com" というサービスドメインに対して、AWSBatchServiceRoleというAWS管理ポリシーを付与する」というものです。
これで、コンピューティング環境が他のAWSリソースに対してアクセスする権限を付与できます。
AWSのドキュメントは下記を参照ください。
(AWSBatchServiceRoleの詳細も記載されています。)
https://docs.aws.amazon.com/jajp/batch/latest/userguide/serviceIAM_role.html

Instance Role

コンテナインスタンスに付与するInstanceRoleです。

template.yaml

InstanceRole:
  Type: AWS::IAM::Role
  Properties:
    AssumeRolePolicyDocument:
      Version: 2012-10-17
      Statement:
        - Effect: Allow
          Principal:
            Service: ec2.amazonaws.com
          Action: sts:AssumeRole
    ManagedPolicyArns:
      - arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role

InstanceProfile:
  Type: AWS::IAM::InstanceProfile
  Properties:
    Roles:
      - !Ref InstanceRole

こちらの内容は、「"ec2.amazonaws.com" というサービスドメインに対して、AmazonEC2ContainerServiceforEC2RoleというAWS管理ポリシーを付与する」というものです。
Batchの背後で構築されているECS内でEC2が起動するのですが、その必要な権限をAmazonEC2ContainerServiceforEC2RoleというAWS管理ポリシーで設定しています。
これは、ECSコンテナインスタンスで使用されるポリシーなのですが、Batchでも同様に使用できます。
この辺りのドキュメントは以下を参照ください。
https://docs.aws.amazon.com/jajp/AmazonECS/latest/developerguide/instanceIAM_role.html?shortFooter=true

ジョブキュー関連

ジョブキュー関連では、以下のジョブキューリソースのみです。
ジョブキューとコンピューティング環境を紐づけています。

template.yaml

JobQueue:
  Type: AWS::Batch::JobQueue
  Properties:
    ComputeEnvironmentOrder:
      - ComputeEnvironment: !Ref ComputeEnvironment
        Order: 1
    Priority: 1

ジョブ定義関連

ジョブ定義関連で、以下のリソースを定義しています。

  • ジョブ定義
  • Job Role

テンプレートは以下です。

template.yaml

JobDefinition:
  Type: AWS::Batch::JobDefinition
  Properties:
    Type: container
    ContainerProperties:
      Image: !Ref Image
      Memory: 256
      Environment:
        - Name: ENVIRONMENT_VARIABLE
          Value: !Ref EnvironmentVariable
        - Name: ENVIRONMENT_VARIABLE_SECURE
          Value: !Ref EnvironmentVariableSecure
      Vcpus: 1
      JobRoleArn: !GetAtt JobRole.Arn

JobRole:
  Type: AWS::IAM::Role
  Properties:
    AssumeRolePolicyDocument:
      Version: 2012-10-17
      Statement:
        - Effect: Allow
          Principal:
            Service: ecs-tasks.amazonaws.com
          Action: sts:AssumeRole

ContainerProperties

ジョブの処理を実行するコンテナへの設定です。
コンテナイメージのリポジトリURLは、外部からパラメータとして入力されたものを使用します。
Memoryやvcpuの他、環境変数をEnvironmentで指定します。
環境変数は指定の仕方を説明するためのサンプルですが、これらも外部からパラメータとして入力します。

JobRole(Arn)

コンテナインスタンスには既に、InstanceRoleが付与されていますが、InstanceRoleでは付与されない、このジョブに特化した権限がある場合は、JobRoleとして指定した方がいいです。
(今回は、特にジョブに特化した権限はないので空にしています。)

Cloudformationスタック作成

VPC環境を作成完了したら、AWS BatchのCloudformationスタックを構築します。
https://github.com/YoshinoriSatoh/cloudformation-templates/blob/master/batch/minimum-template.yaml

こちらのテンプレートには以下のパラメータが指定できます。

EnvironmentVariable: ジョブに渡す環境変数のサンプル
EnvironmentVariableSecure: ジョブに渡す環境変数のサンプル
Image: ジョブで実行するコンテナイメージのリポジトリURL
SecurityGroupIds: VPCのセキュリティグループリスト
SubnetIds: VPCのサブネットIDリスト

EnvironmentVariable / EnvironmentVariableSecure

これらはサンプルで環境変数を渡せることを示しているだけなので、適当な値でいいです。
EnvironmentVariableSecureの方は、マネジメントコンソール上で値がマスクされて表示されます。
これは、Parametersで以下のようにNoEchoをtrueに設定しているためです。

template.yaml

EnvironmentVariableSecure:
    Type: String
    NoEcho: true
    Description: Environment variable secure

見せたくない値はNoEchoを使用するのが良い場合もあります。

ただし、これだけで完全に保護されるわけではないので、ご注意ください。
(本当にセキュアにしようと思ったら、Systems ManagerのParameter storeのSecure Stringを使用するなど、検討しましょう。)

Image

ジョブで実行するコンテナの元となるイメージのリポジトリURLです。
ここでは、単純なログ出力するだけのイメージを用意していますので、以下のURLを指定します。

yoshinorisatoh/sample-node-batch:latest

SecurityGroupIds

事前に作成したVPCのセキュリティグループを指定します。
ここでは、ParametersのTypeにAWS::EC2::SecurityGroup::Idのリストを指定しています。

template.yaml

SecurityGroupIds:
    Type: List<AWS::EC2::SecurityGroup::Id>
    Description: Security group id list for EC2 instance.

この指定で、コンソールには、アカウントに存在するセキュリティグループを選択できるドロップダウンが表示されます。
"batch-minimum-vpc〜"のものを選択します。

このように、予め定義されたTypeがあります。
詳細は、以下ドキュメントの「AWS固有のパラメータ型」を参照してみて下さい。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html

SubnetIds

SecurityGroupIdsと同様ドロップダウンから選択します。
CIDRブロックが10.0.1.0/24のものを選択します。
設定例は以下のようになります。
2019 01 26 2

作成されたスタックの確認

コンピューティング環境

マネジメントコンソールから、[AWS Batch]→[コンピューティング環境]と進みます。

以下のようにリソースが作成されているはずです。
2019 01 26 3

詳細を確認すると以下のように表示されます。
概要では、名前やリソース名(ARN)のほか、テンプレートで指定しているタイプやサービスロールが表示されています。
2019 01 26 4

ComputeResourcesで指定した設定も以下のように表示されています。
2019 01 26 5

ジョブキュー

ジョブキューの画面では、コンピューティング環境と関連付けされていることが確認できます。
2019 01 26 6

ジョブ定義

ジョブ定義では、指定したコンテナイメージのリポジトリURLや環境変数が確認できます。
2019 01 26 7 2019 01 26 17 2019 01 26 8

ジョブの動作確認

ジョブ画面で、「ジョブの実行」をクリックします
2019 01 26 9

ジョブの名称は適当に入力し、ジョブ定義、ジョブキューは今回作成したものをそれぞれ選択します。

選択後、画面下の「Submit Job」
2019 01 26 10

実行直後、ジョブが「submitted」状態になります。

設定に問題がなければ、その後すぐに 「runnable」状態になります。
2019 01 26 11

runnableは、コンテナを実行するEC2インスタンスの起動を待っている状態です。

このタイミングでEC2画面を確認すると、インスタンスが起動されることが確認できます。
2019 01 26 12

ジョブの実行が完了すると、「succeeded」となります。
2019 01 26 13

実行したコンテナでは、内部でログを出力しています。

このログ出力は、AWSの「Cloudwatch Logs」というサービスで確認できます。

Cloudwatchサービスの画面へいき、「ログ」をクリックします。
2019 01 26 14

"/aws/batch/job"をクリック
2019 01 26 15

最新のログストリームをクリック
2019 01 26 16

「Batch processing !!!!!!!」とログ表示されています。
2019 01 26 16

実行完了後、少し時間を置くと、EC2インスタンスはシャットダウンされます。

2019 01 26 18

このように、構築したAWS Batchの環境上で、以下の流れが確認できました。

  • ジョブを発行
  • 実行環境であるコンテナインスタンスが起動する
  • コンテナインスタンス上でジョブ定義されたコンテナが起動する
  • コンテナの処理が実行される
  • コンテナの実行完了後にコンテナインスタンスがシャットダウンする

まとめ

最小限のAWS Batchの構成の解説、Cloudformationテンプレートの解説、スタックの作成、そしてジョブの動作の流れを確認しながら解説しました。

処理の内容によって、IAM Roleに追加の権限が必要だったり、その他調整が必要だったりすると思いますが、ベースは同じような構成になると思います。

AWS Batchを構築する際は、本記事を参考にしてみてください。