kubectl コマンドライン ツールのトラブルシューティング

Google Kubernetes Engine(GKE)を使用している場合、kubectl コマンドライン ツールの問題により、アプリケーションのデプロイやクラスタ リソースの管理ができないことがあります。これらの問題は通常、クラスタがユーザーの ID を認識しない認証の失敗と、ツールがクラスタのコントロール プレーンに到達できない接続の失敗の 2 つのカテゴリに分類されます。

このページでは、これらの問題を診断して解決する方法について説明します。さまざまな認証の問題のトラブルシューティングと、kubectl ツールとクラスタのコントロール プレーン間の接続の問題のデバッグの手順を確認します。必要なプラグインがインストールされ、構成されていることを確認する方法と、SSH や Konnectivity などのサービスのネットワーク ポリシーとファイアウォールの考慮事項を確認する方法について説明します。

この情報は、kubectl コマンドを使用して GKE でアプリケーションまたはクラスタ リソースを管理するユーザーにとって重要です。特に、日々のコアタスクで kubectl コマンドを使用するアプリケーション デベロッパー、プラットフォーム管理者、オペレーターにとって重要です。 Google Cloudのコンテンツで使用されている一般的なロールとタスクの例の詳細については、一般的な GKE ユーザーのロールとタスクをご覧ください。

関連情報については、次のリソースをご覧ください。

認証と認可のエラー

kubectl コマンドライン ツールのコマンドの使用時に認証と承認に関連するエラーが発生した場合は、次のセクションで解決策を確認してください。

エラー: 401 (Unauthorized)

GKE クラスタに接続すると、HTTP ステータス コード 401 (Unauthorized) の認証 / 認可エラーが発生することがあります。この問題は、ローカル環境から GKE クラスタで kubectl コマンドを実行しようとしたときに発生することがあります。詳細については、問題: 認証と承認のエラーをご覧ください。

エラー: Insufficient authentication scopes

gcloud container clusters get-credentials を実行すると、次のエラーが表示されることがあります。

ERROR: (gcloud.container.clusters.get-credentials) ResponseError: code=403, message=Request had insufficient authentication scopes.

cloud-platform スコープのない Compute Engine VM から GKE API にアクセスしようとすると、このエラーが発生します。

このエラーを解決するには、不足している cloud-platform スコープを付与します。Compute Engine VM インスタンスのスコープを変更する手順については、Compute Engine のドキュメントでインスタンスのサービス アカウントの作成と有効化をご覧ください。

エラー: Executable gke-gcloud-auth-plugin not found

kubectl コマンドまたは GKE を操作するカスタム クライアントの実行中に、次のようなエラー メッセージが表示されることがあります。

Unable to connect to the server: getting credentials: exec: executable gke-gcloud-auth-plugin not found

It looks like you are trying to use a client-go credential plugin that is not installed.

To learn more about this feature, consult the documentation available at:
      https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins

Visit cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl#install_plugin to install gke-gcloud-auth-plugin.
Unable to connect to the server: getting credentials: exec: fork/exec /usr/lib/google-cloud-sdk/bin/gke-gcloud-auth-plugin: no such file or directory

この問題を解決するには、必要なプラグインをインストールするの説明に従って gke-gcloud-auth-plugin をインストールします。

エラー: No auth provider found

kubectl またはカスタム Kubernetes クライアントが Kubernetes client-go バージョン 1.26 以降を使用してビルドされている場合、次のエラーが発生します。

no Auth Provider found for name "gcp"

この問題を解決するには、次の操作を行います。

  1. 必要なプラグインをインストールするの説明に従って gke-gcloud-auth-plugin をインストールします。

  2. gcloud CLI を最新バージョンに更新します。

    gcloud components update
    
  3. kubeconfig ファイルを更新します。

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    次のように置き換えます。

    • CLUSTER_NAME: クラスタの名前。
    • CONTROL_PLANE_LOCATION: クラスタのコントロール プレーンの Compute Engine ロケーション。リージョン クラスタの場合はリージョン、ゾーンクラスタの場合はゾーンを指定します。

