第4章 Kubernetes のトラブルシューティング

4.1. 概要

Kubernetes は、Docker フォーマットコンテナーのセットに、アプリケーションをデプロイし、管理するための機能セットを提供します。本書では、Kubernetes Pod、レプリケーションコントローラー、サービス、および結果として生成されるコンテナーの作成および管理に関連した問題のトラブルシューティングに役立ちます。

トラブルシューティングの手法を説明するために、本書では「Kubernetes クラスターを作成して Docker フォーマットのコンテナーイメージを実行する」でデプロイされているコンテナーおよび設定を使用します。ここで説明されている手法は、Red Hat Enterprise Linux 7.1 および RHEL Atomic Host システムで実行される Kubernetes に適用されます。

4.2. Kubernetes のトラブルシューティングについて

Kubernetes のトラブルシューティングを開始する前に、調査対象となる Kubernetes コンポーネントを理解しておく必要があります。それらには以下が含まれます。

  • Master: Kubernetes 環境を管理するために使用するシステムです。
  • Node: コンテナーが Kubernetes によってデプロイされる 1 つ以上のシステムです (以前は minion と呼ばれていました)。
  • Pod: Pod は、各コンテナーに対する docker run コマンドへのオプション、サービスの位置を定義するためのラベルと共に、実行する 1 つ以上のコンテナーを定義します。
  • サービス: サービスにより、Kubernetes 環境内のコンテナーが IP アドレスを識別しなくても、別のコンテナーが提供するアプリケーションを名前 (ラベル) で見つけられるようになります。
  • レプリケーションコントローラー: レプリケーションコントローラーを使用すると、特定の数の Pod が実行されるように指定できます (新規の Pod は必要数に達するまで起動した状態となり、Pod が終了すると、新規の Pod がこれを置き換えるために実行されます。)
  • ネットワーキング (flanneld): flanneld サービスを使用すると、Kubernetes が使用する IP アドレス範囲の設定と関連の設定を行うことができます。この機能はオプションです。yaml および json ファイルが使用されます。使用する Kubernetes の要素は、yaml または json 形式の設定ファイルで作成されます。本書では主に yaml 形式のファイルに焦点を当てます。

とくに以下のコマンドを使用して、上記のコンポーネントのトラブルシューティングを行います。

  • kubectl: (マスターから実行される) kubectl コマンドにより、Kubernetes Pod, サービスおよびレプリケーションコントローラーで、作成、削除、取得 (情報の一覧表示) などの操作を実行できます。このコマンドを使用して yaml/json ファイルをテストし、各種の Kubernetes コンポーネントの状態を表示できます。
  • systemctl: マスターとノード間の通信を容易にするために特定の systemd サービスを Kubernetes で設定する必要があります。さらに、それらのサービスはアクティブかつ有効な状態にしておく必要があります。
  • journalctl: journalctl コマンドを使用して Kubernetes の systemd サービスを確認し、これらのサービスの処理に従います。これをマスターとノードの両方で実行し、それらのシステム上での Kubernetes の障害があるかどうかを確認します。kubernetes でのすべてのデーモンロギングでは systemd ジャーナルを使用します。
  • etcdctl または curl: etcd デーモンは、Kubernetes クラスター情報の保管を管理します。このサービスは、マスターまたはその他のシステムで実行できます。その情報を照会するには RHEL の etcdctl コマンドを使用することができます。RHEL Atomic には etcdctl コマンドがないため、代わりに curl コマンドを使用して etcd サービスを照会できます。

4.3. Kubernetes 用にコンテナー化されたアプリケーションの準備

アプリケーションを kubernetes にデプロイする前に考慮すべきいくつかの点について以下に説明します。

4.3.1. ネットワークの制限

Kubernetes サービスとして実行できるアプリケーションの種類には制限があるため、すべてのアプリケーションを一律に kubernetes に対応させることはできません。Kubernetes におけるサービスは、IP アドレスがサービスのクライアントの iptables に挿入される負荷分散プロキシーです。したがって、Kubernetes にデプロイする予定のアプリケーションについては、以下に該当するかを確認する必要があります。

  • サブプロセス間でのネットワークアドレス変換や NAT をサポートする。
  • フォワードおよびリバース DNS ルックアップを必要としない。Kubernetes はサービスのクライアントにフォワードまたはリバース DNS ルックアップを提供しません。

