観測された事象と影響範囲
kubectlでオペレーションを終え、サーバーを正常にシャットダウンしようとする。
SIGTERMシグナルを送信。
しかし、kube-apiserverのプロセスは一向に終了しない。
タイムアウトを迎え、結局SIGKILLで強制終了するしかない。
Graceful Shutdownが機能しないこの状況は、本番環境では致命的です。
中途半端な状態でデータが書き込まれ、クラスタ全体が不安定になるリスクを常に抱えることになります。
冷や汗をかきながら原因を調査すると、信じがたい事実に突き当たります。
問題は、複雑な設定の不整合でも、リソースの枯渇でもありませんでした。
原因は、ただ「ホスト名が長すぎた」こと。
たった一つの命名規則のミスが、Kubernetesクラスタ全体の可用性を根底から揺るがすトリガーとなるのです。
対象のイシュー詳細
ホスト名が63バイトを超える環境で、kube-apiserver 1.35+ がSIGTERMに応答せずハングする問題
Original: [1] kube-apiserver 1.35+ never shuts down on SIGTERM when its identity Lease cannot be created (e.g. hostname longer than 63 bytes)
ホスト名が63バイトを超えるとLease作成が無限リトライされ、apiserverが正常終了できなくなるバグ。
観測されたエラー構造
E0705 16:05:59 controller.go:201] "Failed to ensure lease exists, will retry"
err="Lease.coordination.k8s.io \"apiserver-...\" is invalid: metadata.labels:
Invalid value: \"sat12-dp146-...-FE94C5DD19A3.local\":
must be no more than 63 bytes" interval="7s"
原因の技術的深掘り
この致命的なデッドロックは、Kubernetesの仕様変更と古くからの制約が不幸にも交差したことで発生します。
Kubernetes v1.35以降、APIサーバーは自身のアイデンティティを管理するためにLeaseオブジェクトを`kube-system`名前空間に作成するようになりました。
このLeaseオブジェクトには、自身の存在を示すために`kubernetes.io/hostname`というラベルが付与され、その値には実行中のホスト名がそのまま利用されます。
ここに、Kubernetesの根源的な制約が立ちはだかります。
すべてのラベルの「値」は、63バイト以下でなければならない、というルールです。
あなたのインフラのホスト名がこの63バイトの制限を超えている場合、Leaseオブジェクトの作成リクエストはAPIサーバーによって永久に拒否され続けます。
そして最悪なことに、v1.35以降のkube-apiserverのシャットダウンシーケンスは、このLease作成処理の完了を待機する設計になっていました。
結果、無限のリトライループから抜け出せず、シャットダウン処理はデッドロックに陥るのです。
これは単なるバグではなく、システム設計における「見えざる依存関係」が引き起こした構造的欠陥と言えるでしょう。
技術検証と解決策(ワークアラウンド)
この問題の直接的な解決策は、言うまでもなくホスト名を63バイト未満に修正することです。
あるいは、Kubernetesのバージョンをダウングレードすることでも回避は可能でしょう。
しかし、それはあくまで対症療法に過ぎません。
根本的な課題は、インフラの基盤設計段階で、このような「見えにくい制約」や「将来の仕様変更」をいかに予測し、回避するアーキテクチャを構築できるかにあります。
独自ドメインの選定、ホスト名の命名規則、ネットワーク設計、そしてサーバーのプロビジョニング。
これら一つ一つの選択が、未来の安定運用を左右するのです。
落とし穴だらけのインフラ構築を、専門家の知見に基づいた盤石な基盤に変えませんか?
最初に正しい一歩を踏み出すことこそが、未来の致命的な障害を回避する最も賢明な投資です。
$ # 現在のホスト名を確認
$ hostname
$ # ホスト名のバイト数(文字数)を確認
$ hostname | wc -c
# Ansible Playbookでの対策例: ホスト名設定時に長さを検証する
- name: Set hostname and validate its length
hosts: all
become: yes
tasks:
- name: Define a valid hostname for k8s node
set_fact:
# 63バイト以下の命名規則を徹底する
new_hostname: "k8s-master-01.prod.example.com"
- name: Fail if hostname exceeds 63 bytes limit
fail:
msg: "Hostname '{{ new_hostname }}' exceeds 63 bytes. (Length: {{ new_hostname | length }} bytes)"
when: new_hostname | length > 63
- name: Apply the new hostname
hostname:
name: "{{ new_hostname }}"