トラブルシューティング

Google Kubernetes Engine の使用中に問題が発生した場合に役立つトラブルシューティング手順について説明します。

Kubernetes リソースのデバッグ

クラスタに関する問題が発生している場合は、Kubernetes のドキュメントでクラスタのトラブルシューティングをご覧ください。

アプリケーション、ポッド、またはコントローラ オブジェクトに問題がある場合は、アプリケーションのトラブルシューティングをご覧ください。

kubectl コマンドが見つかりません

最初に、次のコマンドを実行して kubectl バイナリをインストールします。

sudo gcloud components update kubectl

$PATH 環境変数を変更するかどうかを確認するメッセージが表示されたら、「yes」を選択します。この変数を変更すると、ファイルの完全なパスを入力せずに kubectl コマンドを使用できます。

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

export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/

最後に、次のコマンドを実行して、更新された .bashrc(または .bash_profile)ファイルを読み込みます。

source ~/.bashrc

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

次のコマンドを使用してクラスタのコンテキストを設定します。

gcloud container clusters get-credentials CLUSTER_NAME

CLUSTER_NAME に何を入力すればよいかわからない場合は、次のコマンドを使用してクラスタを一覧表示します。

gcloud container clusters list

kubectl コマンドを実行すると「API バージョンのネゴシエーションができませんでした」というエラーが表示されます

kubectl に認証情報があることを確認します。

gcloud auth application-default login

kubectllogsattachexecport-forward コマンドがハングします

これらのコマンドは、クラスタのマスターがクラスタ内のノードと通信できることを前提にして動作します。ただし、マスターはクラスタのノードと同じ Compute Engine ネットワーク内にはないので、SSH トンネルを利用してセキュアな通信を実現しています。

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

上記の kubectl コマンドのいずれかが動作しない場合、マスターがノードへの SSH トンネルを開くことができない可能性があります。次のような問題がないかどうかを確認してください。

  1. クラスタにノードが存在しない。

    クラスタ内のノードの数を減らして 0 にした場合、SSH トンネルは動作しません。

    この問題を修正するには、クラスタのサイズを変更してノードを 1 つ以上配置します。

  2. クラスタ内のポッドが終了状態のまま復帰しないため、存在しなくなったノードをクラスタから削除できない。

    この問題は Kubernetes バージョン 1.1 にのみ影響しますが、クラスタのサイズの変更を繰り返した場合に発生する可能性があります。

    この問題を修正するには、終了状態のまま数分以上経過しているポッドを削除します。これによって古いノードはマスターの API から削除され、新しいノードに置き換えられます。

  3. ネットワークのファイアウォール ルールでマスターへの SSH アクセスを許可していない。

    すべての Compute Engine ネットワークは「default-allow-ssh」というファイアウォール ルールを使用して作成されます。このルールでは有効な秘密鍵を持つすべての IP アドレスからの SSH アクセスが許可されます。また、GKE はクラスタごとに gke-<cluster_name>-<random-characters>-ssh 形式の SSH ルールも挿入します。このルールでは、クラスタのマスター IP からクラスタのノードへの SSH アクセスが個別に許可されます。どちらのルールも存在しない場合、マスターは SSH トンネルを開くことができません。

    この問題を修正するには、マスターの IP アドレスからすべてのクラスタのノード上にあるタグの付いた VM へのアクセスを許可するファイアウォール ルールを再度追加します。

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

    プロジェクトの「ssh-keys」というメタデータ エントリのサイズが 32 KiB の上限に近づいていると、GKE は SSH トンネルを開くための独自の SSH 認証鍵を追加できません。プロジェクトのメタデータを確認するには gcloud compute project-info describe [--project=PROJECT] を実行し、ssh-keys のリストの長さを調べます。

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

  5. クラスタ内の VM でメタデータ フィールドに認証鍵「ssh-keys」を設定している。

    VM のノード エージェントではプロジェクト全体の SSH 認証鍵よりもインスタンスごとの ssh-keys が優先されるため、クラスタのノードで SSH 認証鍵を個別に設定している場合、ノードはプロジェクトのメタデータ内にあるマスターの SSH 認証鍵を無視します。確認するには、gcloud compute instances describe <VM-name> を実行し、メタデータに「ssh-keys」フィールドがあるかどうかを調べます。

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

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

クラスタからの指標が Stackdriver に表示されません

プロジェクトで Stackdriver Monitoring APIStackdriver Logging API が有効になっていること、プロジェクトを Stackdriver で表示できることを確認します。

