先决条件
EC2
的特权
您对EC2,ECS,AWS Batch等具有完全权限。
0.准备
0.1。完成作业的创建和执行
AWS Batch#2作业已创建并执行
0.2。检查变量
检查
中将继续使用的变量
命令
1 2 3 4 5 6 7 8 9 | cat << ETX CFN_STACK_NAME: ${CFN_STACK_NAME} COMPUTE_ENV_NAME: ${COMPUTE_ENV_NAME} JOB_QUEUE_NAME: ${JOB_QUEUE_NAME} JOB_DEFINITION_NAME: ${JOB_DEFINITION_NAME} CONRAINER_PROPS_FILE: ${CONRAINER_PROPS_FILE} ETX |
结果(示例)
1 2 3 4 5 | CFN_STACK_NAME: aws-batch-xxxxxxxxxx COMPUTE_ENV_NAME: aws-batch-managed-xxxxxxxxxx JOB_QUEUE_NAME: aws-batch-job-queue-xxxxxxxxxx JOB_DEFINITION_NAME: aws-batch-job-def-xxxxxxxxxx CONRAINER_PROPS_FILE: aws_batch_container_props.json |
0.3。AWS CLI版本
具有以下版本的确认操作
- AWS CLI 1.11.36
命令
1 | aws --version |
结果(示例)
1 | aws-cli/1.11.36 Python/2.7.5 Darwin/13.4.0 botocore/1.4.93 |
如果
版本较旧,则将其更新为最新版本。
命令
1 | sudo -H pip install -U awscli |
1.样本申请
- 让我们在AWS Batch中实现常规批次 1
- 使用AWS Batch在COBOL中运行表单输出
- 将创建的表单上载到S3
- 为该工作分配对S3具有上载权限的角色
- 每分钟从CloudWatch Events Lambda提交作业
1.1创建Docker存储库
创建存储库以推送作业执行逻辑
命令
1 2 3 4 | DOCKER_REPO=$( aws ecr create-repository \ --repository-name ${CFN_STACK_NAME}/sample \ | jq -r '.repository.repositoryUri' \ ) && echo ${DOCKER_REPO} |
结果(示例)
1 | xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/aws-batch-xxxxxxxxxx |
1.2。从#1
中生成的堆栈中获取变量
重新获取CloudFormation堆栈生成的结果
命令
1 2 | CFN_STACK_RESULT=$( aws cloudformation describe-stacks \ --stack-name ${CFN_STACK_NAME}) |
从堆栈生成结果(输出)中提取所需的变量。
命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | S3_BUCKET_NAME=$( echo ${CFN_STACK_RESULT} \ | jq '.Stacks[].Outputs[]' \ | jq -r 'select(.OutputKey=="S3Bucket").OutputValue' ) BATCH_JOB_ROLE=$( echo ${CFN_STACK_RESULT} \ | jq '.Stacks[].Outputs[]' \ | jq -r 'select(.OutputKey=="BatchJobRole").OutputValue' ) cat << ETX S3_BUCKET_NAME: ${S3_BUCKET_NAME} BATCH_JOB_ROLE: ${BATCH_JOB_ROLE} ETX |
结果
1 2 | S3_BUCKET_NAME: aws-batch-xxxxxxxxxx-s3bucket-xxxxxxxxxxx BATCH_JOB_ROLE: arn:aws:iam::xxxxxxxxxxxx:role/aws-batch-xxxxxxxxxx-BatchJobRole-xxxxxxxxxxxxx |
1.3。创建工作定义
重新生成容器定义文件。
命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | cat << EOF > ${CONRAINER_PROPS_FILE} { "image": "${DOCKER_REPO}", "command": ["Ref::Arg1", "Ref::Arg2"], "jobRoleArn": "${BATCH_JOB_ROLE}", "environment": [ { "name": "AWS_DEFAULT_REGION", "value": "${AWS_DEFAULT_REGION}"}, { "name": "AWS_S3_BUCKET", "value": "${S3_BUCKET_NAME}"}, { "name": "APP_VERSION", "value": "production!"} ], "vcpus": 1, "memory": 100 } EOF cat ${CONRAINER_PROPS_FILE} |
验证容器定义文件
命令
1 | jsonlint -q ${CONRAINER_PROPS_FILE} |
使用此更新作业定义
命令
1 2 3 4 | aws batch register-job-definition \ --job-definition-name ${JOB_DEFINITION_NAME} \ --container-properties file://${CONRAINER_PROPS_FILE} \ --type container |
结果(示例)
1 2 3 4 5 | { "jobDefinitionArn": "arn:aws:batch:us-east-1:xxxxxxxxxxxx:job-definition/aws-batch-job-def-xxxxxxxxxx:1", "jobDefinitionName": "aws-batch-job-def-xxxxxxxxxx", "revision": 2 } |
1.4。确认用于提交作业的变量
确定名称,以便您可以识别发送的作业
命令
1 | JOB_NAME="job-`date +%s`" |
获取具有最新修订版
的职位定义ARN
命令
1 2 3 4 5 | JOB_DEFINITION_ARN=$( aws batch describe-job-definitions \ --job-definition-name ${JOB_DEFINITION_NAME} \ --status ACTIVE \ | jq -r '.jobDefinitions | max_by(.revision).jobDefinitionArn' \ ) && echo ${JOB_DEFINITION_ARN} |
结果(示例)
1 | arn:aws:batch:us-east-1:xxxxxxxxxxxx:job-definition/aws-batch-job-def-xxxxxxxxxx:2 |
2.生成其他资源以提交工作
2.1。CloudFormation堆栈生成
获取模板
命令
1 2 | curl --location --output ${CFN_STACK_NAME}-job.yaml \ https://raw.githubusercontent.com/supinf/aws-batch-refarch/master/cloudformation/job-executor.yaml |
CloudFormation堆栈生成
命令
1 2 3 4 5 6 7 | aws cloudformation create-stack \ --stack-name ${CFN_STACK_NAME}-job \ --template-body file://${CFN_STACK_NAME}-job.yaml \ --parameters ParameterKey=JobName,ParameterValue=${JOB_NAME} \ ParameterKey=JobQueueName,ParameterValue=${JOB_QUEUE_NAME} \ ParameterKey=JobDefinitionArn,ParameterValue=${JOB_DEFINITION_ARN} \ --capabilities CAPABILITY_IAM |
结果(示例)
1 2 3 | { "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/aws-batch-xxxxxxxxxx-job/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" } |
该堆栈创建以下资源
- 作业输入Lambda
- CloudWatch Events定期启动Lambda
2.2。从生成的资源中获取变量
等待堆栈生成
命令
1 2 | aws cloudformation wait stack-create-complete \ --stack-name ${CFN_STACK_NAME}-job |
结果
1 | 返り値なし |
获取生成的结果
命令
1 2 3 | CFN_STACK_RESULT=$( aws cloudformation describe-stacks \ --stack-name ${CFN_STACK_NAME}-job \ ) && echo ${CFN_STACK_RESULT} | jq . |
从堆栈生成结果(输出)中提取所需的变量。
命令
1 2 3 4 | TRIGGER_ARN=$( echo ${CFN_STACK_RESULT} \ | jq '.Stacks[].Outputs[]' \ | jq -r 'select(.OutputKey=="BatchJobEvent").OutputValue' ) echo ${TRIGGER_ARN} |
结果(示例)
1 | arn:aws:events:us-east-1:xxxxxxxxxxxx:rule/BatchJobTriggerRule |
3.准备作业以运行
接受两个参数和两个环境变量,并创建一个文件
让我们将以下COBOL程序作为作业运行。
https://github.com/pottava/docker-cobol/blob/master/examples/batch.cbl
(该示例使用COBOL语言,但当然可以在具有外壳脚本,Java,Python,Swift,Elixir,Docker的AWS Batch上使用)
3.1。准备入口
准备一个包装器脚本,以很好地接收来自AWS Batch的自变量,并将输出文件上传到S3。
确定文件名
命令
1 | DOCKER_ENTRYPOINT_FILE="entrypoint.sh" |
生成
入口点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | cat << EOF > ${DOCKER_ENTRYPOINT_FILE} #!/bin/bash if [ -z "\$AWS_DEFAULT_REGION" ]; then echo "Missing environment variable 'AWS_DEFAULT_REGION'." 1>&2 exit 1 fi if [ -z "\$AWS_S3_BUCKET" ]; then echo "Missing environment variable 'AWS_S3_BUCKET'." 1>&2 exit 1 fi if [ -z "\$AWS_S3_KEY" ]; then AWS_S3_KEY="result-\$(date +%Y%m%d%H%M)" fi /usr/local/bin/batch \$@ rc=\$? if [ \$rc -ne 0 ] ;then echo "[Error] Executing batch went wrong..." 1>&2 echo "ARGUMENTS: "\$@ 1>&2 echo "APP_VERSION: "\${APP_VERSION} 1>&2 echo "APP_TARGET: "\${APP_TARGET} 1>&2 exit \$rc fi aws --region \$AWS_DEFAULT_REGION s3api put-object \\ --bucket \$AWS_S3_BUCKET --key \$AWS_S3_KEY \\ --body result.txt rc=\$? if [ \$rc -ne 0 ] ;then echo "[Error] Sending job results went wrong..." 1>&2 echo "ARGUMENTS: "\$@ 1>&2 echo "APP_VERSION: "\${APP_VERSION} 1>&2 echo "APP_TARGET: "\${APP_TARGET} 1>&2 echo "AWS_S3_BUCKET: "\${AWS_S3_BUCKET} 1>&2 echo "AWS_S3_KEY: "\${AWS_S3_KEY} 1>&2 exit \$rc fi EOF |
3.2。创建一个Dockerfile
具有通常的文件名
命令
1 | DOCKER_FILE="Dockerfile" |
生成
Docker文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | cat << EOF > ${DOCKER_FILE} FROM debian:wheezy-slim ADD https://raw.githubusercontent.com/pottava/docker-cobol/master/examples/batch.cbl /usr/local/src/ ADD entrypoint.sh / RUN BUILD_PACKAGES="build-essential curl" \\ && apt-get update && apt-get autoremove -y \\ && apt-get install -y \${BUILD_PACKAGES} open-cobol python \\ && chmod +x /entrypoint.sh \\ # Build application && cd /usr/local/bin \\ && cobc -x /usr/local/src/batch.cbl \\ # Install AWS-CLI && curl --location --silent --show-error \\ https://bootstrap.pypa.io/get-pip.py | python \\ && pip install "awscli==1.11.56" \\ # Clean up && apt-get purge -y --auto-remove \${BUILD_PACKAGES} \\ && find / -depth -type d -name test -exec rm -rf {} \\; \\ && find / -depth -type d -name \__pycache__ -exec rm -rf {} \\; \\ && rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/* /root/.cache WORKDIR /app ENV AWS_DEFAULT_REGION=ap-northeast-1 \\ AWS_S3_BUCKET="" \\ AWS_S3_KEY="" \\ APP_VERSION=0.1.0 \\ APP_TARGET=executor ENTRYPOINT ["/entrypoint.sh"] EOF |
3.3。应用程序的Docker映像
在指定ECR的存储库名称时进行构建。
如果线很细,可能最多需要15分钟。
命令
1 | docker build -t ${DOCKER_REPO} . |
结果(示例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Sending build context to Docker daemon 24.06 kB Step 1/7 : FROM debian:wheezy-slim ---> b7230ec23103 Step 2/7 : ADD https://raw.githubusercontent.com/pottava/docker-cobol/master/examples/batch.cbl /usr/local/src/ Downloading 2.687 kB ---> Using cache ---> 723925bd3df1 (中略) Step 7/7 : ENTRYPOINT /entrypoint.sh ---> Running in 94ca4974b074 ---> ca617324a141 Removing intermediate container 94ca4974b074 Successfully built ca617324a141 |
登录到ECR并推送Docker映像
命令
1 2 | aws ecr get-login | sh docker push ${DOCKER_REPO} |
结果(示例)
1 2 3 4 5 6 7 | The push refers to a repository [xxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/aws-batch-xxxxxxxxxx/sample] de07e4081e81: Pushed f0c9c1e82d65: Pushed 4e4c70200302: Pushed d4a5f6671fae: Pushed 6db2a2c16cbd: Pushed latest: digest: sha256:c7e5ef31e1bde0a6ec4327118e5d2976da098e7a5e9fa5a7ee236ceb942e094a size: 1361 |
4.职位提交
Docker映像也已准备就绪。
现在,让我们定期从CloudWatch Events开始预先在CloudFormation中准备的Lambda,然后将作业提交到AWS Batch。
4.1。启用CloudWatch Events
定义了每分钟踢Lambda的规则,但
它在DISABLED停止。
让我们更新为ENABLE并开始该过程。
命令
1 2 3 4 | aws events enable-rule \ --name $( aws events list-rules | jq '.Rules' \ | jq "map(select(.Arn=="${TRIGGER_ARN}"))" \ | jq -r '.[].Name' ) |
结果
1 | 返り値なし |
4.2。检查作业状态
检查正在运行的作业的状态。
结果应该每分钟增加一次。
命令
1 2 3 4 5 | aws batch list-jobs \ --job-queue ${JOB_QUEUE_NAME} \ --job-status SUCCEEDED \ | jq '.jobSummaryList' \ | jq "map(select(.jobName=="${JOB_NAME}"))" |
结果(示例)
1 2 3 4 5 6 7 8 9 10 | [ { "jobName": "job-1488375104", "jobId": "71895de8-b28c-41eb-b94f-43fe2fb7878a" }, { "jobName": "job-1488375104", "jobId": "cbc64814-a27a-48cc-9376-d67c95984505" } ] |
4.3。确认输出表格
首先,让我们显示表单列表
命令
1 2 3 4 | aws s3api list-objects \ --bucket ${S3_BUCKET_NAME} \ | jq '.Contents' \ | jq 'map({Key: .Key, LastModified: .LastModified})' |
结果(示例)
1 2 3 4 5 6 7 8 9 10 | [ { "Key": "result-201703011749", "LastModified": "2017-03-01T17:49:13.000Z" }, { "Key": "result-201703011750", "LastModified": "2017-03-01T17:50:18.000Z" } ] |
选择一个并下载
命令
1 | S3_KEY="result-201703011749" |
命令
1 2 3 | aws s3api get-object \ --bucket ${S3_BUCKET_NAME} \ --key ${S3_KEY} ${S3_KEY} |
结果(示例)
1 2 3 4 5 6 7 8 | { "AcceptRanges": "bytes", "ContentType": "binary/octet-stream", "LastModified": "Wed, 01 Mar 2017 17:49:13 GMT", "ContentLength": 121, "ETag": ""190d1fecd45c7996ab8f124cd60a42ee"", "Metadata": {} } |
尝试打开文件
命令
1 | cat ${S3_KEY} |
结果(示例)
1 2 3 4 5 6 7 | 2 17:48:59 from-AWS-Lambda production! 0dfc1g7b47 1 49 12 2 49 12 3 49 12 4 49 12 5 49 12 |
完毕
这些都是为了更实际的使用。
销毁AWS Batch#4环境
这不是适用于AWS Batch的用例,但这并非不可能。这是一个故事。 ?