期限切れのクラスタ証明書を手動で更新する

このドキュメントでは、ベアメタル版 GKE の期限切れの証明書を手動で更新する方法について説明します。Transport Layer Security(TLS)証明書は、ベアメタル版 GKE のコントロール プレーン コンポーネントで使用されます。これらの証明書の期限が切れると、証明書が更新されるまで、ワークロードとクラスタのライフサイクルを管理する機能が無効になります。期限切れの証明書の影響について詳しくは、証明書の有効期限をご覧ください。

デフォルトでは、TLS 証明書の有効期限は 1 年間です。ベアメタル版 GKE は、クラスタのアップグレード時と認証局のローテーション時に、これらの証明書を自動的に更新します。クラスタは定期的にアップグレードして、安全でサポートされることを維持し、TLS 証明書の有効期限が切れないようにすることをおすすめします。

証明書の有効期限切れが原因で発生したエラー

クラスタの TLS 証明書が期限切れになると、コア コントローラは Kubernetes API サーバーとの TLS 接続を確立できません。この接続がないと、次のエラーが発生します。

  • Unable to connect to the server: x509: Unable to connect to the server

    kubectl を使用してクラスタノードを取得すると、証明書の有効期限を参照するエラーがレスポンスに含まれます。

    kubectl get nodes --kubeconfig KUBECONFIG_PATH
    

    KUBECONFIG_PATH は、クラスタの kubeconfig ファイルへのパスに置き換えます。

    証明書が期限切れになると、レスポンスは次のようになります。

    Unable to connect to the server: x509: certificate has expired or is not yet valid
    
  • could not connect: x509 または rejected connection

    期限切れの証明書は、ピアが相互に通信できないため、etcd クラスタへのアクセスをブロックします。etcd のログに、次のようなエラーエントリが含まれている場合があります。

    W | rafthttp: health check for peer 6221a1d241bb2d0a could not connect: x509: certificate
    has expired or is not yet valid
    I | embed: rejected connection from "10.200.0.4:46108" (error "remote error: tls: bad
    certificate", ServerName "")
    

証明書の有効期限を確認する

このセクションでは、クラスタで使用される証明書の有効期限の時期を確認する手順を説明します。各コントロール プレーンノードで次の手順を実施します。

証明書の有効期限を確認するには:

  1. コントロール プレーン ノードマシンの一つにログインし、次のコマンドを実行します。

    sudo kubeadm certs check-expiration
    

    コマンド出力には、コントロール プレーン コンポーネントとその有効期限用に kubeadm によって作成された証明書が一覧表示されます。

    CERTIFICATE                EXPIRES                  RESIDUAL TIME   CERTIFICATE AUTHORITY   EXTERNALLY MANAGED
    admin.conf                 Nov 28, 2021 19:09 UTC   53m                                     no
    apiserver                  Nov 28, 2021 19:09 UTC   53m             ca                      no
    apiserver-etcd-client      Nov 28, 2021 19:09 UTC   53m             etcd-ca                 no
    apiserver-kubelet-client   Nov 28, 2021 19:09 UTC   53m             ca                      no
    controller-manager.conf    Nov 28, 2021 19:09 UTC   53m                                     no
    etcd-healthcheck-client    Nov 28, 2021 19:09 UTC   53m             etcd-ca                 no
    etcd-peer                  Nov 28, 2021 19:09 UTC   53m             etcd-ca                 no
    etcd-server                Nov 28, 2021 19:09 UTC   53m             etcd-ca                 no
    front-proxy-client         Nov 28, 2021 19:09 UTC   53m             front-proxy-ca          no
    scheduler.conf             Nov 28, 2021 19:09 UTC   53m                                     no
    
    CERTIFICATE AUTHORITY   EXPIRES                  RESIDUAL TIME   EXTERNALLY MANAGED
    ca                      Nov 26, 2031 18:06 UTC   9y              no
    etcd-ca                 Nov 26, 2031 18:06 UTC   9y              no
    front-proxy-ca          Nov 26, 2031 18:06 UTC   9y              no
    
  2. 次のコマンドを実行して、kubelet 証明書の有効期限の時期を確認します。

    sudo openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -text | grep Validity -A2
    sudo openssl x509 -in /var/lib/kubelet/pki/kubelet-server-current.pem -text | grep Validity -A2
    

    各コマンドのレスポンスは、次の出力のようになります。

    Validity
        Not Before: Sep 17 22:27:53 2021 GMT
        Not After : Sep 17 22:33:16 2022 GMT
    

    すべてのコントロール プレーンノードが同時にブートストラップされた場合、証明書の有効期限は互いに数分以内です。このタイミング関係は、すべてのコントロール プレーンノードにわたって適用されます。各コントロール プレーンノードで上記のコマンドを実行することで、有効期限を確認できます。

  3. 管理ワークステーションで次のコマンドを実行して、クラスタの kubeconfig ファイルのクライアント証明書の有効期限の時期を確認します。

    grep 'client-certificate-data' KUBECONFIG_PATH | \
        awk '{print $2}' | base64 -d | openssl x509 -text | grep Validity -A2
    

    レスポンスは次の出力例のようになります。

    Validity
        Not Before: Sep 17 22:27:53 2021 GMT
        Not After : Sep 17 22:33:16 2022 GMT
    
  4. 次のコマンドを実行して、管理クラスタ内のクラスタ kubeconfig の証明書の有効期限を探します。

    kubectl get secret/CLUSTER_NAME-kubeconfig -n CLUSTER_NAMESPACE -o --kubeconfig=ADMIN_KUBECONFIG jsonpath='{.data.value}' | base64 --decode | grep client-certificate-data | awk '{print $2}' | base64 -d | openssl x509 -text | grep Validity -A2
    
    Validity
        Not Before: Sep 17 22:27:53 2021 GMT
        Not After : Sep 17 22:33:16 2022 GMT
    

    管理クラスタの kubeconfig 証明書と管理ワークステーションの kubeconfig ファイル内の証明書は同じです。したがって、このコマンドの出力と前の手順のコマンドは一致している必要があります。

証明書を手動で更新する

クラスタの TLS 証明書を手動で更新するには、以降のセクションの手順を使用してください。

各コントロール プレーンノードの証明書を更新する

影響を受けるクラスタの各コントロール プレーンノードで次の手順を実施します。

  1. /etc/kubernetes フォルダをバックアップします。

  2. 次の kubeadm コマンドを実行して、すべての証明書を更新します。

    このコマンドは、マシン上の既存の認証局(CA)を使用して証明書を更新します。

    sudo kubeadm certs renew all
    

    コマンド出力は次のようになります。

    certificate embedded in the kubeconfig file for the admin to use and for kubeadm itself renewed
    certificate for serving the Kubernetes API renewed
    certificate the apiserver uses to access etcd renewed
    certificate for the API server to connect to kubelet renewed
    certificate embedded in the kubeconfig file for the controller manager to use renewed
    certificate for liveness probes to healthcheck etcd renewed
    certificate for etcd nodes to communicate with each other renewed
    certificate for serving etcd renewed
    certificate for the front proxy client renewed
    certificate embedded in the kubeconfig file for the scheduler manager to use renewed
    
  3. 次のコマンドを実行して、証明書に新しい有効期限があることを確認します。

    sudo kubeadm certs check-expiration
    
  4. 次のコマンドでコンテナを再起動します。

    すべてのコントロール プレーン コンポーネントは動的証明書の再読み込みをサポートしていないため、このステップでコンテナ kube-apiserverkube-schedulerkube-controller-manageretcd が再起動され、更新された証明書です。

    4 つのコンテナのそれぞれについて、次の手順を繰り返します。

    1. 各コンテナのコンテナ ID を探します。

      sudo crictl ps | grep CONTAINER_NAME
      

      CONTAINER_NAME は、コンテナ名 kube-apiserverkube-schedulerkube-controller-manageretcdetcd-defrag ではない)に置き換えます。

      レスポンスは次の例のようになります。

      c331ade490cb6       28df10594cd92      26 hours ago       Running          kube-apiserver ...
      

      コンテナ ID は最初の列の値です。

    2. 各コンテナを停止します。

      sudo crictl stop CONTAINER_ID
      

      CONTAINER_ID を前のステップで確認したコンテナ ID に置き換えます。

      停止したコンテナが終了すると、kubelet は新しいコンテナを代わりに作成し、停止したものを削除します。context deadline exceeded(エラーコード DeadlineExceeded)などのエラーが発生した場合は、コマンドを再実行してください。

