Slide 1

Slide 1 text

Terraformモジュールは、なぜ「魔境」化するのか Copyright © 3-shake, Inc. All Rights Reserved. 1 クラウドネイティブ会議 day2 - 2026年5月15日 羽山 公平(hymaaa_k)

Slide 2

Slide 2 text

Terraform モジュール使ってますか? Copyright © 3-shake, Inc. All Rights Reserved. 2

Slide 3

Slide 3 text

Copyright © 3-shake, Inc. All Rights Reserved. 今回の登壇で話すこと、話さないこと 3 ● なぜ魔境化するのか ● 魔境化との向き合い方 話さないこと ● 既にある魔境の綺麗にする方法 話すこと これから綺麗に作るぞ!という方、なんで使いづらくなるんだろ?と疑問を持っている方むけ

Slide 4

Slide 4 text

Copyright © 3-shake, Inc. All Rights Reserved. 自己紹介 4 羽山 公平 Sreak事業部で、主にAWSやGCP等のクラウド環 境でのSREをしております。 最近では、AIREといったAI+SREといった領域を 調べています!! @hymaaa_k

Slide 5

Slide 5 text

会社紹介 5 会社名 株式会社スリーシェイク 設立日 2015/1/15 Mission: インフラをシンプルにして イノベーションが起こりやすい世界を作る Vision: 労苦〈Toil〉を無くすサービスを適正な価格で提供し続ける 2015 2016 2017 2018 2019 2020 2021 2022 0 50 100 従業員: 200名over Engineer 60% 所在地 東京都中央区銀座8丁目21番1号 住友不動産汐留浜離宮ビル7F  代表者 代表取締役社長 吉田 拓真 Googleクラウド・AWSの両方のエンジニアリングに強みを持つ 日本のSREをリードする インフラ・アプリ・データ・セキュリティ・AI 全方位で顧客の内製化を推進する伴走支援 あらゆるサービスを 連携するハブになる 「いいエンジニア」を あなたのチームに 事業者が抱える セキュリティリスクをゼロに あらゆるSaaSをノーコードで連携する クラウド型ETL/データパイプラインSaaS セキュリティ対策をワンストップで 実現する脆弱性診断SaaS ハイスキル人材の紹介とHR戦略支援の両輪で エンジニア組織の課題に併走 会社・事業部説明資料(SpeakerDeck)

Slide 6

Slide 6 text

あなたのTerraformは「魔境」ですか? 01 Copyright © 3-shake, Inc. All Rights Reserved. 6

Slide 7

Slide 7 text

Copyright © 3-shake, Inc. All Rights Reserved. 魔境って何? 7 # variable.tf variable "complex_map" {} variable "enable_versioning" {} variable "enable_logging" {} variable "enable_replication" {} variable "enable_lifecycle" {} variable "enable_notification" {} # ... 大量に続く リソースが動的 variable の爆増 resource "xxxxxx" "xxxxx" { count = var.enable_nat ? 1 : 0 } moduleの処理を読まないと何が作られるのか分からない状態のこと

Slide 8

Slide 8 text

Copyright © 3-shake, Inc. All Rights Reserved. なぜ生まれるの? 8 S3リソース作るぞ〜 # env/dev/main.tf resource "aws_s3_bucket" "log" { bucket = "log-bucket" } resource "aws_s3_bucket_policy" "log" { ... } …

Slide 9

Slide 9 text

Copyright © 3-shake, Inc. All Rights Reserved. なぜ生まれるの? 9 S3いっぱい使うから毎回書くの良くないな… よし!module作るぞ! # env/dev/main.tf module "log_bucket" { source = "./modules/s3" bucket_name = "my-log-bucket" } module "data_bucket" { source = "./modules/s3" bucket_name = "my-data-bucket" }

Slide 10

Slide 10 text

Copyright © 3-shake, Inc. All Rights Reserved. なぜ生まれるの? 10 S3でlog貯めるなら、 ライフサイクルは設定し てください S3でコンテンツ配信し たいから、 バージョニングしたい

Slide 11

Slide 11 text

