Slide 1

Slide 1 text

データ基盤のための Terraform Workflow を tfaction で構築しよ う 2025-02-27 Shunsuke Suzuki 1

Slide 2

Slide 2 text

自己紹介 (1) Shunsuke Suzuki seli07 (せりな) 2024/08 ~ freee SRE 2022/07 ~ Mercari Platform Engineer 2021/10 ~ Recruit SRE 2019/10 ~ Quipper SRE 2

Slide 3

Slide 3 text

自己紹介 (2) OSS Developer - CLI や GitHub Actions など様々な OSS を開発 ● aqua ● tfcmt ● tfaction ● github-comment ● tfmv ● pinact ● ghalint ● etc 3

Slide 4

Slide 4 text

aqua - CLI Version Manager https://aquaproj.github.io/ 4

Slide 5

Slide 5 text

概要 ● データ基盤そのものの話はほぼしない ● データ基盤のインフラを Terraform で管理するための Workflow を tfaction という OSS を使って構築する話 6

Slide 6

Slide 6 text

Agenda ● IaC や CI, Terraform の説明 ● Terraform Workflow の開発・運用の難しさ ● tfaction の概要 ● なぜ tfaction なのか ● tfaction の機能紹介 7

Slide 7

Slide 7 text

データ基盤には様々なインフラリソースの管理が必要 ● AWS ● Google Clould ○ BigQuery, Cloud Run, Cloud Workflows, etc ● Azure ● etc 8

Slide 8

Slide 8 text

IaC (Infrastructure as Code) による管理 ● コードレビュー可能 ● 似たようなインフラを簡単に構築可能 ● コードを Git のような VCS で管理することで変更履歴を容易に残せる ● linter を用いたテストやドキュメントの生成が可能 ● CI などによる変更の適用の自動化が可能 ● etc 9

Slide 9

Slide 9 text

Terraform による IaC ● あらゆるリソースを統一的な方法で管理 ● リソースの宣言的な管理 ● 充実したコミュニティ・ナレッジ・エコシステム ● 使える人が多く、導入しやすい ● etc 10

Slide 10

Slide 10 text

Terraform をどうやって実行するか 1. ローカルや専用のサーバーから手動実行 2. apply は手動でそれ以外 (plan) は CI 3. CI で自動化 11

Slide 11

Slide 11 text

Why CI? ● 自動化による生産性の向上 ● セキュリティやガバナンスの強化 ○ コードレビューや lint のプロセスの強制 ○ ヒューマンエラーのリスクの軽減 ○ CI のログによる透明性の向上や監査対応 12

Slide 12

Slide 12 text

Terraform の Workflow の実装の難しさ 13

Slide 13

Slide 13 text

シンプルなワークフローを組むのは容易 GitHub Actions で簡単に組める 1. install terraform 2. terraform init 3. terraform plan / apply 14

Slide 14

Slide 14 text

ワークフローを取り巻く環境の変化 ● プロダクトの成長 ● 開発組織の成長 ● データ基盤の利活用の増加 ● ワークフローの利用者や実行頻度の増加 ● 管理対象のリソースの増加 15

Slide 15

Slide 15 text

ワークフローの品質がより重要になってくる ● セキュリティやガバナンスの重要性の増加 ● 開発者体験、生産性 ○ セルフサービス化 ○ ガードレール 16

Slide 16

Slide 16 text

ワークフローの拡張が必要になってくる ● Monorepo の変更されたディレクトリでだけ CI 実行 ● local-path Module が変更されたら依存するディレクトリでも CI 実行 ● コードのフォーマットを強制(なんなら自動修正) ● tflint, trivy, Confest ● terraform-docs でドキュメント生成 ● plan file 使って apply ● Drift 検出 ● etc 18

Slide 17

Slide 17 text

Terraform の Workflow のメンテの難しさ ● 様々な機能を自前で実装するのは大変 ● CI や Platform Engineering に関する専門性が必要 ● 人材確保は容易ではない ● 他にもやるべきことはあるので中々手が回らない ● メンテコストを極力抑えて他のことにリソースを回したい 19

Slide 18

Slide 18 text

OSS 開発者としての理想 ● 各企業や開発組織が似たようなものを独自に開発するのは望ましくない ● あらゆる開発組織が高い品質のワークフローを実現できる OSS の開発 ● ユーザーからワークフローの様々なノウハウが OSS に集約されていく => tfaction の開発 20

Slide 19

Slide 19 text

tfaction の話 21

Slide 20

Slide 20 text