接続性が復元されたことを確認する

この時点で、kubeadm 証明書はすべてのコントロール プレーンノードで更新されます。期限切れの証明書を更新する場合は、次のステップを実施します。

  • Kubernetes API サーバーとの接続を確認するには、任意のコントロール プレーンノードで次の kubectl コマンドを実行します。

    kubectl get nodes --kubeconfig=/etc/kubernetes/admin.conf
    

レスポンスで、クラスタのノードのリストが返されます。証明書が正しく更新されると、TLS または証明書のエラーは返されません。

クラスタの kubeconfig ファイルを置き換える

クラスタの kubeconfig ファイルを更新された証明書を含むものに置き換えるには、次の手順を使用します。

  1. 新しい kubeconfig ファイルを作成するには、管理ワークステーションで次の kubectl コマンドを実行します。

    kubectl --kubeconfig="ADMIN_KUBECONFIG" get secret/CLUSTER_NAME-kubeconfig  \
        -n "CLUSTER_NAMESPACE"  -o jsonpath='{.data.value}'  | base64 --decode > new_kubeconfig.conf
    

    以下を置き換えます。

    • ADMIN_KUBECONFIG: 管理クラスタの kubeconfig ファイルのパス。

    • CLUSTER_NAME: 証明書を更新するクラスタの名前。

    • CLUSTER_NAMESPACE: 証明書を更新するクラスタの名前空間。

    new_kubeconfig.conf ファイルには、更新された証明書データが含まれています。

  2. 新しい認証情報を使用して任意の kubectl コマンドを実行し、新しい kubeconfig が機能することを確認します。

    kubectl get nodes --kubeconfig new_kubeconfig.conf
    
  3. 管理ワークステーションのクラスタ ディレクトリに保存されている古い kubeconfig ファイルの内容を、新しい kubeconfig ファイル new-kubeconfig.conf の内容に置き換えます。

    デフォルトでは、クラスタ構成ファイルへのパスは bmctl-workspace/CLUSTER_NAME/CLUSTER_NAME-kubeconfig です。

