🚢

オンプレ Kubernetes クラスタ のアップデートについて

に公開

本記事は CyberAgent Group SRE Advent Calendar 2025 の6日目 の記事になります。

はじめに

CIU (CyberAgent Infrastructure Unit) の ML Platform の Kise です。
本記事では、私の所属している ML Platform チームが管理している Kubernetes クラスタ のアップデートについてどのようなことをしているのかについて紹介します。
書いた理由はオンプレの Kubernetes クラスタに関する記事があまりなかったからです。

ML Platform チームについて

まず簡単に ML Platform チームについて説明します。
CIU では Cycloud と呼ばれる Private Cloud を運用しており、私はその中の ML Platform (機械学習基盤) チームに所属しています。

ML Platform は、社内の ML/DS の方々に使用していただいており、LLM の学習などに使われていたりします。
私たちは主に以下の活動を行っています。

  • 機械学習ワークロードを実行するためのサービスの新規開発、改修
  • Kubernetes クラスタや各種コンポーネントの運用・保守
  • ML/DS の方々からの問い合わせ対応や要望の対応

この記事では、特に「基盤の運用」の中でも、Kubernetes クラスタのアップデート作業について紹介します。

クラスタ構成について

ML Platform が管理する Kubernetes クラスタの構成について説明します。
ML Platform の管理するサービスは全て単一のクラスタ上で立ち上げられており、シングルクラスタマルチテナントなクラスタになっています。

なぜオンプレミスなのか?

オンプレミス環境での Kubernetes クラスタのアップデートには、クラウド環境とは異なる課題があります。
まず、なぜオンプレミス環境を選択しているのかについて説明します。

オンプレミス環境を選ぶ理由

よくあるオンプレミス環境を選ぶ理由とほぼ同じですが、以下のような理由です。
私たち CIU ではキャッシュアウト削減を目標の一つとして掲げており、自分たちでオンプレの環境を整備することでパブリッククラウドへの支出を削減しようと考えています。

  • 大規模な GPU クラスタを運用する場合、オンプレミスの方がコスト効率が良い
  • パブリッククラウドでは GPU 確保できないケースが存在するが Private Cloud では融通がきく
  • 高速ネットワーク(InfiniBand など)や専用ハードウェアの活用がしやすい
  • 機密性の高いデータを扱う場合、データが社内に留まる

一方で、クラウド環境と比較すると以下のような課題があります:

  • ハードウェアや OS レベルの管理も自分たちで行う必要があり運用負荷が高い
  • GPU は非常に高価なのでリソースの追加に時間がかかる場合がある
  • パブリッククラウドと比較して選ばれるために内製で同じような機能を作成する必要がある

これらの課題を踏まえ、オンプレミス環境での Kubernetes クラスタのアップデートには、クラウド環境とは異なるアプローチが必要になります。

Kubernetes のバージョンについて

Kubernetes のアップデートは平均して4ヶ月に1度行われており、各バージョンのサポートは約1年間行われています。
1年で3マイナーバージョン更新されるので、毎年3マイナーバージョンずつ更新しています。
今年(2025年)は 1.31 -> 1.34 のバージョン更新を行いました。

なぜ1年に1回なのか?

私たちのチームでは1年に1回 Kubernetes のアップデートを定期実行のタスクとして実施しています。
1年に1回にしている理由は以下の通りです。

  • 作業コスト
    • アップデート作業には時間とリソースが必要なため、頻繁に行うと開発作業に影響が生じてしまう
    • メンテナンスを行うには基盤上で動いているユーザのワークロードを停止する必要があるため頻繁に行うのが厳しい
  • サポート期間の考慮
    • Kubernetes のサポート期間(約1年)を考慮し、サポート終了前に更新する必要がある

ただし、セキュリティ上の重要な問題がある場合や各種 Component で使いたい機能がある場合は定期アップデートとは別に緊急対応を行うこともあります。

アップデートで行う必要のある作業

Kubernetes クラスタのアップデートは、単に Kubernetes 本体のバージョンを上げるだけでは完了しません。
クラスタ上で動作している各種コンポーネントも、Kubernetes の新バージョンに対応したバージョンに更新する必要があります。
また筐体の OS / ファームウェア / ドライバーのアップデートも行う必要があります。
もちろん Ansible があるためコマンドを実行するだけではありますが、頻繁に流すものではないので修正が必要であったり、各種バージョンが変わることで壊れたことが幾度となくあります。

これらすべてを網羅的に確認し、必要に応じてアップデートを行う必要があります。

コンポーネントの分類と管理方法

アップデート作業を効率的に進めるため、コンポーネントを管理方法ごとに分類して確認しています。

Ansible で管理するコンポーネント

先ほども述べましたが、Control Plane や Worker Node の設定に関わるコンポーネントは Ansible で管理しています。
Ansible を使用することで、手動作業によるミスを排除し、全ノードで一貫した設定を実現しています。
Ansible を実行することで大まかですが、以下の項目について設定することができます。

  • kubeadm を用いたノードの追加、指定バージョンへの更新
  • Container Runtime の更新
  • OS パッケージの更新
  • NVIDIA ドライバーのインストール / CUDA 環境の整備