tfaction とは https://github.com/suzuki-shunsuke/tfaction ● Terraform Monorepo の高度な workflow を GitHub Actions で構築するための Framework (実態は GitHub Action の集合体) ● OSS (MIT LICENSE) ● 日本国内を中心に様々な企業で導入実績 22

Slide 21

Slide 21 text

tfaction の特徴 ● ワークフロー全体という広い領域をカバーする大きな Framework ● trivy や tflint, conftest, terraform-docs など周辺ツールのサポート ● Drift Detection や コードの自動修正, apply のエラーのハンドリングなど、様々な 機能を提供 ● Monorepo を標準でサポート 23

Slide 22

Slide 22 text

tfaction の基本的な 2 つの workflow 1. PR に対し lint やコードの自動修正、 terraform plan を実行 2. PR がマージされたら terraform apply を実行 PR をテストし、マージしたらデプロイするというシンプルな GitHub Flow 24

Slide 23

Slide 23 text

tfaction の基本的な 2 つの job 1. setup: 変更された Root Module のリストを取得 2. plan / apply: 変更された directory に対して matrix build で terraform plan / apply を実行 25

Slide 24

Slide 24 text

tfaction の設定ファイル 設定は基本 GitHub Actions ではなく設定ファイルに記述 1. tfaction-root.yaml : グローバルな設定や Root Module 群の設定 2. tfaction.yaml : 各 Root Module の設定。空 {} でも良い 設定を細かく制御したり共通化することが可能 26

Slide 25

Slide 25 text

tfaction の機能 1. Monorepo のサポート 2. local-path Module の依存関係の検出 3. terraform plan / apply の結果の分かりやすい通知 4. Linter とのインテグレーション 5. コードの自動修正 6. Renovate による自動 update 7. plan file を用いた安全な apply 8. apply 後に関連 PR を更新 9. apply 失敗対応のサポート 10. 新しい Root Module の Scaffold 27 11. tfmigrate による State Migration 12. Root Module の削除 13. terraform plan -generate-config-out によるコード生成 14. Drift Detection 15. Module 管理

Slide 26

Slide 26 text

1. Monorepo のサポート 28

Slide 27

Slide 27 text

Terraform の Monorepo とは ● 1 つのリポジトリに複数の Terraform Root Module があるリポジトリ ● ディレクトリ階層の分け方は色々 ○ 例: サービスや環境毎にディレクトリを分ける ● Root Module の数は千差万別 (数個 ~ 1,000 over) ● Terraform ではよくあるパターン 29

Slide 28

Slide 28 text

tfaction の Monorepo のサポート ● tfaction は Monorepo を想定 ● 変更された Root Module でのみ CI を実行 ○ 毎回全 Root Module で CI 実行は無駄 (非現実的) ○ Root Module の数が増えてもスケールする (CI の時間が伸びない) 32

Slide 29

Slide 29 text

2. local-path Module の依存関係の検出 33

Slide 30

Slide 30 text

2. local-path Module の依存関係の検出 例: service-a が 同じディレクトリの modules/consul に依存 service-a/ modules/ consul # Module 34

Slide 31

Slide 31 text

local-path Module の依存関係の検出 ● デフォルトでは local-path Module が更新されても Root Module では CI は実行さ れない ● 設定で Root Module でも実行されるようにすることができる 35

Slide 32

Slide 32 text

3. terraform plan / apply の結果の分かりやすい通知 36

Slide 33

Slide 33 text

terraform plan / apply の結果の確認 ● CI で terraform plan / apply を実行したら結果を確認する必要がある ● CI の log を確認するのは面倒・分かりづらい => tfaction では tfcmt で分かりやすく PR にコメント 37

Slide 34

Slide 34 text

● log 確認不要で楽 ● 色付き label ● 要約 ● 削除警告 ● リソース一覧 ● 余計なログの除去 ● etc 38

Slide 35

Slide 35 text

4. Linter とのインテグレーション 39

Slide 36

Slide 36 text

様々な linter に対応 ● tflint ● trivy (tfsec) ● Conftest CI で lint を実行しベストプラクティスへの準拠を強制し、コードの品質を担保 結果を分かりやすく通知 40

Slide 37

Slide 37 text

tflint & reviewdog による自動 review 41

Slide 38

Slide 38 text

PR へのコメント 42

Slide 39

Slide 39 text

5. コードの自動修正 43

Slide 40

Slide 40 text

様々な修正の必要性 ● terraform fmt によるフォーマット ● .terraform.lock.hcl の更新 ● terraform-docs によるドキュメントの更新 ● tflint –fix によるエラーの修正 44

Slide 41

Slide 41 text