上記のいずれかに関連する制限が適用されないか、またはユーザーがそれらの確認項目を無効にできる場合は、このまま継続することができます。

4.3.2. コンテナーの準備

実行しているソフトウェアの種類によって、Kubernetes サービスのクライアントに提供される事前に定義された一部の環境変数を利用できる場合があります。

たとえば、db という名前のサービスの場合、そのサービスを使用する Kubernetes で Pod を起動する場合、Kubernetes は以下の環境変数を Pod のコンテナーに挿入します。

DB_SERVICE_PORT_3306_TCP_PORT=3306
DB_SERVICE_SERVICE_HOST=10.254.100.1
DB_SERVICE_PORT_3306_TCP_PROTO=tcp
DB_SERVICE_PORT_3306_TCP_ADDR=10.254.100.1
DB_SERVICE_PORT_3306_TCP=tcp://10.254.100.1:3306
DB_SERVICE_PORT=tcp://10.254.100.1:3306
DB_SERVICE_SERVICE_PORT=3306

注意: サービス名 (db) は、変数では DB のように大文字で表示されることに注意してください。名前に使用されるダッシュ (-) は、アンダースコア (_) に変換されます。

これらの変数を含むシェル変数を確認するには、docker exec を実行してアクティブなコンテナーにシェルを開き、env を実行してシェル変数を確認します。

# docker exec -it <container_ID> /bin/bash
[root@e7ea67..]# env
...
WEBSERVER_SERVICE_SERVICE_PORT=80
KUBERNETES_RO_SERVICE_PORT=80
KUBERNETES_SERVICE_PORT=443
KUBERNETES_RO_PORT_80_TCP_PORT=80
KUBERNETES_SERVICE_HOST=10.254.255.128
DB_SERVICE_PORT_3306_TCP_PORT=3306
DB_SERVICE_SERVICE_HOST=10.254.100.1
WEBSERVER_SERVICE_PORT_80_TCP_ADDR=10.254.100.50
...

クライアントアプリケーションを起動する際に、これらの変数を利用する必要がある場合があります。たとえば、「Kubernetes クラスターを作成して Docker フォーマットのコンテナーイメージを実行する」で説明されているように Web サーバーや Database アプリケーションを作成する場合、Web サーバーがデプロイする action スクリプトは DB_SERVICE_SERVICE_HOST の値を取得するため、データベースサービスにアクセスするために使用できる IP アドレスを認識できます。

コンテナー間の通信の問題をデバッグする際にこれらのシェル変数を表示すると、サービスおよびポートのアドレスをコンテナーごとに表示するのに役立ちます。

4.4. Kubernetes のデバッグ

Kubernetes のデバッグを開始する前に、Kubernetes の機能の概要を理解しておく必要があります。通常、アプリケーションを Kubernetes に送る際に、以下が実行されます。

  1. 認証時に kubectl コマンドラインが (マスターの) kube-apiserver に送られる。
  2. (マスターの) kube-scheduler プロセスが yaml または json ファイルを読み取り、Pod をノードに割り当てる (ノードは kubelet サービスを実行するシステム)。
  3. (ノードの) kublet サービスは、Pod のマニフェストを 1 つ以上の docker run 呼び出しに変換する。
  4. docker run コマンドは、利用可能なノードで特定されたコンテナーの起動を試行する。

そのため、kubernetes でデプロイされたアプリケーションをデバッグするには、以下を確認する必要があります。

  1. Kubernetes サービスのデーモン (systemd) プロセスが実行中である。
  2. yaml または json の送信が有効である。
  3. kubelet サービスが kube-scheduler から作業の順番を受信する。
  4. 各ノードの kubelet サービスは docker を使用した各コンテナーを正常に起動できる。
注記

上記の一覧には、レプリケーションコントローラーを作成する場合などに重要となる kube-controller-manager がありませんが、これに管理されている Pod がないことを確認できます。またノードをクラスターで登録していますが、利用可能なリソースなどの情報は取得されません。

さらに、アップストリームから一体型の hyperkube バイナリーに移動したため、ここで使用されている用語は近い将来に変更される可能性があります。

