こんにちは、インフラエンジニアのryuです。
Kubernetesのバージョンを上げたら、一部のノードだけkubeletが起動しなくなった。2026年は、こうしたトラブルが起きやすい年になっています。
原因として多いのが、cgroup v1です。ふだん意識することの少ない仕組みですが、2025年から2026年にかけて、KubernetesやsystemdといったLinuxの基盤ソフトウェアが相次いでv1への対応を打ち切りました。
この記事では、cgroupが何をしているのかを簡単に説明したうえで、何がいつ変わったのか、そして自分のサーバーで何を確かめればいいのかを整理します。
cgroupとは?コンテナのリソース制限を支える仕組み¶
まずは、cgroupそのものについて説明しておきます。
cgroup(control groups)は、プロセスをグループにまとめて、CPUやメモリ、ディスクI/Oなどの使用量を制限したり計測したりするLinuxカーネルの機能です。
Dockerでコンテナにメモリの上限を付けたり、KubernetesのPodに resources.limits を書いたりすると、その設定は最終的にcgroupの設定として反映されます。つまり、コンテナのリソース制限の正体はcgroupです。
コンテナだけではありません。systemdも、サービスごとにcgroupを作ってプロセスを管理しています。systemctl status を実行したときに表示される CGroup: の行が、それにあたります。
$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled)
Active: active (running)
CGroup: /system.slice/nginx.service
├─1201 "nginx: master process /usr/sbin/nginx"
└─1202 "nginx: worker process"
コンテナの基本的な仕組みについては、Dockerとは? で解説しています。まだコンテナに触れたことがない人は、先にそちらを読んでおくとイメージしやすいと思います。
cgroup v1とv2は何が違うのか¶
cgroupには、v1とv2の2つの版があります。v2はLinuxカーネル4.5で正式に使えるようになった新しい版です。
一番大きな違いは、階層の作り方です。v1では、CPU用、メモリ用、I/O用というように、制御する資源ごとに別々の階層(ツリー)がありました。v2では、これが1本の階層にまとめられています。
| 項目 | cgroup v1 | cgroup v2 |
|---|---|---|
| 階層 | 資源(コントローラ)ごとに別々 | 1本にまとまった統合階層 |
| マウント先の例 | /sys/fs/cgroup/memory/ など複数 |
/sys/fs/cgroup/ のみ |
| メモリ制御 | 上限を超えると強制終了が中心 | memory.high で段階的に絞れる |
| 負荷の把握 | 限られる | PSI(どれだけ資源待ちが起きているか)を見られる |
| 非rootでの利用 | 難しい | rootlessコンテナを安全に扱いやすい |
資源ごとに階層がばらばらだと、「このプロセスはCPUではこのグループ、メモリでは別のグループ」という食い違いが起きます。管理が複雑になり、カーネル側の実装も重くなっていました。
v2では1つのプロセスは1つのグループにしか属さないので、こうした食い違いが起きません。Kubernetesも、v2を前提にしたメモリ管理の改善をいくつも進めています。
2025年から2026年にかけて何が変わったのか¶
ここからが本題です。v2への移行は何年もかけて少しずつ進んできましたが、ここ1年で「v1だと動かない」という段階に入りました。
主な出来事を時系列で並べると、次のようになります。
| 時期 | 出来事 |
|---|---|
| 2022年8月 | Kubernetes 1.25でcgroup v2対応がGA(一般提供)に |
| 2024年8月 | Kubernetes 1.31でcgroup v1対応がメンテナンスモードに移行 |
| 2025年9月 | systemd 258でcgroup v1(legacy・hybrid)のサポートが削除される |
| 2025年12月 | Kubernetes 1.35で failCgroupV1 の既定値が true になり、v1のノードではkubeletが起動しなくなる |
| 以降 | KEP-5573として、Kubernetesからv1対応のコード自体を削除する計画が進行中 |
Kubernetes:kubeletがv1のノードを拒否するようになった¶
Kubernetesでは、1.31でv1対応がメンテナンスモードになりました。新機能は追加せず、重大なセキュリティ修正や不具合修正だけを行うという扱いです。
そして1.35で、kubeletの設定項目 failCgroupV1 の既定値が true に変わりました。これにより、cgroup v1で動いているノードでは、特に設定をしない限りkubeletが起動に失敗します。
一時的に回避するなら、kubeletの設定で明示的に false にする方法はあります。
# kubeletの設定ファイル(KubeletConfiguration)の一部
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
failCgroupV1: false # v1のノードでも起動させる(一時的な回避策)
ただし、これはあくまで移行までの時間稼ぎです。v1対応のコードそのものを削除する計画も進んでいるので、どこかのバージョンでこの設定も使えなくなると考えておいたほうが安全です。
Kubernetesの全体像がまだつかめていない場合は、kubernetesとは? で基本から説明しています。
systemd:v1ではそもそも起動できない¶
Kubernetesより影響が根深いのが、systemdの変更です。2025年9月にリリースされたsystemd 258では、cgroup v1のサポートが削除されました。
リリースノートには、v1(legacyとhybridの階層)のサポートを削除し、起動時には常にv2がマウントされるという内容が書かれています。あわせて、必要なカーネルの最低バージョンも5.4に引き上げられました。
systemd 258以降では、cgroup v1で起動するという選択肢そのものがなくなった。カーネルの起動オプションでv1を指定しても、もう戻れない。
ディストリビューションでもこの流れは同じです。Red Hat Enterprise Linux 10では、systemdがv1モードでの起動をサポートしなくなり、v2だけが使える状態になっています。
systemdのサービスが思うように動かないときの調べ方は、systemdの言い分をsystemctlとjournalctlで読み解く にまとめています。
クラウド:古いOSイメージがv1のまま残っている¶
クラウドでも同じ動きがあります。Amazon EKSでは、Amazon Linux 2(AL2)ベースのEKS最適化AMIの提供がKubernetes 1.32までとされ、1.33以降はAmazon Linux 2023とBottlerocketのみになりました。
AL2はcgroup v1が既定、Amazon Linux 2023はv2が既定です。EKSのバージョンを上げる計画があるなら、ノードのOSを入れ替える作業がセットで必要になります。
自分のサーバーがv1かv2かを確かめる方法¶
では、手元のサーバーはどちらで動いているのでしょうか。これは1行のコマンドで確かめられます。
$ stat -fc %T /sys/fs/cgroup/
cgroup2fs # この表示ならcgroup v2
cgroup2fs と出ればv2です。tmpfs と出た場合はv1(またはv1とv2が混在するhybrid)で動いています。
v1のサーバーでは、/sys/fs/cgroup/ の下に資源ごとのディレクトリが並んでいるのも特徴です。
# cgroup v1 の場合の例
$ ls /sys/fs/cgroup/
blkio cpu cpuacct cpuset devices freezer memory pids systemd
# cgroup v2 の場合の例
$ ls /sys/fs/cgroup/
cgroup.controllers cgroup.procs cgroup.subtree_control system.slice user.slice
/sys/fs/cgroup/ は、ディスク上のファイルではなくカーネルが情報を見せている仮想的なディレクトリです。/sys や /proc がどういう場所なのかは、Linuxのディレクトリ構成 で説明しています。
ディストリビューションごとの既定値¶
どのディストリビューションのどのバージョンから、v2が既定になったのかを表にまとめました。
| ディストリビューション | cgroup v2が既定になったバージョン | v1が既定のまま残る主な古い版 |
|---|---|---|
| Fedora | 31 | ― |
| Ubuntu | 21.10 | 20.04、18.04 |
| Debian | 11 | 10 |
| RHEL系(Rocky、AlmaLinuxなど) | 9(10ではv2のみ) | 8、7 |
| Amazon Linux | 2023 | Amazon Linux 2 |
RHEL 8やUbuntu 20.04でも、カーネルの起動オプションに systemd.unified_cgroup_hierarchy=1 を加えればv2で起動できます。ただ、長く使うサーバーなら、OSのバージョンアップと合わせてv2へ移るほうが後々の手間は少ないです。
移行する前に確かめておきたいこと¶
v2へ移ること自体は、OSを新しくすれば自然に済みます。注意したいのは、その上で動くアプリケーションやツールがv2に対応しているかどうかです。
アプリケーションがv2のメモリ制限を読めるか¶
特に影響が出やすいのが、コンテナのメモリ上限を自分で読み取って動きを変えるアプリケーションです。
代表例はJavaです。JVMは、コンテナに設定されたメモリ上限を見てヒープサイズを決めます。ところが、古いバージョンのJVMはv2の上限を読めず、ホスト全体のメモリを基準にヒープを確保してしまいます。
その結果、コンテナの上限を超えて強制終了(OOMKilled)される、ということが起こります。Kubernetesの公式ドキュメントでは、v2に対応したバージョンとして次のものが挙げられています。
| 言語・ライブラリ | v2に対応したバージョン |
|---|---|
| OpenJDK / HotSpot | jdk8u372、11.0.16、15以降 |
| Node.js | 20.3.0以降 |
| Go(uber-go/automaxprocs) | v1.5.1以降 |
OSをv2に移すなら、同じタイミングで上で動くランタイムのバージョンも確認しておくのが安全です。v1の頃は問題なかったアプリケーションが、v2に移った途端にメモリ不足で落ちる、という形で表に出てくるからです。
監視やセキュリティのエージェントも対象になる¶
もう1つ見落としやすいのが、サーバーに入れている監視エージェントやセキュリティ製品です。
こうしたツールの中には、/sys/fs/cgroup/memory/ のようなv1のパスを直接読んで、コンテナごとのリソース使用量を集計しているものがあります。v2ではパスの構成が変わるので、古いバージョンのままだと値が取れなくなったり、エラーを出したりします。
確認の手順としては、次のような流れが現実的です。
# 1. ノードのcgroupのバージョンを確認する
$ stat -fc %T /sys/fs/cgroup/
# 2. v1のパスを直接参照している設定やスクリプトがないか探す
$ sudo grep -rn "/sys/fs/cgroup/memory" /etc /opt 2>/dev/null
# 3. 検証用のv2ノードでアプリケーションを動かし、メモリ使用量とOOMの有無を見る
$ kubectl top pod
$ kubectl describe pod <Pod名> | grep -A3 "Last State" # OOMKilled になっていないか
2番目の grep は、あくまで手がかりを探すためのものです。エージェントの対応状況は、最終的には各製品のドキュメントで確認してください。
移行は「ノードの入れ替え」で考える¶
Kubernetesのノードであれば、既存のノードを設定変更でv2に切り替えるより、v2が既定の新しいOSイメージでノードを作り直すほうが確実です。
新しいノードプールを追加し、Podを少しずつ移して、問題がなければ古いノードプールを削除する。この進め方なら、何か起きても元のノードに戻せます。
インフラエンジニアとして押さえておきたいこと¶
cgroupの話は、Kubernetesを運用している人だけのものに見えるかもしれません。でも実際には、systemdを使っているLinuxサーバーならすべてに関係します。
コンテナの仕組みを理解するうえでも、cgroupとnamespaceはLinuxの土台にあたる部分です。Kubernetesやクラウドのマネージドサービスを使っていても、トラブルの原因をたどっていくと最後はLinuxの機能に行き着くことがよくあります。
InfraAcademyの Linuxロードマップ では、プロセスやsystemd、ファイルシステムといった、こうした話の前提になる部分を順番に学べるようにしています。クラウドのノード管理まで含めて学びたい人は、AWSロードマップ もあわせて見てみてください。
OSの基盤ソフトウェアが入れ替わる話は、ほかにも起きています。Ubuntuの標準コマンドがRust製に置き換わった件は そのlsは、GNU製ですか。 で取り上げました。
まとめ¶
最後に、この記事のポイントを振り返っておきます。
- cgroupは、コンテナやsystemdのサービスのリソースを制限・計測するLinuxカーネルの機能
- v2は階層が1本にまとまり、メモリ制御や負荷の把握がしやすくなった
- Kubernetes 1.35から、v1のノードではkubeletが既定で起動しなくなった
- systemd 258ではv1のサポートが削除され、RHEL 10もv2のみになった
stat -fc %T /sys/fs/cgroup/でcgroup2fsと出ればv2- 移行前には、Javaなどのランタイムや監視エージェントがv2に対応しているかを確認する
v1で動いているサーバーは、古いOSのまま残っていることがほとんどです。まずは手元のサーバーで1行のコマンドを実行して、どちらで動いているかを確かめるところから始めてみてください。
参考¶
- About cgroup v2(Kubernetes Documentation)
- Kubernetes 1.25: cgroup v2 graduates to GA(Kubernetes Blog)
- Kubernetes 1.31: Moving cgroup v1 Support into Maintenance Mode(Kubernetes Blog)
- Kubernetes v1.35 Sneak Peek(Kubernetes Blog)
- KEP-5573: Remove cgroup v1 support(Kubernetes Contributors)
- Release systemd v258(GitHub)
- Guide to EKS AL2 & AL2-Accelerated AMIs transition features(Amazon EKS)
- Migrating from CGroups V1 to CGroups V2 in Red Hat Enterprise Linux(Red Hat Customer Portal)