Copyright © 3-shake, Inc. All Rights Reserved. なぜ生まれるの? 11 柔軟にmodule使えるように変数追加しよう! # variable.tf variable "enable_versioning" { default = false } variable "enable_kms" { default = false } variable "enable_logging" { default = false } variable "enable_replication" { default = false } variable "enable_lifecycle" { default = false } # ... 要件に合わせて変数が増える

Slide 12

Slide 12 text

Copyright © 3-shake, Inc. All Rights Reserved. モジュールを作る人も辛い 12 要件によって必要なリソースが違う!! それぞれ管理しないと # modules/s3 resource "aws_s3_bucket_lifecycle_configuration" "xxx" { count = var.enable_lifecycle ? 1 : 0 ... } resource "aws_s3_bucket_versioning" "xxx" { count = var.enable_versioning ? 1 : 0 ... }

Slide 13

Slide 13 text

Copyright © 3-shake, Inc. All Rights Reserved. モジュールを利用する人も辛い 13 modules/s3はどのリソース管理しているのか 処理を見ないと分からない!!! # env/dev/main.tf module "log_bucket" { source = "./modules/s3" enable_versioning = false enable_kms = true enable_logging = true enable_replication = false }

Slide 14

Slide 14 text

AWSコミュニティが管理する汎用モジュール Copyright © 3-shake, Inc. All Rights Reserved. 身近にある魔境 14 module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "5.0.0" enable_nat_gateway = true single_nat_gateway = false # ← この2つの組み合わせで挙動が変わる one_nat_gateway_per_az = true # ← enable_flow_log = true create_flow_log_cloudwatch_iam_role = true #iam_roleが作られる # ... 変数は v5.0.0 で 300 個近くある }

Slide 15

Slide 15 text

なぜ我々は間違えたのか 02 Copyright © 3-shake, Inc. All Rights Reserved. 15

Slide 16

Slide 16 text

Copyright © 3-shake, Inc. All Rights Reserved. この発想が良くない 16 S3いっぱい使うから毎回書くの良くないな… よし!module作るぞ! # env/dev/main.tf module "log_bucket" { source = "./modules/s3" bucket_name = "my-log-bucket" } module "data_bucket" { source = "./modules/s3" bucket_name = "my-data-bucket" }

Slide 17

Slide 17 text

Copyright © 3-shake, Inc. All Rights Reserved. いやでも 17 DRY原則に従っているだけじゃない?

Slide 18

Slide 18 text

Copyright © 3-shake, Inc. All Rights Reserved. DRY原則 18 DRY原則とは「コードを重複させるな」ではなく「知識を重複させるな」という原則 すべての知識はシステム内において、単一、かつ明確な、 そして信頼できる表現になっていなければならない。 — Hunt & Thomas『達人プログラマー』DRY原則 [1]

Slide 19

Slide 19 text

Copyright © 3-shake, Inc. All Rights Reserved. アプリのコードとTerraformのコードの違い 19 ● 処理を記述 ● 「誰が・何のために使うか(文脈)」に依存❌ ○ ex)ソートの処理はどこでも同じ ■ Logの検索 ■ フロントエンドの描写 Terraformのコード ● 状態を記述 ● 「誰が・何のために使うか(文脈)」に依存 ○ ex) s3は用途によって違う ■ Log用のs3 ■ コンテンツのs3 アプリのコード アプリケーションコードは「処理」を記述する。 Terraformコードは「状態」を記述する。 — Gosuke Miyashita「なぜインフラコードのモジュール化は難しいのか」 YAPC::Fukuoka 2025 [2]

Slide 20

Slide 20 text

Copyright © 3-shake, Inc. All Rights Reserved. アプリコードにおけるDRY 20 item_sort user_sort log_sort 共通するsortする処理 コード 切り抜いて DRY達成 処理を記述 def sort(list, key) 知識の単一化=DRY達成 切り抜いたある処理は 処理だけを使いまわせる

Slide 21

Slide 21 text

Copyright © 3-shake, Inc. All Rights Reserved. インフラコードにおけるDRY 21 aws_s3_bucket lifecycle versioning log用のs3 コード まとめて DRY達成 状態を記述 module log_bucket 知識の単一化=DRY達成 data用のs3 aws_s3_bucket lifecycle versioning aws_s3_bucket module data_bucket インフラリソースには文脈があ るので文脈ごとにグループ化

Slide 22

Slide 22 text