問題が解決しない場合は、次の原因が考えられます。

  1. クラスタでモニタリングを有効にしてあることを確認します。

    Developers Console や gcloud コマンドライン ツールを使用して作成したクラスタでは、デフォルトでモニタリングが有効になりますが、これを確認するには、次のコマンドを実行するか、Developers Console でクラスタをクリックしてその詳細を表示します。

    gcloud container clusters describe cluster-name
    

    gcloud コマンドライン ツールの出力では "monitoringService" が "monitoring.googleapis.com" と表示され、Developers Console では Cloud Monitoring が有効になっているはずです。

    モニタリングが有効になっていない場合は、次のコマンドを実行して有効にします。

    gcloud container clusters update cluster-name --monitoring-service=monitoring.googleapis.com
    
  2. クラスタを作成してから、またはモニタリングを有効にしてからどれくらいの時間が経過していますか?

    新しいクラスタの指標が Stackdriver Monitoring に表示されるまでに最長で 1 時間かかります。

  3. heapster がクラスタの "kube-system" 名前空間で実行されていますか?

    クラスタがいっぱいでスケジュールに失敗している可能性があります。kubectl get pods --namespace=kube-system を呼び出して、実行されているかどうかを確認してください。

  4. クラスタのマスターはノードと通信できますか?

    Stackdriver Monitoring はこの通信に依存します。kubectl logs [POD-NAME] を実行すれば、通信できるかどうかを確認できます。このコマンドがエラーを返す場合、SSH トンネルが問題の原因である可能性があります。こちらのセクションをご覧ください。

Stackdriver Logging エージェントに関する問題が発生している場合は、エージェントのトラブルシューティング ドキュメントをご覧ください。

詳細については、Stackdriver のドキュメントをご覧ください。

エラー 404: gcloud container コマンドを呼び出したときにリソースが「見つかりませんでした」

gcloud コマンドライン ツールに対して再度認証を実行します。

gcloud auth login

エラー 400/403: アカウントに編集権限がありません

Compute Engine または Kubernetes Engine のサービス アカウント(あるいはその両方)が削除または編集されています。

Compute Engine または Kubernetes Engine API を有効にすると、サービス アカウントが作成され、プロジェクトにおける編集権限が与えられます。いずれかの時点で権限を編集するか、アカウントを完全に削除するか、あるいは API を無効にした場合、クラスタの作成とすべての管理機能が失敗します。

この問題を解決するには、Kubernetes Engine API を再度有効にする必要があります。これにより、サービス アカウントと権限が正しく復元されます。

  1. [API とサービス] ページにアクセスします。
  2. プロジェクトを選択します。
  3. [API とサービスの有効化] をクリックします。
  4. GKE を検索して、検索結果から API を選択します。
  5. [有効にする] をクリックします。API を以前に有効にしている場合は、まずそれを無効にしてから再度有効にする必要があります。API と関連サービスが有効になるには、数分かかることがあります。

あるいは、gcloud コマンドライン ツールを使用します。

gcloud services enable container.googleapis.com

1.8.x 以前の自動ファイアウォール ルールを 1.9.x 以降で複製する

クラスタで Kubernetes バージョン 1.9.x を実行している場合、自動ファイアウォール ルールが変更されたため、GKE クラスタ内のワークロードが、同じネットワーク上にあるがそのクラスタの外にある他の Compute Engine VM と通信を開始できなくなりました。

次の手順を行って、1.8.x 以前のクラスタの自動ファイアウォール ルールの動作を再現できます。

最初に、クラスタのネットワークを見つけます。

gcloud container clusters describe [CLUSTER_NAME] --format=get"(network)"

次に、コンテナに使用する、クラスタの IPv4 CIDR を取得します。

gcloud container clusters describe [CLUSTER_NAME] --format=get"(clusterIpv4Cidr)"

最後に、ネットワークのファイアウォール ルールを作成します。その CIDR をソース範囲とし、すべてのプロトコルを許可します。

gcloud compute firewall-rules create "[CLUSTER_NAME]-to-all-vms-on-network" --network="[NETWORK]" --source-ranges="[CLUSTER_IPV4_CIDR]" --allow=tcp,udp,icmp,esp,ah,sctp

GCP プロジェクトに対するデフォルトのサービス アカウントを復元する

GKE のデフォルトのサービス アカウント、container-engine-robot が、プロジェクトから誤ってバインド解除されることがあります。GKE サービス エージェントは、サービス アカウントにクラスタ リソースを管理する権限を与える IAM 役割です。この役割バインディングをサービス アカウントから削除すると、デフォルト サービス アカウントはプロジェクトからバインド解除され、アプリケーションのデプロイや他のクラスタ操作の実行をユーザーができなくなる可能性があります。

サービス アカウントがプロジェクトから削除されているか確認するには、gcloud projects get-iam-policy [PROJECT_ID] を実行するか、または Google Cloud Platform Console の [IAM と管理] メニューにアクセスします。そのコマンドまたはダッシュボードでサービス アカウントの中に container-engine-robot が表示されない場合、サービス アカウントはバインド解除されています。

