IaC、あるいはインフラ抽象化レイヤー導入時に考えたらいいんじゃないかと思うことを雑多に書く

この記事はSRE Advent Calendar 2023の4日目の記事です。

qiita.com

3日目は@myu_mxさんのゆるやか成長スタートアップの小さなEnabling SRE的活動でした。

久々のアドカレ参加ですが、少し思いの丈に任せてみようということで経験と主観が強めの記事です。
この辺で語られていたよとかこれは賛同できないというポイントなどもっといい情報があればぜひお知らせください、という感じで雑多に書いて参ります。
TerraformやCloudformationあたりをよく触るのでそのあたりがどうしても頭にありますがなるべく固有の話はしない方向で。

色々書きつつ、基本的には長期的な運用を見越したソフトウェアの運用設計と同じ考えで良いとは思ってます。
最低限のインターフェースを公開し疎結合に設計する、モジュールは交換可能する、ライフサクルを考える、などなど。

ただIaCコードは割と長生きする傾向にあるので、コードを書き始める前に少し注意深く設計しておくと長期的に楽になるんじゃないかと思います。

解決すべき課題を明確にする

  • ここからかー、となる話でもありますが、コード化は手段であり、目的ではないので、課題が何でアプローチが適切なのか、他にやり方はないのか考えるべきです
  • 後述しますが、運用上IaCが向かないリソースというものも当然存在するので、シェルスクリプトやWebコンソールでの手作業も手段の一つとして検討に入れておきましょう

ワンショットで使うか長期的に更新適用し続けるか

  • 環境の初期構築のみに使うか、一度構築してコードの管理下においたものを更新し続けるか、これは導入前に必ず決めたほうが良いでしょう
  • 判断の一つとして、運用中に変更が発生することがほぼなく、消えたらどう考えてもまずいようなリソースは予めワンショットで作成しておき、以降はコード管理下から外しておく方が運用しやすく安全であるケースがあります(典型的にVPCやサービスで利用するドメインのゾーン情報など)

リソースのライフサイクルを考える

  • ライフサイクルがあまりに異なる状態をひとまとめにすると、同時に管理されているほぼ更新のないリソースが足かせになったり依存関係により管理上の手間が増えます
  • あるインフラ環境、認証基盤、なんでも良いのですがそれらの全体のライフサイクルがあるとして、頻繁に更新のかかる部分とそうじゃない部分は分離して、必要な状態のみを参照するような設計を予め考えておくとトータルでメンテが楽になります
  • 個人的には一発で構築するということにこだわらず、システムの境界を跨ぐ部分は状態を分けておいた方が、それぞれのシステムのライフサイクルに合わせて余計な依存関係を持ち込まずに更新可能となるため、特に長期運用するシステムではおすすめです
  • Terraform的にいうとproviderがいくつも混在するようなコード管理は避けた方が良いと考えています

適用範囲を考える

  • コードを書き始める前にどこまでをコード管理をすべきか、を検討する
  • 雑な一般論としてIaCなソリューション各位は宣言的である(ものが多い)故に「どういった状態にするか」は得意で「どうやってその状態にするか」はあまり得意ではないので、後者が重要視されるものは別のツールや手段による運用が向いている
    • 例えばDBの切り替えみたいなオペレーション系
    • 証明書の更新、DNSレコードの変更など、新旧用意して切り替える系
    • snapshotからの復旧など状態をもって運用オペレーションを伴うリソース
  • 変更プロセスに重きをおいて安全性を担保するようなオペレーションが該当するかなと思います
  • 余談としてはクラウドベンダーのWebコンソールなどでは追加のバリデーションが期待できたり、API上提供されてないオペレーションをそれっぽく組み合わせて提供していることもあるのでそういったものにも価値があるということも考えておくとよいでしょう

抽象化レイヤーは必ず動くとは限らない

  • 割と失敗するので失敗しても安全なように設計する
  • 一般に抽象化レイヤーを挟んだトラブルシューティングAPIを直接操作するより面倒になるため、これもトレードオフの一つとして考えておきましょう

必要な機能について確認する

  • 当たり前ですが抽象化レイヤーを挟むと基本的にはその上位のレイヤーの機能に対して遅れて対応されるということを理解しておく
  • AWSのベンリ新機能でました、でもCloudFormationではまだ使えません、みたいなアレです
  • コード書き始める前に、必要な機能がサポートされているか見ておきましょう

先々のバージョンアップペースについて考える

  • ワンショットの利用でない場合、IaCコードは基本的に管理するリソースのライフサイクルとともに生き続けるので(途中でやめることもできるが)、長期的なライフサイクルをある程度考えておいた方が良い
  • コード化にあたって例えばTerraform導入しました、コード化できました、といったときに実際に導入しているのはTerrafom1.6.5であったりAWS CDK2.110.0であったりするし、AWS Provider5.29.0だったりするということを意識する
  • これらの、少なくとも主要なコンポーネントがどの程度のペースでリリースに追随していく必要があるのか、ということを導入時点で考えておくとよいでしょう