4.4.1. Kubernetes の検査およびデバッグ

Kubernetes Master から、実行中の Kubernetes 設定を検査します。上述したように、このセクションのトラブルシューティングの例は、「Kubernetes クラスターを作成して Docker フォーマットのコンテナーイメージを実行する」に記載されている設定で実行されます。

まず、すべての設定を有効にした場合どのように表示されるかについて説明します。次に、セットアップに発生する各種の問題とその修正方法を示します。

4.4.2. Kubernetes の状態の照会

アプリケーションの送信とサービスの作成、 Pod の割り当てのプロセスを手動でデバッグするには、kubectl を使用するのが一番簡単です。どの Pod、サービス、およびレプリケーションコントローラーがアクティブであるかを確認するには、マスターで以下のコマンドを実行します。

# kubectl get pods
POD             IP          CONTAINER(S)     IMAGE(S)  HOST                LABELS                                         STATUS
4e04dd3b-c...   10.20.29.3  apache-frontend  webwithdb node2.example.com/  name=webserver,selectorname=webserver,uses=db  Running
5544eab2-c...   10.20.48.15 apache-frontend  webwithdb node1.example.com/  name=webserver,selectorname=webserver,uses=db  Running
1c971a09-c...   10.20.29.2  db               dbforweb  node2.example.com   name=db,selectorname=db                        Running
1c97a755-c...   10.20.48.14 db               dbforweb  node1.example.com/  name=db,selectorname=db                        Running
# kubectl get services
NAME               LABELS                                   SELECTOR        IP                  PORT
webserver-service  name=webserver                           name=webserver  10.254.100.50       80
db-service         name=db                                  name=db         10.254.100.1        3306
kubernetes         component=apiserver,provider=kubernetes            10.254.92.19        443
kubernetes-ro      component=apiserver,provider=kubernetes            10.254.206.141      80
# kubectl get replicationControllers
CONTROLLER             CONTAINER(S)        IMAGE(S)            SELECTOR                 REPLICAS
webserver-controller   apache-frontend     webwithdb           selectorname=webserver   2
db-controller          db                  dbforweb            selectorname=db          2

以下に、この出力が何を示しているかを説明します。

  • Pod の状態は「Waiting」または「Running」です。ここでは 4 つの Pod がすべて実行されているため、問題はありません。
  • レプリケーションコントローラーは、2 つの apache-frontend と 2 つの db コンテナーを正常に起動しました。それらは node1 および node2 に配信されます。
  • apache-frontend の uses ラベルを使用して、コンテナーが db-service Kubernetes サービスから db コンテナーを見つけられるようにします。
  • サービスの一覧は、各サービスのラベル名で、Pod から要求できる各サービスの IP アドレスとポート番号を特定します。
  • kubernetes および kubernetes-ro サービスは、kube-apiserver systemd サービスへのアクセスを提供します。

この状態になるまでのプロセスで問題が発生した場合は、以下のセクションを参照してトラブルシューティングを行うことができます。

4.5. Kubernetes systemd サービスのトラブルシューティング

Kubernetes は、Kubernetes のマスターおよびノードで実行されるサービスデーモンのセットを使用して実装されます。それらの systemd サービスが適切に実行されていないと失敗します。Kubernetes systemd サービスを使用した場合に潜在的な問題を回避し、それらを修正する方法を以下に示します。

4.5.1. Kubernetes systemd サービスが起動していることの確認

Kubernetes クラスターは、マスターと 1 つ以上のノード (minion) で構成されており、systemd サービスの特定セットを初期化する必要があります。マスターおよび各ノードで以下のサービスが実行していることを確認する必要があります。

  • マスターを最初に起動する: ノードのサービスを起動する前にマスターのサービスを起動する必要があります。マスターが起動していない場合はノードは適切に起動されません。
  • マスターサービス: サービスには、kube-controller-manager、kube-scheduler、flanneld、etcd、および kube-apiserver が含まれます。flanneld サービスはオプションのサービスで、別のシステムで etcd サービスを実行することができます。
  • ノードサービス: サービスには、docker、kube-proxy、kubelet、flanneld が含まれます。flanneld サービスはオプションです。

以下は、マスターおよび各ノード上でこれらのサービスを確認する方法です。