エラー: The gcp auth plugin is deprecated, use gcloud instead

gke-gcloud-auth-plugin をインストールして GKE クラスタに kubectl コマンドを実行すると、次の警告メッセージが表示されることがあります。

WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.25+; use gcloud instead.

このメッセージは、クライアントのバージョンが 1.26 より前の場合に表示されます。

この問題を解決するには、代わりに gke-gcloud-auth-plugin 認証プラグインを使用するようにクライアントに指示します。

  1. テキスト エディタでシェル ログイン スクリプトを開きます。

    Bash

    vi ~/.bashrc

    Zsh

    vi ~/.zshrc

    PowerShell を使用している場合は、この手順をスキップします。

  2. 次の環境変数を設定します。

    Bash

    export USE_GKE_GCLOUD_AUTH_PLUGIN=True
    

    Zsh

    export USE_GKE_GCLOUD_AUTH_PLUGIN=True
    

    PowerShell

    [Environment]::SetEnvironmentVariable('USE_GKE_GCLOUD_AUTH_PLUGIN', True, 'Machine')
    
  3. 環境でこの変数を適用します。

    Bash

    source ~/.bashrc

    Zsh

    source ~/.zshrc
    

    PowerShell

    ターミナルを終了し、新しいターミナル セッションを開きます。

  4. gcloud CLI を更新します。

    gcloud components update
    
  5. クラスタに対する認証:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    次のように置き換えます。

    • CLUSTER_NAME: クラスタの名前。
    • CONTROL_PLANE_LOCATION: クラスタのコントロール プレーンの Compute Engine ロケーション。リージョン クラスタの場合はリージョン、ゾーンクラスタの場合はゾーンを指定します。

問題: kubectl コマンドが見つからない

kubectl コマンドが見つからないというメッセージが表示された場合は、kubectl バイナリを再インストールして $PATH 環境変数を設定します。

  1. kubectl バイナリをインストールします。

    gcloud components update kubectl
    
  2. $PATH 環境変数の変更を求めるメッセージが表示されたら、「y」と入力して続行します。この変数を変更すると、完全なパスを入力せずに kubectl コマンドを使用できます。

    または、~/.bashrc(macOS では ~/.bash_profile)など、シェルの環境変数の格納場所に次の行を追加します。

    export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/
    
  3. 次のコマンドを実行して、更新したファイルを読み込みます。次の例では、.bashrc を使用しています。

    source ~/.bashrc
    

    macOS を使用している場合は、.bashrc ではなく ~/.bash_profile を使用します。

問題: kubectl コマンドを実行すると「接続は拒否されました」というエラーが表示される

kubectl コマンドが「接続は拒否されました」というエラーを返す場合は、次のコマンドを使用してクラスタ コンテキストを設定する必要があります。

gcloud container clusters get-credentials CLUSTER_NAME \
       --location=CONTROL_PLANE_LOCATION

次のように置き換えます。

  • CLUSTER_NAME: クラスタの名前。
  • CONTROL_PLANE_LOCATION: クラスタのコントロール プレーンの Compute Engine のロケーション。リージョン クラスタの場合はリージョン、ゾーンクラスタの場合はゾーンを指定します。

クラスタ名またはロケーションに何を入力すればよいかわからない場合は、次のコマンドを使用してクラスタを一覧取得します。

gcloud container clusters list

エラー: kubectl command timed out

クラスタを作成してクラスタに kubectl コマンドを実行したときに、kubectl コマンドがタイムアウトすると、次のようなエラーが表示されます。

  • Unable to connect to the server: dial tcp IP_ADDRESS: connect: connection timed out
  • Unable to connect to the server: dial tcp IP_ADDRESS: i/o timeout

