インフラのCI/CDは、アプリのCI/CDの流儀をそのまま持ち込むと事故ります。planとapplyの分離、承認ゲート、CIの権限設計という三点を押さえた「型」を、実在の一次情報を引きながら整理します。
01アプリのCIとインフラのCIは、そもそも別物です
アプリケーションのCIは「ビルドしてテストが通ればマージ」で完結します。成果物はアーティファクトで、失敗しても再ビルドすればよい。ところがインフラのCIは、パイプラインの実行そのものが本番のクラウドリソースを作り替えます。terraform applyは取り消せない操作を含み、順序を誤ればステートが壊れ、権限を広く持たせすぎればパイプラインが最強の攻撃対象になります。
つまりインフラのパイプラインで守るべきは「テストが通ること」ではなく、変更内容が人間の目でレビューされ、承認され、正しい権限で、正しい環境に適用されることです。この差を理解しないままon: pushでapplyを回すと、レビューされていない差分が本番に流れ込みます。
02plan と apply を分ける — これが型の中心です
インフラCI/CDの背骨は、terraform planとterraform applyを明確に分離することです。planはPR(プルリクエスト)の段階で自動実行し、その出力をPRのコメントとして貼り出す。applyはマージ後、あるいは承認後に別ステップとして実行する。この分離が、レビューと適用の間に人間の判断を挟む余地を作ります。
HashiCorpのHCP Terraform(旧Terraform Cloud)は、この型を製品として実装しています。VCS連携ワークスペースでは、PRが開かれるとspeculative plan(投機的プラン)を自動実行し、その結果へのリンクをPRに投稿、PRが更新されれば再実行します。speculative planはplanのみでapplyはできず、レビュー専用として設計されています(公式ドキュメント)。
Atlantisも同じ思想です。PRにコメントでatlantis planと書けば該当ディレクトリにterraform planが走り、出力がPRに返る。レビューが済んだらatlantis applyで適用し、対象ディレクトリはPRにロックされて他のPRからの競合を防ぎます(Using Atlantis)。ツールは違えど、「planはPRに出す、applyは分ける、ロックで競合を防ぐ」という骨格は共通です。
03apply のゲート — 手動承認と自動適用の線引き
applyをどう守るか。ここが環境ごとの設計判断になります。選択肢は大きく二つ、手動承認ゲートと自動適用(auto-apply)です。
手動承認の実装は、GitHub Actionsのenvironment機能が分かりやすい例です。environmentにrequired reviewersを設定すると、そのenvironmentを参照するジョブは指定した人・チームの承認なしには進めません。承認が下りるまで、そのジョブはenvironmentのシークレットにもアクセスできません。さらにself-review防止を有効にすれば、デプロイを起動した本人は承認できなくなり、必ず二人以上の目を通せます(Deployments and environments)。
一方で自動適用は、planに問題がなければ承認を待たずにapplyまで走らせる方式です。HCP Terraformでもワークスペースのauto-apply設定で選べます。ただし運用上は、本番は必ず手動承認、開発・サンドボックスは自動適用という環境ごとの使い分けが現実的です。DORAのState of DevOps研究も、デプロイ自動化は本番リスクを減らす基盤である一方、「認証情報を持つ者が任意のバージョンを任意の環境に投入できる」状態を前提に語っており、その裏返しとして誰が何を適用できるかの統制が要ることを示唆しています(DORA: Deployment automation)。
04環境ごとにパイプラインを分ける
dev / staging / prod を一本のパイプラインで貫くと、本番だけ承認を厳しくする、といった差をつけにくくなります。実務では環境ごとにワークスペース(あるいはstateとパイプライン)を分け、環境が上がるほどゲートを厳しくするのが定石です。
- dev:PRでplan、マージで自動apply。回転を優先し、壊れてもすぐ直せる範囲に留めます。
- staging:本番同等の構成で、planレビューは必須。applyは自動でも手動でも、チームの成熟度に合わせます。
- prod:手動承認ゲート必須、self-review禁止、承認者を限定。planの差分は必ず人が読みます。
環境間でどうコードを昇格させるかは、それ自体が設計テーマです。同じモジュールを変数で切り替えるのか、環境ごとにディレクトリを分けるのか——このあたりは環境昇格(dev→staging→prod)の設計で掘り下げます。stateをどう分割するかはIaCのstate管理とも密接に関わります。
05plan 出力のレビュー — 何を見るか
planをPRに貼るところまでは自動化できます。しかしplanを読むのは人間の仕事です。レビューで見るべき勘所を挙げます。
- destroy / replace の有無:
-/+(再作成)や-(削除)は最警戒です。DBやEBS、意図しないリソースの破棄が紛れていないか。plan出力の冒頭サマリ(add / change / destroy の件数)をまず見ます。 - 差分の件数が想定と合うか:小さな変更のはずが数十リソースに波及していたら、モジュールの参照ミスやプロバイダの挙動変化を疑います。
- 機微な値の露出:plan出力にシークレットが平文で出ていないか。出ているなら
sensitive指定やシークレット管理の見直しが要ります。 - ドリフト起因の差分:手作業でコンソール変更された結果、planが予期せぬ巻き戻しを提案していないか。これはドリフト検知の領域です。
件数が多すぎるplanは、そもそもレビュー不能です。1PRあたりの変更を小さく保つ、モジュール境界を意識する、といったPR設計そのものが、レビュー可能性を左右します。ブランチ戦略との相性はGitHub Flow / GitLab Flow / トランクベースで扱っています。
06CI のクレデンシャル — ここが最大の急所
パイプラインは本番を書き換える権限を持ちます。ここに長命のアクセスキーをシークレットとして置くのは、最も避けたい構成です。鍵が漏れれば、そのままクラウド全体への侵入経路になります。
現在の一次情報が推す方式は、OIDC(OpenID Connect)による短命クレデンシャルです。GitHub Actionsは、ジョブ実行時にクラウドプロバイダからそのジョブ限りで有効な短命トークンを直接発行してもらえます。長命の認証情報を保存する必要がなくなります(GitHub Docs: OpenID Connect)。
AWS連携では、IAMにGitHubのOIDCプロバイダ(token.actions.githubusercontent.com)を登録し、aws-actions/configure-aws-credentialsでロールをassumeします。ワークフローにはpermissions: id-token: writeが必要です。そしてAWS側の推奨は、ロールの信頼ポリシーでsubクレームを評価し、どのリポジトリ・どのブランチ・どの環境からのassumeを許すかを絞ることです(Configuring OpenID Connect in AWS)。
sub条件をrepo:org/*のように緩くすると意味が半減します。repo:org/repo:environment:productionまで絞り、本番applyロールはprod用environmentからしかassumeできない形にするのが要点です。権限最小化の実態はIAM最小権限の現実もご参照ください。加えて、planに使うロールとapplyに使うロールを分ける設計も有効です。planは基本的に読み取り中心、applyは書き込み権限が要る。ロールを分ければ、レビュー段階のパイプラインに過剰な書き込み権限を与えずに済みます。
07ツールの選択肢 — Atlantis / HCP Terraform / 自前CI
型が同じでも、実装手段は複数あります。代表的な三択を、実務判断の軸で整理します。
- Atlantis:OSSでセルフホスト。PRコメント駆動でplan/applyし、ディレクトリロックで競合を防ぎます。運用は自前ですが、挙動を細かく制御でき、既存のGit基盤に馴染みます。カスタムワークフローで組織のポリシーに合わせられます。
- HCP Terraform(旧Terraform Cloud):マネージド。VCS連携でspeculative planとapplyゲートが標準装備、stateも預けられます。運用負荷を下げたい組織向け。プラン体系や機能範囲は変わり得るので公式で要確認です。
- 自前CI(GitHub Actions / GitLab CI等):最も柔軟。environmentの承認ゲートやOIDCと組み合わせて型を自作します。自由度が高い反面、planのPR貼付やロックは自前で作り込む必要があります。
どれを選ぶかは、運用リソース・既存基盤・統制要件で決まります。マルチアカウント環境で統一的に回すなら、アカウント横断の統制設計と併せて考える必要があります(マルチアカウント統制)。ポリシーをコードで強制したいなら、planに対するPolicy as Codeをパイプラインに組み込む選択もあります。
—まとめ
インフラのCI/CDは、アプリのCIの延長では設計できません。守るべきは「テストが緑」ではなく、planが人にレビューされ、承認され、適切な短命権限で、正しい環境に適用されることです。
- planはPRで自動実行してレビューへ、applyは分離して承認ゲートの後段に置く。
- 環境が上がるほどゲートを厳しく。prodは手動承認とself-review禁止をセットで。
- planは必ず人が読む。destroy/replace、差分件数、機微値の露出を見る。
- CIの権限はOIDCの短命クレデンシャルへ。信頼ポリシーの
sub条件で発行元を絞る。
この型は、Atlantisでも、HCP Terraformでも、自前CIでも実装できます。手段はどれでも構いません。大事なのは、planとapplyの分離・承認ゲート・権限設計という三点を、自社の制約に合わせて確実に組み込むことです。ハンズオンでの設計支援については手が動かせるコンサルという立ち位置もご覧ください。