shell 如何使用特定的标签版本更新ecs服务?

nwo49xxi  于 2023-01-13  发布在  Shell
关注(0)|答案(2)|浏览(123)

我正在尝试更新一个ecs fargate服务,该服务有多个标记与服务任务定义所使用的给定ecr容器图像相关联。
ECR中的容器图像具有以下标记:2023.3.0-最新版本,测试
正如您所看到的,它只包含一个version标记和一个environment标记,在本例中,环境标记只是“test”。
在任务定义中,我使用标准格式传入了ECR URL:/:测试
我想做的是,当与任务定义关联的特定服务上有更新时,使用与特定版本和环境关联的特定映像。
例如,如何使用另一个映像的特定任务定义更新服务,该映像也用于测试,但具有不同的版本?
到目前为止,我已经运行了许多Jenkins作业,这些作业已经完成了过滤版本和更新与特定环境关联的服务的所有工作。
1.创建repo,将指定版本的容器上载到ecr,用与指定版本关联的标记,并将容器映像推送给ecr。
1.使用指定的环境重新标记映像,在本例中为“test”
第三步是如何使用与版本和环境相关联的特定容器映像更新任务。
比如说,我强制更新了与“test”标签相关的任务,我如何首先过滤“test”标签的特定版本,以便ecs知道要使用哪个版本的“test”?

9q78igpj

9q78igpj1#

几件重要的事情:

  • 任务定义是唯一可以定义任务中的容器应该使用什么图像的地方。
  • 任务定义修订是不可变的--创建后不能更改。
  • 您的任务定义通常只应指定具有唯一图像标签且永不更改的图像。否则,您的任务将具有不确定性和不一致的行为。
  • 要更新服务任务使用的映像,您必须创建新的任务定义修订版本,并更新服务以使用新修订版本。
  • 您可能只想在更新服务 * 之后 * 移动映像上的环境标记,而不是在更新之前。

您的基本步骤应类似于以下内容:
1.构建映像并使用唯一标记将映像推送到ECR
1.创建一个新的任务定义修订,为相应的容器指定唯一标记
1.更新服务以使用新修订版本
1.(可选)等待服务稳定
1.成功更新后,重新标记环境
完成所有这些操作的脚本可能看起来像这样:

# 1. Build the image(s) and push the image(s) to ECR with a unique tag
unique_tag="$BUILD_TAG" # or whatever you want that is unique
new_image="<ecr repo>:$unique_tag"
service_arn="<service ARN>"

env_name="test" # or whatever
cache_image="<ecr repo>:$env_name"

# leverage docker cache from the currently active image in this environment, if it exists
docker pull $cache_image || echo "no cache"
docker build --cache-from "$cache_image" -t <ECR repo>:$unique_tag .
docer push <ECR repo>:$unique-tag .

# 2. Create a new task definition revision

# here we assume you don't store the task definition JSON in the repo, which means we need to get it from API call
# by default, this gets the latest ACTIVE revision, which is usually what you want.
existing_taskdef="$(aws ecs describe-task-definition --task-definition=<your-taskdef-family-name>)"

# create new taskdef using jq to replace the image key in the first container (we assume only one container `.containerDefinitions[0]` is defined in this example)
# describe-task-definition returns some keys that can't be used with register-task-defintiion, so we delete those, too
new_task_definition="$(jq --arg IMAGE "$new_image" '.taskDefinition | .containerDefinitions[0].image = $IMAGE | del(.taskDefinitionArn) | del(.revision) | del(.status) | del(.requiresAttributes) | del(.compatibilities)' <<< "$existing_taskdef")"

# register the new revision
new_revision_arn="$(aws ecs register-task-definition --cli-input-json "$new_taskdefinition" --output text --query 'taskDefinition.taskDefinitionArn')"

# 3. Update the service to use the new revision

aws ecs update-service --service="$service_arn" --task-definition="$new_revision_arn"

# 4. wait for deployment stabilization (omitted for brevity)

# 5 retag the environment

# in subsequent workflows, the newly built image will be used for the cache
docker tag "$new_image" "<ecr repo>:${env_name}"
docker push "<ecr repo>:${env_name}"
8wigbo56

8wigbo562#

找到了一个可行的解决方案,同样的用例是如果你在ecr中有多个版本的镜像,你想通过ecs fargate来部署,并且你不想为每一个创建单独的任务定义,但是保持镜像设置为“测试”,并且每次只更新版本。
与一些观点相反,这是可以做到的。当你用“test”(即2023.1.0或2023.2.0)重新标记你想要的版本时,ecr会将该标记更新到指定的版本,并从指定的前一版本中删除该标记。换句话说,如果你刷新ecr,你会看到“test”标记,或你指定的任何其他标记,切换到了该版本(注意:为了简单起见,我硬编码了下面的版本)。

1. Push the tagged image to ECR

docker load < containername:2023.1.0-latest.tar.gz

SERVICE_NAME="ecsServiceName"
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
ECR_URL="$ACCOUNT_ID.dkr.ecr.<region>.amazonaws.com/SERVICE_NAME:2023.1.0-latest"
    
aws ecr create-repository --repository-name ${SERVICE_NAME:?} --region <region> || true

docker tag containername:2023.1.0-latest $ECR_URL
 
$(aws ecr get-login --region <region> --no-include-email --registry-ids $ACCOUNT_ID)
 
docker push $ECR_URL
    
2. Retag the image with env tag

MY_MANIFEST=$(aws ecr batch-get-image --repository-name $SERVICE_NAME --image-ids imageTag=2023.1.0-latest --region <region> --query images[].imageManifest --output text)

aws ecr put-image --repository-name $SERVICE_NAME --image-tag test --image-manifest "$MY_MANIFEST" --region <region>

3. Update the service with the task definition

aws ecs update-service --cluster ecsClusterName --service $SERVICE_NAME --task-definition ecsTaskDefinitionName --force-new-deployment --region <region>

相关问题