これらのエラーは、kubectl がクラスタ コントロール プレーンと通信できないことを示しています。

この問題を解決するには、クラスタが設定されているコンテキストを確認して設定し、クラスタとの接続性を確保します。

  1. $HOME/.kube/config に移動するか、kubectl config view コマンドを実行して、構成ファイルにクラスタ コンテキストとコントロール プレーンの外部 IP アドレスが含まれていることを確認します。

  2. クラスタの認証情報を設定します。

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION \
        --project=PROJECT_ID
    

    次のように置き換えます。

    • CLUSTER_NAME: クラスタの名前。
    • CONTROL_PLANE_LOCATION: クラスタのコントロール プレーンの Compute Engine ロケーション。リージョン クラスタの場合はリージョン、ゾーンクラスタの場合はゾーンを指定します。
    • PROJECT_ID: クラスタが作成されたプロジェクトの ID。
  3. クラスタで承認済みネットワークを有効にしている場合は、既存の承認済みネットワークのリストに、接続元のマシンの送信 IP が含まれていることを確認します。承認済みネットワークはコンソールまたは次のコマンドで確認できます。

    gcloud container clusters describe CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION \
        --project=PROJECT_ID \
        --format "flattened(controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetwork
    sConfig.cidrBlocks[])"
    

    上記のコマンドの出力で、マシンの送信 IP が承認済みネットワークのリストにない場合は、次のいずれかの操作を行います。

エラー: kubectl commands return failed to negotiate an api version

kubectl コマンドが failed to negotiate an API version エラーを返す場合は、kubectl に認証情報が設定されていることを確認する必要があります。

gcloud auth application-default login

問題: kubectl logsattachexecport-forward コマンドが応答不能になった

kubectl logsattachexec、または port-forward コマンドが応答しなくなった場合、通常は API サーバーがノードと通信できなくなっています。

まず、クラスタにノードが存在するかどうか確認します。クラスタ内のノードの数を減らして 0 にした場合、コマンドは機能しません。この問題を解決するには、クラスタのサイズを変更してノードを 1 つ以上配置します。

クラスタにノードが 1 つ以上ある場合は、SSH トンネルまたは Konnectivity プロキシ トンネルを使用してセキュア通信を実現しているかどうかを確認します。以降のセクションでは、各サービスに固有のトラブルシューティング手順について説明します。

SSH の問題のトラブルシューティング

SSH を使用している場合、GKE は SSH 公開鍵ファイルを Compute Engine プロジェクトのメタデータに保存します。Google 提供のイメージを使用するすべての Compute Engine VM はプロジェクトの共通メタデータとインスタンスのメタデータを定期的にチェックし、承認済みユーザーの VM のリストに追加する SSH 認証鍵がないかどうかを確認します。また、GKE はコントロール プレーンの IP アドレスからクラスタ内の各ノードへの SSH アクセスを許可するファイアウォール ルールを Compute Engine ネットワークに追加します。