マスター: kubernetes マスターサーバーでは、適切なサービスがアクティブであり、有効にされているかどうかが示されます (flanneld はシステムに設定されていない場合もあります)。

# for SERVICES in etcd flanneld kube-apiserver kube-controller-manager kube-scheduler;
    do echo --- $SERVICES --- ; systemctl is-active $SERVICES ;
    systemctl is-enabled $SERVICES ; echo "";  done
--- etcd ---
active
enabled
--- flanneld ---
active
enabled
--- kube-apiserver ---
active
enabled
--- kube-controller-manager ---
active
enabled
--- kube-scheduler ---
active
enabled

Minions (ノード): 各ノードで、適切なサービスがアクティブであり、有効にされていることを確認します。

# for SERVICES in flanneld docker kube-proxy.service kubelet.service; \
do echo --- $SERVICES --- ; systemctl is-active $SERVICES ; \
systemctl is-enabled $SERVICES ; echo "";  done
--- flanneld ---
active
enabled
--- docker ---
active
enabled
--- kube-proxy.service ---
active
enabled
--- kubelet.service ---
active
enabled

マスターまたはノードの systemd サービスのいずれかが無効にされているか、またはこれに障害がある場合は、以下を実行します。

  • Kubernetes クラスターのセクションの Kubernetes サービスの起動について説明している部分を参照して、サービスの有効化またはアクティブ化を試行します。
  • サービスに障害が発生しているシステムで systemd ジャーナルを確認し、問題解決のヒントを探します。1 つの方法として、サービスを表示するコマンドで journalctl を使用することができます。以下は例になります。

    # journalctl -l -u kubelet
    # journalctl -l -u kube-apiserver
  • サービスが依然として起動しない場合は、Kubernetes クラスターの部分を再度参照し、各サービスの設定ファイルが適切にセットアップされていることを確認します。

4.5.2. Kubernetes のファイアウォールの確認

RHEL Atomic には iptables または firewalld サービスはインストールされていません。そのため、デフォルトでは Kubernetes サービスへのアクセスをブロックするファイアウォールのフィルタールールはありません。ただし、RHEL ホストでファイアウォールが実行している場合や、Kubernetes マスターまたはノードに iptables ファイアウォールルールを追加して入力ポートにフィルターを設定している場合は、これらのシステムに公開する必要があるポートがブロックされていないことを確認する必要があります。

以下は netstat コマンドの出力であり、Kubernetes および関連サービスが Kubernetes ノードで listen しているポートを示しています。

# netstat -tupln
tcp6       0      0 :::10249          :::*          LISTEN      125528/kube-proxy
tcp6       0      0 :::10250          :::*          LISTEN      125536/kubelet

注意: kube-proxy サービスはランダムなポートで listen します。デフォルトで使用されているファイアウォールサービスにフィルタリングが使用されているため、これは RHEL Atomic システムでは問題ありません。ただし、ファイアウォールを RHEL Atomic に追加するか、またはデフォルトの RHEL システムを使用する場合、サービス定義で kube-proxy が特定のポートで listen し、ファイアウォールでそれらのポートを開くように設定することができます。

以下は、Kubernetes マスターにおける netstat 出力です。

tcp        0      0 192.168.122.249:7080  0.0.0.0:* LISTEN   636/kube-apiserver
tcp6       0      0 :::8080               :::*      LISTEN   636/kube-apiserver
tcp        0      0 127.0.0.1:10252       0.0.0.0:* LISTEN   7541/kube-controller
tcp        0      0 127.0.0.1:10251       0.0.0.0:* LISTEN   7590/kube-scheduler
tcp6       0      0 :::4001               :::*      LISTEN   941/etcd
tcp6       0      0 :::7001               :::*      LISTEN   941/etcd
出力の 3 列目を参照してください。
ここでは、各サービスが listen している IP アドレスとポート番号が表示されています。それらの各サービスに対してポートが開かれていることを確認します。

4.5.3. Kubernetes の yaml または json ファイルの確認

kubectl create コマンドを使用して、yaml または json ファイルから情報をロードし、Kubernetes 環境 (Pod、サービス、およびレプリケーションコントローラー) をセットアップします。それらのファイルが正しくフォーマットされていなかったり、必要な情報が不足していると失敗します。

