Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Podは生きているのにGoだけが落ちる:GOGCとGOMEMLIMITで追うInvisible...
Search
Watanabe Takeshi(Buzz)
September 10, 2026
Technology
1.6k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Podは生きているのにGoだけが落ちる:GOGCとGOMEMLIMITで追うInvisible OOM Killの謎
2026/09/11(金)の登壇資料です。
https://gocon.jp/2026/
https://gocon.jp/2026/timetable/sponsorSlot2/
Watanabe Takeshi(Buzz)
September 10, 2026
More Decks by Watanabe Takeshi(Buzz)
See All by Watanabe Takeshi(Buzz)
プロダクト思考 × 基盤思考を AIで実現する Compound Engineering
tkc66buzz
1
390
二重開発負債をOne Application化で解くペアーズのグローバルRe:Architect戦略
tkc66buzz
1
130
Platform Engineeringことはじめ~コミュニティと一緒に新たな旅に出よう!
tkc66buzz
0
170
Other Decks in Technology
See All in Technology
宣言型部分更新は何を解決しどこへ向かうのか
shuta13
1
470
AI導入は済んだ。次は統制を作り替える番だ_AI×開発組織 Summit 2026
techtekt
PRO
0
360
"優秀な誰か"の下位互換にならないために
yut0naga1_fa
1
1.8k
フィンテック養成勉強会#68
finengine
0
150
実践!Cloud Run ハンズオン!! / Cloud Run handson
y0hgi
2
300
Gemini Intelligence 入門 ― AppFunctions と Gemini Nano
takuroabe
0
290
[JAWS-UG彩の国埼玉#12]そろそろ準備する?re:Invent2026をやさしく解説 / reinvent2026-sainokuni
sh_fk2
1
360
TinyGoでオブザーバビリティ?OpenTelemetryはTinyGoで使えるのか / Is OpenTelemetry available in TinyGo environment?
ymotongpoo
2
140
Rust で関数型ドメインモデリング
takonda
0
170
Claude の新機能を、 出た日に触って社内に届けるまで
rfdnxbro
1
190
AIカンパニーへの転換を支えた、エンジニアの仕事の再定義
kworkdev
PRO
2
1.3k
Active Record Connection Adaptersにおける長年の課題に再び取り組む
yahonda
0
200
Featured
See All Featured
Testing 201, or: Great Expectations
jmmastey
46
8.3k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
Designing for Performance
lara
612
70k
Statistics for Hackers
jakevdp
799
230k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
8.1k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
530
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
370
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.7k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
630
The World Runs on Bad Software
bkeepers
PRO
72
12k
Transcript
Podは⽣きているのにGoだけが落ちる GOGCとGOMEMLIMITで追うInvisible OOM Kill の謎 2026年09⽉11⽇ Go Conference 2026 1
About Me Buzz | Takeshi Watanabe @buzz_tkc Company 株式会社エウレカ Role
Senior Backend Engineer Hobbies トライアスロン, スノボ, サッカー 2
3
2025年4月頃 4
数日に一回の周期で 5xxエラーが不定期に大量発生し始める 5
✕ Killed Go App 5xxエラー発生後に Goのプロセスが落ちる 6
Panic logがでていない OOM Killedもでていない Podも⽣きている Goのプロセスだけ 突然落ちたように⾒える 7
そんな謎が多い障害を 一つ一つ解き明かしていくお話です 8
Agenda 1 前提:ペアーズのArchitectureと発⽣していた問題 2 第⼀の謎:Invisible OOM 3 第⼆の謎:なぜGoがOOMでKillされたのか 4 第三の謎:なぜGCが⾛らなかったのか
5 問題を解いていく 6 まとめ 9
前提:ペアーズの Architectureと 発生していた問題 10
ペアーズの Architecture(簡略版) • GoのアプリケーションがKubernetes(Amazon EKS)上で動いている • 当時は歴史的経緯もあり、NginxとGoが同じコンテナ内で動いていた Go App Nginx
クライアント (iOS / Android / Web) EKS 11
不定期に起きていた問題 • 5xxエラーが急激に増え、Goのプロセスが落ちる • 同じコンテナのNginxは生きている • エラー発生後、何事もなかったようにすぐに復活する Container Nginx Go
App 12
第⼀の謎 Invisible OOM 13
まずは何が起きたかを確認していく Application panic log なし Container Nginxは稼働、Goだけが不在 Kubernetes/Pod OOMKilled ‧Terminatedなし
Host / Kernel TaskOOM / oom-kill / exit code 137 → ここで初めて OOM だったと判明 14
問題があったコンテナを分析する コンテナは技術的には複数プロセスを動かせるが、1コンテナ1プロセス が推奨。当時は歴史的経緯でNginx + Go の複数プロセス構成だった。 コンテナ ✓ Alive PID1
= init (起動シェル / entrypoint) コンテナの「親」プロセス ✓ Alive ✕ Killed Nginx Go App ⼦プロセス 前段のリバースプロキシ ⼦プロセス‧PID≠1 アプリ本体 15
鍵はkillされたプロセスがPID1かどうか Linux OOM Killer はcontainer memory limitを超えた場合、 コンテナ内のメモリを⼀番使⽤しているプロセスを選んで kill する。
PID1(init)をkill → Container ⾃体が終了 → Status = OOMKilled (=普通はこう⾒える) (今回)⾮PID1 のGoプロセスをkill → PID1 と Nginx は⽣存 → Container は落ちない → OOMKilledもTerminatedも出ない NginxとGoが1つのコンテナに同居しているせいで、OOMの発⽣がログか ら⾒えづらい(Invisible)状態になっていた。 16
補⾜:Kubernetesのバージョンで挙動が変わる 必ずGoだけが kill されると⼀般化はできず、Kubernetes / cgroup の バージョンで挙動が変わる。 バージョン 挙動
Kubernetes 1.27 以前 ⼀番メモリを使⽤しているプロセスのみ killされる。 (=Goだけ落ちる、今回のケース) Kubernetes 1.28 以降 (cgroup v2 +memory.oom.group) 同じcgroup内の任意のプロセスがまとめて killされうる。 17
実際に起きていた挙動の流れ ③liveness probeが失敗(Goの応答なし) ① 何かしらの原因で Container OOM Killが⾛り、 Go だけが
kill される。 kubelet Kernel Go App Nginx ⑤コンテナ再起動で復活 ④Nginxがupstream(Go)不在 で502/503を返し続ける ②PID1とNgixが残るためContainer は即時終了しない Client 18
その結果一時的な 5xxエラーが大量発生しては、 コンテナ再起動で復活を繰り返す 19
Invisible OOMの調査結果 謎 調査結果 • Pod/Containerのstatusに OOMが出ない。 • メトリクス上だと⼀瞬5xxエ ラーが発⽣しては、すぐに回
復する挙動が繰り返される。 • Go(⾮PID1)がKernelにOOM Kill されていた。 • PID1とNginxが⽣存しているため Containerは落ちず、OOMが Pod/ContainerのStatusに出ず観 測しづらい状態となっていた。 20
第⼆の謎 なぜGoがOOMでKillされたのか 21
⾒えないスパイクがあったと推測 • 観測グラフ上では container memory limitの超過は確認できなかった • KernelのOOM Logから、メモリの超過が発⽣したのは確実 ◦
短期間のメモリスパイクが発⽣したと推測 コンテナメモリの推移 メモリ 使用量 container memory limit 到達で即 OOM Kill 実際には⾒えていなかった推移 時間 22
スパイクの発⽣源は単⼀ではなかった 数⽇に1回コンテナが落ち、かつ規則性がないことから、単⼀の原因では なさそうだった。 • 重い処理で⼀時的にメモリに負荷がかかる • リクエストが急増する 上記が不定期に重なった際に、トラフィック起因の散発的なスパイクが発 ⽣し、それが原因でOOMが発⽣したと推測。 23
スパイクを防げなかった原因として GOMEMLIMITが未設定だった GOMEMLIMITとは、Go runtime に与える緩い上限。近づくとGCを積極的 に実⾏し、container memory limitの前でメモリを解放させられる。 container memory
limit 到達で即 OOM Kill GOMEMLIMIT (GC line) メモリ 使用量 GOMEMLIMITに近づくとGCを 積極的に実⾏し、OOMを防ぐ 時間 24
なぜOOMが発⽣したかの調査結果 謎 調査結果 • メトリクス上だとcontainer memory limitの超過は観測 できなかった。 • GoのGCが⾛らなかった。
• KernelのOOM Logと突き合わせ て、短期的かつ散発的なスパイ クが発⽣したと予想。 • GOMEMLIMIT未設定が原因で memory limitの前にGCを発⽕さ せられなかった。 25
第三の謎 なぜGCが⾛らなかったのか 26
実はGOGC=500を設定していたが機能していなかった GOGCとは以下の計算式で算出される、次回のGC実⾏を決める指標。 次回GCの⽬標 = live heap ×(1 + GOGC/100) GOGC=500
live heap × 6 GCが稀に発⽕ (CPU負荷↓) メモリ 使用量 GOGC=100 live heap × 2 GCが頻繁に発⽕ (CPU負荷↑) live heap (前回GC後に⽣きていたheap) 時間 27
GCが⾛るより先にcontainer memory limit へ到達した可能性 CPU負荷を抑える狙いでGOGCを⼤きめにしていたが、そのせいで図のように、 GCの⽬標より先にコンテナの上限に達していた可能性がありそうだった。 GOGC=500で、次回にGCが⾛るライン(live heap × 6)
メモリ 使用量 container memory limit ②GCが⾛るのはもっと上 ① OOM Kill 時間 28
なぜGCが⾛らなかったのかの調査結果 謎 調査結果 GOGCを設定しているのにもかか わらず、なぜOOM前にGCが⾛ら なかったのか。 1. live heapが増える 2.
GOGC=500の相対条件 > container memory limit 3. GCより先にcontainer memory limitへ到達 4. Kernel OOM Kill 29
問題を解いていく 30
今まで起きていた問題を整理 問題 起きていた事象 NginxとGoが 同⼀コンテナに同梱 • • 解消法 コンテナメモリのメトリクス NginxとGoを別コンテナ
に分離する。 が見にくい。 PID1がベースアプリにな らない。 Goがcontainer memory limitを 知らない Goはcontainer memory limitを知らずにheapを伸ば し続ける。 GOMEMLIMITを設定す る。 GCが相対値で決まる スパイク時にGCのラインが GOGC=offを設定する。 container memory limitを超え る。 31
今まで起きていた問題を整理 問題 起きていた事象 NginxとGoが 同⼀コンテナに同梱 • • 解消法 コンテナメモリのメトリクス NginxとGoを別コンテナ
に分離する。 が見にくい。 PID1がベースアプリにな らない。 Goがcontainer memory limitを 知らない Goはcontainer memory limitを知らずにheapを伸ば し続ける。 GOMEMLIMITを設定す る。 GCが相対値で決まる スパイク時にGCのラインが GOGC=offを設定する。 container memory limitを超え る。 32
NginxとGoを別コンテナに分離する 1コンテナ1プロセス(PID1に割り当て)に分離。メモリやCPUといったメトリ クスを個別にトラッキングできるようにした。 副次的に今まで動いていなかったGraceful Shutdownも動くようになった。 Nginx Go App EKS Nginx
Go App EKS 33
今まで起きていた問題を整理 問題 起きていた事象 NginxとGoが 同⼀コンテナに同梱 • • 解消法 コンテナメモリのメトリクス NginxとGoを別コンテナ
に分離する。 が見にくい。 PID1がベースアプリにな らない。 Goがcontainer memory limitを 知らない Goはcontainer memory limitを知らずにheapを伸ば し続ける。 GOMEMLIMITを設定す る。 GCが相対値で決まる スパイク時にGCのラインが GOGC=offを設定する。 container memory limitを超え る。 34
GCのタイミングをGOMEMLIMITに⼀本化する 従来:GOGC=500 だけ 今回:GOGC=off + GOMEMLIMIT 次回GCの⽬標 = live heap
×(1 + GOGC/100) • • live heapに応じてGCのラインが 相対的に動く スパイク時にGCラインが container memory limitを超え うる。(GCより先にOOM Killが 発⽣) • 相対的なGCラインは使⽤しない • GOMEMLIMITに近づいたら、Go runtimeにGCを積極的に実⾏さ せる 35
Kubernetesのコンテナ上限から逆算してGCを制御 Kubernetesのcontainer memory limitの⼿前にGCラインを設定し、スパ イクが発⽣してもOOM前にGCを⾛らせる戦略。 GOMEMLIMIT(GC line) = container memory
limit × 0.8 memory limit メモリ 使用量 GCが積極的に発動するエリア memory limit到達までの余白を作成 ※container momory.requests を applicationのmemory limitとしている GOMEMLIMIT(GC line) memory limit × 0.8 時間 36
上記の改善を⾏った結果 OOMが起きることもなくなり、メモリ使⽤量も安定し、リソースが有効 に活⽤される平⾏線のグラフを実現できた。 37
まとめ 38
まとめ 謎 原因 改善 第⼀の謎 Invisible OOM NginxとGoが同一コンテナに同梱。Go がOOM KillされてもContainerは生存
し、StatusにOOMが出ない。 NginxとGoを別コンテナに分離。 メトリクスを個別に監視。 第⼆の謎 なぜOOM? GOMEMLIMITが未設定。 Goがcontainer memory limitを認識 せず、memory limit前にGCを実⾏で きない。 GOMEMLIMITを設定。 container memory limitの⼿前 でGCを⾛らせる。 第三の謎 なぜGCが⾛ら ない? GOGC=500はlive heap基準の相対判 GOGC=off + GOMEMLIMITに 定。GCラインがcontainer memory limit 一本化。相対値ではなく上限基 を超え、GCより先にOOMが発生。 準でGCさせる。 39
We’re hiring! Career Site 40