😀

Terraform運用をスケールしたい

2022/12/24に公開

この記事は、 NTT Communications Advent Calendar 2022 25 日目の記事です。

はじめに

こんにちは、イノベーションセンターの松本です。ソフトウェアエンジニアとして活動しています。
この記事では、チームが大きくなったときに苦労するTerraform運用について記述します。

上手くいってた頃のTerraform運用

Terraformを開発チームで少人数で使い始めた直後や、また運用担当者だけで使っている状態では問題はありません。
コードを整理して記述し、GitHub等を使ってバージョン管理やレビューすることで、開発者がインフラをセルフサービスで変更できるようになり、多くの仕事を早く終わらせる事ができるようになります。

大きなチームにおけるTerraform運用の混乱

開発チームのメンバーが増えたり開発チームだけでなく運用チームや顧客対応チームもTerraformを使い始めたりと利用者が増えると混乱が起き始めます。

問題というのは以下のようなものです。

構成ドリフトの発生

Terraformのステートと実環境での差が発生する構成ドリフトの発生が増えます。原因は主に2つです。

1つ目はデプロイ先のクラウドやSaaSをメンバーが手動で変更してしまうことです。ほとんどの構成ドリフトはこれが原因で、例えば検証用用にインスタンスを増やしたりリソースを変更したり、なんらかの作業のために一時的にIAMの権限を付与したりというものです。このような変更は作業後に元に戻される事なく忘れ去られ、他のメンバーがTerraformをPlanした段階で差分に気がつきます。そのメンバーは、リソースを消して良いのかとTerraformを利用するメンバーに聞き回って調整する必要がありますので、仕事が遅れます。当初は許容できた構成ドリフトも利用者が増えてくると回数が多くなり許容できなくなります。

2つ目はFWルールなどに他サービスの動的な外部からの情報を利用してOutgoing IPアドレスなどを登録したり、連携するサービス等から自動的に変更される場合です。これらは明らかに必要なことが殆どでしょうから、単にコードを修正してApplyして整合させれば良く、調査や調整は不要ですので仕事が遅れる事はありませんので気にする必要はなさそうです。

想定外のリソースの変更・削除

想定外のリソースが削除されることがありますが、この発生には主に2つの原因が考えられます。

1つ目は、前項にある構成ドリフトがあった場合です。Plan時にレビューされ差分を確認してからApplyされますが、レビューで意図しない差分を見逃すこともあり、結果としてリソースは変更・削除されます。

2つ目は、同じ時期に複数の利用者がPlanしてApplyすることです。これは通常の利用なのですが、例を出すと、利用者Aと利用者Bが同じ時期にmainブランチからpullしたコードを修正し、ユーザAがリソースを作成した後にユーザBが異なるリソースを作成する場合、ユーザBはユーザAの変更を知りませんので、ユーザBがApplyした際にユーザAのリソースを削除してしまいます。これを防ぐために、ユーザBはユーザAの変更がmainに取り込まれるのを待ってからmargeしApplyするような調整が必要となりますので、仕事が遅れます。

いつ誰が変更したのか分かりにくい

デプロイ対象となるクラウドやSaaSは複数使う事があり、いつ誰がどのような変更したかを知るのは大変です。GitHubでcommitログを見たり、クラウドやSaaSの監査ログを見たりしますが、利用する認証情報の種類によっては個人を特定することが難しい場合もあります。

何か問題があった場合、不明点があった場合に、誰か知らないかと広く問いかけたりして返答を待つようなことになり、仕事が遅れます。

どのように対応していくか

このような混乱はなかなか解決しません。どのような対応方法があるか検討していきます。

ルールを作っていく

最初はルールを決めて運用対処していくのですが、これではなかなか解決しません。

  1. 構成ドリフトを防ぐルール

構成ドリフトのほとんどの原因であるクラウドやSaaS等の手動変更を禁止します。しかし、手動変更することで仕事を早く終わらせられる事もありますので、たとえあとで構成ドリフトの発生により誰か他のメンバーの仕事が止まってしまう事になるとしても、なかなかやめられない場合も多いようです。

  1. 予期しない変更や削除を防ぐルール

通常の利用でも複数人で同時に変更作業をしてしまうと、予期しないリソースの変更や削除が起こる場合もあります。

mainからブランチを切ってPR作ってレビューし、Apply後にマージする人もいるでしょうし、マージ後にApplyする人もいます。Applyできたものをマージすれば綺麗なコミットログになりやすいでしょうが、他のメンバーが作成したリソースを削除してしまうかもしれません。これを防ぐには前述したように他のメンバーの変更を待って、そのコードを取り込んでから実行する必要があります。

