LoginSignup
3
3

More than 1 year has passed since last update.

AWS Batch + Fargate + EFSをCloudFormationで構築

Last updated at Posted at 2021-10-25

AWS BatchをFagateで構築したのですが、Fargateの
CloudFormationサンプルが少なかったので参考に投稿します。
ついでにAWS BatchからEFSのマウントも行ってみました。

Fargateを利用する場合、vCPUとMemoryは指定の組み合わせのものだけが利用可能で
vCPUは最大でも4までになります。
リソースに関する定義はEC2とFargateでは結構違うので要注意です。

AWS BatchのEFSマウントは少し苦労したのですが以下の記事を参考にしました。
記事のオペレーションをCFn化しています。
Introducing support for per-job Amazon EFS volumes in AWS Batch

EFSのテンプレート

セキュリティグループのIDですがRef参照の場合
デフォルトVPCに属するかどうかで動きが変わるところがあるので要注意です。
今回は以下のように取得しています。
!GetAtt LambdaSecurityGroup.GroupId

template_efs.yaml
AWSTemplateFormatVersion: '2010-09-09'  

Parameters:
  Env:
    Type: String
  Prifix:
    Type: String

Mappings: 
  EnvMap: 
    dev:
      # EFSを構築するVPCのID
      MyVpcId: "vpc-xxx"
    # EFSを構築するサブネット
      MySubnetID1: "subnet-xxxx"
      MySubnetID2: "subnet-xxxx"
      MySubnetID3: "subnet-xxxx"

Resources:
  LambdaSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !FindInMap [EnvMap, !Ref Env, MyVpcId]
      GroupDescription: Security group for Lambda

  MountTargetSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !FindInMap [EnvMap, !Ref Env, MyVpcId]
      GroupName: !Sub
        - "${prefix}mount-target-security-group"
        - { prefix: !Ref Prifix }
      GroupDescription: Security group for mount target
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: "2049"
          ToPort: "2049"
          CidrIp: 0.0.0.0/0

  # EFS FileSystem
  EfsFileSystem:
    Type: AWS::EFS::FileSystem
    Properties:
      FileSystemTags:
        - Key: "Name"
          Value: "EfsFileSystem For xxxx"
      PerformanceMode: maxIO
      BackupPolicy:
        Status: 'DISABLED'
      Encrypted: False

  EfsMountTarget1:
    Type: AWS::EFS::MountTarget
    Properties:
      FileSystemId: !Ref EfsFileSystem
      SubnetId: !FindInMap [EnvMap, !Ref Env, MySubnetID1]
      SecurityGroups:
      - !GetAtt MountTargetSecurityGroup.GroupId

  EfsMountTarget2:
    Type: AWS::EFS::MountTarget
    Properties:
      FileSystemId: !Ref EfsFileSystem
      SubnetId: !FindInMap [EnvMap, !Ref Env, MySubnetID2]
      SecurityGroups:
      - !GetAtt MountTargetSecurityGroup.GroupId

  EfsMountTarget3:
    Type: AWS::EFS::MountTarget
    Properties:
      FileSystemId: !Ref EfsFileSystem
      SubnetId: !FindInMap [EnvMap, !Ref Env, MySubnetID3]
      SecurityGroups:
      - !GetAtt MountTargetSecurityGroup.GroupId

  # AccessPoint
  EfsAccessPoint:
    Type: 'AWS::EFS::AccessPoint'
    Properties:
      FileSystemId: !Ref EfsFileSystem
      AccessPointTags:
        - Key: "Name"
          Value: "EfsAccessPoint For xxx"
      PosixUser:
        Uid: "1001"
        Gid: "1001"
      RootDirectory:
        CreationInfo:
          OwnerGid: "1001"
          OwnerUid: "1001"
          Permissions: "0777"
        Path: "/mnt/efs"      

Outputs:
  EfsFileSystemId:
    Value: !GetAtt EfsFileSystem.FileSystemId
  EfsAccessPointArn:
    Value: !GetAtt EfsAccessPoint.Arn
  EfsAccessPointId:
    Value: !Ref EfsAccessPoint
  MySubnetID1:
    Value: !FindInMap [EnvMap, !Ref Env, MySubnetID1]
  MySubnetID2:
    Value: !FindInMap [EnvMap, !Ref Env, MySubnetID2]
  MySubnetID3:
    Value: !FindInMap [EnvMap, !Ref Env, MySubnetID3]
  MyVpcId: 
    Value: !FindInMap [EnvMap, !Ref Env, MyVpcId]

  SecurityGroupIdForLambda:
    Value: !GetAtt LambdaSecurityGroup.GroupId

AWS Batchテンプレート

template_batch.yaml
AWSTemplateFormatVersion: '2010-09-09'  

