Upgrade to Pro — share decks privately, control downloads, hide ads and more …

突然のメモリ使用率上昇へ対応! k8sカスタムコントローラー開発事例

Avatar for syossan27 syossan27
April 30, 2025
340

突然のメモリ使用率上昇へ対応! k8sカスタムコントローラー開発事例

MIXI × ココナラのSRE改革大作戦 〜改善のその先へ〜 の資料です
https://mixi.connpass.com/event/352623/

Avatar for syossan27

syossan27

April 30, 2025
Tweet

Transcript

  1. ©MIXI 前提:k8sカスタムコントローラーとは? • k8sでは様々なリソースを管理するコントローラーが動いています ◦ Node ◦ Deployment ◦ ReplicaSet

    ◦ CronJob ◦ etc… ※ つくって学ぶkubebuilder - カスタムコントローラーの基礎 : https://zoetrope.github.io/kubebuilder-training/introduction/basics.html
  2. ©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()
  3. ©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 } // 後続処理は省略 }
  4. ©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() }
  5. ©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) }
  6. ©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)
  7. ©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 }
  8. ©MIXI 非常にお世話になった文献 ※ 実践入門 Kubernetes カスタムコントローラーへの道 : https://amzn.asia/d/8oIrthm • カスタムコントローラーについて、日本語

    で体系的にまとまった文献が少ない中、内 部構造の説明から非常に分かりやすく書か れていました • ただ、本書内で使われているコマンド等は 使えなくなっている可能性が大なので、適 宜最新の内容に変えつつ読み進めていくの がよし