「AnsibleとTerraformの連携が壊れる理由はライフサイクルにあった」第50回:連載総括:Ansible×Terraformを共存させる「ツール境界線」の設計原則


🗺️ 初めての方、シリーズの全体像を知りたい方はこちら

シリーズ全体については、以下のまとめブログで整理しています。

→ 「AnsibleとTerraformの連携が壊れる理由はライフサイクルにあった」第5部まとめブログ:Terraformライフサイクル破壊編で明らかになった「認識の不可視性」の構造 ※近日公開予定


📋 目次

  1. はじめに
  2. 第42〜46回を「不可視性が破壊に転じる局面」で再整理する
  3. 第47〜49回の対処とその限界
  4. まとめ
  5. 連載一覧:「AnsibleとTerraformの連携が壊れる理由はライフサイクルにあった」

1. はじめに

第41回から第49回にかけて、Terraformのライフサイクル操作がAnsibleの設定にどう影響するかを一つずつ扱ってきました。強制再生成による設定消失、prevent_destroyとの衝突、データの全喪失、依存関係を通じた連鎖的再生成、プロビジョニング途中の接続断絶、Volumeによるデータの分離、イミュータブル運用への転換、CI/CDパイプラインでの事前ブロック。これらは個別に見ると独立した8個の障害パターンですが、いずれも 第41回 で示した「認識の不可視性」という一つの構造が、さまざまな局面で表面化したものでした。

第49回 では、CI/CDパイプライン上での機械的なガードレールという、第5部における個別の技術的対策の最後のピースを扱いました。第50回となる今回は、ここで一旦技術的な対策の追加を止め、第41回から第49回までを俯瞰します。

次のセクションでは、まず第42回から第46回を、この不可視性がどのような局面で「破壊」に転じるかという軸で整理し直します。


↑ 目次に戻る


2. 第42〜46回を「不可視性が破壊に転じる局面」で再整理する

第41回 で確認した通り、Ansibleが投じた設定は、Terraformの認識範囲の外側にあるため、リソースが再生成されても保護の対象にはなりません。しかし、この不可視性がどんな時も同じように「設定の消失」という結果を生むわけではありませんでした。第42回から第46回で扱った各回を、この不可視性がどのような条件で表面化し、どのような結果につながったかという観点で分類し直します。

回 事象 不可視性との関係
第42回 強制再生成による設定消失 不可視性が最も素直な形で「破壊」に転じたケース
第43回 prevent_destroyとAnsibleの詰まり 不可視性への対処(破棄の禁止)が、別種の障害(デプロイの停止)に置き換わっただけだったケース
第44回 データ消失障害 不可視性の影響範囲が、静的な設定から動的なデータにまで及び、被害の性質(復元可能性)が変わるケース
第45回 連鎖的再生成 不可視性が、直接触っていないリソースにまで依存関係を通じて伝播するケース
第46回 ハーフデプロイ状態 一見「破壊」に見える事象(taint化)が、実際にはコンテナ側のデータ消失には至らなかったケース

第42回 では、name属性の変更やreplace_triggered_byによってコンテナが再生成されると、Ansibleが投じた設定が、そのまま静かに失われることを確認しました。これは、第41回 で整理した不可視性が、最も直接的な形で表面化したケースです。

第43回 では、この消失を防ぐためにprevent_destroyを設定しても、破棄そのものが一律で拒否されるだけで、意図した再構築の要求もろともterraform applyが停止することを確認しました。不可視性への対処が、消失とは別種の障害を生んだケースです。

第44回 では、第42回 で扱った設定の消失と、稼働後に生成され続けるデータの消失とを区別しました。前者は再実行で復元できますが、後者は復元できません。同じ不可視性が引き起こす消失であっても、被害の質はこの回で分かれています。

第45回 では、変更対象として直接指定していないネットワークの再生成が、networks_advancedの参照構造を通じてコンテナ群にまで波及し、第44回 と同じデータ消失が、依存関係を経由しても起きることを確認しました。