Control Plane と Worker Node 間の Version Skew

Kubernetes では Control Plane と Worker Node 間でバージョンの差(version skew)が許容されていますが、一定の制約があります。

Version Skew ポリシー

Kubernetes の公式ドキュメント(Version Skew Policy)では、以下の version skew がサポートされています。

kube-controller-manager, kube-scheduler, cloud-controller-manager(Control Plane)

  • kube-controller-manager, kube-scheduler, and cloud-controller-manager must not be newer than the kube-apiserver instances they communicate with. They are expected to match the kube-apiserver minor version, but may be up to one minor version older (to allow live upgrades).
  • kube-controller-manager、kube-scheduler、cloud-controller-manager は、通信する kube-apiserver より新しいバージョンであってはならない
  • kube-apiserver のマイナーバージョンと一致することが期待されるが、最大 1 マイナーバージョン古くても良い(ライブアップグレードを可能にするため)

例えば、kube-apiserver が v1.34 の場合:

  • kube-controller-manager、kube-scheduler、cloud-controller-manager は v1.33、v1.34 がサポートされる

kubelet(Worker Node)

  • kubelet must not be newer than kube-apiserver.
  • kubelet may be up to three minor versions older than kube-apiserver (kubelet < 1.25 may only be up to two minor versions older than kube-apiserver).
  • kubelet は kube-apiserver より新しいバージョンであってはならない
  • kubelet は kube-apiserver より最大 3 マイナーバージョン古くても良い(ただし、kubelet < 1.25 の場合は最大 2 マイナーバージョン)

例えば、kube-apiserver が v1.34 の場合:

  • kubelet は v1.31、v1.32、v1.33、v1.34 がサポートされる
  • kubelet が v1.35 以上はサポートされない

アップデート時の注意点

上記の Version Skew のためすべてのノードを一度にアップデートすることは難しいです。
そのため、以下のような段階的なアプローチを取ります。v1.31 -> v1.34 に更新した場合の例を挙げると

  1. Control Plane の更新の場合は最大 1 マイナーバージョンが許容されているため以下のように一つずつ上げていきます:
  • v1.31 -> v1.32
  • v1.32 -> v1.33
  • v1.33 -> v1.34
  1. Worker Node の更新の場合は Control Plane より最大 3 マイナーバージョン古くても良いため v1.31 -> v1.34 一括で更新可能です
  • v1.31 -> v1.34

上記のように段階的に更新することで、version skew の範囲内で安全にアップデートを進めることができます。
ただし、アップデート期間中は version skew の制約を常に意識し、古すぎるバージョンのノードが残らないように注意が必要です。
また起動を止めることのできないワークロードがある場合は PDB (PodDisruptionBudget) などを用いてアップデートする Worker Node を分割する必要があります。

ArgoCD で管理するコンポーネント

ノード上で稼働する各コンポーネントは ArgoCD で GitOps 的に管理しています。
各コンポーネントのアップデートは以下の点を確認しています。

  • Kubernetes バージョンとの互換性
    • コンポーネントのリリースノートで対応バージョンを確認
    • 特に major version のアップデートがある場合は注意深く確認
  • 依存関係の変更
    • 他のコンポーネントとの依存関係が変わっていないか
    • 破壊的変更がないか
  • 設定の変更
    • 設定項目の追加・削除・変更
    • デフォルト値の変更

主要なコンポーネントの例

更新が大体1年に1回なので Major バージョンが上がっているケースも多々あり、基本的に最低一つのコンポーネントは大きな BreakingChange が入っています。
またイメージの Registry が変わっているみたいなことも結構あります。
Kubernetes の最新バージョンに対応していないものもあったりするので Issue を立てたり go.mod の k8s.io のモジュールのバージョン見たりして確認したりしています。
2025 年に行った中で大きな変更があったのは以下のようなものがありました:

上記の対応のようなものを全ての OSS を使用したコンポーネントで確認しています。

ML Platform チームが開発しているコンポーネント

ML Platform チームは、プラットフォームの開発と運用の両方を行っています。
開発しているカスタムコントローラーやサービスも、Kubernetes のバージョンアップに合わせて更新が必要です。

これらのコンポーネントは利用者である ML / DS の方々が効率的に機械学習の開発・運用を行えるよう、日々改善を続けています。

依存関係の更新

Go で開発されているコンポーネントの場合、以下の依存関係を更新する必要があります。

  • k8s.io/client-go
  • k8s.io/api
  • k8s.io/apimachinery
  • sigs.k8s.io/controller-runtime
  • sigs.k8s.io/controller-tools

これらの依存関係を新しい Kubernetes バージョンに対応したバージョンに更新し、必要に応じてコードの修正も行います。
テストで Kubernetes の FakeClient を多用しているため大きめの修正が入った場合は修正が必要になることがあります。

アップデート作業の流れ

