[CDK/CFn] ECSでCapacityProviderを更新する
CDK deploy で ECS Cluster を更新しようとしたところ下記のようなエラーが発生しました。
The specified capacity provider is in use and cannot be removed. (Service: AmazonECS; Status Code: 400; Error Code: ResourceInUseException;
このエラーは、「Capacity Provider の指定が変更されているが、Service が古い Capacity Provider を使っているので変更できない」というエラーです。このエラーを解消するには、AWS API を叩いて全ての Service について Capacity Provider Strategy を更新してあげる必要があります。
状況確認
まず Cluster で現在の Capacity Provider / Default Capacity Provider Strategy を確認します。
$ aws ecs describe-clusters --cluster $CLUSTER_NAME | jq '.clusters[]'
{
"clusterArn": "arn:aws:ecs:ap-northeast-1:123456789012:cluster/ClusterA",
"clusterName": "ClusterA",
"status": "ACTIVE",
"registeredContainerInstancesCount": 4,
"runningTasksCount": 5,
"pendingTasksCount": 0,
"activeServicesCount": 5,
"statistics": [],
"tags": [],
"settings": [],
"capacityProviders": [
"CapacityProviderA",
"CapacityProviderB"
],
"defaultCapacityProviderStrategy": [
{
"capacityProvider": "CapacityProviderA",
"weight": 1,
"base": 0
},
{
"capacityProvider": "CapacityProviderB",
"weight": 0,
"base": 0
}
]
}
次に、CDK でどんな Capacity Provider / Default Capacity Provider Strategy に変更されようとしたのか確認します。cdk.out/XXX.template.json を確認すると、Cluster の設定が下記のようになっていました。
"ClusterXYZ": {
"Type": "AWS::ECS::ClusterCapacityProviderAssociations",
"Properties": {
"CapacityProviders": [
{
"Ref": "CapacityProviderARef"
}
],
"Cluster": {
"Ref": "ClusterARef"
},
"DefaultCapacityProviderStrategy": [
{
"CapacityProvider": {
"Ref": "CapacityProviderARef"
},
"Weight": 1
}
]
},
"Metadata": {
"aws:cdk:path": "Project/Cluster/Cluster/Cluster"
}
},
たしかに、Capacity Provider の指定が 1 つ減っています。
次に、Service のほうの現状も確認してみます。
$ aws ecs describe-services --services="$(aws ecs list-services --cluster $CLUSTER_NAME --query serviceArns)" --cluster $CLUSTER_NAME --query 'services[].{serviceName: serviceName, capacityProviderStrategy: capacityProviderStrategy}'
[
{
"serviceName": "ServiceA",
"capacityProviderStrategy": null
},
{
"serviceName": "ServiceB",
"capacityProviderStrategy": [
{
"capacityProvider": "CapacityProviderA",
"weight": 1,
"base": 0
},
{
"capacityProvider": "CapacityProviderB",
"weight": 0,
"base": 0
}
]
},
{
"serviceName": "ServiceC",
"capacityProviderStrategy": null
},
{
"serviceName": "ServiceD",
"capacityProviderStrategy": null
},
{
"serviceName": "ServiceE",
"capacityProviderStrategy": null
}
]
1 つの Service が古い Capacity Provider を Strategy に含んでいますね。
この状態で、put-cluster-capacity-provider を実行すると、cdk deploy のときと同じエラーが出るはずです。
$ aws ecs put-cluster-capacity-providers --cluster ClusterB --capacity-providers '["CapacityProviderA"]' --default-capacity-provider-strategy '[
{
"capacityProvider": "CapacityProviderA",
"weight": 1,
"base": 0
}
]'
An error occurred (ResourceInUseException) when calling the PutClusterCapacityProviders operation: The specified capacity provider is in use and cannot be removed.
解決編
全ての Service から古い Capacity Provider の指定を取り除けば(新しい Strategy を設定しなおせば) OK です。
今回は一件だったので、Service Name を指定して AWS CLI で設定しなおしました。
$ aws ecs update-service --cluster $CLUSTER_NAME --service ServiceB --capacity-provider-strategy '[
{
"capacityProvider": "CapacityProviderA",
"weight": 1,
"base": 0
}
]' --force-new-deployment
--force-new-deployment を設定しないと Capacity Provider Strategy のアップデートはできません。タスクが再配置されるので注意してください。
全ての Service のアップデートを行えば、cdk deploy がうまくいくようになるはずです。
Discussion