🔄 kubectlでkubelet証明書の自動更新を設定する — ConfigMapベースのrotateCertificatesを完全にマスターする

ノードごとにSSH接続して設定を修正する時代は終わった。

ConfigMap一つでクラスタ全体を制御せよ。

>

>

ConfigMap一つでクラスタ全体のワーカーノードの証明書更新サイクルを一括制御する物語 — 数十個の時計(ノード)を同時に同期させる時計職人の精密さ。


🎯 この記事で扱うこと

  • kube-systemネームスペースのkubelet-config ConfigMapの構造と役割
  • ConfigMapを修正してrotateCertificates: trueを適用する全体手順
  • 変更をワーカーノードの/var/lib/kubelet/config.yamlに反映する方法
  • 自動更新が実際に動作するか検証する方法
  • アップグレード時に設定が上書きされる問題と対処方法

📌 導入 / 背景

kubeletクライアント証明書は、基本的に1年の有効期間を持ちます。クラスタ規模が大きくなるにつれて、ワーカーノードごとにSSHで接続して/var/lib/kubelet/config.yamlを修正する方法は現実的に不可能です。

kubeadmで構成されたクラスタは、これを解決するための構造をすでに備えています。kubeadmはBootstrap Tokenを活用したTLSブートストラップ過程でkubelet-config ConfigMapをダウンロードし、/var/lib/kubelet/config.yamlに書き込みます。つまり、kube-systemのConfigMapを修正し、各ノードでこれをダウンロードして適用する流れが公式にサポートされています。

rotateCertificates: trueに設定すると、kubeletは証明書全体の寿命の約70〜90%の時点でCSRを自動的に提出し、kube-controller-managerがこれを監視してクラスタCAキーで署名・承認することで、クライアント証明書が自動更新されます。


🔍 概念説明

ConfigMapとローカルconfig.yamlの関係

kubeadmクラスタでは、kubeletの設定は2箇所に存在します。

場所 役割
kube-system/kubelet-config (ConfigMap) クラスタ全体基準設定 (Single Source of Truth)
/var/lib/kubelet/config.yaml (各ノード) ノードで実際にkubeletが読み込む設定ファイル

これら2つのファイルは自動的に同期されません。ConfigMapを修正した後、各ワーカーノードで直接ダウンロードして反映する過程が必要です。この点が重要です。

ConfigMapに保存された設定と/var/lib/kubelet/config.yamlの内容は自動的に同期されません。ノードローカル設定を永続的に維持するには、/var/lib/kubelet/config.yamlを直接手動で更新するか、/var/lib/kubelet/kubeadm-flags.envにフラグを追加し、kubeletを再起動する必要があります。

rotateCertificatesの動作原理

kubeletが–bootstrap-kubeconfigフラグでブートストラップされるように設定されている場合、初期証明書でKubernetes APIに接続してCSRを提出します。CSRが一定基準を満たすとcontroller-managerが自動承認し、–cluster-signing-durationパラメータで指定された期間の証明書を署名してkubeletに渡します。有効期限が近づくと、kubeletは残りの時間の30%〜10%の間のいずれかの時点で自動的に新しいCSRを提出します。


💻 実習 / 例示コード

Step 0. 現在の状態確認

# ConfigMap名を確認 (バージョンによって名前の形式が異なる場合があります)
kubectl get configmap -n kube-system | grep kubelet

# Kubernetes 1.24+の場合: kubelet-config
# 旧バージョン: kubelet-config-1.{minor} (例: kubelet-config-1.27)
# 現在のConfigMapの全内容を確認
kubectl get configmap kubelet-config -n kube-system -o yaml

出力例のdata.kubelet部分を確認します:

data:
  kubelet: |
    apiVersion: kubelet.config.k8s.io/v1beta1
    kind: KubeletConfiguration
    authentication:
      ...
    rotateCertificates: false   # ← この部分をtrueに変更

Step 1. ConfigMap修正 (コントロールプレーンで)

方法 A — kubectl edit (対話型編集)