以下のセクションでは、yaml または json ファイルが破損している場合に生じる問題を解決するためのヒントを紹介します。

4.5.3.1. Kubernetes サービス作成時のトラブルシューティング

Kubernetes サービス (kubectl で作成) は IP アドレスおよびポートをラベルに割り当てます。このサービスを使用する必要のある Pod はラベルでそのサービスを参照できるため、IP アドレスおよびポート番号を直接認識する必要はありません。以下は、db-service.yaml という名前のサービスファイルの例とサービスを作成する際に生じる問題の一覧です。

id: "db-service"
kind: "Service"
apiVersion: "v1beta1"
port: 3306
portalIP: "10.254.100.1"
selector:
  name: "db"
labels:
  name: "db"
# kubectl create -f db-service
# kubectl get services
NAME          LABELS                                  SELECTOR  IP             PORT
db-service    name=db                                 name=db   10.254.100.1   3306
kubernetes-ro component=apiserver,provider=kubernetes     10.254.186.33  80
kubernetes    component=apiserver,provider=kubernetes     10.254.198.9   443

注意: kubernetes-ro および kubernetes サービスが表示されない場合は、kube-scheduler systemd サービス (systemctl restart kube-scheduler.service) を再起動します。

表示された結果がこれと異なる場合は、以下を参照してください。

  • サービスが正常に作成されている場合でも、LABELS と SELECTOR が設定されていない場合、出力結果は以下のようになる可能性があります。

    # kubectl get services
    NAME         LABELS     SELECTOR  IP             PORT
    db-service            10.254.100.1   3306

    selector: および labels: の下の name: フィールドがそれぞれ 2 文字分インデントされていることを確認します。この場合、各 name: "db" 行の前にある 2 つの空白を削除したので、それらの値は kubectl で使用されませんでした。

  • サービスを作成したことを忘れて再作成しようとしたり、サービスの yaml で特定した IP アドレスに他のサービスがすでに割り当てられている場合でサービスを新たに作成しようとすると、以下のメッセージが生成されます。

    create.go:75] service "webserver-service" is invalid: spec.portalIP:
        invalid value '10.254.100.50': IP 10.254.100.50 is already allocated

    そのサービスが必要ない場合は、異なる IP アドレスを使用するか、現在そのポートを使用しているサービスを停止するかのいずれかを実行できます。

  • "Service" オブジェクトが登録されていないことを示す以下のようなエラーが発生する理由がいくつかあります。

    7338 create.go:75] unable to recognize "db-service.yaml": no object named "Services" is registered

    上記の例では、「Service」は「Services」と誤って綴られています。「Service」と正しく綴られている場合は、apiVersion が正しいことを確認します。同様のエラーは、無効な値 "v1beta99" が apiVersion に使用される場合に生じます。その場合、"v1beta99" が存在しないことではなく、オブジェクトの「Service」が見つからないことを報告します。

    1. 以下は、上記の例のフィールドがない場合に発生するエラーメッセージの一覧です。

      1. id: missing: service "" is invalid: name: required value ''
      2. kind: missing: unable to recognize "db-service.yaml": no object named "" is registered
      3. apiVersion: missing: service "" is invalid: [name: required value '', spec.port: invalid value '0']
      4. port: missing: service "db-service" is invalid: spec.port: invalid value '0'
      5. portalIP: missing: No error is reported because portalIP is not required
      6. selector: missing: No error is reported, but SELECTOR field is missing and service may not work.
      7. labels: missing: Not an error, but LABELS field is missing and service may not work.

4.5.3.2. Kubernetes レプリケーションコントローラーおよび Pod 作成のトラブルシューティング

Kubernetes の Pod を使用して、1 つ以上のコンテナーを関連付け、実行オプションを各コンテナーに割り当て、それらのコンテナーをまとめてユニットとして管理します。レプリケーションコントローラーを使用すると、確認する Pod をいくつ実行するかを指定できます。以下は、Web サーバーの Pod を定義する yaml ファイルと、2 つの Pod インスタンスが実行中であることを確認できるレプリケーションコントローラーの例です。

