
Kubernetesの1行修正で年600時間を削減——Cloudflareが直面したPVマウントの罠
Kubernetesの設定ファイルをたった1行書き換えるだけで、年間600時間ものエンジニア工数を削減した事例がある。Cloudflare(クラウドフレア)のインフラチームが直面したこの問題は、システムの規模が拡大するにつれて静かに忍び寄る「デフォルト設定の罠」を浮き彫りにした。
原因は、ストレージの権限管理を行うKubernetesの標準的な振る舞いにあった。数百万ものファイルを抱えるボリュームにおいて、再起動のたびに30分ものダウンタイムが発生していた事態を、彼らはどのように特定し、解決したのだろうか。
本記事では、CloudflareのエンジニアであるBraxton Schafer氏が公開したデバッグの過程と、大規模なKubernetes運用において見落としがちなパフォーマンスのボトルネックについて詳しく解説する。
Atlantisの再起動がなぜか「30分」もかかる謎

Cloudflareでは、Terraform(テラフォーム)によるインフラ管理の自動化ツールとして「Atlantis(アトランティス)」を利用している。Terraformはコードでインフラを定義するツールだが、Atlantisを導入することで、GitHubやGitLabのプルリクエスト上で実行計画(Plan)の確認や適用(Apply)が可能になる。
AtlantisはKubernetes上で「StatefulSet(ステートフルセット)」として動作しており、リポジトリの状態を保持するためにPV(Persistent Volume / 永続ボリューム)を使用している。StatefulSetとは、Pod(ポッド)の再起動後もデータの永続性を保証するための仕組みだ。
頻繁な再起動がエンジニアの時間を奪う
問題は、このAtlantisを再起動するたびに発生していた。新しいプロジェクトの設定を読み込ませたり、認証情報を更新したりするために、Cloudflareでは月に約100回ほどの再起動を行っていた。しかし、再起動を開始してからPodが正常に立ち上がるまで、毎回30分もの時間がかかっていたという。
この間、エンジニアはインフラの変更を行うことができず、作業が完全にブロックされてしまう。月100回の再起動で毎回30分待機が発生すれば、月間で50時間、年間では600時間もの時間が「ただの待ち時間」として消えていく計算だ。これは、一人のエンジニアが数ヶ月間フルタイムで働く時間に匹敵する大きな損失である。
「inode不足」がきっかけで表面化した問題
この遅延が決定的な問題として認識されたのは、ストレージの「inode(アイノード)」が枯渇した際だった。inodeとは、ファイルシステム上でファイルやディレクトリの情報を管理するためのデータ構造だ。ファイルが大量に作成されると、ディスク容量が残っていてもinodeが足りなくなり、新しいファイルが作成できなくなる。
Cloudflareの環境では、ファイルシステムを拡張することでしかinodeを増やせない仕様だった。拡張を反映させるにはPodの再起動が必要となり、そのたびに30分のダウンタイムが発生する。チームは当初、アラートの通知設定を調整して「見かけ上の問題」を回避することも検討したが、根本的な原因の調査に乗り出すことを決めた。
Kubernetesのログを深掘りして見えてきたボトルネック

調査を開始したBraxton Schafer氏は、まずkubectl rollout restartコマンドを実行し、新しいPodが立ち上がる様子を観察した。Pod自体はすぐにスケジュールされるものの、ステータスが「Init(初期化中)」のまま30分間も停止していることが判明した。
Podのイベントログを確認しても、イメージのプルが開始されるまでに不可解な空白時間があることしかわからなかった。そこで氏は、より低レイヤーのログを確認するため、各ノードで動作するコンポーネント「kubelet(クブレット)」のログを調査した。
kubeletのログに隠された「空白の時間」
kubeletは、各ノードでPodの実行を管理し、ボリュームのマウントなどを制御する重要なエージェントだ。システム管理ツールであるKibana(キバナ)を使ってログを分析したところ、PVのマウント自体は成功しているものの、その直後にタイムアウトエラーが発生し、リトライを繰り返している様子が記録されていた。
ログには「context deadline exceeded(処理時間の制限を超過した)」というメッセージが並んでいた。何らかの処理が異常に時間を要しており、Kubernetesの監視機構がそれを「失敗」とみなして処理を中断、再試行するというループに陥っていたのだ。
数百万個のファイルが引き起こす権限変更の罠
さらに詳細なログを追うと、決定的なメッセージが見つかった。そこには「Setting volume ownership(ボリュームの所有権を設定中)」という記述があった。実はこれが、30分もの時間を浪費させていた真犯人だった。
Kubernetesには、Pod内のプロセスがボリュームにアクセスできるように、マウント時に所有権を自動で調整する機能がある。具体的には、PodのsecurityContextで指定されたfsGroupのIDに合わせて、ボリューム内の全ファイルに対して再帰的にchgrp(グループ変更)を実行する。Atlantisのようなツールは運用期間が長くなるほど管理するファイル数が増大し、Cloudflareの環境では数百万個ものファイルが蓄積されていた。高速なストレージであっても、数百万個のファイルに対して一つずつ権限を確認・変更していく処理には膨大な時間がかかるのは必然だ。
わずか1行の修正でパフォーマンスが劇的に改善