kubelet の証明書を確認して etcd-defrag を再起動する

クラスタ証明書を手動で更新するプロセスを完了するには、各コントロール プレーンノードで次の手順を実施します。

  1. 次のコマンドを実行して、コントロール プレーンノードにログインし、kubelet クライアントとサービス提供証明書の有効期限を確認します。

    コントロール プレーンにアクセスできる限り、kubelet 証明書は自動的にローテーションされます。kubelet 証明書の自動更新期間は、コントロール プレーン コンポーネント証明書の有効期限よりも短いです。そのため、kubelet 証明書が以前に更新されている可能性があります。

    sudo openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -text | grep Validity -A2
    sudo openssl x509 -in /var/lib/kubelet/pki/kubelet-server-current.pem -text | grep Validity -A2
    

    それぞれのコマンドの出力は、次の例のようになります。

    Validity
        Not Before: Nov 28 18:04:57 2022 GMT
        Not After : Nov 28 19:04:57 2023 GMT
    
  2. 次のコマンドを使用して、etcd-defrag コンテナを再起動します。

    etcd-defrag コンテナは、apiserver-etcd クライアント証明書を使用して etcd と通信し、更新された証明書を取得するために再起動する必要があります。

    kubectl rollout restart daemonset etcd-defrag -n kube-system --kubeconfig KUBECONFIG_PATH
    

これで、クラスタ証明書を更新する手動手順を完了しました。すべての Pod が正しく実行されており、コントロール プレーン コンテナの TLS エラーが報告されていないことを確認します。