在使用 Amazon EKS (Elastic Kubernetes Service) 管理容器化应用程序时,我们经常需要更新应用程序的 Docker 镜像,并重新部署服务。这个过程包括构建新的 Docker 镜像、推送到 Amazon ECR (Elastic Container Registry)、更新 EKS 节点组的 AMI (Amazon Machine Image) 以及重新部署 Kubernetes 服务。手动执行这些步骤不仅繁琐,而且容易出错。

为了简化这个过程,我编写了一个 Bash 脚本,可以自动完成上述所有步骤。该脚本具有以下功能:

  1. 构建新的 Docker 镜像并推送到 Amazon ECR
  2. 获取 BottleRocket AMI 的快照 ID
  3. 更新 EKS 节点组的 AMI 快照 ID
  4. 更新 Kubernetes Deployment 的镜像版本
  5. 发送 DingDing 通知,通知重启成功

脚本代码

#!/bin/bash

# 设置环境变量
ENV=test
USER=${ENV}-ai
HOST=10.0.9.136
SERVER_NAME=tree
IMAGE_REPO="820600610568.dkr.ecr.us-east-1.amazonaws.com/ai"
DINGDING_TOKEN=5ecc827755c91854fca04d34b58e255e3ac39475ee92bfebbc1159b6369d42b9

# 构建 Docker 镜像并推送到 ECR
build_image(){
  local VERSION="$(date +%Y%m%d%H%M%S)"
  export IMAGE="${IMAGE_REPO}/${SERVER_NAME}:${VERSION}"
  sed -i 's/env="dev"/env=os.getenv("ENV_NAME", "dev")/' run.py #不同环境sqs不一样
  #sed -i "s|{env}-light|${ENV}-${SERVER_NAME}|g" run.py
  sudo /usr/local/bin/aws ecr get-login-password --region us-east-1 | sudo docker login --username AWS --password-stdin "${IMAGE_REPO}"
  docker build -t ${IMAGE} .
  docker push ${IMAGE}
  docker rmi -f ${IMAGE}
}

# 获取 BottleRocket 镜像快照 ID
get_snapshot_id(){
  local SNAPSHOT_LOG="/root/stable-diffusion-on-eks/utils/bottlerocket-images-cache/${ENV}-${SERVER_NAME}-ai-log.txt"
  cd /root/stable-diffusion-on-eks/utils/bottlerocket-images-cache || return
  ./snapshot.sh "${IMAGE}" | tee "${SNAPSHOT_LOG}"
  export SNAPSHOT_ID=$(grep -oEi 'snap-[a-z0-9]+' "${SNAPSHOT_LOG}" | tail -1)
  if [ -z "$SNAPSHOT_ID" ]; then
    echo "new_snapshot_id is empty"
    send_dingding "failure"
    exit 1
  fi 
}

# 更新 EKS 服务
update_service(){
  # 更新 EC2NodeClass 的镜像快照 ID
  ssh "${USER}@${HOST}" "kubectl patch EC2NodeClass ${ENV}-${SERVER_NAME}-ai-gpu --type='json' -p '[{\"op\":\"replace\", \"path\":\"/spec/blockDeviceMappings/1/ebs/snapshotID\", \"value\":\"${SNAPSHOT_ID}\"}]'"
  # 更新 Deployment 的镜像版本
  ssh "${USER}@${HOST}" "kubectl set image deployment/${ENV}-${SERVER_NAME}-ai ${ENV}-${SERVER_NAME}-ai=${IMAGE}"

}

# 发送 DingDing 通知
send_dingding(){
  if [ "$1" == "success" ]; then
    color='#00EC00'
  else
    color='#FF0000'
  fi

  curl "https://oapi.dingtalk.com/robot/send?access_token=${DINGDING_TOKEN}" \
      -H 'Content-Type: application/json' \
      -d ' {"msgtype": "markdown","markdown": {"title":"Restart '"${ENV}-${SERVER_NAME}-ai"' '"$1"'","text": "<font face='"'黑体'"' color='"'$color'"'>Restart '"${ENV}-${SERVER_NAME}-ai tag:${VERSION} SNAPSHOT_ID:${SNAPSHOT_ID}"' '"$1"'</font>\n"}}'
}


# 执行主要步骤
build_image
get_snapshot_id
update_service
send_dingding "success"
  • 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.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.

使用方法

  1. 将脚本保存为一个文件,例如 update_service.sh
  2. 根据您的实际环境,修改脚本开头的环境变量值。
  3. 确保已经安装了 AWS CLI 和 Docker,并且具有相应的权限。
  4. 在脚本所在目录执行 bash update_service.sh

脚本将自动执行以下步骤:

  1. 构建新的 Docker 镜像并推送到 Amazon ECR。
  2. 获取 BottleRocket AMI 的快照 ID。
  3. 使用新的快照 ID 更新 EKS 节点组的 AMI。
  4. 使用新的 Docker 镜像版本更新 Kubernetes Deployment。
  5. 发送 DingDing 通知,通知重启成功。

通过使用这个脚本,您可以大大简化 Docker 镜像更新和 EKS 服务重新部署的过程,提高效率并减少手动操作的风险。