kubectl edit configmap kubelet-config -n kube-system

エディタが開いたら、data.kubeletブロック内部でrotateCertificates項目を探して修正します。存在しない場合は直接追加します。

# 修正前
rotateCertificates: false

# 修正後
rotateCertificates: true

保存してエディタを終了すると、ConfigMapが即座に更新されます。

方法 B — kubectl patch (スクリプトベースの自動化に適している)

# 現在のkubelet設定を抽出
kubectl get configmap kubelet-config -n kube-system 
  -o jsonpath='{.data.kubelet}' > /tmp/kubelet-config-current.yaml

# rotateCertificates項目を確認
grep rotateCertificates /tmp/kubelet-config-current.yaml
# sedで値を変更 (false → true、または存在しない場合は追加)
sed -i 's/rotateCertificates: false/rotateCertificates: true/' 
  /tmp/kubelet-config-current.yaml

# rotateCertificates項目が全くない場合
grep -q 'rotateCertificates' /tmp/kubelet-config-current.yaml || 
  echo "rotateCertificates: true" >> /tmp/kubelet-config-current.yaml
# 修正された内容をConfigMapに反映
kubectl create configmap kubelet-config 
  -n kube-system 
  --from-file=kubelet=/tmp/kubelet-config-current.yaml 
  --dry-run=client -o yaml | kubectl apply -f -

Step 2. ワーカーノードで設定反映

ConfigMapを修正しても、ワーカーノードのkubeletは即座に変更を認識しません。各ワーカーノードで以下の手順を実行する必要があります。

方法 A — kubeadm upgrade node活用 (推奨)

# ワーカーノードで実行 (SSH接続後)
sudo kubeadm upgrade node phase kubelet-config

# kubeletを再起動
sudo systemctl daemon-reload
sudo systemctl restart kubelet

kubeadm upgrade node phase kubelet-configコマンドは、クラスタに保存されたkubelet-config ConfigMapをダウンロードし、該当ノードのkubelet設定をアップグレードします。

方法 B — ConfigMapを直接ダウンロードして置き換え

# ワーカーノードで実行 (kubectlアクセス可能な環境が必要)

# ConfigMapからkubelet設定を抽出
kubectl get configmap kubelet-config -n kube-system 
  -o jsonpath='{.data.kubelet}' > /tmp/kubelet-config-new.yaml

# 既存のconfigをバックアップ
sudo cp /var/lib/kubelet/config.yaml 
  /var/lib/kubelet/config.yaml.bak.$(date +%Y%m%d)

# 新しい設定を適用
sudo cp /tmp/kubelet-config-new.yaml /var/lib/kubelet/config.yaml

# 適用を確認
grep rotateCertificates /var/lib/kubelet/config.yaml
# kubeletを再起動
sudo systemctl daemon-reload
sudo systemctl restart kubelet

# 再起動状態を確認
sudo systemctl status kubelet

Step 3. 複数ノードに一括適用 (スクリプト)

ノードが複数台ある場合、以下のスクリプトを活用して一括処理できます。

#!/bin/bash
# apply-kubelet-rotate.sh
# すべてのワーカーノードにrotateCertificates設定を一括適用

WORKER_NODES=$(kubectl get nodes 
  --selector='!node-role.kubernetes.io/control-plane' 
  -o jsonpath='{.items[*].metadata.name}')

for NODE in $WORKER_NODES; do
  echo "=== 처리 중: $NODE ==="

  # 1. ConfigMapの最新設定をダウンロード
  ssh $NODE "sudo kubeadm upgrade node phase kubelet-config"

  # 2. kubeletを再起動
  ssh $NODE "sudo systemctl daemon-reload && sudo systemctl restart kubelet"

  # 3. 適用結果を確認
  ssh $NODE "grep rotateCertificates /var/lib/kubelet/config.yaml"

  echo "=== $NODE 완료 ==="
  sleep 3  # ノード間の間隔
done

echo "전체 완료"
chmod +x apply-kubelet-rotate.sh
./apply-kubelet-rotate.sh