GKE サービス エージェントの役割バインディングを削除した場合は、次のコマンドを実行して役割バインディングを復元します。

PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format "value(projectNumber)")
gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
  --member "serviceAccount:service-${PROJECT_NUMBER}@container-engine-robot.iam.gserviceaccount.com" \
  --role roles/container.serviceAgent

役割バインディングが付与されたことを確認するには、次のコマンドを実行します。

gcloud projects get-iam-policy $PROJECT_ID

サービス アカウント名が container.serviceAgent 役割とともに表示される場合、役割バインディングは付与されています。例:

- members:
  - serviceAccount:service-1234567890@container-engine-robot.iam.gserviceaccount.com
  role: roles/container.serviceAgent

デプロイされたワークロードに関する問題のトラブルシューティング

ワークロードのポッドに問題がある場合、GKE がエラーを返します。ポッドのステータスを調べるには、kubectl コマンドライン ツールか Google Cloud Platform Console を使用します。

kubectl

クラスタで実行しているすべてのポッドを表示するには、次のコマンドを実行します。

kubectl get pods

出力:

NAME            READY   STATUS              RESTARTS    AGE
[POD_NAME]      0/1     CrashLoopBackOff    23          8d

特定のポッドに関する詳細情報を取得するには、次のコマンドを実行します。

kubectl describe pod [POD_NAME]

Console

次の手順を行います。

  1. GCP Console で GKE の [ワークロード] ダッシュボードに移動します。

    GKE の [ワークロード] ダッシュボードに移動

  2. 目的のワークロードを選択します。[概要] タブにワークロードのステータスが表示されます。

  3. [管理対象ポッド] セクションで、エラー ステータス メッセージをクリックします。

以下のセクションでは、ワークロードによって返される一般的なエラーとその解決方法について説明します。

CrashLoopBackOff

CrashLoopBackOff は、コンテナが再起動後に繰り返しクラッシュしていることを示します。コンテナはさまざまな理由でクラッシュすることがあり、ポッドのログを調べると根本原因のトラブルシューティングに役立ちます。

デフォルトでは、クラッシュしたコンテナは 5 分間までの指数的遅延で再起動します。この動作設定を変更するには、Deployment のポッド仕様の spec: restartPolicy の下の restartPolicy フィールドを設定します。このフィールドのデフォルト値は Always です。

kubectl コマンドライン ツールか GCP Console を使用して、ポッドのコンテナがクラッシュしている理由を調べることができます。

kubectl

クラスタで実行しているすべてのポッドを表示するには、次のコマンドを実行します。

kubectl get pods

CrashLoopBackOff エラーがあるポッドを探します。

ポッドのログを取得するには、次のコマンドを実行します。

kubectl logs [POD_NAME]

[POD_NAME] は問題のあるポッドの名前です。

-p フラグを渡して、ポッドのコンテナの前のインスタンスのログ(存在する場合)を取得することもできます。

Console

次の手順を行います。

  1. GCP Console で GKE の [ワークロード] ダッシュボードに移動します。

    GKE の [ワークロード] ダッシュボードに移動

  2. 目的のワークロードを選択します。[概要] タブにワークロードのステータスが表示されます。

  3. [管理対象ポッド] セクションで、問題のあるポッドをクリックします。
  4. ポッドのメニューで、[ログ] タブをクリックします。

クラッシュしたコンテナの「終了コード」を調べる

終了コードは、kubectl describe pod [POD_NAME] の出力の containers: [CONTAINER_NAME]: last state: exit code フィールドにあります。

  • 終了コードが 1 の場合、コンテナがクラッシュした理由はアプリケーションがクラッシュしたからです。
  • 終了コードが 0 の場合は、アプリの実行時間を確認してください。コンテナは、アプリケーションのメインプロセスが終了したときに終了します。アプリの実行が非常に速く終了する場合、コンテナは再起動を続行している可能性があります。

実行中のコンテナに接続する

ポッドへのシェルを開きます。

kubectl exec -it [POD_NAME] -- /bin/bash

ポッド内にコンテナが複数ある場合は、-c [CONTAINER_NAME] を追加します。

これで、そのコンテナから bash コマンドを実行できます。ネットワークをテストしたり、アプリケーションで使用されているファイルやデータベースにアクセスできるかどうかを調べたりできます。

ImagePullBackOff と ErrImagePull

ImagePullBackOffErrImagePull は、コンテナが使用するイメージをイメージ レジストリからロードできないことを示します。

この問題は、GCP Console または kubectl コマンドライン ツールを使用して確認できます。

kubectl

ポッドのコンテナ イメージに関する詳細情報を表示するには、次のコマンドを実行します。

kubectl describe pod [POD_NAME]

Console