CI による修正の自動化 ● コードを CI で自動で修正することでコードの品質を担保 ● ローカルで修正する手間が省ける ○ ローカル環境にも依存しなくなる 45

Slide 42

Slide 42 text

terraform fmt による自動フォーマット 46

Slide 43

Slide 43 text

terraform-docs によるドキュメントの自動生成 47

Slide 44

Slide 44 text

6. Renovate による自動 update 48

Slide 45

Slide 45 text

Renovate による自動更新 ● Renovate: Dependabot のように dependency を update するツール ● Terraform Provider や Module などを Renovate で自動更新できる ● マージまで自動化すると人間の負担が減って楽 ● しかし、自動マージでインフラの変更が勝手に適用されると危険 49

Slide 46

Slide 46 text

自動マージによるインフラの変更の適用の防止 50

Slide 47

Slide 47 text

7. plan file を用いた安全な apply 51

Slide 48

Slide 48 text

● レビューした plan の結果と違う結果が apply されると危険 ● terraform plan で生成した plan file を用いて apply を実行すると plan と同じ結果 を apply できて安全 52

Slide 49

Slide 49 text

plan file とは ● terraform plan の -out option で生成されるバイナリファイル ● plan の結果を保持している ● terraform apply 時に plan file を渡すと plan 結果をそのまま apply できる ● plan file は state file のバージョン情報を保持しており、 apply 実行時に plan file に保持されたバージョンが古くなっていると apply が失敗する ○ 古い結果が apply されるのが防がれるので安全 53

Slide 50

Slide 50 text

● tfaction は plan file を GitHub Actions Artifact で管理することで安全に apply を 実行 ○ plan file が改竄されると任意の結果を apply できて非常に危険 ○ GitHub Actions Artifact は改竄不可なので安全 54

Slide 51

Slide 51 text

8. apply 後に関連 PR を更新 55

Slide 52

Slide 52 text

● 同じ Root Module に対する PR が同時に複数作られることはままある ● ある PR がマージされた場合、同じ Root Module に対する PR を更新する必要が ある ○ CI の結果が変わりうるため ○ terraform plan を再実行し stale になった plan file を再作成するため 56

Slide 53

Slide 53 text

apply 後に関連 PR を自動更新 同じ Root Module に対する PR を自動で更新 57

Slide 54

Slide 54 text

9. apply 失敗対応のサポート 58

Slide 55

Slide 55 text

apply 失敗時の対応 ● plan に成功したけど apply に失敗するのは良くある ● 失敗したら何かしら対応が必要 59

Slide 56

Slide 56 text

apply 失敗時の対応の課題 ● 失敗に気づかないことがある ● apply 失敗時にどうすればよいかわからない人もいる ● PR を新たに作るのが地味に面倒 ● すぐに修正できず忘れ去られる場合がある 60

Slide 57

Slide 57 text

Follow up PR の自動生成 ● apply 失敗時にメンションして通知 ● 失敗を修正するための PR を自動生成 ● 後述する Drift Detection を有効にすると Issue として管理可能 61

Slide 58

Slide 58 text

62 メンション やるべきことの案内

Slide 59

Slide 59 text

63

Slide 60

Slide 60 text

10. 新しい Root Module の Scaffold 64

Slide 61

Slide 61 text

新しい Root Module の Scaffold ● Monorepo に新しい Root Module を追加する際、一から書くのは大変 ● tfaction では workflow を実行してテンプレートを元に生成できる ○ テンプレートは自分で用意する必要がある ○ workflow 経由なのでローカル環境に依存しない 65

Slide 62

Slide 62 text

66

Slide 63

Slide 63 text

67

Slide 64

Slide 64 text

11. tfmigrate による State Migration 68

Slide 65

Slide 65 text

tfmigrate とは terraform state mv, rm や terraform import による State 操作をコードで定義して自動 化するツール 実際に変更を適用する前に terraform plan で差分がないか検証できる Terraform による import, moved, removed block のサポートにより以前より使う機会 は減ったが、複数の State を跨った State 操作をしたい場合は便利 69

Slide 66

Slide 66 text

tfaction の tfmigrate のサポート ● workflow で .tfmigrate.hcl やマイグレーションファイルの雛形を生成できる ● CI で tfmigrate を実行可能 70

Slide 67

Slide 67 text

71

Slide 68

Slide 68 text

12. Root Module の削除 72

Slide 69

Slide 69 text

Root Module の削除 ● サービスの終了などで Root Module ごと削除したくなることはままある ● 単にディレクトリを消してしまうとリソースがそのまま残ってしまう ● backend や provider など最低限のコード以外を削除するのは地味に面倒 73