原因が「再帰的な権限変更」であると特定できれば、解決策は非常にシンプルだった。Kubernetes 1.20以降、この振る舞いを制御するための新しい設定項目が追加されている。それがfsGroupChangePolicy(エフエスグループ・チェンジ・ポリシー)だ。
デフォルトでは、このポリシーはAlways(常に実行)に設定されている。つまり、Podが起動するたびに、すでに権限が正しく設定されていようがいまいが、すべてのファイルをスキャンして権限を上書きしようとする。これが大規模なボリュームにおいて致命的な遅延を引き起こす。
fsGroupChangePolicyの設定とは
解決策は、このポリシーをOnRootMismatch(ルートディレクトリが不一致の場合のみ実行)に変更することだ。この設定にすると、Kubernetesはまずボリュームのルートディレクトリの権限を確認する。もしルートの権限がすでに正しく設定されていれば、配下のファイルに対する再帰的なスキャンをスキップする。
spec:
template:
spec:
securityContext:
fsGroupChangePolicy: OnRootMismatchこの1行をマニフェストファイルに追加するだけで、権限変更のプロセスが大幅に簡略化される。Cloudflareのケースでは、これまで30分かかっていた再起動時間が、わずか30秒にまで短縮された。実に60倍の高速化だ。
30分から30秒へ、驚異的な短縮効果
この修正により、エンジニアがデプロイの待ち時間に拘束されることがなくなった。また、再起動が長引くことによって発生していた「Podが正常に起動しない」という偽のアラートに、オンコール担当者が夜中に叩き起こされることもなくなったという。技術的には極めて単純な変更だが、組織全体の生産性に与えたインパクトは計り知れない。
大規模システムにおける「デフォルト設定」の落とし穴

今回の事例から学べる最も重要な教訓は、Kubernetesの「安全なデフォルト設定」が、規模の拡大とともに牙を向く可能性があるということだ。fsGroupによる自動的な権限変更は、初心者が権限エラーに悩まされないようにするための親切な機能として設計されている。
しかし、エンタープライズレベルの運用において、数テラバイトのデータや数百万のファイルを扱うようになると、その「親切心」がシステムの可用性を損なう要因へと変わる。これは、小規模なプロジェクトでは決して表面化しない問題だ。
小規模なら問題ないが、スケールするとボトルネックになる
多くのインフラエンジニアは、マウントが遅い場合にネットワークやストレージ装置の性能を疑う。しかし、今回のケースのように「OSレベルのファイル操作」がバックグラウンドで走っていることに気づくには、深いオブザーバビリティ(観測性)が必要だ。Braxton Schafer氏が、Kubernetesのイベントログだけでなく、kubeletのシステムログまで掘り下げたことが早期解決の鍵となった。
SRE的視点での教訓
SRE(Site Reliability Engineering / サイト信頼性エンジニアリング)の観点では、「なぜシステムはこのように振る舞うのか?」という問いを持ち続けることの重要性が再確認された。30分の待ち時間を「そういうものだ」と受け入れてしまえば、年間600時間の損失は永遠に解消されなかっただろう。
もし読者の環境でも、特定のPodの起動が異常に遅かったり、ボリュームをマウントする際にInitコンテナで止まっていたりする場合は、securityContextの設定を見直してみる価値がある。特に、大量の静的ファイルを保持するCMSや、データベースのバックアップファイルを扱うPodなどは、同様の問題を抱えている可能性が高い。
この記事のポイント
- 原因の特定: Atlantisの再起動に30分かかっていたのは、Kubernetesがマウント時に全ファイルの所有権を再帰的に変更していたため。
- 1行の修正:
fsGroupChangePolicy: OnRootMismatchを設定することで、不要な権限変更をスキップできる。 - 劇的な改善: Cloudflareはこの修正により、再起動時間を30分から30秒に短縮し、年間600時間の工数を削減した。
- 教訓: 安全のためのデフォルト設定が、大規模環境では深刻なパフォーマンス低下を招くことがある。
- 推奨アクション: 大容量PVを使用するPodでは、
securityContextの設定を監査し、不必要な再帰処理を避ける設定を検討すべきだ。
出典
- Cloudflare Blog「A one-line Kubernetes fix that saved 600 hours a year」(2026年3月26日)

・ 複数業界における17年間のデジタルビジネス開発経験
・ ウェブサイト開発のためのHTML、PHP、CSS、Java等の実用的知識
・ 15ヶ国語対応の多言語SaaSの開発経験
・ 17年間にも及ぶ、Eコマース長期運営経験
・ 幅広い業界でのSEO最適化の豊富な経験
