[JAWS-UG CLI] AWS Batch#3更实际的用法


先决条件

EC2

的特权

您对EC2,ECS,AWS Batch等具有完全权限。

0.准备

0.1。完成作业的创建和执行

AWS Batch#2作业已创建并执行

0.2。检查变量

检查

#1#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的用例,但这并非不可能。这是一个故事。 ?