CDK 指定 Physical names 運作方式

POSTED BY   Chris
2021 年 12 月 4 日
CDK 指定 Physical names 運作方式

有看過 CDK 官方文件CDK best practice 文件的人大概都知道,當我們在開發 CDK 時,任何資源都盡量不要使用 physical name,而為什麼不這樣做的原因,在文件上的解釋雖然滿清楚,但具體上怎麼運作的還是不清楚,相信剛看完文件也可能會一知半解,所以這篇來講一下具體底層運作的方式

 

原理概述

CDK 底層都是 CloudFormation 在運作,Physical name 相關的文件也可以參考一下這裡,而在每個服務的 CloudFormation 文件中的每個欄位,都會有 Update requires 這個屬性,這個屬性有兩個值,No interruptionReplacement

只要遇到 No interruption 的屬性,就算 Resource physical name 有指定,CDK deploy 在 CloudFormation 部署時,一樣不會有任何影響,但如果是 Replacement 的話,CloudFormation 在 deploy 過程時就會報錯了,原因是因為 Replacement 屬性變更時,CloudFormation 會試著先建出一個與原來 Resource 一模一樣的資源後,再刪除舊的,以此來替代舊資源並更新屬性,那又因為要建一個一模一樣的資源時,因為資源有指定 physical name,所以要依此名稱再建立時就報這個資源已經存在,無法新建,以下就來做個小實驗來當實例說明

 

實例說明

首先用 CDK 來建立資源,並找一個屬性是 Replacement,這邊我用 ECS Service 中的 propagateTags 屬性來實驗,CDK 代碼如下

TypeScript
const ecsEcr = new ecrAssets.DockerImageAsset(this, 'ECSECR', {
  directory: path.join(__dirname, '../flask.d'),
});

const vpc = ec2.Vpc.fromLookup(this, 'DefaultVpc', { isDefault: true });

const cluster = new ecs.Cluster(this, 'Cluster', {
  vpc,
});

const fargateTaskDefinition = new ecs.FargateTaskDefinition(
  this,
  'TaskDef',
  {
    memoryLimitMiB: 1024,
    cpu: 256,
  },
);

fargateTaskDefinition.addContainer('test-container', {
  image: ecs.ContainerImage.fromDockerImageAsset(ecsEcr),
  portMappings: [{ containerPort: 80, hostPort: 80 }],
});

new ecs.FargateService(this, 'Service', {
  serviceName: 'test-physical-name',
  cluster,
  taskDefinition: fargateTaskDefinition,
  desiredCount: 0,
  circuitBreaker: {
    rollback: true,
  },
  assignPublicIp: true,
  vpcSubnets: vpc.selectSubnets({
    subnetType: ec2.SubnetType.PUBLIC,
  }),
  propagateTags: ecs.PropagatedTagSource.TASK_DEFINITION, // another value is ecs.PropagatedTagSource.SERVICE
});

這邊注意到代碼中故意指定 serviceNametest-physical-name,也就是指定了 physical name, 另一個要關注的是最後的 propagateTags 屬性

在第一次 deploy 時用 ecs.PropagatedTagSource.TASK_DEFINITION,等部署完成沒問題後,再改成 ecs.PropagatedTagSource.SERVICE 後再部署,在 AWS Console 的 CloudFormation 中就會出現如下錯誤訊息

如圖紅框所示,會出現 "Resource of type 'AWS::ECS::Service' with identifier 'test-physical-name' already exists.",而這邊也可以很清楚看到 CloudFormation 在 User Initiated 後,就開始建新資源,如果建立成功,就會繼續刪除舊資源

原理比較了解後,那到底什麼時候需要指定 phsical name 呢?在官方文件中有提到 cross-environment references 的時候需要,但可以用 core.PhysicalName.GENERATE_IF_NEEDED 讓 CDK 來幫我們判斷,因為 CloudFormation 本身是 regional 的限制,預設無法跨 region or account,所以才會有這個問題

 

結論

有時候要真正懂一個機制的運作,還真的非得要動手試試才行,最近常聽到 精神時光屋 這個詞,也就是大家都會覺得時間不夠用,太多東西要學,當然我自己也是這麼覺得,雖然我們沒有精神時光屋,但藉由一些熱心的朋友分享文章後,我們也可以快速學習到一些原理,也有點類似精神時光屋了 :),好像有點扯遠了,希望這篇對大家有幫助

歡迎留言
0

您可能也想看

Workaround for AWS Grafana alerting
2023 年 8 月 3 日
AWS, DevOps
AWS VPC Endpoint 使用場景
2022 年 3 月 14 日
AWS, CDK, Network
CDK Pipelines – 專為 CDK 打造的 CI/CD 利器
2021 年 11 月 7 日
AWS, CDK, DevOps, CI/CD