Copyright © 3-shake, Inc. All Rights Reserved. 同じ S3 だけど、「知識」は違う 22 目的     :監査・デバッグ データの性質 :一定期間で価値が低下 削除保護   :不要(コスト優先で消す) アクセス制限 :管理者のみ ライフサイクル : x日で削除・安価なストレージへ ログ用のS3 目的     :ビジネス継続・収益 データの性質 :長期間に渡り高い価値を持つ 削除保護   :必須(事故=事業停止) アクセス制限 :細かい(個人情報・機密情報) ライフサイクル : 原則永久保持 or 長期保管 データ用のS3 「同じリソース」や「同じコード」という理由で共通化すると、 片方の都合(コスト削減)で、もう片方の資産(データ)を破壊してしまう可能性ある

Slide 23

Slide 23 text

Copyright © 3-shake, Inc. All Rights Reserved. この「知識」が違うということは 23 リソースが持つ”仕様”や”データ”のライフサイクルが違うということ

Slide 24

Slide 24 text

Copyright © 3-shake, Inc. All Rights Reserved. 改めて考えると良くない 24 S3いっぱい使うから毎回書くの良くないな… よし!module作るぞ! # env/dev/main.tf module "log_bucket" { source = "./modules/s3" bucket_name = "my-log-bucket" } module "data_bucket" { source = "./modules/s3" bucket_name = "my-data-bucket" }

Slide 25

Slide 25 text

魔境化をコントロールするために 03 Copyright © 3-shake, Inc. All Rights Reserved. 25

Slide 26

Slide 26 text

Copyright © 3-shake, Inc. All Rights Reserved. 抽象化をする 26 "A good module should raise the level of abstraction by describing a new concept in your architecture that is constructed from resource types offered by providers." 優れたモジュールは、プロバイダが提供するリソースタイプから構成されるアーキテクチャにおける新しい概念を定義すること で、抽象化のレベルを引き上げるべきである。 — Terraform 公式ドキュメント "When to write a module" [3] Log用のs3 ● 監査・アクセスログを保存する ● 改ざん不可・長期保存が前提 ● 変更要件はガバナンス依存 aws_s3_bucket bucket_policy lifecycle 新しい概念を定義

Slide 27

Slide 27 text

Copyright © 3-shake, Inc. All Rights Reserved. 抽象化をする 27 ● 概念を定義することでそのmoduleが何のた めにあるかが決まる ● 何が必要で何が不要かの判断基準ができる ラベリングされる ● コードを読まなくても表す概念がわかる 目的や責務が決まる

Slide 28

Slide 28 text

Copyright © 3-shake, Inc. All Rights Reserved. では、その概念を誰のために定義するのか? 28 ● インフラに詳しい ● モジュールを使う・管理 ● インフラ構成は自分で作る SRE・インフラ ● インフラは専門外 ● モジュールを使うだけ ● インフラ構成は作って欲しい フロント・バック・DS 利用者も作者も嬉しいモジュール 利用者に嬉しいモジュール

Slide 29

Slide 29 text

Copyright © 3-shake, Inc. All Rights Reserved. では、その概念を誰のために定義するのか? 29 ● インフラに詳しい ● モジュールを使う・管理 ● インフラ構成は自分で作る SRE・インフラ ● インフラは専門外 ● モジュールを使うだけ ● インフラ構成は作って欲しい フロント・バック・DS 利用者も作者も嬉しいモジュール 利用者に嬉しいモジュール ここが大事 ここが大事

Slide 30

Slide 30 text

Copyright © 3-shake, Inc. All Rights Reserved. 利用するユーザを考えた設計 30 ターゲット:SRE→SRE(管理も利用する) 自分たちのコードを整理するため。リソースの配 置や依存関係(構成)を綺麗にまとめる共通化 SREが組み合わせて使う「パーツ」だからこ そ、魔境化しないでシンプルに保つ。 ブラックボックス・カプセル化(隠蔽) ターゲット:SRE→アプリ(利用だけする) インフラを意識させないため。「セキュアなログ 保存」「Webサイト公開」という機能そのものを 届けるためのカプセル化 アプリ開発者に「価値」だけを届けるために、 裏側の複雑性を引き受ける。 ホワイトボックス・テンプレート(共通化)

Slide 31

