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
突然のメモリ使用率上昇へ対応! k8sカスタムコントローラー開発事例
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
syossan27
April 30, 2025
590
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
突然のメモリ使用率上昇へ対応! k8sカスタムコントローラー開発事例
MIXI × ココナラのSRE改革大作戦 〜改善のその先へ〜 の資料です
https://mixi.connpass.com/event/352623/
syossan27
April 30, 2025
More Decks by syossan27
See All by syossan27
一人でちいさくはじめる Platform Engineering
syossan27
4
3k
一人SREが歩んだPlatform Engineeringスモールスタート実践録 ~ クラウドネイティブ会議版 ~
syossan27
4
2.3k
プロポーザル サポートガイドを読み解いていこう!
syossan27
3
1k
幻滅期を越える サイトリライアビリティ エンジニアリング
syossan27
1
270
一人SREが歩んだ Platform Engineering スモールスタート実践録
syossan27
2
2k
SREって何? 現場で学んだサイト信頼性の第一歩
syossan27
5
1.7k
知識0からカンファレンスやってみたらこうなった!
syossan27
5
790
監視 やばい
syossan27
12
11k
最先端を追う前に、まず広めよう! 〜AIツールの普及活動のすすめ〜
syossan27
2
1.6k
Featured
See All Featured
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
380
The agentic SEO stack - context over prompts
schlessera
0
920
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
Building AI with AI
inesmontani
PRO
1
1.2k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
280
Test your architecture with Archunit
thirion
2
2.4k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
880
Designing for humans not robots
tammielis
254
26k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Transcript
©MIXI 突然のメモリ使用率上昇へ対応! k8sカスタムコントローラー開発事 例 株式会社MIXI 井上 翔太
©MIXI 自己紹介 名前:しょっさん X(旧: Twitter)/ mixi2:@syossan27 所属:MIXI 活動: • SRE
Kaigi • SRE Magazine • ゆるSRE勉強会
©MIXI Fanstaのご紹介 • スポーツ観戦ができる飲食店に特化した検索サービス • スポーツ観戦できる飲食店をエリアやチーム、放映予定から検索し、予約できる • お店にとってはスポーツ観戦ができることを告知し、集客することができる • [New]
事前決済ができるようになりました! ©Fansta
©MIXI ある日のこと・・・
©MIXI ある日突然・・・ まぁもし、なにかが起こっても爆速で対処しますよ! 最近は昔に比べると、特にエラーも起こらず平和ですなぁ〜
©MIXI ある日突然・・・ まぁもし、なにかが起こっても爆速で対処しますよ! ハッハッハッ! 最近は昔に比べると、特にエラーも起こらず平和ですなぁ〜
©MIXI ある日突然・・・ まぁもし、なにかが起こっても爆速で対処しますよ! ハッハッハッ! 最近は昔に比べると、特にエラーも起こらず平和ですなぁ〜 やばい!
©MIXI 何が起こったのか? 起因は一部のGraphQLクエリの修正 • 修正したGraphQLクエリでは非常に大きいレスポンスを返すように なってしまっていた • 結果、メモリ使用量が急速に肥大化 • メモリがサチることでレイテンシの悪化につながった
• k8sを利用していたため、HPAでメモリ使用率がある一定を超えたら スケールするようにしていたが、スケール数も上限に達していた
©MIXI すぐに直したいが・・・
©MIXI ある日突然・・・ まぁもし、なにかが起こっても爆速で対処しますよ! 最近は昔に比べると、特にエラーも起こらず平和ですなぁ〜
©MIXI なんとかするっきゃねぇ!
©MIXI k8sカスタムコントローラー、作りました pre-oom-killer ※ GitHub - syossan27/pre-oom-killer : https://github.com/syossan27/pre-oom-killer
©MIXI 前提:k8sカスタムコントローラーとは? • k8sでは様々なリソースを管理するコントローラーが動いています ◦ Node ◦ Deployment ◦ ReplicaSet
◦ CronJob ◦ etc… ※ つくって学ぶkubebuilder - カスタムコントローラーの基礎 : https://zoetrope.github.io/kubebuilder-training/introduction/basics.html
©MIXI 前提:k8sカスタムコントローラーとは? • このコントローラーを自作することができる! • コントローラーを自作することで、独自のロジックをk8s内に持ち込むこと ができます • また、独自リソース(CR)を定義し、それを利用するためにカスタムコン トローラーを作成することもできます
• 有名なカスタムコントローラーだと ◦ cert-manager ◦ external-secrets ◦ などなど • とはいえ、きちんとk8sの内部処理を理解していかないといけないので、ち とハードルは高め
©MIXI カスタムコントローラーを作ってみよう やりたいこと:指定したメモリ使用率に達したらPodをevictする • evict(立ち退き)とは、Podに対して終了を要請すること • 当初調べた時に、 zapier/preoomkiller-controller というカスタムコン トローラーもあったが、こちらはメモリ使用量を指定するタイプで取
り回しが悪かった • やりたいことはほぼpreoomkiller-controllerが実現していたので、こ ちらを参考にする形で実装する
©MIXI カスタムコントローラーを作ってみよう - 処理イメージ
©MIXI カスタムコントローラーを作ってみよう - クライアント設定
©MIXI カスタムコントローラーを作ってみよう client-goを使い、k8sクライアントを作成 • kubernetes/client-go を利用して、 k8sクライアントを作成 • シグナルハンドラー、k8s APIやmetrics
API へ接続する設定を渡して作成します • 最後に、コントローラー構造体にそれらを 入れ、監視ループを走らせます config, err := clientcmd.BuildConfigFromFlags(masterUrl, kubeconfig) if err != nil { log.Fatal(err) } clientset, err := kubernetes.NewForConfig(config) if err != nil { log.Fatal(err) } metricsClientset, err := metrics.NewForConfig(config) if err != nil { log.Fatal(err) } ctx := SetupSignalHandler() controller := NewController(ctx, clientset, metricsClientset, time.Duration(interval)*time.Second) controller.Run()
©MIXI カスタムコントローラーを作ってみよう - Pod検出
©MIXI カスタムコントローラーを作ってみよう 監視ループを回し、対象Podを検出 • 対象となるannotationが付与されたPodを 検出します • annotationはdeploymentに以下のように設 定する ◦
pre-oom-killer.v1alpha1.k8s.io/target-container-name: "app" • ここで検出したPodで更に処理を行う podList, err := c.clientset.CoreV1().Pods("").List( c.context, metav1.ListOptions{ LabelSelector: PodLabelSelector, }, ) for _, pod := range podList.Items { podName, podNamespace := pod.ObjectMeta.Name, pod.ObjectMeta.Namespace podTargetContainer, ok := pod.ObjectMeta.Annotations[TargetContainerName] if !ok { log.WithFields(log.Fields{ "pod": podName, "namespace": podNamespace, }).Errorf("PodTargetContainerNameFetchError: %s", err) continue } // 後続処理は省略 }
©MIXI カスタムコントローラーを作ってみよう - Pod検出
©MIXI カスタムコントローラーを作ってみよう - メモリ使用率チェック メモリ使用率をチェックし、超過でevict • 対象となるPodで設定されているevictにす るメモリ使用率を取得する • メモリの最大値・使用量を取得する
podMemoryUsageThreshold, err := resource.ParseQuantity(pod.ObjectMeta.Annotations[MemoryUsa geThresholdAnnotation]) // メモリの最大値を取得 var containerLimitsMemory *resource.Quantity for _, container := range pod.Spec.Containers { containerLimitsMemory = container.Resources.Limits.Memory() } // メモリの使用量を取得 containerMemoryUsage := &resource.Quantity{} podMetrics, err := c.metricsClientset.MetricsV1beta1().PodMetricses(podNamespac e).Get(c.context, podName, metav1.GetOptions{}) for _, containerMetrics := range podMetrics.Containers { containerMemoryUsage = containerMetrics.Usage.Memory() }
©MIXI カスタムコントローラーを作ってみよう - メモリ使用率チェック メモリ使用率をチェックし、超過でevict • 対象となるPodで設定されているevictにす るメモリ使用率を取得する • メモリの最大値・使用量を取得する
• 最後に、メモリ使用率を取得し、超過した 場合にPodをevictさせる // メモリ使用率を算出 containerMemoryUsagePercentage := (float64(containerMemoryUsage.Value()) / float64(containerLimitsMemory.Value())) * 100 if containerMemoryUsagePercentage > float64(podMemoryUsageThreshold.Value()) { _, err := evictPod(c.context, c.clientset, podName, podNamespace, "v1", false) }
©MIXI カスタムコントローラーを作ってみよう - メモリ使用率チェック メモリ使用率をチェックし、超過でevict • 対象となるPodで設定されているevictにす るメモリ使用率を取得する • メモリの最大値・使用量を取得する
• メモリ使用率を取得し、超過した場合にPod をevictさせる • 最後に作成したクライアントを通して evictする eviction := &policy.Eviction{ TypeMeta: metav1.TypeMeta{ APIVersion: policyGroupVersion, Kind: EvictionKind, }, ObjectMeta: metav1.ObjectMeta{ Name: podName, Namespace: podNamespace, }, DeleteOptions: deleteOptions, } err := client.PolicyV1beta1().Evictions(eviction.Namespace).Evict(ctx, eviction)
©MIXI カスタムコントローラーを作ってみよう - Pod検出
©MIXI カスタムコントローラーを作ってみよう - 終了処理 シグナルをハンドリングし、終了させる • SIGTERMとSIGINTをハンドリングし、 キャッチしたら終了させる • シグナルハンドラを多重で呼び出さないよ
う、onlyOneSignalHandlerを作成 var onlyOneSignalHandler = make(chan struct{}) var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} func SetupSignalHandler() context.Context { close(onlyOneSignalHandler) c := make(chan os.Signal, 2) ctx, cancel := context.WithCancel(context.Background()) signal.Notify(c, shutdownSignals...) go func() { <-c cancel() <-c os.Exit(1) }() return ctx }
©MIXI 実装は以上! 思ったより簡単ですね
©MIXI カスタムコントローラーを作ってみると k8sの内部処理も併せて理解できるメリットも!
©MIXI 非常にお世話になった文献 ※ 実践入門 Kubernetes カスタムコントローラーへの道 : https://amzn.asia/d/8oIrthm • カスタムコントローラーについて、日本語
で体系的にまとまった文献が少ない中、内 部構造の説明から非常に分かりやすく書か れていました • ただ、本書内で使われているコマンド等は 使えなくなっている可能性が大なので、適 宜最新の内容に変えつつ読み進めていくの がよし
©MIXI 後日談
©MIXI pre-oom-killerを参考にカスタムコントロー ラーを作ってくれた方が! ※ GitHub - phamngocsonls/k8s-oom-killer : https://github.com/phamngocsonls/k8s-oom-killer
©MIXI ご清聴ありがとうございました