はじめに
皆様こんにちは、ソーシャル経済メディア「NewsPicks」(Media Infrastructureチーム)エンジニアの北見です。
現在、私は弊社サービスの一部のインフラ刷新を行なっている最中で、ここ数ヶ月 AWS CDKを触っておりました。
前職では Infrastructure as Code
として Terraform
を使ったことがあるのですが、少なくともAWS
を使うという条件においては CDKを使うべき という結論に辿り着きました。
今回はそのように考えるようになった理由について説明していこうと思います。
前提
Terraform
はパブリッククラウドにおける Infrastructure as Code
の走りとして様々な現場に導入実績があり、それに対するリスペクトは持つべきです。
しかしよくある「AvsB」というメリデメの構図で「どっちでもいいよ、好みだよ」と投げっぱなしにするとそれは無責任のように思えますし、 特にAWS初学者にとってむしろ混乱のもとなので、個人的見解として言い切ります。
「AWSでInfrastructure as Codeをしたいなら、CDKを使うべき」 です。
なんで使うべきなの?
私が考える、CDK
を使う「べき」理由は↓ の3つです
1. インフラをプログラミングできる
2. アプリケーションエンジニアにオーナーシップが生まれる
3. 楽しい!
理由1. インフラをプログラミングできる
Terraform
でもインフラのコード・バージョン管理は可能です。
しかし過去 Terraform
を書いていた私は、
「これは設定ファイルの管理を頑張っているんじゃないか?」
という感が拭えませんでした。
一方、CDK
はプログラミング言語で記述されますから、
.tf
ファイルと比べて認知負荷が小さいVSCode
のような軽量エディタでサクサク書ける( 公式ドキュメント の紹介がありますが、特にtypescript
とは相性が良い)- シンタックスレベルでエラーが静的にチェックされるので、typoのようなミスが少ない
- 業務要件に応じて独自の構造を作れるので、分割と管理がたやすい
- エディタ(or IDE)でメソッドやプロパティがサジェストされるので、編集時のストレス少ない
といった恩恵を受けられます。
例えば、「とあるCodeBuildにS3のBucketへのアップロード権限を付与する」というリソース構成を書く場合を考えてみましょう。
Terraform
なら
resource "aws_codebuild_project" "example_project" { name = "NewsPicksProject" description = "NewsPicks" } resource "aws_s3_bucket" "newspicks_bucket" { bucket = "newspicks-bucket" acl = "private" lifecycle_rule { enabled = true expiration { days = 30 } } } resource "aws_s3_bucket_policy" "newspicks_bucket_policy" { bucket = aws_s3_bucket.newspicks_bucket.bucket policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Principal = "*" Action = "s3:PutObject" Resource = "${aws_s3_bucket.newspicks_bucket.arn}/*" Condition = { StringEquals = { "aws:Referer" = aws_codebuild_project.example_project.service_role } } } ] }) }
となりますが、CDK
(typescript) なら
const project = new codebuild.Project(this, "CodeBuild", { name : "NewsPicksProject" description : "NewsPicks" }); const s3Bucket = new s3.Bucket(this, `NewspicksBucket`, { bucketName: "newspicks-bucket", removalPolicy: cdk.RemovalPolicy.DESTROY, versioned: false, lifecycleRules: [ { expiration: Duration.days(30), }, ], }); s3Bucket .grantPut(project);
となります。明らかに少ない記述量でやりたいことを実現できている。
特筆すべきは grantPut
メソッドで、
「S3へのアップロード権限をCodeBuildに与える」
という「やりたいことの本質」を簡潔に表現できます。(内部でPolicyの作成も勝手にやってくれている)
また各種プロパティは型安全なので、例えば過って expiration
に文字列を代入してしまうこともありません。
理由2. アプリケーションエンジニアにオーナーシップが生まれる
ある程度規模が大きくなったWeb系企業においては、インフラチームとアプリケーション開発チームに分業することは珍しくありません。
弊社でもSREチームが存在し、開発者体験の向上や安定したサービス提供のために日々仕事をしています。
ですが、個々のドメインを担当するメンバーは、基本的にそのアプリケーションが動作するインフラにも責任を持っています。
「SREチーム任せにするのではなく、担当ドメインのインフラ改善は自分たちでやっていこう( ∵CDKで簡単に構成変えられるから )」
断言しますが、CDKなしに、今のNewsPicksは存在してません。
これらは弊社の過去の取り組み紹介事例になりますが、全て CDK
を活用しています。
CDK
で楽ができるからエンジニアのリソースの空きが生まれ、その空きが改善への投資とオーナーシップを生んでいっていると良いでしょう。
理由3. 楽しい!
CDK
は楽しいです。
少ない労力で本質的なことに注力している感があり、実際その通りなのです。
我々エンジニアも人間ですし、体力も忍耐も限度があります。
本質的に向かい合う必要のないエラーに時間を使いすぎるのは嫌ですし、逆に自分なりに構成を考えてインフラ構築するのは楽しいです。
本質的に必要な部分に集中できる環境が CDK
なのです。
注意すべきCDKの代表的な落とし穴
ここまで CDK
の利点を紹介してきましたが、実際にやってみて体感した落とし穴も存在するので、いくつか紹介させて頂きます。
AWSの最低限の知識は必要
落とし穴というより AWS
を扱う上で当たり前なことになりますが、当然 AWS
に関するサービスに対する基本的な知識は必要とされます。
arn
って何?RDS
って何?- 権限?
Policy
って何?
という状態で、例えばコンテナを利用したWebアプリケーション開発をするのは難しいでしょう。
意図しない挙動になった際、CDKの内部実装を追う必要がある
CDK
は便利である反面、内部でよしなにやってくれている部分も多いです。(特にPolicyを自動生成してくれているケースが多い印象)
その「よしなに」が影響で意図しない挙動となった場合、CDKのコードを追ってみる必要があります。
スタック間参照で意図せずリソースの更新・削除ができなくなることがある
CDK
には「スタック」という概念が登場します。
VPN
や RDS
などのリソースは各スタック内で作成され、例えば「ネットワークスタック」内部でVPNやSecurityGroup、「データベーススタック」の内部でRDSが作成されることになります。
そうなると当然、とあるスタックに所属するリソースを別のスタックから参照したい場合がでてきます。
(例:SecurityGroupのサブネットを複数の別スタックで利用する)
しかしリソースをそのままスタック間参照した状態でデプロイした後、参照されているリソースの名前/IDの変更 or リソースそのものの削除をしようとすると、高確率でエラーとなります。
これを回避するには、ルールベースの命名規則を採用するのが1つの回答です。 リソースへの参照をする際、シンボルを直接渡さず名前でリソースの解決を行うようする方法になります。
また私はまだ活用できておりませんが、exportValue を利用する方法もあるようです。
最後に
私はもう CDK
なしに AWS
を触れなくなってしまいました。
皆様も少しだけでも良いので触ってみて、 CDK
の便利さを体感して欲しいです。
ありがとうございました。