Slide 31 text

Copyright © 3-shake, Inc. All Rights Reserved. 利用するユーザを考えた設計 31 ターゲット:SRE→SRE(管理も利用する) 自分たちのコードを整理するため。リソースの配 置や依存関係(構成)を綺麗にまとめる共通化 SREが組み合わせて使う「パーツ」だからこ そ、魔境化しないでシンプルに保つ。 ブラックボックス・カプセル化(隠蔽) ターゲット:SRE→アプリ(利用だけする) インフラを意識させないため。「セキュアなログ 保存」「Webサイト公開」という機能そのものを 届けるためのカプセル化 アプリ開発者に「価値」だけを届けるために、 裏側の複雑性を引き受ける。 ホワイトボックス・テンプレート(共通化) 魔境化させない 魔境化を受け入れる

Slide 32

Slide 32 text

Copyright © 3-shake, Inc. All Rights Reserved. ホワイトボックス:「構成」の抽象化は魔境化させない 32 moduleが決めるもの ● リソース構成や依存関係 ● ドメイン特有の定石・お作法等の設定 ユーザに委ねるもの ● 意思決定が必要な値 ● どこで・どう組み合わせて使うか module "app_log" { source = "./modules/log_s3" # どう使うか?(app?aws_audit?) bucket_name = "app_log" # 意思決定が必要な値 retention_days = 90 storage_class = "GLACIER" }

Slide 33

Slide 33 text

Copyright © 3-shake, Inc. All Rights Reserved. ホワイトボックス:「構成」の抽象化は魔境化させない 33 知識の集約 ● ドメイン特有の設定値等を強制 ● 変更を安全かつ即座に全体へ波及させる コードの認知負荷の低減 ● 実装の詳細を「論理的なグループ」に置換 ● 「正しく書く」ための労力を、アーキテク チャ上の「意思決定」のみに集中 利用者 管理者

Slide 34

Slide 34 text

Copyright © 3-shake, Inc. All Rights Reserved. ブラックボックス:「機能」の抽象化は魔境化を受け入れる 34 moduleが決めるもの ● 変数に応じた最適なリソース構成 ● 変数に応じた最適なリソースの設定 ユーザに委ねるもの ● 「何を実現したいか」という目的の入力 ● ビジネス上の要求レベル ○ 具体的な手段は委ねない module "app_log" { source = "./modules/log_platform" # 目的や意図だけを出す # 何を入れるか(app,alb,db,aws_audit) log_source = "app" }

Slide 35

Slide 35 text

Copyright © 3-shake, Inc. All Rights Reserved. ブラックボックス:「機能」の抽象化は魔境化を受け入れる 35 ガバナンスと標準化の強制 ● セキュリティや可用性設計はモジュールが自 動的に最適化する。 ● 利用者を「サービスを動かすこと」に全集中 できるようにする 専門外の認知負荷を限りなく減らす ● 実装の詳細を「単一の機能」に置換 ● 具体的なリソースを意識させない 利用者 管理者

Slide 36

Slide 36 text

Moduleをどう作っていけば良いか 04 Copyright © 3-shake, Inc. All Rights Reserved. 36

Slide 37

Slide 37 text

Copyright © 3-shake, Inc. All Rights Reserved. ホワイトボックスの場合:ドメインの「標準部品」を定義する 37 SRE/インフラ担当者 プロジェクト全体の構成を把握し、各リソースの ライフサイクルの違いを理解しているインフラに 詳しく、責任が持てる層 どんな概念か? 「計算機+IAM+ログ」の最小単位 汎用的なECSやCloud Runを、プロジェクトの規 約に沿った「api-svc標準部品」として定義する 誰が利用するか?

Slide 38

Slide 38 text

Copyright © 3-shake, Inc. All Rights Reserved. ホワイトボックス:ユーザーに「委ねる」設計 38 module "user_api" { source = "./modules/api/svc" # 1. 意思決定(コスト・スペック) cpu = 512 memory = 1024 # 2. 配線(どこで・どう組み合わせるか) iam_policy_arns = ["arn:xxx:xxx:" ] sg_rules = ["sg-xxxx"] } Ecs module どこで・どう組み合わせて使うか ● 外部リソースの接続に必要な値を露出させる ● 変則的な構成変更にも柔軟に対応できる疎結 合なインターフェースを維持する。 意思決定が必要な値 ● 意思決定が必要な値を露出させる ● コストや運用方針に関わるパラメータはモ ジュールが決め打ちせず、利用者に委ねる。

Slide 39

Slide 39 text

Copyright © 3-shake, Inc. All Rights Reserved. ブラックボックスの場合:ドメインの「プラットフォーム」を定義する 39 アプリケーション開発者 インフラの詳細は意識せず、セルフサービスで迅 速にAPIを公開したい層 どんな概念か? 「APIサービス実行環境」そのもの 計算機だけでなく、通信経路や付随するセキュリ ティ設定までを一つの機能として定義 誰が利用するか?

Slide 40

Slide 40 text

Copyright © 3-shake, Inc. All Rights Reserved. ブラックボックス:ユーザーに「委ねる」設計 40 module "user_api" { source = "./modules/api/svc" # 1. 目的:インフラの「形」を決定 visibility = "internal" db_usage = "shared" service_name = "payment-api" # 2. 要求レベル:パラメータの「質」を決定 resiliency = "high" # 冗長化の要 否 data_sensitivity = "pii" # データの機 密 } ビジネス上の要求レベル ● 冗長構成の要否や、データの機密度といった 「要求水準」を入力させる ● 入力された値に基づき、モジュールが自動適 用する。 「何を実現したいか」という目的 ● 公開範囲や接続先など、ドメインの意図だけを 入力させる ● 具体的なリソースを隠蔽し、利用者の認知負荷 を極限まで下げる。

Slide 41

Slide 41 text

まとめ 05 Copyright © 3-shake, Inc. All Rights Reserved. 41

Slide 42

Slide 42 text

文脈が違うリソース=「共通しない知識」 を無理にまとめてしまうから Copyright © 3-shake, Inc. All Rights Reserved. なぜモジュールは「魔境化」するのか? 42

Slide 43

Slide 43 text

Copyright © 3-shake, Inc. All Rights Reserved. 魔境化に向かう2つのパターン 43 SREが管理しやすいはずの「透明なモジュー ル」を作ろうとしたが、知識(ライフサイク ル)が違うものを無理に共通化した結果、変数 やロジックが大量な魔境になる。 ホワイトボックスの失敗 =「間違ったDRY」 アプリ開発者が詳細を意識しなくていいよう に、インフラの構築ロジックをすべてモジュー ル内部にカプセル化する。 ブラックボックスの目的 =「高い抽象度」

Slide 44

Slide 44 text

Copyright © 3-shake, Inc. All Rights Reserved. 魔境との付き合い方・向き合い方 44 対象:同じチームでモジュールの利用・管理 ● 知識(ライフサイクル)ごとにモジュー ルを適切に分離し、シンプルさを保つ。 ● 利用者だけでなく、管理者の認知負荷も 考えて作る 魔境化させては「いけない」ケース 対象:モジュールの利用・管理が別チーム ● 利用者の優れたUX(認知負荷の極小 化)を考えて作る ● モジュール提供側が「魔境の複雑さ」を 背負い、責任を持って管理し続ける。 魔境化を「受け入れる」べきケース 「魔境化」は一概に悪ではない。「誰が管理し、誰が使うか」で割り切りを変える。

Slide 45

Slide 45 text

[1] David Thomas, Andrew Hunt 著, 村上 雅章 訳『達人プログラマー』p.96 (Kindle版) [2] Gosuke Miyashita「なぜインフラコードのモジュール化は難しいのか — アプリケーションコードとの本質的な違いから考える」 https://speakerdeck.com/mizzy/yapc-fukuoka-2025 [3] HashiCorp "Creating Modules — When to write a module" https://developer.hashicorp.com/terraform/language/modules/develop#when-to-write-a-m odule Copyright © 3-shake, Inc. All Rights Reserved. 参考資料・文献 45

Slide 46

Slide 46 text

46 採用情報 スリーシェイク公式Note Sreake事業部 採用中ポジション情報 もし何か気になることがある方は、DMや相談乗りますので連絡ください!!

Slide 47

Slide 47 text

ご清聴ありがとうございました。 Copyright © 3-shake, Inc. All Rights Reserved. 47