次の手順を行います。

  1. GCP Console で GKE の [ワークロード] ダッシュボードに移動します。

    GKE の [ワークロード] ダッシュボードに移動

  2. 目的のワークロードを選択します。[概要] タブにワークロードのステータスが表示されます。

  3. [管理対象ポッド] セクションで、問題のあるポッドをクリックします。
  4. ポッドのメニューで、[イベント] タブをクリックします。

イメージが見つからない場合

イメージが見つからない場合:

  1. イメージの名前が正しいことを確認します。
  2. イメージのタグが正しいことを確認します(:latest またはタグなしを試して最新のイメージを pull します)。
  3. イメージにレジストリ フルパスがある場合は、使用している Docker レジストリにそのパスが存在することを確認します。イメージ名のみを指定した場合は、Docker Hub レジストリを確認してください。
  4. Docker イメージを手動で pull してみます。

    • ノードに SSH 接続します。
      たとえば、us-central1-a ゾーンの example-instance に SSH 接続するには、次のコマンドを実行します。

      gcloud compute ssh example-instance --zone us-central1-a
      
    • docker pull [IMAGE_NAME] を実行します。
      このオプションが機能すると、ポッドで ImagePullSecret の指定が必要になる場合があります。ポッドがイメージ pull シークレットを参照できるのはそれぞれの名前空間内だけであるため、このプロセスを名前空間ごとに 1 回行う必要があります。

「permission denied」または「no pull access」というエラーが発生した場合は、ログインしていることと、イメージへのアクセス権があることを確認してください。

非公開レジストリを使用している場合は、イメージを読み取るためのキーが必要な場合があります。

PodUnschedulable

PodUnschedulable は、リソースが不足しているかなんらかの構成エラーのためにポッドをスケジュールできないことを示します。

リソースが不十分

CPU、メモリ、またはその他のリソースが不足していることを示すエラーが発生する場合があります。たとえば、「No nodes are available that match all of the predicates: Insufficient cpu (2)」は、2 つのノードで、ポッドのリクエストを満たせる CPU が十分にないことを示します。

デフォルトの CPU リクエストは 100m、または CPU の 10%(あるいは 1 コア)です。それより多いリソース、あるい少ないリソースをリクエストする場合は、ポッド仕様の spec: containers: resources: requests で値を指定します。

MatchNodeSelector

MatchNodeSelector は、ポッドのラベルセレクタに一致するノードがないことを示します。

これを確認するには、ポッド仕様の nodeSelector フィールド(spec: nodeSelector の下)に指定されているラベルを確認します。

クラスタ内のノードがどのようにラベルされているか確認するには、次のコマンドを実行します。

kubectl get nodes --show-labels

ラベルをノードに添付するには、次のコマンドを実行します。

kubectl label nodes [NODE_NAME] [LABEL_KEY]=[LABEL_VALUE]

詳細については、ノードにポッドを割り当てるを参照してください。

PodToleratesNodeTaints

PodToleratesNodeTaints は、ノード taint を許容しているノードが現在ないため、ポッドをノードにスケジュールできないことを示します。

これが該当することを確認するには、次のコマンドを実行します。

kubectl describe nodes [NODE_NAME]

出力で、Taints フィールドを確認すると、Key-Value のペアとスケジューリングの結果が一覧表示されています。

リストされた結果が NoSchedule の場合、そのノードは、一致する容認がなければ、ポッドをスケジュールできません。

この問題を解決する方法の 1 つは、taint を削除することです。たとえば、NoSchedule taint を削除するには、次のコマンドを実行します。

kubectl taint nodes [NODE_NAME] key:NoSchedule-

PodFitsHostPorts

PodFitsHostPorts は、ノードが利用しようとしているポートがすでに使用中であることを示します。

この問題を解決するには、ポッド仕様の spec: containers: ports: hostPort の下の hostPort 値を確認してください。この値を別のポートに変更することが必要になる場合があります。

最低限の有用性がない

ノードに十分なリソースがあるのに Does not have minimum availability メッセージが表示される場合は、ノードに SchedulingDisabled ステータスや Cordoned ステータスがあるかを調べます。このような場合、ノードは新しいポッドを受け入れません。

kubectl

ノードのステータスを取得するには、次のコマンドを実行します。

kubectl get nodes

ノードでスケジューリングを可能にするには、次のコマンドを実行します。

kubectl uncordon [NODE_NAME]

Console

次の手順を行います。

  1. GCP Console で GKE の [ワークロード] ダッシュボードに移動します。

    GKE の [クラスタ] ダッシュボードに移動

  2. 目的のクラスタを選択します。[ノード] タブに、ノードとそのステータスが表示されます。

ノードでスケジューリングを可能にするには、次の手順を行います。

  1. リストで、目的のノードをクリックします。

  2. [ノードの詳細] で、[閉鎖解除] ボタンをクリックします。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...