Webサービスのインフラは年々複雑化しており、コード化なしにインフラを構築するのはどんどん難しくなっています。最近はIaC(Infrastructure as Code)のPulumiを使ってインフラをコード化しているので、使用感を書いてみようかと思います。
むかし話
私がまだ新卒だった2011年〜2012年あたりでは、ChefとCapistranoを使ってAWSのEC2のサーバーの構築を自動化していたような気がします。私がメインでやっていたわけではないのですが、Capistranoあたりは少し触っていました。 その後はAnsibleも少し扱ったことがありますが、このあたりまでの記憶はほぼないので省略します。
明確に記憶があるのはAWSのリソースをYAMLで宣言的に記述できるAWS CloudFormationです。 CloudFormationはEC2の中身をセットアップをするようなものではなく、AWS上のリソースを用意するためのものです。EC2のサーバーを立てる、RDSを立てる、WAFを立てる、といったAWS上でのリソース全体を構築します。
この時代は既にサーバーの中身の構築はDockerにトレンドが移行していました。CloudFormationでAWS上のリソースを用意して、サーバーの中はDockerのImageを動かすということをしていました。
YAMLでリソースを作るの大変すぎ問題
CloudFormationはYAMLで書きます。これがなかなか辛いです。 当たり前ですがYAMLには型がないので、ドキュメント見ながら書いてても普通に間違えちゃうんですよね。タイポというより、オプション等のネストの指定の仕方などYAMLでの構成を間違えてしまいます。
悪いことにAWS側のYAMLの検証が微妙で、記述が間違ってても普通にデプロイが走ってしまうことがままあり…というか今は分かりませんが当時は間違っててもほぼ通ってしまい、実行時にミスが分かってロールバックされるのが辛いです。もっと酷いとロールバックできなくなって手動で戻さないといけない時もあります。
顕著に悪い部分が出るのは、DBやCloudFrontなど作るのに時間がかかるリソースの作成や更新の時ですね。デプロイ始めてから30分後にロールバックされてしまうと、1日8時間勤務だとして16回しか試せないという…。
また、プログラミング言語で書けば一瞬で終わるようなものを地道に書かなければならなかったり、YAML上で特殊な記法を使って保守性を高める必要があったりする点も微妙でした。
そしてPulumiへ
とにかくYAMLが嫌で、型のあるモダンなプログラミング言語でAWSを構築したいという思いでPulumiに飛び込んでいきました。 今であればAWS CDKも良いと思うのですが、当時はまだ生まれたてだったので選択肢には入りませんでした。
PulumiはモダンなIaCです。簡単に特徴をまとめると、次の通りです。
- TypeScript、Python、Go、.Net(C#など)といったプログラミング言語でインフラの構成を宣言的に記述できます
- AWSやGCPなどマルチクラウドのリソースを構築できます
- Kubernetesのマニュフェストなどもプログラミング言語で書けます
私はTypeScriptで書いていますが、とても生産性が高いです。
Pulumiを実運用した感想
しばらく運用しているので簡単に感想でも。
良いところ
TypeScriptで書けるのはとても便利です。 型がある点だけでなく、インフラでのコンテキストスイッチが小さくて済む点もお気に入りですね。私はフロントもバックエンドもTypeScriptで書くので、いざインフラのコードを書く時も違和感なく書けます。
もう1つお気に入りなのは、PulumiではDevOpsで必要なワークフロー全体をシームレスに統合できるところです。 例えば、k8sのサポートがかなり入ってるので、PulumiのコードとしてDockerのimageを作って、レジストリに上げて、k8sのマニュフェスト更新するところまでワンストップで短い行数で記述できます。あとはGithubのPull Requestのマージ時にそのコードをCI/CDでキックするだけで、自動的にk8sのPodを入れ替えることができます。 他にも、アプリケーションやインフラで使用する各種シークレットの管理もできます。DBのパスワードをコード上で作ってから、k8sのPodの環境変数に埋め込んだりできるので、パスワード管理しなくて良い部分も多いです。
他にもインフラの構築を便利にするもの(例えばDBの移行スクリプト的なものを作れるAPIなど)がたくさんあり、痒いところに手が届きます。
微妙なところ
Pulumiはマルチクラウドに対応しており、AWSやGCPなど様々なところでリソースを作れます。AWSやGCP以外にも、変わったところでは認証基盤であるAuth0でテナントを立てたりできます。
これはProviderという、雑に言うとプラグインシステムのようなものを本体と一緒に使うことで実現されています。AWSのProviderやGCPのProviderがあり、それ経由でリソースを構築するということです。
そのPulumiのAWSのProviderなんですが、なんと競合のTerraformがOSSとして作っているterraform-provider-awsをベースに、型を導入するなど手を加えて使っているんですね。ドキュメントにもしっかりとThis Pulumi package is based on the aws Terraform Provider.と書かれています。
それ自体は良いのですが、terraform-provider-awsで対応が遅れているリソースは当然Pulumiにもないんですよね。例えばAWSにWAFv2のリソースが作れるようになってから半年以上は、Terraformが対応できてなかったのでPulumiも同時に対応していないという状況だったと思います。
また、terraform-provider-awsから生成した型が微妙なところがちらほら。インスタンスタイプなど、明らかに型をUnion(またはEnum)で表現できるところをstringにまとめちゃっていて、タイポできる余地が残っているところがあります。
まとめ
正直、Pulumiにはかなり満足しています。今までのインフラ構築の体験の中でベストな体験です。 AWSのリソースを作るということ以上に、アプリケーションとインフラの構築プロセスの全てがちゃんと便利になっている実感があります。
しかし不満がないわけではなく、不満の一部はAWS CDKに分があるように思うので、時間があればAWS CDKも見てみようかなと思っています。