AWS CDKで初心者がハマったこと2選

## はじめに
こちらは [エーピーコミュニケーションズ Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ap-com) の 23 日目の記事となります。

2024年に入り、初めてAWS CDKに触れる機会がありました。
今となっては非常に使いやすいツールだと理解しているのですが、その中で2つほどドハマりしたことがあったため、振り返りながら整理します。

## 前提・筆者のスキルレベル
前提として簡単な筆者のスキルレベルになりますが、AWSについては認定資格レベルでの知識はありましたが、ほとんど実務的に操作をしたことがない状態です。
またCloudFormationについてもIaCってやつでしょ？程度しか知識がない状態でAWS CDKを触り始めることになりました。

コーディング的な面でも趣味的にPythonなどを利用したことがある程度で、Typescriptに関しては全く知識がない状態です。

前提から分かるようにコーディング的な面で苦労したことも勿論たくさんありましたが、AWS的な面での知識や経験が足りないことで苦戦した部分も色々とありました。
もしかするとCDKやCloudFormationでは一般的な事象で、知って当然の事だったのかもしれませんが、前提知識がないためそんな判断もできませんでした。
ここでは実際にハマってしまったことの改善策のメモとして記事を残そうと思います。

ここでは記憶に残っており単純解決が可能なことを2挙げます。
もし同様に悩まれている方が居ればご参考にしていただけますと幸いです。

## デフォルトで作成されたルートテーブルが削除できない
[VPCコンストラクタ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.Vpc.html)は非常に強力なツールです。
CDKコードの構成内容から自動的にルーティングを判断して、ルートテーブルの作成などをしてくれます。
一方で、利用方法によっては便利機能が非常に厄介になってしまうことがあります。

要件として、自動的にルートテーブルの作成とルーティングを独自に設定したい場合、別途ルートテーブルの作成などを行うこともあると思います。
一部曖昧な記憶かもしれませんが、自動で作成されたルートテーブルにはルート情報を追加・削除することができないため、別途で作成することになった経緯だったと記憶しております。

別で正しいルートテーブルを作成しルーティングを終えた後に、デフォルトで作成されたルートテーブルが残ってしまいます。

そこで削除を試みるのですが、どうしても削除ができない。
そんな時には以下のコマンドを試してみてください。(関連しそうなリソース全てを入れています)

```
vpc.publicSubnets.forEach((subnet) => {
      subnet.node.tryRemoveChild("EIP")
      subnet.node.tryRemoveChild("NATGateway")
      subnet.node.tryRemoveChild("DefaultRoute")
      subnet.node.tryRemoveChild("RouteTable")
      subnet.node.tryRemoveChild("RouteTableAssociation")
})
vpc.privateSubnets.forEach((subnet) => {
      subnet.node.tryRemoveChild("EIP")
      subnet.node.tryRemoveChild("NATGateway")
      subnet.node.tryRemoveChild("DefaultRoute")
      subnet.node.tryRemoveChild("RouteTable")
      subnet.node.tryRemoveChild("RouteTableAssociation")
})
vpc.isolatedSubnets.forEach((subnet) => {
      subnet.node.tryRemoveChild("EIP")
      subnet.node.tryRemoveChild("NATGateway")
      subnet.node.tryRemoveChild("DefaultRoute")
      subnet.node.tryRemoveChild("RouteTable")
      subnet.node.tryRemoveChild("RouteTableAssociation")
})
```

自動的に作成されるルートテーブルですが、自動的にルーティングをしてくれる便利機能があるように、自動的に他リソースとの依存関係を作ってしまうために削除ができません。
そのため、一度依存関係を持つリソースを削除し再作成をした上で再度対象のリソースを作成しなおしてルーティング設定をする必要があります。
ひと手間掛かりますが、美しい構成とするためには必要でした。

もう少しスマートな解決方法も試行錯誤してみたのですが、現状ではこのやりかたが着地点となりました。
もっと良い方法があればどなたか教えてください！

## カスタムリソースがエラーになった際のタイムアウト時間が非常に長い
デプロイ時に掛かるタイムアウトの待機時間がデフォルトで1時間に設定されています。
何度も試行錯誤をしている際に、待ち時間が長くかかるのは非常にストレスです。

タイムアウトまで時間がかかる、また、ロールバックが終わるまでに時間がかかると多くの時間を浪費してしまい、とても無駄な時間です。
解消方法としては単純ですが、以下の`ServiceTimeout`を設定しておくだけでタイムアウト時間が短くなるので絶対におすすめです。
```
new cdk.CustomResource(this, `customResource`, {
    properties: {
        ServiceTimeout: 5,
    },
});
```
## 番外編：カスタムリソースを毎回動作させたい
カスタムリソースの処理をアップデート時にも必ず動作させたい場合などの対処方法もご紹介します。
CDKのデプロイ時に、すでにデプロイ済のスタックに対してリソースの状態に変更がない場合、CDKの判断として更新がかからない様な挙動になっている(と思う)のですが、必ず毎回動作させたいものがある場合などに更新時刻を定義しておくと、カスタムリソースがアップデートされて動作します。

具体的には`LastUpdated`として、更新日時を設定します。
非常に有効なので合わせてご紹介させていただきました。

```
new cdk.CustomResource(this, `customResource`, {
    properties: {
        LastUpdated: new Date().toISOString(),
    },
});
```

## おわりに
他にも細々とハマった個所はあるのですが、整理しきれていない部分も多いため記事としては解決方法として提示できる簡単な2つだけとしました。
AWS CDKはとても楽しく魅力的ですが、取っ付きづらく難しく感じてしまう部分も多々あるため、敷居が高いものとなっています。

その反面、綺麗にコードが書けた時の嬉しさや思い通りに動かすことができた時の楽しさがあると思っています。
使いこなせれば非常に強力なツールですが、日々更新されていく仕様の中で身に着けることは一朝一夕にとはいかないと思います。

CDKを触る中で公式ドキュメント以外の情報量が少ないと感じることが多々ありましたが、生成系AIの力なども借りつつどんどんと世の中で利用されるようになり、スタンダードなツールとして一般的に利用されるものになると嬉しいと思いました。
現状ではAmazonQをもってしても、正しい定義情報が作成できないことも多々ありますが、そういう面でもまだまだこれからの技術の進化が楽しみであるとともに、これからもCDKの情報を追って触ってみようと思いました！