次の設定では、SSH 通信で問題が発生する可能性があります。

  • ネットワークのファイアウォール ルールで、コントロール プレーンからの SSH アクセスが許可されていない。

    すべての Compute Engine ネットワークは default-allow-ssh というファイアウォール ルールを使用して作成されます。このルールでは有効な秘密鍵を持つすべての IP アドレスからの SSH アクセスが許可されます。また、GKE は一般公開クラスタごとに gke-CLUSTER_NAME-RANDOM_CHARACTERS-ssh 形式の SSH ルールも挿入します。このルールでは、クラスタのコントロール プレーンからクラスタのノードへの SSH アクセスが個別に許可されます。

    どちらのルールも存在しない場合、コントロール プレーンは SSH トンネルを開くことができません。

    これが問題の原因であることを確認するには、構成にこれらのルールが含まれているかどうかを確認します。

    この問題を解決するには、クラスタのすべてのノードにあるタグを特定し、コントロール プレーンの IP アドレスからそのタグを持つ VM へのアクセスを許可するファイアウォール ルールを再度追加します。

  • プロジェクトの ssh-keys 用の共通メタデータ エントリがいっぱいになっている。

    プロジェクトの ssh-keys というメタデータ エントリが最大サイズの上限に近い場合、GKE は SSH トンネルを開くための独自の SSH 認証鍵を追加できません。

    これが問題かどうかを確認するには、ssh-keys のリスト内の長さを確認します。プロジェクトのメタデータを表示するには、次のコマンドを実行します。必要に応じて、--project フラグを含めます。

    gcloud compute project-info describe [--project=PROJECT_ID]
    

    この問題を解決するには、不要になった SSH 認証鍵を削除します。

  • クラスタ内の VM でメタデータ フィールドにキー ssh-keys を設定している。

    VM のノード エージェントではプロジェクト全体の SSH 認証鍵よりもインスタンスごとの SSH 認証鍵が優先されるため、クラスタのノードで SSH 認証鍵を個別に設定している場合、ノードはプロジェクトのメタデータ内にあるコントロール プレーンの SSH 認証鍵を無視します。

    これが問題であることを確認するには、gcloud compute instances describe VM_NAME を実行して、メタデータで ssh-keys フィールドを探します。

    この問題を解決するには、インスタンスのメタデータからインスタンスごとの SSH 認証鍵を削除します。

Konnectivity プロキシの問題のトラブルシューティング

クラスタが Konnectivity プロキシを使用しているかどうかを判断するには、次のシステム Deployment を確認してください。

kubectl get deployments konnectivity-agent --namespace kube-system

クラスタが Konnectivity プロキシを使用している場合の出力は次のようになります。

NAME                 READY   UP-TO-DATE   AVAILABLE   AGE
konnectivity-agent   3/3     3            3           18d

Konnectivity プロキシを使用していることを確認したら、Konnectivity エージェントに必要なファイアウォール アクセス権があることと、ネットワーク ポリシーが正しく設定されていることを確認します。

必要なファイアウォール アクセスを許可する

ネットワークのファイアウォール ルールで、次のポートへのアクセスが許可されていることを確認します。

  • コントロール プレーン ポート: クラスタの作成時に、Konnectivity エージェントはコントロール プレーンとの接続をポート 8132 で確立します。kubectl コマンドを実行するときに、API サーバーとクラスタとの通信にこの接続が使用されます。ポート 8132 でクラスタ コントロール プレーンへの外向きトラフィックが許可されていることを確認してください(API サーバーでは 443 が使用されます)。外向きアクセスを拒否するルールがある場合は、ルールを変更するか、例外を作成する必要があります。
  • kubelet ポート: Konnectivity エージェントはユーザーのクラスタノードにデプロイされるシステム Pod であるため、ファイアウォール ルールで次の種類のトラフィックが許可されていることを確認してください。

    • Pod 範囲からワークロードへのポート 10250 での着信トラフィック。
    • Pod 範囲からの発信トラフィック。

    ファイアウォール ルールでこのタイプのトラフィックが許可されていない場合は、ルールを変更してください

ネットワーク ポリシーを調整する

クラスタのネットワーク ポリシーで次のいずれかが行われている場合、Konnectivity プロキシで問題が発生する可能性があります。

  • kube-system Namespace から workload Namespace への上り(内向き)トラフィックをブロックします。
  • ポート 8132 でクラスタ コントロール プレーンへの下り(外向き)をブロックします。

ワークロード Pod のネットワーク ポリシーによって上り(内向き)がブロックされている場合、konnectivity-agent ログには次のようなエラー メッセージが含まれます。

"error dialing backend" error="dial tcp POD_IP_ADDRESS:PORT: i/o timeout"

エラー メッセージの POD_IP_ADDRESS は、ワークロード Pod の IP アドレスです。

下り(外向き)がネットワーク ポリシーによってブロックされている場合、konnectivity-agent ログには次のようなエラー メッセージが含まれます。