私たちの管理するクラスタには Dev / Stg / Prd の環境があるため、メンテナンスの差分反映用のブランチを作成し、担当者がそのブランチに向けて各コンポーネント更新の PR を作成して取り込み Dev / Stg でまずは確認を行ってから Prd のクラスタにメンテナンスの時間を設けて反映する形をとっています。
大まかな流れとしては以下のようになっています。

  1. アップデート対象のコンポーネントの洗い出し、更新先のバージョン確認、互換性の確認
  2. アップデート時に有効化したい Feature Flag の機能の確認やハードウェアの設定の確認
  3. 更新作業の担当者振り分け
  4. OS、ファームウェア、ドライバーなどの更新、Dev のクラスタの Kubernetes Version の更新実施
  5. 担当者が Dev のクラスタで各コンポーネントを更新し、動作確認
  6. OS、ファームウェア、ドライバーなどの更新、Stg のクラスタの Kubernetes Version の更新実施
  7. メンテナンスに入れ、Prd での作業実施
  8. 振り返り (KPT)

上記の作業を行い本番環境までの更新作業が完了します。大体作業の開始から1~2ヶ月くらいかかる作業になっています。

ここまでがオンプレ環境のクラスタ更新についてでした。
ここからはこれまでのトラブルをまとめます。

過去のトラブルと学び

これまでのアップデート作業では、いくつかのトラブルに遭遇しました。
ここでは、その中でも特に印象的だったトラブルと、そこから得られた学びを共有します。

Kubernetes 1.30 -> 1.31 アップグレード時の問題

kubeadm を使用して Kubernetes 1.30 から 1.31 にアップグレードする際、予期しない問題が発生しました。

問題の概要

アップグレード中に、コンテナが起動できなくなる問題が発生しました。
原因は、Kubernetes 1.31 で導入されたアルファ機能 ControlPlaneKubeletLocalMode が有効化されていなかったことです。

原因

ControlPlaneKubeletLocalMode は Kubernetes 1.31 で導入されたアルファ機能ですが、kubeadm 1.31 の内部処理がこの機能に依存していました。
本来は kubeadm がこの機能の導入を 2 バージョンに跨って対応するべきでしたが、1.31 では必須となっていました。

この機能がない状態で 1.31 と 1.30 のコンポーネントが共存すると、API の互換エラーや kubeadm の処理エラーが発生し、コンテナが起動できなくなります。

対応方法

以下の対応を行いました:

  1. ClusterConfiguration の更新: v1beta3 から v1beta4 に更新(kubeadm 1.31 では v1beta3 はサポート対象外)
  2. ControlPlaneKubeletLocalMode の有効化: ClusterConfiguration の featureGates に ControlPlaneKubeletLocalMode: true を設定
  3. Control Plane の一時的な分離: アップグレード中、kube-apiserver が kubeadm upgrade を実行する Control Plane のみで稼働する状態を作成
  • その他の Control Plane の staticPod(etcd 以外)を /etc/kubernetes/manifest から一時的に退避して停止

学び

  • アルファ機能への注意: アルファ機能であっても、kubeadm の内部処理が依存している場合がある
  • リリースノートの詳細確認: マイナーバージョンアップでも、破壊的変更や必須設定がある可能性がある

ArgoCD アップデート時の Kustomize 互換性問題

ArgoCD をアップデートした際、Kustomize の Major バージョンが上がり、既存の kustomize build が全て失敗するようになりました。

問題の概要

ArgoCD の新バージョンでは、内部で使用している Kustomize の Major バージョンが上がっていました。
これにより、既存の Kustomize マニフェストが新しいバージョンで解釈できなくなり、ArgoCD でのアプリケーション同期が失敗しました。

原因

  • ArgoCD が内部で使用する Kustomize のバージョンが major アップデートされていた
  • 既存の Kustomize マニフェストが新しいバージョンの構文や仕様に対応していなかった

対応方法

  • Kustomize マニフェストの修正: 新しいバージョンに対応した構文に修正
  • 段階的な移行: 影響範囲を確認しながら、アプリケーションごとに順次対応

学び

  • 依存ツールのバージョン確認: ツールのアップデート時は、内部で使用している依存ツールのバージョンも確認する
  • Major バージョンアップの注意: Major バージョンアップでは、破壊的変更が含まれる可能性が高い
  • 事前検証の重要性: 本番環境に適用する前に、開発環境やステージング環境で十分に検証する

まとめ

オンプレミス環境での Kubernetes クラスタのアップデートは、単にバージョンを上げるだけでなく、以下のような観点で包括的に進める必要があります:

  • 網羅的なコンポーネント確認: クラスタ上で動作しているすべてのコンポーネントを確認
  • 自動化による一貫性確保: Ansible などを活用した自動化により、手動作業によるミスを排除
  • 事前準備: リソース調整や動作確認計画の策定
  • 段階的な進め方: 影響範囲を考慮した段階的なアップデート

これらの取り組みにより安全に Kubernetes クラスタをアップデートできています。

終わりに

今回は私たちの業務の一部である、Kubernetes クラスタのアップデートの内容について流れと内容を紹介しました。
ML Platform では一緒に働いてくれる方を募集しています。
今回紹介した以外にも刺激的な仕事がたくさんありますので、興味がある方は応募いただけますと嬉しいです。カジュアル面談も行っています。

https://hrmos.co/pages/cyberagent-group/jobs/ciu003

Discussion