CDKロジカルIDの255文字制限、実は240文字+8桁ハッシュの内訳だった

  • AWS
  • CDK
  • CloudFormation

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

結論

CDKが生成するロジカルIDは最大255文字で合ってるけど、内訳がある。

  • 人間が読める部分(construct pathを連結したもの): 最大240文字
  • 一意性確保用のハッシュ: 8文字固定

<human-readable-portion><8-character-hash> で合計255文字。ここを「255文字まで」としか覚えてないと、長いconstruct IDを付けたときにどこで削られるか分からなくなる。

あと、ロジカルIDの制約とS3バケット名・Lambda関数名みたいな物理名の制約は完全に別物。ここを一緒くたにすると勘違いする。

ロジカルIDの生成アルゴリズム

CDKの公式ドキュメントによると、生成手順はこう。

  1. construct treeのpath要素を連結する(スタック自身は除く)
  2. 読みやすくするためのヒューリスティックを適用する
  3. パス全体の8文字ハッシュを末尾に付けて一意性を確保する
flowchart TD
    A[construct path\nStack1/DataBucket/Resource] --> B[パス連結\nスタック名は除外]
    B --> C[ヒューリスティック適用\nDefault除去・Resource除去等]
    C --> D[8文字ハッシュ付加]
    D --> E[ロジカルID\nDataBucketXXXXXXXX]

ハッシュが必要な理由は、A/B/C と A/BC みたいに連結すると同じ文字列になるパスを区別するため。CloudFormationのロジカルIDは英数字のみでスラッシュが使えないから、単純連結だと衝突する。

スタック直下(パスが単一要素)のリソースは、名前が255文字以下ならハッシュなしでそのまま使われる。

ヒューリスティックの中身

人間可読部分を作る際、CDKは以下を適用する。

  • Default というpath要素は人間可読部分からもハッシュ計算からも完全に除去される
    • 既存constructを新しいconstructで包んで、内側のIDを Default にすると元と同じロジカルIDになる。リファクタ時に既存リソースを置き換えずに済む仕組みはこれ
  • Resource というpath要素は人間可読部分からは隠されるが、ハッシュ計算には含まれる
    • L1 construct(CfnXxx)は慣習的に Resource というIDを使う
  • 連続する重複要素は片方が省略される

物理名の制約はロジカルIDとは別物

ここを混同しがちだけど、ロジカルID(CloudFormationテンプレート内の識別子)と物理名(実際にAWS上で使われる名前)は制約が別。

  • S3バケット名: 3〜63文字、小文字・数字・ピリオド・ハイフンのみ
  • Lambda関数名: 64文字

CDKが自動生成する物理名には、スタック名やハッシュが追加されることがあるので、bucketName や functionName を明示指定しない場合、想定より長くなって物理名の制約に引っかかることがある。特にネストスタック配下だと <root-stack-name>-XXXXXXXXXXXX-<construct-name> みたいな形式になりやすく、Lambda関数名の64文字制限に普通に当たる。

実務上の注意点

  • construct IDは短く保つ。長いパスは読みやすさのためのヒューリスティックだけでは吸収しきれない
  • 物理名を明示的に指定したいリソースは bucketName / functionName などのプロパティで直接渡す
  • ロジカルIDを変えるとCloudFormationはリソースを作り直す(削除→作成)。既存リソースのIDは不用意に変更しない
  • 既にロジカルIDが変わってしまったケースは cdk refactor で旧IDと新IDのマッピングができる(実機で試してはいない)

参考: Identifiers and the AWS CDK