我在使用 CDK 管理不活动的 ECS 任务定义时遇到问题。此外,CloudFormation 漂移检测似乎错过了这种“注销”。
重现
将以下内容放入app.py中:
from aws_cdk import (
aws_ecs as ecs,
core,
)
class ExampleStack(core.Stack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
task_defn = ecs.FargateTaskDefinition(self, "ExampleTaskDefinition", cpu=256, memory_limit_mib=512)
task_defn.add_container("ExampleContainer", image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample"))
app = core.App()
ExampleStack(app, "ExampleStack", env={"region": "us-east-1"})
app.synth()
部署它:
$ cdk deploy
...
2/4 | 7:10:50 PM | CREATE_IN_PROGRESS | AWS::ECS::TaskDefinition | ExampleTaskDefinition (ExampleTaskDefinition47549670)
2/4 | 7:10:50 PM | CREATE_IN_PROGRESS | AWS::ECS::TaskDefinition | ExampleTaskDefinition (ExampleTaskDefinition47549670) Resource creation Initiated
3/4 | 7:10:51 PM | CREATE_COMPLETE | AWS::ECS::TaskDefinition | ExampleTaskDefinition (ExampleTaskDefinition47549670)
4/4 | 7:10:52 PM | CREATE_COMPLETE | AWS::CloudFormation::Stack | ExampleStack
✅ ExampleStack
Stack ARN:
arn:aws:cloudformation:us-east-1:865458870989:stack/ExampleStack/47a559b0-2386-11ea-a6f0-0a4fdb0c1726
...
确认任务定义:
$ aws ecs list-task-definitions --region=us-east-1
{
"taskDefinitionArns": [
"arn:aws:ecs:us-east-1:865458870989:task-definition/ExampleStackExampleTaskDefinition169C2730:1"
]
}
注销任务定义:
$ aws ecs deregister-task-definition --task-definition arn:aws:ecs:us-east-1:865458870989:task-definition/ExampleStackExampleTaskDefinition169C2730:1 --region=us-east-1
...
"status": "INACTIVE",
...
问题 1: 此时,CloudFormation 漂移检测继续将任务定义显示为“IN_SYNC”。
我的猜测是,这是因为 ECS 任务定义保持可发现的方式 (https://docs.aws.amazon.com/AmazonECS/latest/userguide/deregister-task-definition.html): “目前,非活动任务定义仍然可以在您的帐户中无限期地发现”
问题 1: CloudFormation 有没有办法将其检测为漂移?
问题 2:CDK 无法再次部署此堆栈。例如,如果我将 ECS 集群和服务添加到 app.py:
from aws_cdk import (
aws_ecs as ecs,
core,
)
class ExampleStack(core.Stack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
task_defn = ecs.FargateTaskDefinition(self, "ExampleTaskDefinition", cpu=256, memory_limit_mib=512)
task_defn.add_container("ExampleContainer", image=ecs.ContainerImage.from_registry("amazon/amazon-ecs-sample"))
cluster = ecs.Cluster(self, "ExampleServiceCluster")
ecs.FargateService(
self,
"ExampleService",
cluster=cluster,
task_definition=task_defn,
assign_public_ip=False,
desired_count=1,
min_healthy_percent=0,
max_healthy_percent=100,
service_name="ExampleService"
)
app = core.App()
ExampleStack(app, "ExampleStack", env={"region": "us-east-1"})
app.synth()
我现在会收到以下错误:
$ cdk deploy
...
16/27 | 7:18:30 PM | CREATE_FAILED | AWS::ECS::Service | ExampleService/Service (ExampleServiceC7919DA2) TaskDefinition is inactive (Service: AmazonECS; Status Code: 400; Error Code: ClientException; Request ID: dbb927b6-b2ba-495b-be47-b202a2802465)
new BaseService (/tmp/jsii-kernel-9athIS/node_modules/@aws-cdk/aws-ecs/lib/base/base-service.js:98:25)
\_ new FargateService (/tmp/jsii-kernel-9athIS/node_modules/@aws-cdk/aws-ecs/lib/fargate/fargate-service.js:35:9)
...
问题2:有没有一种简单的方法可以让这个堆栈再次工作而不完全破坏它?我想我还可以更改 TaskDefinition 的某些内容(例如,将名称更改为“ExampleTaskDefinition1”)以触发新 ARN 的创建,但这似乎有点笨拙。有更好的方法吗?
提前致谢!
我相信我也有同样的问题,在手动更改 ECS 任务定义后,尝试更新 ECS 服务属性 将导致更新失败,因为 CloudFormation 记住的服务的特定任务定义版本现在“不活动” ”。我认为这是因为 CloudFormation 想要应用所有 ECS 服务属性,并且在不更改任务定义的情况下,它将尝试使用非活动任务定义。
解决方案是对任务定义进行重大更改,即需要根据 CloudFormation AWS::ECS::TaskDefinition
文档进行替换。例如,更改任务的内存大小。更改完成后可以改回来。 CloudFormation 实现“需要替换”的方式是创建一个全新的任务定义(而不仅仅是现有任务定义的新版本)并更改 ECS 服务以使用新定义 - 并且它实际上并不关心版本旧的定义。然后,CloudFormation 将尝试通过删除它知道的版本来删除旧任务定义,但如果有更多版本(由于手动更改 - CloudFormation 永远不会创建新版本,它始终以版本 1 为目标),则任务定义本身将不会被删除,所有手动版本将保留。您可能想手动删除它们。
备注:
Resource of type 'AWS::ECS::TaskDefinition' with identifier
'arn:aws:ecs:XX-XXXX-X:XXXXXXXXXXXX:task-definition/XXXX...:VERSION'
was not found.