第46回 は、この並びの中で性質が異なります。Ansibleのプロビジョニング実行中の事故によってtaintedとしてマークされるのは、プロビジョナー自体を保持するnull_resource.provisionであり、target-node1〜3のコンテナは、事故の前後で一切変化がありませんでした。「破壊」に見える事象が起きても、それが必ずしもコンテナ側のデータ消失に直結するとは限らないことを、この回は示しています。

こうして並べると、第41回 で示した不可視性は、常に同じ結果を生む単一の現象ではなく、どのリソースが再生成の対象になるか、そこにどのようなデータが存在するか、あるいは対処そのものがどう作用するかによって、現れ方が変わるものだったことが分かります。

次のセクションでは、この不可視性そのものに向き合った、第47回から第49回の対処を整理します。


↑ 目次に戻る


3. 第47〜49回の対処とその限界

第41回から第46回で確認した不可視性そのものに向き合ったのが、第47回から第49回の3つの対処です。それぞれの内容と、その対処が及ぶ範囲を整理します。

対処 該当回 内容 限界
データを守る 第47回 Volumeの分離によるデータの永続化 保護されるのは明示的にマウントした範囲のみで、それ以外(パッケージ等)は従来通り失われる
境界そのものを動かす 第48回 ビルド時へのAnsible適用の前倒し(イミュータブル化) 強制再生成による設定消失は解消するが、稼働後に生成されるデータの消失には及ばない。設定変更のたびに再ビルドが必要になる運用コストを伴う
境界の侵犯を検知して止める 第49回 CI/CDパイプラインでの機械的なガードレール prevent_destroyのような恒久的な禁止ではなく、着脱可能な一時的チェック工程にとどまる

第47回 では、docker_volumeをコンテナとは独立したリソースとしてマウントし、コンテナが再生成されてもVolume自体は影響を受けないことを確認しました。ただし、保護されるのはVolumeのマウントパスとして明示的に指定した範囲に限られ、それ以外の場所に投じられたパッケージ等は、第44回 で確認したのと同じように失われることも、あわせて確認しました。

第48回 では、Ansibleを実行時ではなくビルド時に適用し、設定をdocker_imageというコンテナとは別のリソースに焼き込む転換を確認しました。第42回 で確認した強制再生成による設定消失は、この転換によって実質的に解消されます。ただし、この効果が及ぶのは静的な設定に限られ、第44回 で扱ったような稼働後のデータ消失には及びません。また、設定を変更するたびにイメージの再ビルドが必要になるという、新しい運用コストも生まれます。

第49回 では、terraform planの結果をJSON形式で解析し、危険な変更が計画された時点でCI/CDパイプラインのジョブを止める仕組みを確認しました。第43回 で扱ったprevent_destroyが、コードに組み込む恒久的で無条件の制約だったのに対し、このガードはCI/CDワークフロー側に置かれた着脱可能な一時的チェック工程にとどまります。

この3つは、いずれも 第41回 の不可視性そのものを解消しているわけではありません。第47回 はデータの置き場所を変え、第48回 は設定の焼き込み先を変え、第49回 は破棄が計画された事実を人間の目に触れさせるだけです。また、これらは互いに排他的な選択肢でもありません。第48回 自身が整理した通り、イミュータブル運用に移行してもステートフルなデータの保護は別途必要であり、実際の運用では複数の対処を重ねて使うことになります。

次のセクションでは、この回で整理した内容をまとめます。


↑ 目次に戻る


4. まとめ

