概要
AWS Batch の理解のために以下のハンズオンを実施してみた。
なお、一部手順は手動から CLI または CloudFormation で実行するようにアレンジしています。
事前準備
CloudFormation のデプロイ
必要な AWS リソースを CloudFormation でデプロイしておきます。
wget https://static.us-east-1.prod.workshops.aws/public/66da963d-7962-425a-bf2b-082e9436fb97/static/handson.yaml
aws cloudformation create-stack --stack-name batch-handson --template-body file://./handson.yaml --capabilities CAPABILITY_NAMED_IAM
論理ID | タイプ |
---|---|
MyComputeEnv | AWS::Batch::ComputeEnvironment |
MyJobDefinition | AWS::Batch::JobDefinition |
MyJobQueue | AWS::Batch::JobQueue |
IGW | AWS::EC2::InternetGateway |
PublicSubnetRoute | AWS::EC2::Route |
PublicSubnetRT | AWS::EC2::RouteTable |
PublicSubnet1 | AWS::EC2::Subnet |
PublicSubnet2 | AWS::EC2::Subnet |
PublicSubnetRTAssociation1 | AWS::EC2::SubnetRouteTableAssociation |
PublicSubnetRTAssociation2 | AWS::EC2::SubnetRouteTableAssociation |
VPC | AWS::EC2::VPC |
VPCIGWAttachement | AWS::EC2::VPCGatewayAttachment |
AWSBatchServiceRole | AWS::IAM::Role |
CodeBuildRole | AWS::IAM::Role |
ecsTaskExecutionRole | AWS::IAM::Role |
手動デプロイ
ECR リポジトリの作成
ECR リポジトリを作成します。
aws ecr create-repository --repository-name queens
アプリケーションの準備と動作確認
コンパイルし、動作確認を行います。
curl -O https://www.arch.cs.titech.ac.jp/~kise/nq/package/qn24b-version1.0.tgz
tar -zxvf qn24b-version1.0.tgz
gcc -O2 version1.0/base/queens.c -o queens
./queens 16
qn24b base version 1.0.1 2004-09-02
=============================================
qn24b base version 1.0.1 2004-09-02
problem size n : 16
total solutions : 14772512
correct solutions : 14772512
million solutions/sec : 4.962
elapsed time (sec) : 2.977
=============================================
アプリケーションのコンテナ化
Dockerfile を作成し、ビルド後動作確認をします。
FROM public.ecr.aws/amazonlinux/amazonlinux:latest
COPY ./queens /usr/local/bin/queens
# program execute
CMD /usr/local/bin/queens 16
docker build -t queens .
docker run queens
qn24b base version 1.0.1 2004-09-02
=============================================
qn24b base version 1.0.1 2004-09-02
problem size n : 16
total solutions : 14772512
correct solutions : 14772512
million solutions/sec : 2.694
elapsed time (sec) : 5.483
=============================================
ECR へ push
ECR へ コンテナイメージ を push します
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com
docker tag queens:latest 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/queens:latest
docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/queens:latest
ジョブ定義の更新
AWS Batch > ジョブ定義 > handson-def を開き、「アクション」から「リビジョンの作成」を開きます。
「ステップ 2」の「コンテナ設定」で「イメージ」を自身のイメージの URI に書き換えます。
ジョブの実行と確認
AWS Batch > ジョブ > 新しいジョブを送信 を開き、「名前」、「ジョブ定義」、「ジョブキュー」を次の図の通り指定します。
ジョブが実行され、「Succeeded」になったことが確認できました。また、「ログ記録」を確認するとローカルで実行した内容と同じ結果が得られました。
自動デプロイ
CodeCommit リポジトリの作成と clone
CodeCommit リポジトリを作成しておきます。
aws codecommit create-repository --repository-name handson-repo
作成した CodeCommit リポジトリを clone し、handson-repo リポジトリに移動しておきます。
git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/handson-repo
cd handson-repo
buildspec.yaml の作成
この buildspec.yaml は手動デプロイで行った作業を自動デプロイに落とし込んでいるだけのようなので、ここでの詳しい説明は省きます。
version: 0.2
phases:
pre_build:
commands:
- AWS_ACCOUNT_ID=$(echo ${CODEBUILD_BUILD_ARN} | cut -f 5 -d :)
- aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com
- REPOSITORY_URI=$AWS_ACCOUNT_ID.dkr.ecr.ap-northeast-1.amazonaws.com/queens
- IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
build:
commands:
- docker build -t $REPOSITORY_URI:latest .
- docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
post_build:
commands:
- docker push $REPOSITORY_URI:latest
- docker push $REPOSITORY_URI:$IMAGE_TAG
- cat job-definition-template.json | jq --arg IMAGE_URI $REPOSITORY_URI:$IMAGE_TAG '.image|=$IMAGE_URI' > job-definition.json
- aws batch register-job-definition --job-definition-name handson-def --type container --platform-capabilities FARGATE --container-properties file://job-definition.json
ジョブ定義の作成
ジョブ定義で指定するコンテナのプロパティを作成します。
{
"image": "TBD",
"command": [],
"executionRoleArn": "arn:aws:iam::123456789012:role/service-role/ecsTaskExecutionRole-handson",
"volumes": [],
"environment": [],
"mountPoints": [],
"ulimits": [],
"resourceRequirements": [
{
"value": "0.25",
"type": "VCPU"
},
{
"value": "512",
"type": "MEMORY"
}
],
"secrets": [],
"networkConfiguration": {
"assignPublicIp": "ENABLED"
},
"fargatePlatformConfiguration": {
"platformVersion": "LATEST"
},
"runtimePlatform": {
"operatingSystemFamily": "LINUX",
"cpuArchitecture": "X86_64"
}
}
リポジトリへ push
手動デプロイで作成した Dockerfile と queens を handson-repo ディレクトリ配下にコピーします。
cp ../Dockerfile .
cp ../queens .
リポジトリへ push するファイルは以下の通りとなります。
.
├── Dockerfile
├── buildspec.yaml
├── job-definition-template.json
└── queens
CodeCommit へ push します。
git add .
git commit -m "my first commit"
git push
CodePipeline の作成
CloudFormation で CodePipeline をデプロイします。
AWSTemplateFormatVersion: "2010-09-09"
Resources:
S3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: !Sub "codepipeline-${AWS::Region}-20240403"
IAMRole:
Type: "AWS::IAM::Role"
Properties:
Path: "/service-role/"
RoleName: !Sub "AWSCodePipelineServiceRole-${AWS::Region}-${CodeBuildProject}"
AssumeRolePolicyDocument: {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "codepipeline.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
MaxSessionDuration: 3600
ManagedPolicyArns:
- !Sub "arn:aws:iam::${AWS::AccountId}:policy/service-role/AWSCodePipelineServiceRole-${AWS::Region}-${CodeBuildProject}"
CodeBuildProject:
Type: "AWS::CodeBuild::Project"
Properties:
Name: "handson-pipeline"
Source:
GitCloneDepth: 1
GitSubmodulesConfig:
FetchSubmodules: false
InsecureSsl: false
Location: !Sub "https://git-codecommit.${AWS::Region}.amazonaws.com/v1/repos/handson-repo"
Type: "CODECOMMIT"
Artifacts:
Type: "NO_ARTIFACTS"
Cache:
Type: "NO_CACHE"
Environment:
ComputeType: "BUILD_GENERAL1_SMALL"
Image: "aws/codebuild/amazonlinux2-x86_64-standard:5.0-24.03.20"
ImagePullCredentialsType: "CODEBUILD"
PrivilegedMode: true
Type: "LINUX_CONTAINER"
ServiceRole: !Sub "arn:aws:iam::${AWS::AccountId}:role/service-role/codebuild-handson-role"
TimeoutInMinutes: 60
QueuedTimeoutInMinutes: 480
EncryptionKey: !Sub "arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/s3"
BadgeEnabled: false
LogsConfig:
CloudWatchLogs:
Status: "ENABLED"
S3Logs:
Status: "DISABLED"
EncryptionDisabled: false
Visibility: "PRIVATE"
CodePipelinePipeline:
Type: "AWS::CodePipeline::Pipeline"
Properties:
Name: !Ref CodeBuildProject
RoleArn: !GetAtt IAMRole.Arn
ArtifactStore:
Location: !Ref S3Bucket
Type: "S3"
Stages:
-
Name: "Source"
Actions:
-
Name: "Source"
ActionTypeId:
Category: "Source"
Owner: "AWS"
Provider: "CodeCommit"
Version: "1"
Configuration:
BranchName: "master"
OutputArtifactFormat: "CODE_ZIP"
PollForSourceChanges: "false"
RepositoryName: "handson-repo"
OutputArtifacts:
-
Name: "SourceArtifact"
Region: !Ref AWS::Region
Namespace: "SourceVariables"
RunOrder: 1
-
Name: "Build"
Actions:
-
Name: "Build"
ActionTypeId:
Category: "Build"
Owner: "AWS"
Provider: "CodeBuild"
Version: "1"
Configuration:
ProjectName: !Ref CodeBuildProject
InputArtifacts:
-
Name: "SourceArtifact"
OutputArtifacts:
-
Name: "BuildArtifact"
Region: !Ref AWS::Region
Namespace: "BuildVariables"
RunOrder: 1
aws cloudformation create-stack --stack-name handson-pipeline --template-body file://./handson-pipeline.yaml --capabilities CAPABILITY_NAMED_IAM
パイプラインの実行
Dockerfile で 16 → 10 にし、push します。
FROM public.ecr.aws/amazonlinux/amazonlinux:latest
COPY ./queens /usr/local/bin/queens
# program execute
CMD /usr/local/bin/queens 10
git add .
git commit -m "change queens param"
git push
デベロッパー用ツール > CodePipeline > パイプライン > handson-pipeline にいくと、自動デプロイが成功していることが確認できます。
ジョブの実行と確認
AWS Batch > ジョブ > handson-def を確認すると、イメージが書きかわっていることがわかります。
buildspec.yaml で指定したIMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
の部分です。
AWS Batch > ジョブ > 新しいジョブを送信 を開き、「名前」、「ジョブ定義」、「ジョブキュー」を次の図の通り指定します。