AWS Batch に EFS をマウントした実行環境をマネジメントコンソールから構築する

2022.03.14

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS Batch で EC2 スポットインスタンスを使い、コンテナには EFS をマウントし、環境を構築するのはマネジメントコンソールから作成して AWS Batch を実行するのに必要なコンポーネントを確認したい。そんなときにちょうど良い資料が見つからなくて困ったので自分で作りました。マネジメントコンソールから作成しても30分もあればジョブ実行テストできる状態になるかと思います。

本ブログを見てできるもの

AWS Batch + EFS の実行環境をマネジメントコンソールから構築します。

  • AWS Batch (EC2 Spot)・単一ノードで動作する実行環境
    • 単一ノードは標準ジョブや、配列ジョブに対応、マルチノードの並列実行環境ではない方です
  • AWS Batch に EFS マウント方法
  • テストジョブでコンテナに EFS がマウントされているか確認できる

前提

  • AWS Batch を起動する VPC があること
  • AWS Batch にマウントする EFS があること
    • EFS One Zone も可
    • ただし AWS Batch を起動する AZ には注意!

事前準備

AWS Batch をマネジメントコンソールから構築する前に作成しておくと都合の良いリソースが3つあります。AWS Batch で使う IAMロール2つと、セキュリティグループ1つです。

IAMロールの設定はやや紛らわしいため、マネジメントコンソールからの作成を諦め CloudFormation テンプレートを用意しました。

AWS Batch では実行ロールと、ジョブロールと呼ばれている IAMロールがあり、ジョブロールの方に EFS へアクセスできる権限(IAMポリシー)を付与する必要があります。ここが紛らわしくて設定を誤りそうです。

事前準備する最低限必要なリソースは以下のテンプレートから作成できます。

batch.yaml

AWSTemplateFormatVersion: "2010-09-09"
Description: Batch

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Common Settings
        Parameters:
          - ProjectName
          - Environment

Parameters:
  ProjectName:
    Description: Project Name
    Type: String
    Default: unnamed
  Environment:
    Description: Environment
    Type: String
    Default: dev
    AllowedValues:
      - prod
      - dev
      - stg
  VPCID:
    Type: AWS::EC2::VPC::Id

Resources:
  # --------------------------------------------
  # IAM Role for AWS Batch
  # --------------------------------------------
  # AWS Batch Execution Role (ECS Task Execution Role)
  ECSTaskExecutionRole1:
    Type: "AWS::IAM::Role"
    Properties:
      RoleName: !Sub ${ProjectName}-${Environment}-BatchExecutionRole
      Path: "/"
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
  # AWS Batch Job Role (ECS Task Role)
  ECSTaskRole1:
    Type: "AWS::IAM::Role"
    Properties:
      Path: "/"
      RoleName: !Sub ${ProjectName}-${Environment}-BatchJobRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonElasticFileSystemFullAccess

  # --------------------------------------------
  # Security Group
  # --------------------------------------------
  SecurityGroup1:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub ${ProjectName}-${Environment}-batch-sg
      GroupDescription: AWS Batch Security Group
      SecurityGroupEgress:
        - CidrIp: "0.0.0.0/0"
          IpProtocol: "-1"
      VpcId: !Ref VPCID
      Tags:
        - Key: Name
          Value: !Sub ${ProjectName}-${Environment}-batch-sg

CloudFormation から上記テンプレートのファイルをアップロードします。

AWS Batch を起動する予定の VPC を選択してください。

基本次へ、次へでよいのですが、IAMロールを作成するため承認を求められます。チェックを入れてからスタックの作成を実行してください。

リソースタブを確認すると作成されたリソースを確認できます。

AWS Batch

ここからが本題の AWS Batch の設定作業です。ここからはマネジメントコンソールのみで作成していきます。

左ペインに以下の順番で並んだ項目があります。リソースを作成する順番は逆順に作っていくと AWS Batch の実行環境が整います。早速マネジメントコンソールからリソースを作ってみましょう。

  1. ジョブ
  2. ジョブ定義
  3. ジョブキュー
  4. コンピューティング環境

コンピューティング環境

コンピューティング環境を作成します。起動タイプは EC2 タイプなのか、Fargate タイプなのか、最大使えるCPU数は何コアにするか、どこの VPC で AWS Batch を起動するなどのコンピューティングリソースのインフラ寄りの設定をします。

マネージド型を選択します。マネージド型と聞くと AWS Batch の Fargateタイプのことかと思いますが EC2タイプも選択できます。アンマネージド型は本当に一からリソース管理することになります。

EC2の スポット を使います。

EC2のスポットインスタンスで起動するインスタンスタイプを指定します。今回はc5d系のインスタンスタイプを選択してみました。選択したインスタンスタイプの中からジョブ実行時に指定する CPU数、メモリサイズに合わせてよしなにインスタンスタイプを選択・起動してくれます。

残念ながら最新のインスタンスタイプにはまだ対応していませんので現時点だとc6i系のインスタンスタイプは選択できません。

配分戦略はSPOT_CAPACITY_OPTIMIZEDにしましたが、コストを最適化したい場合はBest Fitを選択してください。