マージしたものをすぐにApplyするようにした方が意図しないリソースの変更や削除は防げるように思います。

マージ後に直ぐにApplyするルールを作るのが良さそうです。このルールは上手くいきそうに思うのですが、構成ドリフトの多い環境では、—targetオプションを指定して自分の変更のみを適用するようになるようです。そして構成ドリフトを見逃して意図しない変更や削除することは続きます。

自動化を始める

ルールを決めてもなかなか問題は解決しません。構成ドリフトは発生し続けますし、これを起因としてマージ直後にApplyするルールも守られなくなります。そこで、自動化の仕組みを作ることを考えます。

  1. PRベースの自動化を始める。

AtrantisはTerraformの自動化として使われているオープンソースのプロダクトです。GitHubのPRを作ると自動的にPlanが実行され、チームメンバーによるレビューの後にPRのコメントを使ってコマンドを入力することでApplyできます。ローカルPCに強い権限の認証情報を準備したりTerraformやProviderのバージョンに悩まされることなくApplyできますので、今まで手動実行を好んでたケースでもAtrantisを使う便益を得ることができ、構成ドリフトも防げて適用手順も統一できそうに思えます。
しかし、AtrantisはApply後にマージするという方式です。複数メンバーで同時に作業すると、予期しない変更が起きてしまう可能性があります。これを防ぐためにAtrantisの持つロック機能が使えそうです。また、-checkout-strategy=mergeオプションをつける事で、Plan時にmainをマージできるので予期しない変更を防げそうです。
また、AtrantisはPRに全ての変更について記録されるようになりますので、いつ誰が変更したのかは追いかけやすくなります。

  1. IaC向けのCI/CDを利用する

test実行やポリシーの適用、承認、適用などをCI/CDを使って実現することで早く安全な実行環境を作ります。
GitHub Actions やCircle CIのような汎用的なCI/CDツールを使うのも良いのですが、多くの努力が必要です。HashiCorpが提供するmanaged TerraformであるTerraform Cloud やその他のTerraform Cloud Alternativesを利用するのも良さそうです。なお、SpaceliftはCI/CDを名乗っていますが、その他のプロダクトは、terraformの自動化やremote backendと名乗っており保有する機能も違いますので、採用するプロダクトの決定には必要なユースケースを検討して実験が必要そうです。

プロダクト名 情報源
Terraform Cloud https://cloud.hashicorp.com/products/terraform
Spacelift https://spacelift.io/
Env0 https://www.env0.com/
Scalr https://www.scalr.com/
  1. 構成ドリフトの検知を始める

構成ドリフトは発生しやすく、放置すると他のチームメンバーの仕事を止めてしまうだけではなく、設定内容によってはセキュリティリスクも生じますので、早めに検知して対処した方が良いと思います。構成ドリフト検知機能はTerraform Cloudでも実装されており、同様の機能は多くのTerraform Cloud AlternativesやOSSでも提供されています。

プロダクト名 情報源
Spacelift https://docs.spacelift.io/concepts/stack/drift-detection
Env0 https://docs.env0.com/docs/drift-detection
driftctl https://driftctl.com/

Spaceliftを使ってみる

私たちのチームはCI/CDのプロダクトを開発するチームで、他社のプロダクトを試すワークショップを開催した際にSpaceliftを試してみました。専用のプロダクトらしく簡単な操作でIaCの自動化環境を始める事ができました。

以下は、GitHubのPRをマージによるApplyを試した例です。

これはStackの一覧画面です。

SpaceliftはStackという単位でTerraformの実行を管理しますので、ステートの数だけStackを作ることになります。

スタック一覧

Stackの実行履歴です。

スタック実行履歴

実行履歴の詳細を見ると、PlanやApplyの実行結果も確認する事ができます。

実行がどのユーザによってどこに適用されたかグラフィカルに表示する事もできます。

また、現在のリソースの状況をグラフィカルに表示できます。

Policyの作成は画面上のエディタで記述し試しながら作成することができました。

おわりに

多くの利用者でTerraformを運用するのは難しく、構成ドリフトの発生や予期しないリソースの変更や削除により調整に長い時間を使ってしまったり、問題が発生した場合に何が発生しているのか実行を追いかけるのは大変です。
IaCのために一般的なCI/CDツールを使うと構築に大きな手間が掛かりますが、専用のツールを使うと随分と少ない手間で構築ができることが分かります。
今回は、チーム内のワークショップの中でSpaceliftを試してみましたが、ビジュアライズやPolicyの作成機能など、私たちのチームが開発するプロダクトの参考にすることができました。

今年のNTT Communications Advent Calendar 2022 はこれで終わりです。ご覧いただきありがとうございました。

Discussion