"cannot connect once" err="rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp CP_IP_ADDRESS:8132: i/o timeout

このエラーの CP_IP_ADDRESS は、クラスタ コントロール プレーンの IP アドレスです。

これらの機能はクラスタの正常な動作に必須ではありません。クラスタのネットワークを外部アクセスから完全に遮断した場合、これらのような機能が動作しなくなることに注意してください。

ネットワーク ポリシーの Ingress ルールまたは Egress ルールが問題の原因であることを確認するには、次のコマンドを実行して、影響を受ける Namespace のネットワーク ポリシーを見つけます。

kubectl get networkpolicy --namespace AFFECTED_NAMESPACE

上り(内向き)ポリシーの問題を解決するには、ネットワーク ポリシーの spec.ingress フィールドに次の行を追加します。

ingress:
- from:
  - namespaceSelector:
      matchLabels:
        kubernetes.io/metadata.name: kube-system
    podSelector:
      matchLabels:
        k8s-app: konnectivity-agent

下り(外向き)ポリシーの問題を解決するには、ネットワーク ポリシーの spec.egress フィールドに次の行を追加します。

egress:
- to:
  - ipBlock:
      cidr: CP_IP_ADDRESS/32
  ports:
  - protocol: TCP
    port: 8132

ネットワーク ポリシーで上り(内向き)ルールと下り(外向き)ルールを組み合わせて使用している場合は、両方を調整することを検討してください。

IP マスカレード エージェントを調整する

送信元 IP アドレスが Pod IP アドレス範囲内にある場合、クラスタ コントロール プレーンは Konnectivity エージェントからのトラフィックを受け入れます。クラスタ コントロール プレーンへのトラフィックの送信元 IP アドレスをマスカレードするように ip-masq-agent の構成を変更すると、Konnectivity エージェントで接続エラーが発生する可能性があります。

この問題を解決し、Konnectivity エージェントからクラスタ コントロール プレーンへのトラフィックがノード IP アドレスにマスカレードされないようにするには、ip-masq-agent ConfigMap の nonMasqueradeCIDRs リストにコントロール プレーンの IP アドレスを追加します。

nonMasqueradeCIDRs:
- CONTROL_PLANE_IP_ADDRESS/32

この構成の詳細については、IP マスカレード エージェントをご覧ください。

エラー: kubectl コマンドが失敗し、エージェントが使用できないというエラーが表示される

GKE コントロール プレーンから Pod への接続が必要な kubectl コマンド(kubectl execkubectl logskubectl port-forward など)を実行すると、次のエラー メッセージのようなエラー メッセージが表示されてコマンドが失敗することがあります。

Error from server: error dialing backend: No agent available
failed to call webhook: Post "https://WEBHOOK_SERVICE.WEBHOOK_NAMESPACE.svc:PORT/PATH?timeout=10s": No agent available
v1beta1.metrics.k8s.io failed with: failing or missing response from https://NODE_IP:10250/apis/metrics.k8s.io/v1beta1: Get "https://NODE_IP:10250/apis/metrics.k8s.io/v1beta1": No agent available

これらのエラーは、GKE コントロール プレーンとクラスタのノード間の安全な通信トンネルである Konnectivity に問題があることを示しています。特に、コントロール プレーンの konnectivity-serverkube-system Namespace の正常な konnectivity-agent Pod に接続できないことを意味します。

