はじめに
「私…全ての手動作成AWSリソースを生まれる前に消し去りたい。全ての宇宙、過去と未来の全ての手動作成AWSリソースを…この手で!」
そんなことを思われた経験はないでしょうか?私は常に思っています。
こんにちは。ソーシャル経済メディア「NewsPicks」のSREチームの安藤です。 先日の JAWS-UG CDK支部 #14 にて、テーマが「IaC Generator祭り」だったこともあり、以下のタイトルでLT発表させていただきました。
上記の発表はAWS CDKのコミュニティのライトニングトークということもあり簡単なTIPS紹介が中心だったので、本記事では改めて背景と概要について紹介します。
背景
NewsPicksというサービスは10年以上の歴史があり、サービス開始当初からAWSを利用していました。
現在は、Infrastructure as Code (IaC)にAWS CDKを全面採用し、インフラを担当するSREチームだけでなく、多くのプロダクト開発エンジニアがインフラの構成変更をコードで行いデプロイしています。バックエンド開発に関わるエンジニアの大半はCDKによるインフラのデプロイ経験があるという状況です。
AWS CDKはNewsPicksのプロダクト開発エンジニアに好まれており、AWSを使うならCDKを使うべきと強火の主張をするファンがいるほどの人気です。 tech.uzabase.com
インフラエンジニアとしてのキャリアが長い筆者としては、インフラの定義をDSLで記述するか汎用プログラミング言語で記述するかの議論は馴染み深く、メリット・デメリットにも頷けるところではありますが、それなりの規模の開発組織でバックエンド開発者がインフラの構成変更を自律的に行うツールとしてのCDKはかなり筋が良い選択肢だと思います。
Web開発者が使い慣れたTypeScript開発環境(VSCode)でLinter/Formatter/入力補完の支援を受けられ、各種プロパティが型安全であり、AWSのベストプラクティスに沿った設定やインターフェースがデフォルトで組み込まれたL2 Constructによってシンプルに記述できること、SREチームとしても設定値にTypeScriptの柔軟な型(Union型など)を利用して安全にインフラを変更するための制約を提供できるなど、CDKのメリットを上げればきりがありません。
結局インフラのコードは「インフラを上手く運用できる」ことが重要であり、数十人の開発者でCDKのコードを毎日のように修正しても事故なく本番に適用できているNewsPicksの現場は、筆者の十数年のエンジニアキャリアの中でも過去一でIaCを使いこなして上手くAWSインフラを運用できていると感じます。
NewsPicksの約70名のエンジニアに対してSREチームが5名でなんとか足りていることも、開発者がインフラをセルフサービスで変更できる仕組みが整っていてスケールできていることの証左かと思います。SREチームがインフラ変更依頼を受けて作業するモデルではこのスケールは難しいでしょう。
しかしNewsPicksのAWSサービス利用歴は10年以上、対してCDKはGAして5年程度と、この数年でAWSインフラもほとんどが作り直されてIaC化されたとはいえ、サービス開始当初から存在するストレージやネットワークのリソースは当然のように手動作成されていてコードとして管理されていませんでした。
コード化されていないと以下のように困ったやりとりが生じることがあります。
開発チーム「このネットワーク設定の変更のPRを出したいと思ったんですが、CDKのコードってどこにありますか?🤔」
SREチーム「う、、ごめんなさい〜🙏手動作成なので、dev環境で変更手順を検証して、本番のマネコンで変更権限を持った人とのペア作業でリリース実施していただけますか?🙇」
NewsPicksでは、開発者自身でCDKのコードを変更しPRを出してインフラの変更を行うことができます。CDKに慣れたメンバーにとっては、はっきり言って今更マネコンでぽちぽち検証してペア作業で本番リリースするなどストレスの極みです。
CDKによる変更は、SREチームのレビューでPRが承認されることを条件に開発チームのメンバーが本番適用できるようにしていますが、マネコンやCLIによる本番環境の変更はIAMの権限で制限しているため、手動作成AWSリソースは、開発者がセルフサービスでインフラの変更を行う開発者体験を阻害していました。
そんなわけで手動作成AWSリソースを少しずつでも減らしていきたいと考えたのが本記事で紹介する取り組みのきっかけです。
cdk importを行うために検討すること
CDKには cdk import
というCLIコマンドがあり、既存リソースをCDK管理にすることが可能です。
docs.aws.amazon.com
ただし、これを行うには実際の環境にデプロイされたリソースを作成するCDKのコードを用意する必要があります。
本番環境に作成されたリソースのプロパティを目視確認でコード化するには手間がかかりますし、手作業で差分が発生するミスも怖いです。
そこで、IaC Generatorと cdk migrate
を利用します。
docs.aws.amazon.com docs.aws.amazon.com
IaC Generatorは、実環境に作成された任意のAWSリソースを選択し、CloudFormationテンプレートを生成してくれるサービスです。cdk migrate
は、CloudFormationテンプレートをCDKのコードに変換するCLIコマンドです。
IaC Generatorと cdk migrate
によって手動作成AWSリソースのIaC化の大部分を自動で行うことができます。
ただしそのままでは実際に運用できるコードにはなりません。 cdk migrate
を実行すると新しいCloudFormationスタック単位のCDKコードが作成されるので、IaCのデプロイ単位であるスタックが無造作に増えてしまうことになります。また、設定値がすべてハードコードされているので環境別のデプロイにも対応できない、IaCとしては片手落ちの状態です。
そのため cdk migrate
と cdk import
の間で、既存のCDKコードのスタックに取り込んで管理できるようにするための書き換え作業が必要と判断しました。
ここはさすがに人の目による確認が必要ですし、自動でIaC化されたコードに修正を加えて本番リソースとの差分が発生しないことを複数人で担保するために、 IaC Generator -> cdk migrate
-> [書き換え作業] -> cdk import
までを一気通貫でモブプロで実施し本番適用を終わらせてしまおうと考えました。
毎月の当番制で「cdk import day」というイベントを開催
ここからは発表資料に記載の内容です。
SREチームでは毎月持ち回りで当番が主体となって「cdk import day」という1時間の定例モブプロを行っています。
モブプロの流れは以下の通りで、ポイントは「1時間で終わるように設計する。頑張らない」という点です。
- (事前準備)IaC Generatorのスキャンを開始しておく
- 取り込み対象のリソース・スタックを決める
- IaC Generatorでリソースを作成して、テンプレートを作成
- 作成したテンプレートから
cdk migrate
でスタックのコードを作成 - スタックのコードをConstructに(みんなで)書き換える
- 既存のCDKのスタックにConstructを移植(本番環境のみデプロイされるように)してPR作成
cdk import
で既存のCDKコードで管理するCloudFormationスタックにimport- CloudFormationで本番環境のドリフト検出 -> 既存リソースと差分が発生していないことを確認
- PRをマージして完了
「1リソースだけ、本番だけでよい、活動を継続して少しずつでも手動作成AWSリソースがIaC化されることが重要」 と考えて取り組んでいます。
IaC Generatorによる自動生成では、「設定値がすべてハードコードされているので環境別のデプロイにも対応できない」という制約がありますが、この制約は受け入れることにしました。
とりあえず本番リソースを取り込んでCloudFormationで管理できるようにしてしまえば、以降のコードのリファクタリングは cdk diff
による差分チェックで安全に行えますし、本番以外の環境に対する変更はモブプロでなくても一人でできるので気楽です。
環境別のデプロイに対応した既存CDKコードに本番環境のリソースだけを cdk import
する方法は、環境別パラメータによって移植したConstructのデプロイを制御することで実現しています。
これによって、自動でIaC化されたコードに加える修正を最小限にして、1時間のモブプロで既存のCDKコードの管理下にIaC化する作業を行えるようになりました。
LT発表時の反応
LT発表時の反応は以下の通りで、CDKのプロの方々からもありがたい賞賛の言葉をいただきました。
本番だけ管理する、頑張らない、大事ですね!1時間でできるところまでやっているのがすごく良いアプローチ #jawsug_cdk
— Kenji Kono (@konokenj) 2024年5月22日
これは AWS CDK 本家の機能フラグと同じ考え方ですね。いいパラメータの使い方だ。#jawsug_cdk pic.twitter.com/gfQeL6Hm8A
— ゆっきー (@WinterYukky) 2024年5月22日
余談
余談ですが、なぜ1時間の定例なのに 「cdk import day
」なのか?という点については、SREチームの他の会議体でも〜dayという定例イベントがある慣習に倣ったものです。
「Debug Friday」や「Security Day」といった、重要だが緊急ではないタスクの優先度を定期的に高めるために「この日はバグ潰し・この日はセキュリティ改善に専念するぞ」という意気込みをチームとして設定しているので、「今日はcdk importの日」というチーム文化を新たに作りたかったという思いもあります。
SREチームのその他の定例イベントについてもしご興味がありましたら、以下のスライドをご覧ください。
おわりに
定期的なcdk importをチームの文化、仕組みとして導入することで手動作成リソースを継続してIaC化する取り組みをご紹介しました。
「すべてのリソースがIaC化されていて、開発チームがコードによる変更を行いセルフサービスで本番にデプロイできる」という状態は、モダンで開発者体験の良い環境だと思います。10年モノのサービスがモダンで開発者体験の良い環境を目指していくには、不断の努力を継続する必要があります。
どうせ努力を継続するなら、チームで楽しくわいわいやっていきたいですね。ちなみに筆者は2年前から「早く隠居してcdk importするだけのおじさんになりたい」と言い続けていますが、cdk importを本業にする前にまだまだやることがたくさんあるので、せめてチームの定例活動にしようと思ったのでした。
早く隠居してcdk importするだけのおじさんになりたいという話をした
— あんどぅ (@integrated1453) 2022年7月29日