id: "webserver-controller"
kind: "ReplicationController"
apiVersion: "v1beta1"
desiredState:
  replicas: 2
  replicaSelector:
    selectorname: "webserver"
  podTemplate:
    desiredState:
      manifest:
        version: "v1beta1"
        id: "webserver-controller"
        containers:
          - name: "apache-frontend"
            image: "webwithdb"
            ports:
              - containerPort: 80
    labels:
      name: "webserver"
      selectorname: "webserver"
      uses: "db"
labels:
  name: "webserver-controller"
# kubectl create -f webserver-service.yaml
# kubectl get pods
POD         IP          CONTAINER(S)     IMAGE(S)    HOST
       LABELS                                             STATUS
f28980d...  10.20.48.4  apache-frontend  webwithdb   node1.example.com/
       name=webserver,selectorname=webserver,uses=db      Running
f28a0a8...  10.20.29.9  apache-frontend  webwithdb   node2.example.com/
       name=webserver,selectorname=webserver,uses=db      Running
# kubectl get replicationControllers
CONTROLLER           CONTAINER(S)    IMAGE(S)   SELECTOR               REPLICAS

webserver-controller apache-frontend webwithdb  selectorname=webserver 2

注意: この出力では、Pod 名の後ろが切り捨てられ、長い行は折り返して表示されています。

表示された結果がこれと異なる場合は、以下を参照してください。

  • id: missing: CONTROLLER 列に "webserver-controller" の代わりに生成された数字や文字のセットが表示された場合、yaml ファイルにはおそらく id 行がありません。
  • apiVersion set wrong: "unable to recognize "webserver-rc.yaml": no object named "ReplicationController" is registered" というメッセージが表示される場合、apiVersion の値が無効か、または ReplicationController の綴りが正しくない可能性があります。
  • selectorname: missing: "replicationController "webserver-controller" is invalid: spec.selector: required value 'map[]'" というメッセージが表示される場合、replicaSelector 行の後には selectorname が設定されません。selectorname のインデントが適切に行われていない場合、"unable to get type info from "webserver-rc.yaml": couldn’t get version/kind: error converting YAML to JSON: yaml: line 7: did not find expected key." のようなメッセージが表示されます。

4.6. トラブルシューティングの手法

Kubernetes クラスターで生じていることを詳細に調べる必要がある場合に参照できる手法を以下に示します。

4.6.1. etcd データベースのクロールおよび修正

etcd サービスは、Kubernetes がクラスター間で情報を統合するために使用するデータベースを提供します。データベースを直接表示して問題を修正する方法があります (または、修正ができない場合はデーターベースを削除します)。

etcd データベースからのデータの表示: kubectl get コマンドを使用して etcd データベースから必要な情報のほとんどを照会できます。ただし、このデータベースが設定が予想したものと異なる場合は、etcdctl コマンドを使用して etcd データベースを直接照会できます。

etcdctl コマンドを ls オプションと共に使用すると、データベースのディレクトリー構造を一覧表示できます。値を取得するには、get オプションを使用します。たとえば、データベースの root を表示するには、以下を入力します。

# etcdctl ls /
/coreos.com
/registry

etcd データベースの Kubernetes イベントを一覧表示するには、以下を入力します。

# etcdctl ls /registry/events/default/

/registry/events/default/679ec44e-e882-11e4-926b-52540...
/registry/events/default/e1f4b268-e87d-11e4-926b-52540...
/registry/events/default/node2.example.com.13d8e2c0b644c20b
/registry/events/default/679ec44e-e882-11e4-926b-52540...
/registry/events/default/5271ec4f-edc1-11e4-8ee6-52540...
/registry/events/default/node1.example.com.13d8e29653ad9bbc

データが特定のイベントに関連付けられていることを確認するには、get オプションを使用します (node1 引数を /registry/events/default/ ディレクトリーのエントリーに置き換えます)。

# etcdctl get \
  /registry/events/default/node1.example.com.13d8e29653ad9bbc | \
  python -mjson.tool
{
    "apiVersion": "v1beta1",
    "creationTimestamp": "2015-04-27T09:40:16-04:00",
    "host": "node1.example.com",
    "id": "node1.example.com.13d8e29653ad9bbc",
    "involvedObject": {
        "kind": "Minion",
        "name": "node1.example.com",
        "namespace": "default",
        "uid": "node1.example.com"
    },
    "kind": "Event",
    "message": "Starting kubelet.",
    "namespace": "default",
    "reason": "starting",
    "source": "kubelet",
    "timestamp": "2015-04-27T09:40:16-04:00",
    "uid": "f020d047-ece2-11e4-8ee6-5254001aa4ee"
}