Step 4. 自動更新動作検証

# rotateCertificatesが有効になっているか確認 (各ノードで)
sudo grep rotateCertificates /var/lib/kubelet/config.yaml

# 現在の証明書の有効期限を確認
sudo openssl x509 
  -in /var/lib/kubelet/pki/kubelet-client-current.pem 
  -noout -enddate

# kubeletログで証明書更新の試行を確認
sudo journalctl -u kubelet --since "1 hour ago" | grep -i rotate
sudo journalctl -u kubelet --since "1 hour ago" | grep -i certificate
# CSRリストで自動提出されたリクエストを確認 (コントロールプレーンで)
kubectl get csr | grep "system:node"

# 出力例 — Approved,Issued状態であれば正常
# NAME        SIGNERNAME                               REQUESTOR                CONDITION
# csr-abc12   kubernetes.io/kube-apiserver-client-kubelet  system:node:worker-1   Approved,Issued
# 実際に適用されたkubelet設定をリアルタイムで確認 (APIプロキシを活用)
kubectl proxy &
curl -s http://127.0.0.1:8001/api/v1/nodes/<노드명>/proxy/configz | 
  python3 -m json.tool | grep rotateCertificates

Step 5. RBAC — 自動承認の前提条件確認

rotateCertificates: trueだけでは不十分です。ノードグループがCSRを自動承認できるRBAC権限を持っている必要があります。

# クライアント証明書の自動更新権限を確認
kubectl get clusterrolebinding | grep "auto-approve"
kubectl get clusterrolebinding | grep "node-client"

ない場合は、以下のコマンドで作成します:

# ノードグループにクライアント証明書の自動更新権限を付与
kubectl create clusterrolebinding auto-approve-renewals 
  --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeclient 
  --group=system:nodes

⚠️ 注意事項 / よくある間違い

1. ConfigMapの修正だけでは終わらない ConfigMapを修正しても、実行中のkubeletは自動的に再ロードしません。必ずkubeadm upgrade node phase kubelet-configまたは直接ファイルを置き換えた後、systemctl restart kubeletを実行する必要があります。

2. kubeadmアップグレード時の上書きに注意 kubeadmアップグレード時、/var/lib/kubelet/config.yamlの内容がクラスタ全体のkubelet-config ConfigMapの内容で上書きされる可能性があります。したがって、設定を永続的に維持するには、ConfigMap自体を修正するか、/var/lib/kubelet/kubeadm-flags.envにフラグを追加する必要があります。

3. serving証明書は自動承認されない rotateCertificatesはクライアント証明書の自動更新を制御します。serving証明書(serverTLSBootstrap: true)は別の設定であり、この場合controller-managerは自動承認しないため、管理者が直接kubectl certificate approveを実行する必要があります。

4. ConfigMapの名前がバージョンごとに異なる kubeadm 1.24未満ではkubelet-config-1.{minor}形式です。以下のコマンドで正確な名前をまず確認してください。

kubectl get configmap -n kube-system | grep kubelet-config

5. YAMLのインデントエラーに注意 ConfigMapのdata.kubeletフィールドは、YAML文字列の中にさらにYAMLが入る構造です。kubectl edit使用時にインデントが間違っているとkubeletが設定をパースできないため、保存前に必ず確認してください。


✅ まとめ / 締めくくり

ConfigMapベースのrotateCertificates設定の流れをまとめると以下のようになります。

  1. kubectl get configmap kubelet-config -n kube-systemで現在の設定を確認
  2. kubectl editまたはpatchでrotateCertificates: trueを反映
  3. 各ワーカーノードでkubeadm upgrade node phase kubelet-configを実行
  4. systemctl restart kubeletで再起動
  5. kubectl get csrと証明書の有効期限で正常動作を確認

この方式の主な利点は、ConfigMapがSingle Source of Truthの役割を果たす点です。今後新しいノードが追加された際、kubeadm joinを実行するだけで同じ設定が自動的にデプロイされます。これにより管理の複雑さが大幅に軽減されます。


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です