AWS Batch を起動する VPC, サブネットを選択します。EFS One Zone(シングルAZのタイプ)を利用している場合は、EFS One Zoneと同じAZのサブネットのみを選択してください。セキュリティグループは CloudFormation から作成したセキュリティグループを選択してください。

Amazon EFS file systems using One Zone storage classes have a single mount target located in the same availability zone as the file system. To use the EFS mount helper, the AWS compute instance and the EFS file system must be located in the same availability zone.

引用: Using EFS mount helper to mount EFS file systems - Amazon Elastic File System

コンピューティング環境の作成します。

数分でCREATINGの表示がVALIDになり、コンピューティング環境の作成は完了です。

ジョブキュー

ジョブキューから作成します。ジョブキューにさきほど作成したコンピューティング環境を紐付けてジョブのキューイングリソースとして使われます。

ジョブキュー名を決めます。ジョブを登録する際に毎回ここの名前を選択します。なので、わかりやすり名前をつけると良いです。

ジョブキューにジョブを入れたら使うコンピューティング環境を選択しました。さきほど作成したコンピューティング環境を選択して紐付けます。ちなみに複数紐付けすることも可能です。

数分でCREATINGの表示がVALIDになり、コンピューティング環境の作成は完了です。

ジョブ定義

ジョブ定義を作成します。コンテナイメージや、コンテナにマウントする EFS の設定など基本的なジョブ設定をします。ジョブを登録する際に上書きできる項目も多いのであくまでもジョブの基本設定です。

単一ノードを選択します。実行タイムアウトは最小値の60秒としています。実際に利用するときは実行するジョブに応じて適切な秒数を指定してください。長時間計算処理することが見込まれているジョブに対して60秒設定ですと、開始1分で処理が打ち切られる動きをします。

EC2 タイプでコンピューティング環境を作成していますので EC2 を選択します。実行ロールは CloudFormationで作成した IAMロールのExcecutionが含まれている方を選択します。

コンテナイメージはAmazon Linux2のイメージを選択しています。実際は ECR にプッシュした自前のイメージや、Docker Hub などパブリックなリポジトリにある使いたいイメージを指定します。今回は EFS がマウントできるか確認したいので Amazon Linux 2コンテナを起動して df -hを実行させます。

ジョブで使うコンピューティングリソースを指定します。

ジョブロール設定を有効にします。ロール

マウントポインタの設定と、ボリューム設定を有効化します。EFSを有効化をクリックすると、EFS のファイルシステム ID を入力できるようになります。名前は適当につけてよいのですがマウントポイントの設定で使う名前と合わせる必要があります。ここではefs-1と名付けた EFS をコンテナの/mnt/efsに EFS をマウントする設定内容です。

EFS のファイルシステム ID の指定する値はマウントしたい EFS のここで表示されている ID の部分です。

ジョブ定義が完成しました。

以上でジョブを実行できる環境の準備が整いました。

補足

EFS のセキュリティグループのインバウンドに AWS Batch からのアクセスを許可しましょう。まず、EFS のセキュリティグループを確認しましす。

インバウンドルールにNFS(TCP 2049)を選択し、ソースは CloudFormation で作成した AWS Batch のセキュリティグループを選択します。

ジョブ

新しいジョブを送信からジョブをジョブキューに登録します。

ジョブ定義、ジョブキューはさきほど作成したものを選択します。

コマンドは上書きが可能です。EFS がコンテナにマウントできるか動作確認をしたいのでこのまま実行してみます。

送信!EC2タイプの AWS Batch は文字通り EC2 が起動してきてその上でコンテナが実行されます。なので、ジョブが開始するまで時間がかります。

5分程度放置してからジョブを確認してみましょう。

ジョブは成功していました。

一番下までスクロールするとジョブのログを確認できます。df -hの実行結果が表示されています。EFS が /mnt/efsにマウントされていることが確認できました。

ジョブが失敗したり、/mnt/efsが確認できないときは、このあたりが疑わしいです。

  • IAMロール(ジョブロール)の設定の見直し
    • 実行ロールと、ジョブロールが逆さまになっている
  • EFS のセキュリティグループのインバウンドで AWS Batch を許可
  • AWS Batch のコンテナが起動するサブネットがインターネットと通信できない
    • NAT Gateway へのルートや、ECR からコンテナを pull するなら ECR 用の VPC エンドポイントが必要

補足

今回は1vCPU, 2048 Memory指定でしたのでc5d.largeが起動していました。AWS Batch は ECS をラップしたサービスのため、ECS の画面からも確認できます。EC2 タイプで起動している場合はEC2 のダッシュボードからも使われたリソースを確認できます。

ジョブのコマンド入力は1行で済む簡単なコマンドしか入力できなく、実際に利用するときはS3や、EFS上に保存しておいたスクリプトを実行させたり、自前のコンテナイメージ内にスクリプトを仕込んでおいて実行させる使い方をします。

おわりに

AWS Batch + EFS の構成を学びたいというときに EFS をマウントするにあたり、IAMロールの設定が ECS に馴染みがないと必要なリソースがなにかわかりづらいなと思いチュートリアル的なブログを作成しました。EFS のマウント方法は雰囲気掴めるかと思いますので、自前のコンテナを実行したり、ジョブのコマンドからスクリプトを実行することで本格的な AWS Batch の利用が可能です。

参考