この問題を解決するには、次のことを試してください。

  1. konnectivity-agent Pod の正常性を確認します。

    1. konnectivity-agent Pod が実行されているかどうかを確認します。

      kubectl get pods -n kube-system -l k8s-app=konnectivity-agent
      

      出力は次のようになります。

      NAME                                   READY   STATUS    RESTARTS  AGE
      konnectivity-agent-abc123def4-xsy1a    2/2     Running   0         31d
      konnectivity-agent-abc123def4-yza2b    2/2     Running   0         31d
      konnectivity-agent-abc123def4-zxb3c    2/2     Running   0         31d
      

      Status 列の値を確認します。Pod のステータスが Running の場合は、接続に関する問題のログを確認します。それ以外の場合は、Pod が実行されていない理由を調査します。

    2. 接続に関する問題のログを確認します。Pod のステータスが Running の場合は、接続の問題についてログを確認します。kubectl logs コマンドは Konnectivity に依存するため、Google Cloud コンソールでログ エクスプローラを使用します。

      1. Google Cloud コンソールで、[ログ エクスプローラ] に移動します。

        [ログ エクスプローラ] に移動

      2. クエリペインに次のクエリを入力します。

        resource.type="k8s_container"
        resource.labels.cluster_name="CLUSTER_NAME"
        resource.labels.namespace_name="kube-system"
        labels."k8s-pod/k8s-app"="konnectivity-agent"
        resource.labels.container_name="konnectivity-agent"
        

        CLUSTER_NAME は、使用するクラスタの名前に置き換えます。

      3. [クエリを実行] をクリックします。

      4. 出力を確認します。konnectivity-agent ログを確認するときは、エージェントが接続できない理由を示すエラーを探します。認証エラーや権限エラーは、トークン レビューをブロックする構成ミスのある Webhook を示していることがよくあります。「接続拒否」または「タイムアウト」エラーは通常、ファイアウォール ルールまたはネットワーク ポリシーが TCP ポート 8132 のコントロール プレーンへのトラフィックをブロックしているか、Konnectivity エージェントと他のノード間のトラフィックをブロックしていることを意味します。証明書エラーは、ファイアウォールまたはプロキシが暗号化された TLS トラフィックを検査して干渉していることを示しています。

    3. Pod が実行されていない理由を調査します。Pod のステータスが Pending または実行されていない状態の場合は、原因を調査します。konnectivity-agent は DaemonSet ではなく Deployment として実行されます。Deployment として実行されるため、エージェント Pod はノードのサブセットでのみ実行する必要があります。ただし、その特定のノードのサブセットが使用できない場合、サービス全体が失敗する可能性があります。

      Pod が実行されない一般的な原因は次のとおりです。

      • Pod のスケジュール設定を妨げるカスタム ノード taint。
      • ノードリソース(CPU またはメモリ)が不足している。
      • GKE システム イメージをブロックする制限付き Binary Authorization ポリシー。

      特定の Pod が実行されていない理由の詳細を取得するには、kubectl describe コマンドを使用します。

      kubectl describe pod POD_NAME -n kube-system
      

      POD_NAME は、実行されていない Pod の名前に置き換えます。

  2. アドミッション Webhook を調べて、TokenReview API リクエストをブロックしていないことを確認します。konnectivity-agent はサービス アカウント トークンに依存しているため、トークン レビューが妨害されると、エージェントが接続できなくなる可能性があります。Webhook が原因の場合、障害のある Webhook が削除または修復されるまで、Konnectivity は復元できません。

  3. ファイアウォール ルールで、GKE ノードからポート 8132 のコントロール プレーンの IP アドレスへの TCP 下り(外向き)トラフィックが許可されていることを確認します。この接続は、konnectivity-agent が Konnectivity サービスに到達するために必要です。詳細については、必要なファイアウォール アクセスを許可するをご覧ください。

  4. 重要な Konnectivity トラフィックを制限するネットワーク ポリシー ルールがないことを確認します。ネットワーク ポリシーのルールでは、kube-system Namespace 内のクラスタ内トラフィック(Pod 間)と、konnectivity-agent Pod から GKE コントロール プレーンへの下り(外向き)トラフィックの両方を許可する必要があります。

次のステップ

  • このドキュメントで問題を解決できない場合は、サポートを受けるで、次のトピックに関するアドバイスなど、詳細なヘルプをご覧ください。