本番環境を壊さずにインフラ変更をテストする方法
ある開発者がファイアウォールルールを少し変更しました。「ちょっとした設定変更だ」と思ったのです。数分後、誰もアプリケーションにアクセスできなくなりました。ユーザーからエラー報告が相次ぎ、チームは原因究明に奔走します。
このようなシナリオは、多くのチームが認めたくないほど頻繁に発生しています。インフラの変更には隠れたリスクが伴います。データベースの設定ミスはデータを破壊する可能性があります。ネットワークポリシーの変更はサービス全体を孤立させかねません。そしてアプリケーションコードとは異なり、インフラの問題は多くの場合、すべてに一度に影響を及ぼします。
すべてのチームが答えを出さなければならない問いがあります。それは、本番環境に適用する前に、インフラの変更をどこでテストするのか、ということです。
インフラにおける環境問題
チームが手動でサーバーを管理していた時代、この答えは曖昧なことがほとんどでした。テスト用サーバーを用意しているチームもあれば、「小さな設定変更だから」と直接本番環境を変更するチームもありました。インフラにおける小さな変更が、影響範囲も小さいままであることは稀です。
アプリケーションにはこの問題に対する自然な答えがあります。ステージング環境です。新機能をステージングでテストし、動作を確認してから本番環境にデプロイします。インフラにも同じアプローチが必要ですが、ひとつ注意点があります。
インフラを完全にコピーできるとは限りません。サーバー、ネットワーク、データベースの複製には実際にコストがかかります。数十台のサーバー、ロードバランサー、データベースクラスターを備えた本番環境をミラーリングするステージング環境は、インフラ費用を何倍にも膨らませる可能性があります。課題は、徹底的なテストとコスト管理のバランスを見つけることです。
基本原則:テストの前に隔離する
すべてのインフラ変更は、本番環境に触れる前に、隔離された環境を経由しなければなりません。ここでの隔離は厳格です。ステージング環境は本番環境とリソースを一切共有してはいけません。データベースの共有も、ネットワークの共有も、実際のユーザーデータへのアクセスも禁止です。
もしステージングと本番が同じサーバーを共有していたり、同じVPC内にあったりするなら、それは隔離とは言えません。ステージングでのミスが本番環境に波及する可能性があります。設定を誤ったステージングデータベースが本番データを上書きするかもしれません。共有ネットワークルールがステージングサービスを本番トラフィックにさらす恐れもあります。
隔離だけでは十分ではありません。ステージング環境は、本番環境の構成を可能な限り再現する必要があります。本番環境がロードバランサーの背後に3台のサーバーを配置しているなら、ステージングも同じ構成にすべきです。本番環境が特定のデータベースバージョンを使用しているなら、ステージングもそれに合わせなければなりません。
目標は、ステージングを本番と同じくらい強力にすることではありません。目標は、特定の構成でのみ現れる問題を発見することです。小さなステージングインスタンスでは問題なく動作するデータベースクエリが、本番環境の負荷下ではタイムアウトするかもしれません。簡略化したセットアップでは通るネットワークルールが、実際のトポロジーでは正当なトラフィックをブロックする可能性もあります。
実践的な環境レイヤー
ほとんどのチームは、複数のインフラ環境レイヤーを用意することになります。各レイヤーは異なる目的を持ち、コストと忠実度の間で異なるトレードオフがあります。
開発環境は、開発者が小さな変更をテストするためのものです。最小限のリソースと簡略化された構成を使用できます。クラスターの代わりに1台の小さなサーバー、レプリケーション構成の代わりにローカルデータベースなどです。重要な要件は、ステージングおよび本番環境からの隔離です。開発環境は、偶発的にでも本番リソースに触れてはいけません。
ステージング環境は、統合テストのためのものです。規模は小さくても、本番環境の構成を可能な限り忠実にミラーリングする必要があります。同じオペレーティングシステムバージョン、同じランタイムバージョン、同じネットワークトポロジーです。違いは通常、容量にあります。サーバー台数が少ない、インスタンスが小さい、ストレージが少ないなどです。しかし、構成パターンは一致していなければなりません。
本番環境は、実際のサービスを実行します。変更がここに到達するのは、開発環境とステージング環境でのテストを通過した後だけです。
以下の図は、変更が各環境レイヤーをどのように流れ、検証ゲートが未検証の変更を本番環境に到達させないようにするかを示しています。
設定の落とし穴
多くのチームをつまずかせる詳細があります。それは環境固有の設定です。データベースのパスワード、APIキー、サーバーアドレスが環境間で異なるのは明らかです。しかし、その他の設定は一貫しているべきです。
オペレーティングシステムのバージョンは全環境で同じであるべきです。ランタイムのバージョンも一致させる必要があります。ログ記録のルールも同一であるべきです。これらが環境間で異なると、問題が潜む隙間が生まれます。特定のOSバージョンでのみ発生するバグが、ステージングで異なるバージョンを使っているために表面化しないかもしれません。
解決策は、設定を種類ごとに分離することです。環境固有の値は環境ごとに別々のファイルに格納します。共通の設定は一度記述して、すべての環境に適用します。オペレーティングシステムのバージョンをアップグレードするときは、3つの異なるファイルではなく、1か所を変更するだけですみます。
CI/CDがインフラ環境を管理する方法
インフラ変更のパイプラインは、明確な順序に従います。
- コードレビューまたは計画ツールを通じて変更をレビューする
- 変更を自動的にステージングに適用する
- リソースが正しく作成されたことを確認するテストを実行する
- 既存のリソースが壊れていないことを検証する
- 同じ変更を本番環境に適用する
各ステップは、同じInfrastructure as Codeツールを通じて実行されます。同じTerraformプラン、同じAnsibleプレイブック、同じPulumiプログラムが最初にステージングに対して実行されます。それが合格すれば、本番環境に対して実行されます。
このプロセスにより、すべてのインフラ変更が、実際のユーザーに影響を与える前に、本番環境をミラーリングした環境を経由することが保証されます。パイプラインは、手動プロセスではしばしば省略される規律を強制します。
インフラ環境のための実践的チェックリスト
- ステージングは本番環境とは別のVPCまたはアカウントにある
- ステージングは本番データベースやストレージにアクセスできない
- ステージングは本番環境と同じOSバージョンとランタイムバージョンを使用する
- 共通設定は一度定義され、全環境で共有される
- 環境固有の値は別ファイルに分離されている
- パイプラインは変更を最初にステージングに適用し、次に本番環境に適用する
- ステージング適用後にテストを実行し、正しさを検証する
次のステップ
隔離された環境でインフラ変更をテストすることで、ほとんどの問題は本番環境に到達する前に発見できます。しかし、すべてを捕捉できるわけではありません。ステージングで完全に動作する変更でも、本番環境の規模や実際のトラフィックパターンの下で適用されると、問題を引き起こす可能性があります。
ここでポリシーとガバナンスの出番です。次のステップは、どのような変更が許可されるか、誰が承認できるか、本番デプロイ前にどのような条件を満たす必要があるかについてのルールを定義することです。しかし、それは別の記事のトピックです。
今のところ、具体的な教訓はこれです。インフラの変更が、隔離されたステージング環境を経由せずに直接本番環境に適用されているなら、あなたはほんの小さな設定変更から本番障害に至る一歩手前です。まず環境を整え、パイプラインに規律を守らせましょう。ユーザーが感謝してくれます。