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.1k
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
370
二重開発負債をOne Application化で解くペアーズのグローバルRe:Architect戦略
tkc66buzz
1
130
Platform Engineeringことはじめ~コミュニティと一緒に新たな旅に出よう!
tkc66buzz
0
160
Other Decks in Technology
See All in Technology
OpenClawでAzure DevOpsのWiki更新を自動化する - クラウドAIだけでは届かない場所へ
yutakaosada
0
130
HacobuにおけるFDEとは/登壇資料(戸井田 裕貴)
hacobu
PRO
1
520
AIエージェント時代のPlatform as a Product —— テックリードがPdMとして回す発見・導入・計測 / Platform as a Product in the AI Agent Era
toshi0607
1
500
AI駆動開発で仕様はどこまで書くべきか? ― 人とAIの責務境界から考える開発プロセスの実践
takahiromatsui
1
210
行動するAIのためのオントロジー | DevRev — Encraft #26.pdf
dvrv_tknrszk
1
590
VS Code × GitHub Copilot での Fabric 開発
ryomaru0825
1
140
高負荷プロダクション環境におけるAWS Lambdaのリアル 〜スケールとコストを左右する実行ライフサイクルの技術仕様〜
maimyyym
2
800
Kiro Meetup #8 Kiro アップデート (2026/3/21〜2026/9/24)
katzueno
1
300
Swap and Memory Reclaim - Squeezing Out More RAM
ennael
PRO
1
800
spanner-autoscalerに学ぶ CRD設計パターン 〜自動化と緊急時対応を両立する Kubernetesコントローラーの作り方〜
tkuchiki
0
200
AIに任せた品質は、誰が見立てるのか - AI時代のテストマネジメント
nakanao
3
3.3k
AIに書かせて、プラットフォームで縛る ― EKSプラットフォームで実践した責任境界と権限設計
elmodev09
1
1k
Featured
See All Featured
Agile that works and the tools we love
rasmusluckow
331
22k
Believing is Seeing
oripsolob
1
230
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
2
930
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
340
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
470
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
74
42k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
270
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
33
5k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
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