本記事でやること
- AWS Batchのコンピューティング環境やジョブ定義などをCloudFormationを使って構築する
- AWS Batchにジョブを送り、S3のバケット名を取得するアプリケーションを実行する
上記を達成するために予め行うこと
- AWS ECRを使ってアプリケーションのDocker imageをpushする
以下に関しては、記載しないので他の記事を参照してください。
- AWS ECSを使用するにあたって必要なVPCやSubnet、セキュリティーグループの作成
- AWS BatchやECSにアクセスするためのIAMロールの作成
対象読者
- Dockerについて一通り基礎的な書籍を読んで、何か動くものを作りたい方
- AWS BatchやCloudFormationを使って何かしたい方
使用言語
python 3.6.3
AWS ECRを使ってアプリケーションのDocker imageをpushする
AWS ECSがコンテナを作成する際にpullするDocker imageを予めAWS ECRにpushする。
また、アプリケーションのファイルやディレクトリ構成は以下の通り。
.
├── infra
│ ├── Dockerfile
│ ├── .vault_password
│ ├── .aws
│ │ └── config
│ │ └── credentials
│ └── batch_config
│ └── cloudformation.yml
└── run.py
FROM hogehoge.ecr.ap-northeast-1.amazonaws.com/python:latest
# userの作成
RUN groupadd -g 10000 test && \
useradd -u 10000 -g test -s /bin/bash test && \
echo 'test:test' | chpasswd
ENV HOME /home/test
WORKDIR $HOME
RUN chown test:test -hR ./
USER test
ADD --chown=test:test infra/ $HOME
# 暗号化されているaws認証情報を復元する
RUN ansible-vault decrypt .aws/credentials --vault-password-file .vault_password
ADD --chown=test:test . test
USER root
WORKDIR /home/test/test
CMD ["python", "run.py"]
上記、Dockerfileのベースとなっているimageに関しては、こちらの記事で紹介しているので適宜参照してください。(ベースとなっているimageは、pythonイメージにansibleをインストールしたimageです)
Dockerfile内のCMD
箇所で実行しているアプリケーションのファイルの中身は以下のようになっています。(S3のバケット名を取得するスクリプトになっています)
from boto3.session import Session
def get_bucket_list():
resource = Session(profile_name="local").resource("s3")
for bucket in resource.buckets.all():
print(bucket.name)
if __name__ == '__main__':
get_bucket_list()
上記Dockerfileをinfra/
以下に置き、下記のコマンドでAWS ECRにプッシュする。
# ECRにログインする
$(aws ecr get-login --no-include-email --region ap-northeast-1 --profile hoge)
# イメージのビルド(イメージの名前は適当に"python"とする)
docker build -t test-app .
# 上でビルドしたイメージにタグをつける(hogehogeの部分には)
docker tag test-app:latest hogehoge.dkr.ecr.ap-northeast-1.amazonaws.com/test-app:latest
# イメージをAWS ECRにプッシュする
docker push hogehoge.dkr.ecr.ap-northeast-1.amazonaws.com/test-app:latest
AWS Batchの環境をAWS CloudFormationを使って構築する
以下のcloudformation.yml
ファイルを使ってAWS Batchの環境を構築する。set parameters
の箇所でのsubnet-idやEC2インスタンスのkeyペア、ECS / BatchのIAMロールのARNは各自用意をしコピペする。
AWSTemplateFormatVersion: 2010-09-09
Description: Build AWS Batch environment
# =======set parameters======== #
Parameters:
SubnetIds:
Description: Subnets For ComputeEnvironment
Type: List<AWS::EC2::Subnet::Id>
Default: subnet-id
SecurityGroupIds:
Description: SecurityGroups For ComputeEnvironment
Type: List<AWS::EC2::SecurityGroup::Id>
Default: sg-id
KeyPair:
Description: key pair
Type: String
Default: key
image:
Type: String
Description: image in container registory
Default: hogehoge.ecr.ap-northeast-1.amazonaws.com/awsbatch/test-app:latest
ecsInstanceRole:
Type: String
Description: Role For AWS EcsInstanceRole
Default: arn:aws:iam::hogehoge:instance-profile/ecsInstanceRole
AWSBatchServiceRole:
Type: String
Description: Role For AWS BatchRole
Default: arn:aws:iam::hogehoge:role/service-role/AWSBatchServiceRole
# =======Batch======== #
# create ComputeEnvironment
Resources:
MyComputeEnv:
Type: "AWS::Batch::ComputeEnvironment"
Properties:
Type: MANAGED
ServiceRole: !Ref AWSBatchServiceRole
ComputeEnvironmentName: "test-batch-compute-environment"
ComputeResources:
MaxvCpus: 256
MinvCpus: 0
DesiredvCpus: 0
SecurityGroupIds: !Ref SecurityGroupIds
Type: EC2
Subnets: !Ref SubnetIds
Ec2KeyPair: !Ref KeyPair
InstanceRole: !Ref ecsInstanceRole
InstanceTypes:
- optimal
Tags:
Name: "test-batch-computer"
State: ENABLED
# Create JobQueue
MyJobQueue:
Type: AWS::Batch::JobQueue
Properties:
ComputeEnvironmentOrder:
- Order: 1
ComputeEnvironment: !Ref MyComputeEnv
State: ENABLED
Priority: 1
JobQueueName: "s3_get_bucket_list"
# Create JobDefinition
MyJobDefinition:
Type: AWS::Batch::JobDefinition
Properties:
Type: container
JobDefinitionName: "test-batch-job"
ContainerProperties:
Memory: 16000
Vcpus: 1
Image: !Ref image
RetryStrategy:
Attempts: 1
aws cliを使って以下のコマンドでAWS Batchの環境を自動構築する。
aws cloudformation create-stack \
--stack-name aws-batch \
--template-body file://$PWD/infra/batch_config/cloudformation.yml \
--profile hoge
AWS Batchにジョブを送り、S3のバケット名を取得するアプリケーションを実行する
上記のコマンドでAWS Batchの環境が構築されたことを確認できたら、以下のコマンドでジョブを送信する。
JOB_DEFINITION_ARN=$( aws batch describe-job-definitions \
--job-definition-name "s3_get_bucket_list" \
--status ACTIVE \
--profile hoge \
| jq -r '.jobDefinitions | max_by(.revision).jobDefinitionArn' \
) && echo ${JOB_DEFINITION_ARN}
aws batch submit-job \
--job-name "test-job" \
--job-queue "s3_get_bucket_list" \
--job-definition ${JOB_DEFINITION_ARN} \
--profile hoge
ジョブのキューがSUCCEEDEDになったら、AWS CloudWatch LogsにS3のバケット名が出力されていることが確認できたら無事完了です。
また、無事完了できたら今回CloudFormationで作成した諸々の環境は、削除しておきましょう。
削除するためには以下のコマンド実行します。
aws cloudformation delete-stack --stack-name aws-batch --profile hoge
終わりに
前回の記事では、ローカル環境でDockerコンテナを作成・起動をしAWS S3のバケット名を取得しましたが、今回はAWS Batchを使ってECSでコンテナを作成・起動を行いました。
また今回はターミナルでコマンドを叩いてAWS Batchにジョブを送信しましたが、AWS lambdaを使ってジョブを送信することも可能です。またCloudwatch eventsでlambdaを定期的に起動することが出来ればBatchも定期実行することができます。次回は、AWS lambdaでBatchにジョブを送るlambda functionに関する記事を作成出来ればと思います。