インフラ変更にもコード変更と同じ規律が必要な理由
こんなシナリオを想像してみてください。チームの誰かが新しいサービスのためにポートを開放する必要がありました。その人はクラウドコンソールにログインし、ファイアウォールルールを追加して、そのまま作業を終えました。5分後、本番アプリケーション全体にアクセスできなくなりました。新しいルールが誤ってデータベースへのトラフィックをブロックしてしまったのです。何が変更されたのか、誰が変更したのか、どうすればすぐに元に戻せるのか、誰もわかりません。
このシナリオは、多くのチームが認めるよりもはるかに頻繁に発生しています。インフラの変更(ファイアウォールルール、ロードバランサーの設定、ストレージポリシー、ネットワーク設定など)は毎日起こるものではありません。しかし、ひとたび問題が発生すると、すべてが停止します。1つのセキュリティグループの設定ミスでアプリケーションがユーザーから見えなくなり、1つのDNS変更ミスでトラフィックがどこにも行かなくなります。
問題は、多くのチームがインフラ変更をアプリケーションコード変更とは異なる方法で扱っていることです。コード変更はプルリクエスト、コードレビュー、自動テスト、段階的なロールアウトを経ます。一方、インフラ変更はコンソールへの直接アクセス、アドホックなコマンド、共有クレデンシャルを通じて行われることがよくあります。この規律の差が盲点を生み、やがて障害を引き起こします。
Infrastructure as Codeは基盤であって、解決策ではない
Infrastructure as Code(IaC)とは、インフラ設定をファイルに記述し、リポジトリで管理し、自動化を通じて適用することを意味します。Terraform、Pulumi、AWS CDKなどのツールがこれを可能にします。しかし、リポジトリにIaCファイルがあるだけでは十分ではありません。規律は、それらのファイルへの変更をどのように管理するかから生まれます。
もし誰かがmainブランチに変更をプッシュし、レビューなしで本番環境に適用できてしまうなら、クラウドコンソールのシナリオと同じ問題を抱えていることになります。ツールは再現性をもたらしますが、安全性をもたらすわけではありません。安全性はプロセスから生まれます。
インフラ変更のためのテンプレート
すべてのインフラ変更は、再現可能なシーケンスに従うべきです。このシーケンスは、どのIaCツールを使用しているかに関係なく機能します。最も一般的な障害パターンからチームを守ります。
以下のフローチャートは、推奨されるシーケンスと判断ポイントを示しています。
コード変更から始める
すべてのインフラ変更は、インフラリポジトリへのプルリクエストとして開始しなければなりません。例外はありません。クラウドコンソール、サーバー上のCLIコマンド、手動スクリプトを介して、本番インフラを直接変更してはいけません。
プルリクエストは、何が変更されたかを正確に示します。新しいリソース、変更されたネットワーク設定、削除されたストレージバケットなどです。チームメンバーは差分をレビューし、質問し、何かが実行される前に問題を発見できます。変更の影響を理解している少なくとも1人のレビューアを必須にしてください。ネットワークやセキュリティグループなどの重要なインフラについては、2人のレビューアを検討してください。
適用前にプランを実行する
IaCツールは、実際に変更を加えずに何が変わるかを表示できます。Terraformではこれをプラン、Pulumiではプレビューと呼びます。概念は同じです。ツールが現在の状態と設定を比較し、作成、変更、削除されるすべてのリソースをリストアップします。
このプランをプルリクエストプロセスの一部として実行してください。出力を保存し、PRに添付します。レビューアは予期しない変更がないか確認します。削除されるべきでないリソースが削除されようとしていないか?間違った環境に変更が適用されようとしていないか?プランに驚くような内容があれば、先に進む前に停止して調査してください。
例えば、セキュリティグループ変更のTerraformプランは次のようになります。
Terraform will perform the following actions:
# aws_security_group_rule.app_ingress will be updated in-place
~ resource "aws_security_group_rule" "app_ingress" {
id = "sgrule-1234567890"
~ from_port = 8080 -> 8443
protocol = "tcp"
~ to_port = 8080 -> 8443
type = "ingress"
# (5 unchanged attributes hidden)
}
Plan: 0 to add, 1 to change, 0 to destroy.
この出力は、どのルールがどのように変更されるかを正確に示しており、レビューアは変更が適用される前にミスを発見できます。
まず非本番環境でテストする
本番環境に適用する前に、ステージング環境または開発環境に変更を適用してください。完全なインフラステージング環境がない場合は、本番環境の重要な部分をミラーリングした小さなレプリカを作成してください。一部のチームは、変更をテストするために専用のインフラアカウントまたはプロジェクトを運用しています。
ステージング環境がどうしても不可能な場合は、少なくとも本番環境に対して読み取り専用モードでプランを実行してください。これにより、実際に何も変更せずに、何が変わるかを可視化できます。
ラップトップではなくパイプライン経由で適用する
実際の適用コマンドは、開発者のマシンではなくCI/CDパイプラインで実行する必要があります。パイプラインは、誰がいつ適用をトリガーしたか、何が変更されたかを記録します。この監査証跡は、デバッグとコンプライアンスに不可欠です。
パイプラインは、適用が途中で失敗した場合、すぐに停止する必要があります。失敗後に他のリソースへの変更を続行させてはいけません。部分的なインフラ変更は診断が難しく、修正はさらに困難です。
ロールバック計画を用意する
適用する前に、問題が発生した場合に変更を元に戻す方法を把握しておいてください。イミュータブルインフラの場合は、新しいリソースを破棄し、以前の状態から古いリソースを再作成します。ミュータブルインフラの場合は、変更を加える前に設定のスナップショットまたはバックアップを取得してください。
インフラの状態ファイルはバージョン管理されたバックエンドに保存してください。迅速に復元できるように、最後に正常だった状態ファイルを保持しているチームもあります。ロールバック計画は文書化され、テストされている必要があり、インシデントの最中に考え出すものではありません。
適用後に検証する
適用がエラーなく完了したからといって、すべてが正常であると想定してはいけません。新しいリソースが実行されていることを確認してください。ネットワーク接続が機能することをテストしてください。インフラに依存するアプリケーションが正常であることを確認してください。
この検証を可能な限り自動化してください。リソースの状態を確認し、エンドポイントにpingを送信し、接続テストを実行するシンプルなスクリプトで、適用コマンドが報告しない問題を発見できます。
インフラ変更のための実用的なチェックリスト
- 変更はインフラリポジトリのプルリクエストとして開始されている
- 変更の影響を理解している少なくとも1人のレビューアがPRを承認している
- プラン出力がレビューされ、期待と一致している
- 変更が最初に非本番環境に適用されている
- 適用はローカルマシンではなくパイプライン経由で実行される
- ロールバック計画が文書化され、準備されている
- 適用後の検証チェックに合格している
このチェックリストは官僚主義ではありません。クラウドコンソールでの1回のクリックから始まり、チームが何が起こったのかを必死に理解しようとする障害から身を守るためのものです。
まとめ
インフラ変更は、高リスクかつ低頻度の操作です。この組み合わせが危険です。めったに行わない作業はミスを犯しやすく、影響範囲が広いため、そのミスはより大きなダメージを与えます。
インフラ変更をアプリケーションコード変更と同じ厳格さで扱ってください。プルリクエスト、レビュー、プラン、ステージング環境、パイプライン実行、検証はオプションの追加機能ではありません。これらはインフラを安定に保つための最低限のプロセスです。使用するツールよりも、適用する規律の方が重要です。