上記の出力は python の json.tool フォーマットのモジュールにパイプされ、読みやすくなります。node1.example.com は Minion として定義され、それに関連付けられているイベントが kublet サービスを起動していることを確認できます。

以下は、その他の etcdctl を使用した ls の実行例です。これらは、レジストリーにあるトップレベルのエントリー、minions の名前、サービスの名前、および使用されているサブネットを示しています。

# etcdctl ls /registry/
/registry/events
/registry/minions
/registry/nodes
/registry/pods
/registry/services
/registry/controllers
# etcdctl ls /registry/minions
/registry/minions/node1.example.com
/registry/minions/node2.example.com
# etcdctl ls /registry/services/endpoints/default/
/registry/services/endpoints/default/db-service
/registry/services/endpoints/default/kubernetes
/registry/services/endpoints/default/kubernetes-ro
/registry/services/endpoints/default/webserver-service
# etcdctl ls /coreos.com/network/subnets/
/coreos.com/network/subnets/10.20.1.0-24
/coreos.com/network/subnets/10.20.24.0-24
/coreos.com/network/subnets/10.20.56.0-24

以下は、etcdctl を使用した get の実行例です。最初の例は、db サービスの詳細を示しています。2 つ目の例は、node1 のホスト IP アドレスおよび他の情報について示しています。最後の例は、flannel によって割り当てられるサブネットワークの情報を示しています。

# etcdctl get \
    /registry/services/endpoints/default/db-service/  \
    |  python -mjson.tool
{
    "apiVersion": "v1beta1",
    "creationTimestamp": "2015-04-21T18:29:43-04:00",
    "endpoints": [
        "10.20.1.3:3306",
        "10.20.24.3:3306"
    ],
    "id": "db-service",
    "kind": "Endpoints",
    "namespace": "default",
    "resourceVersion": 312,
    "selfLink": "/api/v1beta1/endpoints/db-service?namespace=default",
    "uid": "e87f9435-e875-11e4-926b-5254001aa4ee"
}
# etcdctl get /registry/minions/node1.example.com | python -mjson.tool

{
    "apiVersion": "v1beta1",
    "creationTimestamp": "2015-04-21T16:59:22-04:00",
    "hostIP": "192.168.122.116",
    "id": "node1.example.com",
    "kind": "Minion",
    "resources": {
        "capacity": {
            "cpu": "1",
            "memory": 3221225472
        }
    },
    "status": {},
    "uid": "4926bc0c-e869-11e4-926b-5254001aa4ee"
}
# etcdctl get /coreos.com/network/subnets/10.20.24.0-24 | python -mjson.tool

{
    "BackendData": {
        "VtepMAC": "86:b1:2e:96:5f:35"
    },
    "BackendType": "vxlan",
    "PublicIP": "192.168.122.116"
}

注意: etcdctl が選択できない場合は、curl コマンドを代わりに使用できます。たとえば、curl でデータベースの root を表示するには、etcdctl ls / コマンドの代わりに curl -L http://master:4001/v2/keys/ | python -mjson.tool を使用します。この curl コマンドの形式を使用して、ディレクトリーとキー値の両方を表示します。ノードをマスターの etcd サービスに接続できないと思われる場合は、以下の curl コマンドを使用して、ノードからその接続をテストできます。

# curl -s -L http://master.example.com:4001/version

etcd データベースの修正: 情報が同期されない場合、etcd データベースで問題を修正することができます。キーの内容を変更するためのコマンドには、etcdctl update および etcdctl set コマンドがあります。ただし、注意して使用しないと、これらの値を変更した時に、問題を修正せずに別の問題を発生させることになります。

ただし、etcd データベースが完全に利用できない場合は、一度削除してから再度起動できます。etcd デーモンを -f オプションと共に実行することにより、これを実行できます。