この回で整理した内容を確認します。

  • 第41回 で示した「認識の不可視性」という一つの構造が、第42回から第46回でそれぞれ異なる形をとって現れていたことを整理した。強制再生成による直接的な設定消失(第42回)、防御策自体が別の障害に置き換わったケース(第43回)、被害の性質が変わるケース(第44回)、依存関係を通じた伝播(第45回)、そして「破壊」に見えて実際には消失に至らなかったケース(第46回)と、同じ不可視性でも現れ方は一様ではなかった
  • 第47回 のVolume分離、第48回 のイミュータブル運用への転換、第49回 のCI/CDパイプラインガードという3つの対処は、いずれも不可視性そのものを解消するのではなく、データの置き場所、設定の焼き込み先、あるいは検知の仕方を変えるものであることを確認した
  • 3つの対処にはそれぞれ限界がある。第47回 の保護範囲は明示的にマウントした場所に限られ、第48回 は稼働後のデータ消失には及ばず再ビルドという運用コストを伴い、第49回 のガードは恒久的な禁止ではなく着脱可能な一時的チェックにとどまる。これら3つは排他的な選択肢ではなく、実際の運用では組み合わせて使われうるものである
  • 検証環境はDockerコンテナだったが、扱ってきた構造(tfstateの記録範囲、ライフサイクル制御、依存関係の伝播等)はプロバイダーに依存しない性質であり、読者が自身の環境(AWS・GCP等)に置き換えて応用できる余地がある

↑ 目次に戻る


📑 連載の移動 前の記事:【Ansible×Terraform編】第49回


🗺️ 初めての方、シリーズの全体像を知りたい方はこちら

シリーズ全体については、以下のまとめブログで整理しています。

→ 「AnsibleとTerraformの連携が壊れる理由はライフサイクルにあった」第5部まとめブログ:Terraformライフサイクル破壊編で明らかになった「認識の不可視性」の構造 ※近日公開予定


↑ 目次に戻る


5. 連載一覧:「AnsibleとTerraformの連携が壊れる理由はライフサイクルにあった」

第5部:Terraformライフサイクル破壊編

回数 テーマ、記事タイトル 概要
第41回 なぜTerraformはAnsibleが投じた設定を知らないのか TerraformのState管理メカニズムと、Ansibleが変更するコンテナ内部状態の「認識の不可視性」を解剖する根本解説回。
第42回 create_before_destroyやreplace_triggered_byによる強制再生成 HCLのライフサイクル制御(lifecycleブロック)によって強制再生成(ForceNew)が発生し、Ansibleの設定が消し飛ぶ現象の再現。
第43回 prevent_destroy設定時におけるAnsibleプロビジョニングの詰まり 誤破壊防止のprevent_destroyと、Ansibleの再実行(再プロビジョニング)要求がバッティングしてデプロイが詰まる障害。
第44回 リソース再生成に伴うAnsible生成データの全喪失(データ消失障害) Terraform側がリソースを破棄、再生成(Destroy & Create)した際、Ansibleで作成したデータベースやファイルなどの状態が全消去される問題。
第45回 ネットワークや依存リソースの変更に引きずられる連鎖的再生成 依存関係にあるネットワーク(Docker Network)や上位リソースの変更により、ターゲット全体が連鎖破壊される現象。
第46回 プロビジョニング途中の接続切断とState不整合(ハーフデプロイ状態) Ansible実行中に接続が切断、エラー停止した際、TerraformのStateが「作成完了」と「プロビジョニング未完了」の半端な状態になる問題。
第47回 ステートフルなデータ(Volume/DB)を保持しながらの安全な再構築 内部データをDocker Volumeに分離し、コンテナ(リソース)が再生成されてもAnsibleの投入データを生かす設計。
第48回 イミュータブルインフラストラクチャにおけるAnsibleの限定的役割 「実行時にAnsibleで設定する」のを取りやめ、ビルド時にAnsibleを組み込んでコンテナイメージを焼き込む運用へのシフト。
第49回 CI/CD環境において再構築事故を物理的に防ぐパイプラインガード GitHub Actions等で誤ってDestroy & Createが走らないよう、terraform planの差分ログを解析して自動ブロックするガードレール設計。
第50回 連載総括:Ansible×Terraformを共存させる「ツール境界線」の設計原則 50回を通じた結論。「どこまでをTerraformに任せ、どこからをAnsibleに委ねるか」の境界線(アンチパターンと原則)のまとめ。

↑ 目次に戻る