Slide 70

Slide 70 text

tfaction.yaml の destroy option ● destroy option を有効にすることで CI で全リソースを削除可能 ○ terraform plan 実行時に –destroy option が設定される 74

Slide 71

Slide 71 text

13. terraform plan -generate-config-out によるコード生成 75

Slide 72

Slide 72 text

terraform plan -generate-config-out ● import block を元にコードを自動生成するコマンド ● 生成されるコードは完璧ではないが、 0 から自分で書くより圧倒的に楽 ● 権限的にローカルで terraform plan が実行できないと通常使うのが難しい 76

Slide 73

Slide 73 text

terraform plan -generate-config-out workflow 77 ● workflow_dispatch で実行可能 ● 生成されたコードが commit される

Slide 74

Slide 74 text

14. Drift Detection 78

Slide 75

Slide 75 text

Drift Detection とは ● Drift: IaC においてコードによるインフラの定義と実際のインフラの状態が乖離した 状態 ● Drift Detection: Drift を自動で検出する機能 79

Slide 76

Slide 76 text

Terraform における Drift の主な原因 ● Terraform 以外によるインフラの変更 ● terraform apply の失敗 Terraform を運用していれば Drift は避けられない 80

Slide 77

Slide 77 text

Why Drift Detection? ● Drift はなるべく早く解消すべき ● Drift はコードの信頼性をなくす ○ コードでなく実際のインフラの状態を確認する必要が出てくる ● Drift はブロッカーにもなる ○ terraform plan 時に予期せぬ差分として現れる ○ 差分の原因を逐一確認する必要が出てくる 81

Slide 78

Slide 78 text

tfaction における Drift Detection ● Root Module ごとに GitHub Issue を作成して Drift を管理 ● Issue は Drift が検出されたら Open, 解消されたら Close される ● Drift の検出・解消のたびに Issue に結果がコメントされる ● Drift Detection のタイミングは 2 種類 ○ terraform apply 実行時 ○ schedule workflow で terraform plan を定期的に実行時 82

Slide 79

Slide 79 text

tfaction の Drift Detection のタイミング ● terraform apply 実行時 ○ 失敗したら Drift があると判定 ● schedule workflow で terraform plan を定期的に実行時 ○ No change でなければ Drift があると判定 83

Slide 80

Slide 80 text

84 Issue が作られる

Slide 81

Slide 81 text

apply の結果次第で reopen / close 85

Slide 82

Slide 82 text

定期的な Drift のチェック 86

Slide 83

Slide 83 text

● Drift を Issue で管理できる ● Issue を見ればいつから Drift があるのかだいたい分かる ● あくまで Drift を検出するだけで自動で修正したりはしない ○ 如何に Drift (Issue) に対処するかはユーザーに委ねられている 87

Slide 84

Slide 84 text

15. Module 管理 88

Slide 85

Slide 85 text

Module 管理 ● 独自の Terraform Module を如何に管理するかは難しい問題 ● 色々やりようはある ○ local-path Module ○ S3, GCS ○ GitHub ○ HCP Terraform ○ etc 89

Slide 86

Slide 86 text

Module 管理 ● tfaction では標準的な管理方法を提供 ○ 同じ Monorepo に集約 ○ GitHub Source で versioning して管理 ○ Scaffold, Test, Release といった一連の開発フローをサポート ● ただし自分の好きな方法で管理することも可能 90

Slide 87

Slide 87 text

まとめ 91

Slide 88

Slide 88 text

まとめ ● データ基盤のインフラを Terraform で管理するための Workflow を tfaction で構築 ● ビジネスや開発組織の成長に伴い、より生産性やセキュリティ・ガバナンスが求め られる ● tfaction の様々な機能を活用し、高度なワークフローを少ない運用コストで管理 92

Slide 89

Slide 89 text

93

Slide 90

Slide 90 text

今後やりたいこと ● Security の強化 ○ よりセキュアな Secret 管理 ● Linter 設定の管理の改善 ○ 少ない運用コストで適切な設定を適用していくという課題への道筋を提示 ● apply before merge の検討 ● tfaction の導入ハードルの低減 ● Module 管理の改善 ○ Renovate による update の自動化 ● Terraform のテストのサポート ● 設定ファイルの JSONSchema の自動生成 94

Slide 91

Slide 91 text

pull_request_target で GitHub Actions の改竄を防ぐ tfmv - Terraform のリソース名のリファクタリング tfprovidercheck - 危険な Terraform Provider の実行を防ぐ Shunsuke Suzukiさんの記事一覧 | Zenn 95