警告: etcd データベースを削除する前に、kubectl delete コマンドを使用して、問題のあるサービス、Pod、レプリケーションコントローラーまたは minions を削除します。データベースを削除する必要が依然としてあると思われる場合は、すべてを最初から作成し直す必要があることに注意してください。

etcd データベースを削除するには、以下を入力します。

# etcd -f

4.6.2. Kubernetes コンポーネントの削除

Kubernetes のコンポーネントを停止し、削除するには注意が必要です。Kubernetes は物事を特定の状態に維持するように設計されているため、コンテナーや Pod を削除するだけで、別のコンポーネントが起動することがよくあります。そのため、Kubernetes 環境で一部またはすべてのコンポーネントを削除する必要がある場合は、「Kubernetes クラスターの作成」の「Kubernetes の削除」サクションにある指示に従うことをお勧めします。

コンポーネントを削除する順番を間違えると、以下のような問題が発生します。

  • Pod を削除したのに再起動した: レプリケーションコントローラーを最初に停止しないと Pod が再起動します。レプリケーションコントローラーを停止 (docker stop replicationControllers webserver-controller) してから Pod を停止します。
  • コンテナーを停止して削除したのに再起動した: Kubernetes クラスターを使用する場合、docker stop を実行してコンテナーを直接停止することはできません。レプリケーションコントローラーは、新しいコントローラーを起動して、停止したコンテナーを再起動します。

4.6.3. 「WAITING」状態で停止した Pod

Pod は一定期間「waiting (待機状態)」状態になることがあります。以下が考えられる原因です。

  • Docker イメージの取得に時間がかかる: これを確認するには、Pod が割り当てられている minion に ssh を直接実行し、以下を実行します。

    # journalctl -f -u docker

    これにより、イメージを取得する docker のログが表示されます。dockerhub イメージを取得する要求は断続的に失敗する可能性がありますが、kubelets は継続的に再試行します。

  • Pod が割り当てられていない: Pod が割り当てられていない場合は、kubectl get minions を実行して、ノードがマスターで利用できることを確認します。ノードが停止しているか、または応答しない可能性があります。割り当てられていない Pod は、クラスターが提供できるよりも多くのレプリケーション数を設定することによって発生する可能性もあります。
  • コンテナー Pod が起動直後に終了する: 作成した Dockerfile が、サービスを起動するために適切に書き込まれていないか、または docker CMD 操作に失敗しているため、起動直後に POD が終了する場合があります。docker run コマンドでコンテナーイメージをテストし、コンテナー自体が壊れていないことを確認します。
  • コンテナーからの出力の確認: コンテナーからのメッセージの出力は、kubectl log コマンドで表示できます。これは、コンテナー内で実行されているアプリケーションに関する問題をデバッグするのに役立ちます。以下は、利用可能な Pod を一覧表示し、必要な Pod のログメッセージを表示する方法です。

    # kubectl get pods
    POD                                   IP         CONTAINER(S) IMAGE(S)            HOST                 LABELS                          STATUS
    e1f4b268-e87d-11e4-926b-5254001aa4ee  10.20.24.3 db           dbforweb node1.example.com/   name=db,selectorname=db         Running
    # kubectl log e1f4b268-e87d-11e4-926b-5254001aa4ee
    2015-04-28T16:09:36.953130209Z 150428 12:09:36 mysqld_safe Logging to '/var/log/mariadb/mariadb.log'.
    2015-04-28T16:09:37.137064742Z 150428 12:09:37 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
  • docker からのコンテナー出力の確認: 一部のエラーは kubelet にまでは影響しません。終了したコンテナーについて docker ログを直接確認し、どんな問題が発生したかを確認することができます。以下はその方法です。

    1. コンテナーの実行に問題のあるノードにログインします。
    2. このコマンドを実行して終了した実行を参照します。

      # docker ps -a
      61960bda2927  rhel7/rhel-tools:latest "/usr/bin/bash" 47 hours ago
            Exited (0) 43 hours ago      myrhel-tools4
    3. docker logs を使用してコンテナーのすべての出力を確認します。

      # docker logs 61960bda2927

コンテナーセッションから出力全体を確認できるようにする必要があります。たとえば、コンテナーにシェルを開いた場合、docker logs を実行する際にシェルから実行したすべてのコマンドを確認できます。