Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
チームメンバー迷わないIaC設計
Search
hayama
February 28, 2026
Technology
6.7k
12
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
チームメンバー迷わないIaC設計
hayama
February 28, 2026
More Decks by hayama
See All by hayama
AI Agentをシステムに組み込む前にゆるく向き合ってみる
hayama17
0
110
Terraformモジュールは、なぜ「魔境」化するのか
hayama17
3
260
Leaky Vessels/CVE-2024-21626から分かるコンテナセキュリティ
hayama17
0
190
Other Decks in Technology
See All in Technology
[チョークトーク資料]AWS DevOps Agent を使いこなす / AWS Dev Ops Agent Chalk Talk AWS Summit Japan 2026
kinunori
4
760
作る力から、見極める力へ — AI時代に広がるエンジニアの価値と役割
rince
0
320
起点・思考・出力で分解する 〜PM業務の自動化設計〜
kazu_kichi_67
1
1k
GitHub Copilot app最速の発信の裏側
tomokusaba
1
250
人材育成分科会.pdf
_awache
4
320
從開發到部署全都交給 AI:實作 AI 驅動的自動化流程
appleboy
0
150
2026-06-24_人とAIの責務分離に基づく開発プロセスの提案.pdf
takahiromatsui
0
110
When Platform Engineering Meets GenAI
sucitw
0
170
感情と身体を置き去りにしない、エンジニアの生きのこり方 ──いまから、ここから「自分の状態」を扱うという選択
saorimurooka
0
320
新しいUbuntu/GNOMEが使いたいからXからWaylandへ移行頑張ってるの巻 2026-06-20
nobutomurata
0
160
技術・能力を向上する原理原則 #きのこセッションa #きのこ2026
bash0c7
0
110
いまさら聞けない「仕様駆動開発入門」 〜AI活用時代の開発プロセスを考える〜
findy_eventslides
2
190
Featured
See All Featured
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Navigating Weather and Climate Data
rabernat
0
230
Rebuilding a faster, lazier Slack
samanthasiow
85
9.5k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.9k
Producing Creativity
orderedlist
PRO
348
40k
Agile that works and the tools we love
rasmusluckow
331
22k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
310
The Mindset for Success: Future Career Progression
greggifford
PRO
0
370
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
1.8k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.4k
Documentation Writing (for coders)
carmenintech
77
5.4k
Transcript
チームメンバーが 迷わないIaC設計 読むときも、実行するときも、どんなときも 2026/02/28 SRE Kaigi 2026 延長戦 @hymaaa_k
hym(@hymaaa_k) 株式会社スリーシェイクでプラットフォーム基盤を構築 したり、SRE支援を行っています。 イベントに参加・運営したりするイベント驚き屋 IaCが難しいよねって世論に対抗したい 2
今日お話しすること IaCの課題を設計で解消する こんな経験ありませんか? diff追ってたはずが、変数→tfvars→module→……「あれ、何見てたんだっけ?」 plan 打ったら関係なさそうなリソースまで出てきて「これ関係ある…?」 「ここ見てね」って言ったのに翌日「どこから読めばいいですか?」って聞かれる 技術的な難しさではなく、設計の問題として IaC を捉え直す
3
なぜIaCは難しいのか 「処理」ではなく「状態」を書くから 通常のプログラミング = 処理を書く 「何をするか」を書く コードを一方向に読めば結果が予測できる IaC = 状態を書く
「どうあるべきか」を書く 「今どうなっているか」が別に存在する コードだけ読んでも答えがわからない 状態を扱う以上、コンテキストスイッチは構造的に多くなりがち 4
IaCで「迷う」とは? 状態を扱うから生まれる3つの迷い 読むだけではわからない 変数や分岐を自分で処理しない と、最終的な状態が組み立てら れない 差分が読めない 変更の結果が意図通りか、影響 範囲はどこまでか、判断できな い
どこまで抽象化すべきかわから ない 何を隠して何を見せるか、その 線引きが判断できない 根っこにあるのはコンテキストスイッチだと思っています 5
心がけている5つの原則 まずはコードの構造の話から 6
原則 1: 条件分岐を減らす コードを読むだけで状態がわかるようにする 条件分岐があると、コードを読んだだけでは最終的な値がわからない。読み手が頭の中で実行する必要がある コンテキストスイッチが発生する ファイル間の移動: 変数定義を探す → tfvarsの値を確認
脳内処理: 条件を組み立てる、レビュー時はすべてのパターンを追い直す 7
原則 1: 悪い例 resource "aws_instance" "app" { instance_type = var.env
== "prod" ? ( var.workspace == "shared" ? "t3.xlarge" : "t3.large" ) : "t3.micro" monitoring = var.env == "prod" && var.workspace != "batch" root_block_device { volume_size = var.env == "prod" ? ( var.workspace == "batch" ? 200 : 100 ) : 20 } } 2つの変数の組み合わせで分岐(CDKの if 文やPulumiの条件式でも同じ問題が起きる) 3属性 × 2変数 = 読み手が処理する分岐が6箇所 8
原則 1: 良い例 構造で解決する # prod/shared/main.tf resource "aws_instance" "app" {
instance_type = "t3.xlarge" monitoring = true root_block_device { volume_size = 100 } } prod/shared/main.tf を開けば答えがわかる。分岐ゼロ データで解決する locals { config = { prod-shared = { type = "t3.xlarge" vol = 100, mon = true } prod-batch = { type = "t3.large" vol = 200, mon = false } dev-default = { type = "t3.micro" vol = 20, mon = false } } }["${var.env}-${var.workspace}"] 組み合わせを表にする。計算不要で「表を見るだけ」 どちらもコンテキストスイッチを不要にする。読むだけで答えがわかる 9
原則 2: 構造で語る 管理単位を分けて認知のコンテキストスイッチを減らす 管理単位が大きいと、変更対象以外のリソースまで認知範囲に入ってくる コンテキストスイッチが発生する 差分出力のノイズ: 変えたのはECSだけなのに、VPC・ALB・RDSも表示される 安全確認の往復: 「これ触って大丈夫?」と確認して回る
10
原則 2: 悪い例 Terraform terraform/ ├── main.tf # VPC、ALB、ECS、RDS、 │
# S3、CloudFront...全部入り ├── variables.tf └── outputs.tf 1つのStateに全リソースが同居。 terraform plan で100個 のリソースが表示される CDK export class MyStack extends Stack { constructor(scope: Construct, id: string) { // 全部ここに3000行... const vpc = new ec2.Vpc(...); const alb = new elbv2.ApplicationLoadBalancer(...); const cluster = new ecs.Cluster(...); const db = new rds.DatabaseInstance(...); } } 1つのStackに全リソースが同居。 cdk synth で全リソース が一気に出力される 変更の影響範囲を絞れない。見たい差分だけを見ることができない 11
原則 2: 良い例 Terraform - Stateを分割 terraform/ ├── network/ #
State1: VPCだけ ├── platform/ # State2: ALB、ECSだけ └── data/ # State3: RDS、S3だけ terraform plan の出力がState単位に限定される。 「今は ネットワークだけ」と集中できる CDK - Stackを分割 // NetworkStackはVPCだけ class NetworkStack extends Stack { ... } // PlatformStackはALB、ECSだけ class PlatformStack extends Stack { ... } cdk synth NetworkStack で対象を限定できる 分割すれば見る範囲が限定される。変更対象だけに集中できる 12
原則 3: 分割粒度はライフサイクル 変更頻度で分けて実行時のコンテキストスイッチを減らす Terraform State、CDK Stack、Pulumi Stack など管理単位の呼び方は違っても、変更頻度が違うものが同居している と実行のたびに余計な確認が発生します
コンテキストスイッチが発生する 無関係な差分の混入: アプリをデプロイしたいだけなのに、ネットワーク層の差分も表示される 毎回の安全確認: 「これ触って大丈夫?」と確認する往復が毎回発生 13
原則 3: 悪い例 platform/ ├── alb.tf # 月1回の変更 ├── ecs_cluster.tf
# 月1回の変更 ├── ecs_service.tf # 日次でデプロイ ← ここだけ頻度が違う └── ecs_task_def.tf # 日次でデプロイ ← ここだけ頻度が違う 役割で分けた結果、変更頻度が全く違うリソースが同居。planのたびにクラスタやALBの差分も表示される 変更頻度の違うリソースが同居し、毎回の安全確認が避けられない 14
原則 3: 良い例 小さいプロダクト → プロダクトごと product-a/ # 変更頻度が近いリソースが自然にまとまる product-b/
shared/ # 共通リソース プロダクト内のリソースは変更タイミングが近いので、そ のまま管理単位になる 大きいプロダクト → レイヤーで分割 01-network/ # 月1回 02-compute/ # 週1回 03-apps/ # 日次デプロイ プロダクト内で変更頻度に差が出てきたら、レイヤーで分 ける 変更頻度が近いものだけが同居する。確認対象が減り集中できる 15
「どこまでやるか」の線引き 抽象化と管理範囲の話 16
原則 4: 目的を考えた抽象化 実装へのコンテキストスイッチをコントロールする IaCの抽象化(module、Construct等)は、利用者と実装の境界を決める設計判断です 手段は2つあり、リソースの扱い方が異なります テンプレート(共通化) リソースを固定し、繰り返しを減らす ←→ カプセル化(隠蔽)
関心事だけ受け取り、リソースは内部で決定する テンプレートはコンテキストスイッチのコストを下げ、カプセル化はさせない 17
原則 4: 2つの手段 誰が作り、誰が使うかで設計が変わる 目的と手段がブレると、コンテキストスイッチが制御できなくなる インフラ・ SREチーム → 抽象化 中身も
把握する → インフラ・ SREチーム 作る人 = 使う人。繰り返しを減らして整理する 抽象化 = DRY原則。同じリソース定義を書かせない 共通化 Platform チーム → 抽象化 中身は 見せない → App チーム 作る人 ≠ 使う人。複雑さを吸収して迷わせない 抽象化 = インターフェース。チーム間の境界を定義する 隠蔽 18
原則 4: 悪い例 module "service" { source = "./modules/service" family
= "user-api" image = "ecr.../user-api:v1.2.3" cpu = 256 memory = 512 container_port = 8080 subnet_ids = module.network.private_ids vpc_id = module.network.vpc_id # 特定のサービスのために追加されたパラメータ legacy_port_mapping = { 8080 = 80 } # → ListenerRuleが追加される skip_service_discovery = true # → ServiceDiscoveryが消える } リソースの増減が入り込み、状態だけでなくリソースまで管理・確認が必要になっている 例外対応のために、実装を確認するコンテキストスイッチが増える 19
原則 4: 良い例 テンプレート(繰り返しを避けたい) module "service" { source = "./modules/service"
family = "user-api" image = "ecr.../user-api:v1.2.3" cpu = 256 memory = 512 container_port = 8080 subnet_ids = module.network.private_ids vpc_id = module.network.vpc_id } # 例外が必要なら module を使わず直接書く DRY原則。インフラの関心事を変数として全て露出する カプセル化(複雑さを隠したい) module "service" { source = "./modules/service" app_name = "user-api" image = "ecr.../user-api:v1.2.3" container_port = 8080 legacy_port_mapping? → 対応 skip_service_discovery? → 対応 } インターフェース。Appチームの関心事(app名・image・ port)だけを渡す 目的が明確なら、不要なコンテキストスイッチが発生しない 20
原則 5: IaCだけで管理しない 不要なコンテキストスイッチを避ける どのIaCツールでも、全てをコード化しようとすると条件分岐が増え、コンテキストスイッチが増えます コンテキストスイッチが増える 初回セットアップをTerraformで管理 → is_first_run 変数を確認
→ 「今は初回?」と考える → enable_locking 変数 も確認 → 「ロックは有効?」と考える... 本来1回きりの作業に、永続的なコンテキストスイッチが残る 21
原則 5: 悪い例 # 初回セットアップのために複雑な条件分岐 resource "aws_s3_bucket" "state" { count
= var.is_first_run ? 1 : 0 # ... } resource "aws_dynamodb_table" "lock" { count = var.is_first_run && var.enable_locking ? 1 : 0 # ... } 1回きりの作業をコード化し、複雑な条件分岐を追加 is_first_run、enable_locking など、複数の変数を確認して理解する往復が毎回発生する 22
原則 5: 良い例 # docs/setup.md ## 初回セットアップ手順 1. S3バケットを手動で作成 aws
s3 mb s3://my-terraform-state 2. backend設定を追加 3. terraform initを実行 シンプルなドキュメントとして記述 手順書を見るだけで完結。コード内の条件分岐を確認する往復が不要 23
まとめ 5つの原則 1. 分岐を減らす — 読むだけで結果がわかる 2. 構造で語る — 見る範囲を限定する
3. ライフサイクルで分割 — 変更対象だけに集中する 4. 目的を考えた抽象化 — 実装へのコンテキストスイッ チをコントロールする 5. IaCだけで管理しない — コード化しない判断をする 明日からできること まずは自分のIaCで ? や if を検索して、条件分岐 の数を数えてみる 1つのStateやStackが管理するリソース数を確認す る。多すぎたら分割を検討 余裕があれば、moduleの目的が「共通化」か「隠 蔽」かチームで話してみる そのIaC、何回コンテキストスイッチが発生しますか? 24
about 3-shake 25
We are Hiring 3-shakeは一緒にSRE界隈を盛り上げてくれる仲間を大募集中です! Mobility、FinTech、通信など大規模SREを存分に経験できます 是非、カジュアル面談しましょう! 26
ありがとうございました ご質問・ご相談はお気軽にお問い合わせください @hymaaa_k | https://3-shake.com
Appendix 抽象化の2つの手段 — 共通化と隠蔽 28
抽象化の2つの手段 誰が作り、誰が使うかで設計が変わる 同じmoduleでも、目的が違えばインターフェースが変わる インフラ・ SREチーム → module 中身も 把握する →
インフラ・ SREチーム 作る人 = 使う人。繰り返しを減らして整理する 共通化 Platform チーム → module 中身は 見せない → App チーム 作る人 ≠ 使う人。複雑さを吸収して迷わせない 隠蔽 29
共通化: インフラ・SREチームの内部整理 同じパターンの繰り返しを減らす 呼び出し側(SREチーム自身が書く) module "service" { source = "./modules/service"
family = "user-api" image = "ecr.../user-api:v1.2.3" cpu = 256 memory = 512 container_port = 8080 subnet_ids = module.network.private_ids vpc_id = module.network.vpc_id alarm_actions = [aws_sns_topic.alert.arn] } module内部(チーム全員が読む前提) # ECS TaskDefinition → パラメータで構成 # ECS Service → パラメータで構成 # TargetGroup → パラメータで構成 # CloudWatch Alarm → パラメータで構成 # # 「何が作られるか」は呼び出し側から # 全て把握できる。 # moduleはボイラープレートの削減が目的 特徴: インターフェースは「インフラの関心事」を全て露出する。チーム内の全員がmoduleの中身を理解している前提。 中身へのコンテキストスイッチがしやすい設計 30
隠蔽: Platformチーム → Appチームへの提供 アプリチームにインフラの詳細を見せない Appチームが書くコード module "service" { source
= "git::https://.../modules/service" app_name = "user-api" image = "ecr.../user-api:v1.2.3" container_port = 8080 replicas = 3 # これだけ。あとはPlatformチームが面倒を見る } module内部(Appチームは触らない) # VPC, Subnet → 自動選択 # ALB, TargetGroup → 自動作成 # SecurityGroup → ベストプラクティス適用 # CloudWatch Alarm → 標準メトリクス設定 # IAM Role → 最小権限で自動生成 特徴: インターフェースは「アプリの関心事」だけ。ネットワーク・監視・セキュリティはmodule内で決定する。Appチ ームが中身を見る必要がない=コンテキストスイッチが発生しない 31
共通化と隠蔽の比較 共通化 隠蔽 誰が作る インフラ・SREチーム Platformチーム 誰が使う 作った本人たち Appチーム インターフェース
インフラの関心事を全て露出 アプリの関心事だけ module内部 見る前提 見なくていい 例外対応 moduleを使わない判断をする module内部で吸収 パラメータ数 多い 少ない 目指すもの 繰り返させない 迷わせない どちらが正しいかではない。目的が違えばインターフェースが変わる 共通化なのに隠蔽のインターフェース → SREチームが迷う(中で何が起きてるかわからない) 隠蔽なのに共通化のインターフェース → Appチームが迷う(パラメータ多すぎ) 32
テンプレートにリソースの増減が入ったら リソースの変化パターンごとの対処 数が増える(例: レプリカ、サブ ネット) count や for_each で動的なテ ンプレートにする。リソースの種
類は固定のまま 0→1で生える(例: ListenerRule) それはこのmoduleが管理すべきも のではない。module外で管理す る 条件で消える(例: ServiceDiscovery) それはこのmoduleが管理すべきも のではない。最初からmoduleに 含めない テンプレートはリソース宣言を固定するもの。増減が必要ならmoduleの境界を見直す 33