# これらのパラメータはtemplate_efs.yamlで生成したものを親テンプレートから受け取る
Parameters:
  Env:
    Type: String
  Prifix:
    Type: String
  EfsSubnetID1:
    Type: String
  EfsSubnetID2:
    Type: String
  EfsSubnetID3:
    Type: String
  MyVpcId:
    Type: String
  EfsFileSystemId:
    Type: String
  EfsAccessPointId:
    Type: String

Mappings: 
  EnvMap: 
    dev:
      EcrRepoForBatch: "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/repo-name:latest"

Resources:
  SecurityGroupForBatch:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref MyVpcId
      GroupDescription: Security group for Batch Compute Env
      Tags:
      - Key: "Name"
        Value: !Sub
         - "${prefix}security-group-batch"
         - { prefix: !Ref Prifix }

  # コンピューティング環境
  MyComputeEnv:
    Type: "AWS::Batch::ComputeEnvironment"
    Properties:
      Type: MANAGED
      State: ENABLED
      ComputeEnvironmentName: !Sub
        - "${prefix}my-compute-env"
        - { prefix: !Ref Prifix }
      ComputeResources:
        # 最大vcpu数
        MaxvCpus: 256
        # 最小vcpu
        # This parameter isn't applicable to jobs that are running on Fargate resources,
        # and shouldn't be specified.
#        MinvCpus: 0
        SecurityGroupIds:
          - !GetAtt SecurityGroupForBatch.GroupId
        Type: FARGATE
        Subnets:
          - !Ref MySubnetID1
          - !Ref MySubnetID2
          - !Ref MySubnetID3

  # JOBキュー定義
  MyJobQueue:
    Type: AWS::Batch::JobQueue
    Properties:
      ComputeEnvironmentOrder:
        - Order: 1
          ComputeEnvironment: !Ref MyComputeEnv
      State: ENABLED
      Priority: 1
      JobQueueName: !Sub
        - "${prefix}my-job-queue"
        - { prefix: !Ref Prifix }

  MyJobRole:
    Type: AWS::IAM::Role
    Properties:
      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'
        - 'arn:aws:iam::aws:policy/AmazonElasticFileSystemFullAccess'

  # JOB定義
  MyJobDefinition:
    Type: AWS::Batch::JobDefinition
    Properties:
      Type: container
      PlatformCapabilities: 
        - FARGATE
      JobDefinitionName: !Sub
        - "${prefix}my-job-definition"
        - { prefix: !Ref Prifix }
      Timeout:
        AttemptDurationSeconds: 43200
      RetryStrategy:
        Attempts: 1
      ContainerProperties:
        # 自動IP割当(プライベート環境の場合はDISABLEDにする)
        NetworkConfiguration:
          AssignPublicIp: ENABLED
        FargatePlatformConfiguration:
          PlatformVersion: 1.4.0
        Image: !FindInMap ["EnvMap", !Ref Env, "EcrRepoForBatch"]
        JobRoleArn:  !GetAtt MyJobRole.Arn
        # リソース定義。VPCとMEMORYの組み合わせがあるのでドキュメント参照
        ResourceRequirements:
          - Type: VCPU
            Value: 4
          - Type: MEMORY
            Value: 8192
        Volumes:
          - EfsVolumeConfiguration:
              FileSystemId: !Ref EfsFileSystemId
              AuthorizationConfig:
                AccessPointId: !Ref EfsAccessPointId
                Iam: "ENABLED"
              # ホスト内のルートディレクトリとしてマウントする
              # Amazon EFS ファイルシステム内のディレクトリ
              # AccessPointを指定する場合、ルートは「/」にする必要がある。
              RootDirectory: "/"
              TransitEncryption: "ENABLED"
            Name: "efs-volume"
        MountPoints:
          - ContainerPath: "/mnt/efs"
            SourceVolume: "efs-volume"
        ExecutionRoleArn: !GetAtt MyJobRole.Arn
        Command:
          - 'job.sh'

Dockerfile

AWS Batchのイメージ作成用Dockerfileサンプル。
Amazon Linux2をベースにpython3.8とAWSCLIv2をインストールしています。

FROM public.ecr.aws/amazonlinux/amazonlinux:latest

RUN yum install -y amazon-linux-extras
RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

# AWS CLIv2インストール
COPY awscliv2.zip /tmp
RUN unzip /tmp/awscliv2.zip -d /tmp/awscli
RUN /tmp/awscli/aws/install --bin-dir /usr/bin --install-dir /usr/bin/aws-cli

#Python3.8インストール
RUN amazon-linux-extras install python3.8 -y
RUN yum install -y python38-devel
RUN pip3.8 install --upgrade pip
RUN pip install setuptools --upgrade
RUN pip install boto3

以上

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3