AWSのAuto Scaling Group(ASG)やECS、AzureのVMSS、GCPのMIG(マネージドインスタンスグループ)でオートスケーリングを運用しているインフラ担当者に向けた内容です。IaC(Infrastructure as Code、インフラをコードで管理する仕組み)を導入したチームで、ある日突然スケーリングの挙動が変わり、原因が追えなくなる現象について整理します。
前任者が退職し、Terraformの適用は中途半端。2年前の障害対応中に誰かがコンソールでしきい値を変更した記録も残っていない。そんな状態のオートスケーリング設定に触るのが怖い、という状況に心当たりがあるなら、以下は実際に起きうる落とし穴の話です。
何が起きるか:気づかれない上書き
オートスケーリングのポリシーは、コードとコンソール操作という2つの書き手が、互いに気づかないまま競合しやすい設定です。
AWSのASGやECSでは、スケーリングポリシーはグループ本体とは別のAPIオブジェクトとして存在します。TerraformやCloudFormationでポリシーを定義していると、次回のapply実行時に、それ以降コンソールで加えた変更がすべて無言で元に戻ります。障害対応時に効果があったしきい値の調整も例外ではありません。逆にコンソールで手動作成したポリシーはコード側から見えず、「ドリフト(コードと実環境のズレ)のクリーンアップ」のタイミングで消えることもあります。
AzureのVMSS(Virtual Machine Scale Sets)では、オートスケール設定はautoscaleSettingsという1つのリソースにまとまっています。複数のプロファイルやルールを内包する構造のため、ARMテンプレートやBicep、Terraformで再定義すると、一部のルールだけでなく調整済みのプロファイル全体がまとめて置き換わります。
GCPのMIGでも構図は同じです。オートスケーラーはインスタンスグループに紐づく独立したオブジェクトで、gcloudコマンドでの編集とTerraformでの定義が丸ごと上書きし合います。MIGを一度削除して再作成すると、コンソールでの調整は跡形もなく消え、コードに書かれた内容だけが復元されます。
どのクラウドでも共通しているのは、オートスケーリングポリシーが「複数の書き手を持つ独立したオブジェクトで、最後に書き込んだ側が勝つ」という単純な仕組みで動いている点です。マージも警告も発生しません。デプロイもPRもアラートもないまま、本番の挙動だけが変わります。
なぜ起きるか:仕組みを分解する
原因は3段階に分けて考えると理解しやすくなります。
1段階目は、オートスケーリングポリシーが「グループ本体とは別のAPIリソース」として設計されている点です。EC2インスタンスの起動テンプレートのような設定は1箇所に集約されがちですが、スケーリングポリシーはASGやMIG、VMSSにアタッチされる別オブジェクトとして扱われます。
2段階目は、IaCツールの適用モデルが「宣言した状態への完全同期」である点です。Terraformはコード上の定義と実際のリソース状態を比較し、差分があれば実環境をコードに合わせて書き換えます。これは意図した挙動ですが、コンソールでの変更を「差分」としてしか認識できません。
3段階目は、監査の仕組みが後追いでしか機能しない点です。CloudTrailやAzureのアクティビティログ、GCPの監査ログはポリシー変更を記録しますが、デフォルトでは変更を検知してもアラートは飛びません。誰が何を変えたかは追えても、変更が起きた瞬間には誰も気づけない構造になっています。
自分のプロジェクトが該当するか確認する
該当するかどうかは、実際に動いているポリシーとコード上の定義を突き合わせれば分かります。まずは各クラウドで「今そこにある」ポリシーを棚卸しします。
# AWS: ASGのスケーリングポリシー一覧
aws autoscaling describe-policies \
--query 'ScalingPolicies[].[AutoScalingGroupName,PolicyName,PolicyType]' \
--output table
# AWS: ECS(Application Auto Scaling)のポリシー一覧
aws application-autoscaling describe-scaling-policies \
--service-namespace ecs
# Azure: VMSSのオートスケール設定一覧
az monitor autoscale list -o table
# GCP: MIGのオートスケーラー設定一覧
gcloud compute instance-groups managed list \
--format="table(name,zone,autoscaler)"この出力とTerraformの.tfファイルやStateファイルの内容を見比べてください。API側にはあるのにコードに定義がない、あるいはその逆のポリシーが1つでもあれば、二重管理の状態にあると判断できます。
もう一つの確認方法はterraform planの実行です。ポリシー関連のリソースで差分が出る場合、それはコードと実環境がズレている証拠です。差分が「追加」でなく「変更」として出ている場合は特に注意が必要で、次のapplyで実環境側の設定が上書きされます。
対策の手順
1. まず何もいじらず現状を輸入する
最初にやるべきは調整ではなく「唯一の正」を決めることです。多くの場合IaC側を正とし、実環境の状態をそのままコードに取り込みます。
# 例: ASGのスケーリングポリシーをTerraform管理下に取り込む
terraform import aws_autoscaling_policy.example my-policy-nameAzureやGCPでもARMのインポート機能やgcloud相当のコマンドで同様に対応します。取り込んだ直後にterraform planを実行し、差分がゼロ(no-op)になるまでコードを調整してください。これにより、2年前の障害対応時のしきい値変更も、コミットメッセージ付きでコードに残ります。
2. 設定の匂いを確認する
コードと実環境が一致した状態になったら、以下の観点で設定を点検します。
- クールダウンが120秒未満:スケールアップとダウンを繰り返すオシレーション(振動)が起き、コストと可用性の両方を損なう
- ターゲット使用率が90%超:スケーリングの発動が遅すぎて、新しいキャパシティが到着する頃には障害が既に発生している
- ターゲット使用率が30%未満:常時過剰プロビジョニング状態で、オートスケーリングの体裁をしたコスト増要因になっている
minとmaxが同値:実質固定台数の構成で、オートスケーリングとして機能していない- 想定していたはずのグループにポリシーが存在しない、あるいはステップスケーリングとターゲット追跡が同じメトリクスに重複して設定されている
3. 書き手を一本化し、それ以外の変更を検知する
コードとコンソールという2つの書き手が並立している状態を終わらせます。デプロイパイプラインのみがポリシーを変更できるようにし、それ以外の経路での変更を検知します。
CloudTrailのPutScalingPolicy、Application Auto ScalingのPutAutoScalingPolicy、Azureのアクティビティログ、GCPの監査ログには、いずれもポリシー変更のイベントが記録されます。デプロイパイプラインのIAMプリンシパル以外からの変更にアラートを設定しておけば、次の「気づかれない上書き」を「すぐ気づける上書き」に変えられます。障害対応中の緊急変更自体は禁止せず、そのあとにコード化するかロールバックするかのフォローアップタスクを起票するフローにしておくと運用が回ります。
4. 一本化できてから初めて調整する
書き手が一本化され、監視も整った段階で、ようやくチューニングに入ります。変更は1つずつ、必ずデプロイパイプラインを通して行い、変更前後でメトリクスを比較する運用にすると、次に引き継ぐ人が同じ調査を繰り返さずに済みます。
まとめ
引き継いだオートスケーリング設定が信用できない場合、まずはdescribe-policiesやaz monitor autoscale listなどで実環境の状態を確認してください。
次に、コードと実環境の差分をterraform planなどで洗い出し、いきなり調整するのではなく現状をそのままコードに取り込みます。
クールダウン時間やターゲット使用率、minとmaxの関係を点検し、書き手をパイプラインに一本化してから、それ以外の変更経路にアラートを設定してください。
この順序を踏むことで、2年前の「誰かが直した」設定を、誰でも読めるコードとして引き継げる状態にできます。