图片生成Gif任务 - I

在本节中,我们将使用 AWS Batch 从 S3 中提取图像,从中创建动画 GIF 视频,然后将结果上传回 S3。

动画 GIF 的源图像 动画 GIF

具体来说,我们将:

  1. 编写一个简单的脚本来创建动画 GIF。
  2. 编写 Dockerfile 容器规范来打包脚本及其依赖项。
  3. 创建 ECR 存储库来保存自定义容器映像。
  4. 构建容器镜像并将其上传到ECR存储库。
  5. 创建执行任务的批处理Job Definition
  6. 提交作业。
  7. 查看结果。

创建 S3 存储桶

将需要一个 S3 存储桶来存储源图像和结果动画 GIF:

export BUCKET_NAME=batch4eks-$(uuidgen --random | cut -d'-' -f1)
echo "export BUCKET_NAME=${BUCKET_NAME}" | tee -a ~/.bash_profile

aws s3 mb s3://${BUCKET_NAME}

cat << EOF
***** Take Note of Your Bucket Name *****
Bucket Name = ${BUCKET_NAME}
*****************************************
EOF

创建容器并将其上传到 ECR 存储库

在本章中,我们将创建容器 Dockerfile 配置文件,其中安装了所有必需的软件包。

创建ECR

export ECR_REPO_NAME_GIF=eks-make-gif-$(uuidgen --random | cut -d'-' -f1)
echo "export ECR_REPO_NAME_GIF=${ECR_REPO_NAME_GIF}" | tee -a  ~/.bash_profile

aws ecr create-repository \
    --repository-name ${ECR_REPO_NAME_GIF} \
    --image-scanning-configuration scanOnPush=true \
    --region ${AWS_REGION}

repositoryUri的值保存到的 Bash 环境和 Bash 配置文件中:

export ECR_REPO_GIF="${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPO_NAME_GIF}"
echo "export ECR_REPO_GIF=${ECR_REPO_GIF}" >> ~/.bash_profile

创建 Docker 镜像

创建一个用于存放 Dockerfile 的项目目录:

mkdir make-gif
cd make-gif

创建一个脚本来下载图片,并将其推送到 S3 存储桶中。它需要两个位置参数:图像的源 URL;以及 GIF 的输出位置:

cat > copy-to-s3.sh <<EOF
#!/bin/bash
# make a temp directory for this job
tmp_dir=\$(mktemp -d -t copy-to-s3-XXXXXXXXXX)
cd \$tmp_dir

# pull pictures from source
curl -o src_image "\$1"

# upload to given S3 key
aws s3 cp src_image "\$2"
EOF

创建一个脚本来收集源图像并生成动画 GIF,然后将其上传到 S3 存储桶中。它将使用上面两个位置参数:

cat > make-gif.sh <<EOF
#!/bin/bash
# make a temp directory for this job
tmp_dir=\$(mktemp -d -t make-gif-XXXXXXXXXX)
cd \$tmp_dir

# pull pictures from S3 source
aws s3 sync \$1 .

# create the gif
convert -delay 50 -loop 0 * movie.gif

# upload it back to s3
aws s3 cp movie.gif \$2
EOF

使脚本可执行:

chmod +x *.sh

为容器创建 Dockerfile:

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

RUN yum install -y ImageMagick unzip glibc-devel less groff

RUN cd /tmp &&\
  curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
  unzip awscliv2.zip && \
  ./aws/install

COPY copy-to-s3.sh /usr/local/bin/copy-to-s3.sh
COPY make-gif.sh /usr/local/bin/make-gif.sh
' > Dockerfile

现在应该有一个如下所示的目录:

make-gif/
├── copy-to-s3.sh
├── Dockerfile
└── make-gif.sh

构建容器并将其推送到 ECR:

echo "Logging in to  ECR..."
aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
echo "Build started on `date`"
echo "Building the Docker image..."
docker build -t $ECR_REPO_NAME_GIF:latest .
docker tag $ECR_REPO_NAME_GIF:latest $ECR_REPO_GIF:latest
echo "Build completed on `date`"
echo "Pushing the Docker image..."
docker push $ECR_REPO_GIF:latest

image-20240107190256455

现在,在私有 ECR 存储库中拥有一个可访问的工作容器,可以在批处理作业中使用。

添加访问 ECR 和 S3的权限

Batch任务的Pod将需要访问S3和 ECR。本节我们将使用IRSA实现

获取提供的用于访问 S3 和 ECR 的policy文档:

curl 'https://pingfan.s3.amazonaws.com/files/ecr-s3-access-iam-policy.json' --output ecr-s3-access-iam-policy.json

创建policy并将 ARN 存储在环境变量中

export BATCH_EKS_S3ECR_POLICY_ARN=$(aws iam create-policy --policy-name "ecr-s3-access-iam-policy" --policy-document file://./ecr-s3-access-iam-policy.json --output text --query Policy.Arn)

创建 IAM 角色并使用eksctl将其与 Kubernetes Service Account关联:

export BATCH_EKS_S3ECR_SA="${BATCH_EKS_CLUSTER_NAME}-s3ecr-sa"
export BATCH_EKS_S3ECR_ROLE="${BATCH_EKS_CLUSTER_NAME}-s3ecr-role"

eksctl create iamserviceaccount --name ${BATCH_EKS_S3ECR_SA} \
  --namespace ${BATCH_EKS_NAMESPACE} \
  --cluster ${BATCH_EKS_CLUSTER_NAME} \
  --role-name ${BATCH_EKS_S3ECR_ROLE} \
  --attach-policy-arn ${BATCH_EKS_S3ECR_POLICY_ARN} \
  --approve

将这些值保存在的 Bash 配置文件中以供以后使用:

echo "export BATCH_EKS_S3ECR_SA=${BATCH_EKS_S3ECR_SA}"  >> ~/.bash_profile
echo "export BATCH_EKS_S3ECR_ROLE=${BATCH_EKS_S3ECR_ROLE}"  >> ~/.bash_profile
echo "export BATCH_EKS_S3ECR_POLICY_ARN=${BATCH_EKS_S3ECR_POLICY_ARN}" >> ~/.bash_profile

结果如下:

image-20240107190804414