これは、このセクションの複数ページの印刷可能なビューです。 印刷するには、ここをクリックしてください.

このページの通常のビューに戻る.

クラスターのトラブルシューティング

一般的なクラスターの問題をデバッグします。

このドキュメントはクラスターのトラブルシューティングに関するもので、あなたが経験している問題の根本原因として、アプリケーションをすでに除外していることを前提としています。 アプリケーションのデバッグのコツは、アプリケーションのトラブルシューティングガイドをご覧ください。 また、トラブルシューティングドキュメントにも詳しい情報があります。

kubectlのトラブルシューティングについては、kubectlのトラブルシューティングを参照してください。

クラスターのリストアップ

クラスターで最初にデバッグするのは、ノードがすべて正しく登録されているかどうかです。

以下を実行します。

kubectl get nodes

そして、期待するノードがすべて存在し、それらがすべて Ready 状態であることを確認します。

クラスター全体の健全性に関する詳細な情報を得るには、以下を実行します。

kubectl cluster-info dump

例: ダウンあるいは到達不能なノードのデバッグ

デバッグを行う際、ノードの状態を見ることが有用なことがあります。 たとえば、そのノード上で動作しているPodが奇妙な挙動を示している場合や、なぜPodがそのノードにスケジュールされないのかを知りたい場合などです。 Podと同様に、kubectl describe nodekubectl get node -o yamlを使用してノードに関する詳細情報を取得できます。 例えば、ノードがダウンしている(ネットワークから切断されている、またはkubeletが停止して再起動しないなど)場合に見られる状況は以下の通りです。 ノードがNotReadyであることを示すイベントに注意し、また、Podが動作していないことにも注意してください(NotReady状態が5分間続くとPodは追い出されます)。

kubectl get nodes
NAME                     STATUS       ROLES     AGE     VERSION
kube-worker-1            NotReady     <none>    1h      v1.23.3
kubernetes-node-bols     Ready        <none>    1h      v1.23.3
kubernetes-node-st6x     Ready        <none>    1h      v1.23.3
kubernetes-node-unaj     Ready        <none>    1h      v1.23.3
kubectl describe node kube-worker-1
Name:               kube-worker-1
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=kube-worker-1
                    kubernetes.io/os=linux
Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Thu, 17 Feb 2022 16:46:30 -0500
Taints:             node.kubernetes.io/unreachable:NoExecute
                    node.kubernetes.io/unreachable:NoSchedule
Unschedulable:      false
Lease:
  HolderIdentity:  kube-worker-1
  AcquireTime:     <unset>
  RenewTime:       Thu, 17 Feb 2022 17:13:09 -0500
Conditions:
  Type                 Status    LastHeartbeatTime                 LastTransitionTime                Reason              Message
  ----                 ------    -----------------                 ------------------                ------              -------
  NetworkUnavailable   False     Thu, 17 Feb 2022 17:09:13 -0500   Thu, 17 Feb 2022 17:09:13 -0500   WeaveIsUp           Weave pod has set this
  MemoryPressure       Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
  DiskPressure         Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
  PIDPressure          Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
  Ready                Unknown   Thu, 17 Feb 2022 17:12:40 -0500   Thu, 17 Feb 2022 17:13:52 -0500   NodeStatusUnknown   Kubelet stopped posting node status.
Addresses:
  InternalIP:  192.168.0.113
  Hostname:    kube-worker-1
Capacity:
  cpu:                2
  ephemeral-storage:  15372232Ki
  hugepages-2Mi:      0
  memory:             2025188Ki
  pods:               110
Allocatable:
  cpu:                2
  ephemeral-storage:  14167048988
  hugepages-2Mi:      0
  memory:             1922788Ki
  pods:               110
System Info:
  Machine ID:                 9384e2927f544209b5d7b67474bbf92b
  System UUID:                aa829ca9-73d7-064d-9019-df07404ad448
  Boot ID:                    5a295a03-aaca-4340-af20-1327fa5dab5c
  Kernel Version:             5.13.0-28-generic
  OS Image:                   Ubuntu 21.10
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  containerd://1.5.9
  Kubelet Version:            v1.23.3
  Kube-Proxy Version:         v1.23.3
Non-terminated Pods:          (4 in total)
  Namespace                   Name                                 CPU Requests  CPU Limits  Memory Requests  Memory Limits  Age
  ---------                   ----                                 ------------  ----------  ---------------  -------------  ---
  default                     nginx-deployment-67d4bdd6f5-cx2nz    500m (25%)    500m (25%)  128Mi (6%)       128Mi (6%)     23m
  default                     nginx-deployment-67d4bdd6f5-w6kd7    500m (25%)    500m (25%)  128Mi (6%)       128Mi (6%)     23m
  kube-system                 kube-proxy-dnxbz                     0 (0%)        0 (0%)      0 (0%)           0 (0%)         28m
  kube-system                 weave-net-gjxxp                      100m (5%)     0 (0%)      200Mi (10%)      0 (0%)         28m
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests     Limits
  --------           --------     ------
  cpu                1100m (55%)  1 (50%)
  memory             456Mi (24%)  256Mi (13%)
  ephemeral-storage  0 (0%)       0 (0%)
  hugepages-2Mi      0 (0%)       0 (0%)
Events:
...
kubectl get node kube-worker-1 -o yaml
apiVersion: v1
kind: Node
metadata:
  annotations:
    kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock
    node.alpha.kubernetes.io/ttl: "0"
    volumes.kubernetes.io/controller-managed-attach-detach: "true"
  creationTimestamp: "2022-02-17T21:46:30Z"
  labels:
    beta.kubernetes.io/arch: amd64
    beta.kubernetes.io/os: linux
    kubernetes.io/arch: amd64
    kubernetes.io/hostname: kube-worker-1
    kubernetes.io/os: linux
  name: kube-worker-1
  resourceVersion: "4026"
  uid: 98efe7cb-2978-4a0b-842a-1a7bf12c05f8
spec: {}
status:
  addresses:
  - address: 192.168.0.113
    type: InternalIP
  - address: kube-worker-1
    type: Hostname
  allocatable:
    cpu: "2"
    ephemeral-storage: "14167048988"
    hugepages-2Mi: "0"
    memory: 1922788Ki
    pods: "110"
  capacity:
    cpu: "2"
    ephemeral-storage: 15372232Ki
    hugepages-2Mi: "0"
    memory: 2025188Ki
    pods: "110"
  conditions:
  - lastHeartbeatTime: "2022-02-17T22:20:32Z"
    lastTransitionTime: "2022-02-17T22:20:32Z"
    message: Weave pod has set this
    reason: WeaveIsUp
    status: "False"
    type: NetworkUnavailable
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:13:25Z"
    message: kubelet has sufficient memory available
    reason: KubeletHasSufficientMemory
    status: "False"
    type: MemoryPressure
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:13:25Z"
    message: kubelet has no disk pressure
    reason: KubeletHasNoDiskPressure
    status: "False"
    type: DiskPressure
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:13:25Z"
    message: kubelet has sufficient PID available
    reason: KubeletHasSufficientPID
    status: "False"
    type: PIDPressure
  - lastHeartbeatTime: "2022-02-17T22:20:15Z"
    lastTransitionTime: "2022-02-17T22:15:15Z"
    message: kubelet is posting ready status. AppArmor enabled
    reason: KubeletReady
    status: "True"
    type: Ready
  daemonEndpoints:
    kubeletEndpoint:
      Port: 10250
  nodeInfo:
    architecture: amd64
    bootID: 22333234-7a6b-44d4-9ce1-67e31dc7e369
    containerRuntimeVersion: containerd://1.5.9
    kernelVersion: 5.13.0-28-generic
    kubeProxyVersion: v1.23.3
    kubeletVersion: v1.23.3
    machineID: 9384e2927f544209b5d7b67474bbf92b
    operatingSystem: linux
    osImage: Ubuntu 21.10
    systemUUID: aa829ca9-73d7-064d-9019-df07404ad448

ログの確認

今のところ、クラスターをより深く掘り下げるには、関連するマシンにログインする必要があります。 以下は、関連するログファイルの場所です。 (systemdベースのシステムでは、代わりにjournalctlを使う必要があるかもしれないことに注意してください)

コントロールプレーンノード

  • /var/log/kube-apiserver.log - APIの提供を担当するAPIサーバーのログ
  • /var/log/kube-scheduler.log - スケジューリング決定責任者であるスケジューラーのログ
  • /var/log/kube-controller-manager.log - スケジューリングを除く、ほとんどのKubernetes組み込みのコントローラーを実行するコンポーネントのログ(スケジューリングはkube-schedulerが担当します)

ワーカーノード

  • /var/log/kubelet.log - ノード上でコンテナの実行を担当するKubeletのログ
  • /var/log/kube-proxy.log - サービスのロードバランシングを担うKube Proxyのログ

クラスター障害モードの一般的な概要

これは、問題が発生する可能性のある事柄と、問題を軽減するためにクラスターのセットアップを調整する方法の不完全なリストです。

根本的な原因

  • VMのシャットダウン
  • クラスター内、またはクラスターとユーザー間のネットワークパーティション
  • Kubernetesソフトウェアのクラッシュ
  • データの損失や永続的ストレージ(GCE PDやAWS EBSボリュームなど)の使用不能
  • Kubernetesソフトウェアやアプリケーションソフトウェアの設定ミスなど、オペレーターのミス

具体的なシナリオ

  • apiserver VMのシャットダウンまたはapiserverのクラッシュ
    • その結果
      • 新しいPod、サービス、レプリケーションコントローラーの停止、更新、起動ができない
      • Kubernetes APIに依存していない限り、既存のPodやサービスは正常に動作し続けるはずです
  • apiserverのバックアップストレージが失われた
    • その結果
      • apiserverが立ち上がらない
      • kubeletは到達できなくなりますが、同じPodを実行し、同じサービスのプロキシを提供し続けます
      • apiserverを再起動する前に、手動でapiserverの状態を回復または再現する必要がある
  • サポートサービス(ノードコントローラー、レプリケーションコントローラーマネージャー、スケジューラーなど)VMのシャットダウンまたはクラッシュ
    • 現在、これらはapiserverとコロケーションしており、使用できない場合はapiserverと同様の影響があります
    • 将来的には、これらも複製されるようになり、同じ場所に配置されない可能性があります
    • 独自の永続的な状態を持っていない
  • 個別ノード(VMまたは物理マシン)のシャットダウン
    • その結果
      • そのノード上のPodの実行を停止
  • ネットワークパーティション
    • その結果
      • パーティションAはパーティションBのノードがダウンしていると考え、パーティションBはapiserverがダウンしていると考えています。(マスターVMがパーティションAで終了したと仮定)
  • Kubeletソフトウェア障害
    • その結果
      • クラッシュしたkubeletがノード上で新しいPodを起動できない
      • kubeletがPodを削除するかどうか
      • ノードが不健全と判定される
      • レプリケーションコントローラーが別の場所で新しいPodを起動する
  • クラスターオペレーターエラー
    • その結果
      • PodやServiceなどの損失
      • apiserverのバックエンドストレージの紛失
      • ユーザーがAPIを読めなくなる
      • その他

軽減策

  • 対処法: IaaSプロバイダーの自動VM再起動機能をIaaS VMに使用する

    • 異常: Apiserver VMのシャットダウンまたはApiserverのクラッシュ
    • 異常: サポートサービスのVMシャットダウンまたはクラッシュ
  • 対処法: IaaSプロバイダーの信頼できるストレージ(GCE PDやAWS EBSボリュームなど)をapiserver+etcdを使用するVMに使用する

    • 異常: Apiserverのバックエンドストレージが失われる
  • 対処法: 高可用性構成を使用します

    • 異常: コントロールプレーンノードのシャットダウンまたはコントロールプレーンコンポーネント(スケジューラー、APIサーバー、コントローラーマネージャー)のクラッシュ
      • 1つ以上のノードまたはコンポーネントの同時故障に耐えることができる
    • 異常: APIサーバーのバックアップストレージ(etcdのデータディレクトリーなど)が消失
      • HA(高可用性)etcdの構成を想定しています
  • 対処法: apiserver PDs/EBS-volumesを定期的にスナップショットする

    • 異常: Apiserverのバックエンドストレージが失われる
    • 異常: 操作ミスが発生する場合がある
    • 異常: Kubernetesのソフトウェアに障害が発生する場合がある
  • 対処法:レプリケーションコントローラーとServiceをPodの前に使用する

    • 異常: ノードのシャットダウン
    • 異常: Kubeletソフトウェア障害
  • 対処法: 予期せぬ再起動に耐えられるように設計されたアプリケーション(コンテナ)

    • 異常: ノードのシャットダウン
    • 異常: Kubeletソフトウェア障害

次の項目

1 - リソースメトリクスパイプライン

Kubernetesでは、コンテナのCPU使用率やメモリ使用率といったリソース使用量のメトリクスが、メトリクスAPIを通じて提供されています。これらのメトリクスは、ユーザーがkubectl topコマンドで直接アクセスするか、クラスター内のコントローラー(例えばHorizontal Pod Autoscaler)が判断するためにアクセスすることができます。

メトリクスAPI

メトリクスAPIを使用すると、指定したノードやPodが現在使用しているリソース量を取得することができます。 このAPIはメトリックの値を保存しないので、例えば10分前に指定されたノードが使用したリソース量を取得することはできません。

メトリクスAPIは他のAPIと何ら変わりはありません。

  • 他のKubernetes APIと同じエンドポイントを経由して、/apis/metrics.k8s.io/パスの下で発見できます。
  • 同じセキュリティ、スケーラビリティ、信頼性の保証を提供します。

メトリクスAPIはk8s.io/metricsリポジトリで定義されています。 メトリクスAPIについての詳しい情報はそちらをご覧ください。

リソース使用量の測定

CPU

CPUは、一定期間の平均使用量をCPU coresという単位で報告されます。 この値は、カーネルが提供する累積CPUカウンターの比率を取得することで得られます(LinuxとWindowsの両カーネルで)。 kubeletは、比率計算のためのウィンドウを選択します。

メモリ

メモリは、測定値が収集された時点のワーキングセットとして、バイト単位で報告されます。 理想的な世界では、「ワーキングセット」は、メモリ不足で解放できない使用中のメモリ量です。 しかし、ワーキングセットの計算はホストOSによって異なり、一般に推定値を生成するために経験則を多用しています。 Kubernetesはスワップをサポートしていないため、すべての匿名(非ファイルバックアップ)メモリが含まれます。 ホストOSは常にそのようなページを再請求することができないため、メトリックには通常、一部のキャッシュされた(ファイルバックされた)メモリも含まれます。

メトリクスサーバー

メトリクスサーバーは、クラスター全体のリソース使用量データのアグリゲーターです。 デフォルトでは、kube-up.shスクリプトで作成されたクラスターにDeploymentオブジェクトとしてデプロイされます。 別のKubernetesセットアップ機構を使用する場合は、提供されるdeployment components.yamlファイルを使用してデプロイすることができます。 メトリクスサーバーは、Summary APIからメトリクスを収集します。 各ノードのKubeletからKubernetes aggregator経由でメインAPIサーバーに登録されるようになっています。

メトリクスサーバーについては、Design proposalsで詳しく解説しています。

Summary APIソース

Kubeletは、ノード、ボリューム、Pod、コンテナレベルの統計情報を収集し、Summary APIで省略して消費者が読めるようにするものです。

1.23以前は、これらのリソースは主にcAdvisorから収集されていました。しかし、1.23ではPodAndContainerStatsFromCRIフィーチャーゲートの導入により、コンテナとPodレベルの統計情報をCRI実装で収集することができます。

注意: これはCRI実装によるサポートも必要です(containerd >= 1.6.0, CRI-O >= 1.23.0)。

2 - リソース監視のためのツール

アプリケーションを拡張し、信頼性の高いサービスを提供するために、デプロイ時にアプリケーションがどのように動作するかを理解する必要があります。 コンテナ、PodService、クラスター全体の特性を調べることにより、Kubernetesクラスターのアプリケーションパフォーマンスを調査することができます。 Kubernetesは、これらの各レベルでアプリケーションのリソース使用に関する詳細な情報を提供します。 この情報により、アプリケーションのパフォーマンスを評価し、ボトルネックを取り除くことで全体のパフォーマンスを向上させることができます。

Kubernetesでは、アプリケーションの監視は1つの監視ソリューションに依存することはありません。 新しいクラスターでは、リソースメトリクスまたはフルメトリクスパイプラインを使用してモニタリング統計を収集することができます。

リソースメトリクスパイプライン

リソースメトリックパイプラインは、Horizontal Pod Autoscalerコントローラーなどのクラスターコンポーネントや、kubectl topユーティリティに関連する限定的なメトリックセットを提供します。

これらのメトリクスは軽量、短期、インメモリーのmetrics-serverによって収集され、metrics.k8s.io APIを通じて公開されます。

metrics-serverはクラスター上のすべてのノードを検出し 各ノードのkubeletにCPUとメモリーの使用量を問い合わせます。

kubeletはKubernetesマスターとノードの橋渡し役として、マシン上で動作するPodやコンテナを管理する。 kubeletは各Podを構成するコンテナに変換し、コンテナランタイムインターフェースを介してコンテナランタイムから個々のコンテナ使用統計情報を取得します。この情報は、レガシーDocker統合のための統合cAdvisorから取得されます。

そして、集約されたPodリソース使用統計情報を、metrics-server Resource Metrics APIを通じて公開します。 このAPIは、kubeletの認証済みおよび読み取り専用ポート上の /metrics/resource/v1beta1 で提供されます。

フルメトリクスパイプライン

フルメトリクスパイプラインは、より豊富なメトリクスにアクセスすることができます。 Kubernetesは、Horizontal Pod Autoscalerなどのメカニズムを使用して、現在の状態に基づいてクラスターを自動的にスケールまたは適応させることによって、これらのメトリクスに対応することができます。 モニタリングパイプラインは、kubeletからメトリクスを取得し、custom.metrics.k8s.io または external.metrics.k8s.io APIを実装してアダプタ経由でKubernetesにそれらを公開します。 CNCFプロジェクトのPrometheusは、Kubernetes、ノード、Prometheus自身をネイティブに監視することができます。 CNCFに属さない完全なメトリクスパイプラインのプロジェクトは、Kubernetesのドキュメントの範囲外です。

次の項目

以下のような追加のデバッグツールについて学びます:

3 - ノードの健全性を監視します

Node Problem Detectorは、ノードの健全性を監視し、報告するためのデーモンです。 Node Problem DetectorDaemonSetとして、あるいはスタンドアロンデーモンとして実行することができます。

Node Problem Detectorは様々なデーモンからノードの問題に関する情報を収集し、これらの状態をNodeConditionおよびEventとしてAPIサーバーにレポートします。 Node Problem Detectorのインストール方法と使用方法については、Node Problem Detectorプロジェクトドキュメントを参照してください。

始める前に

Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:

制限事項

  • Node Problem Detectorは、ファイルベースのカーネルログのみをサポートします。 journaldのようなログツールはサポートされていません。

  • Node Problem Detectorは、カーネルの問題を報告するためにカーネルログフォーマットを使用します。 カーネルログフォーマットを拡張する方法については、Add support for another log format を参照してください。

ノード問題検出の有効化

クラウドプロバイダーによっては、Node Problem DetectorAddonとして有効にしている場合があります。 また、kubectlを使ってNode Problem Detectorを有効にするか、Addon podを作成することで有効にできます。

kubectlを使用してNode Problem Detectorを有効化します

kubectlNode Problem Detectorを最も柔軟に管理することができます。 デフォルトの設定を上書きして自分の環境に合わせたり、カスタマイズしたノードの問題を検出したりすることができます。 例えば:

  1. node-problem-detector.yamlのようなNode Problem Detectorの設定を作成します:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: node-problem-detector-v0.1
      namespace: kube-system
      labels:
        k8s-app: node-problem-detector
        version: v0.1
        kubernetes.io/cluster-service: "true"
    spec:
      selector:
        matchLabels:
          k8s-app: node-problem-detector  
          version: v0.1
          kubernetes.io/cluster-service: "true"
      template:
        metadata:
          labels:
            k8s-app: node-problem-detector
            version: v0.1
            kubernetes.io/cluster-service: "true"
        spec:
          hostNetwork: true
          containers:
          - name: node-problem-detector
            image: registry.k8s.io/node-problem-detector:v0.1
            securityContext:
              privileged: true
            resources:
              limits:
                cpu: "200m"
                memory: "100Mi"
              requests:
                cpu: "20m"
                memory: "20Mi"
            volumeMounts:
            - name: log
              mountPath: /log
              readOnly: true
          volumes:
          - name: log
            hostPath:
              path: /var/log/
  2. Node Problem Detectorkubectlで起動します。

    kubectl apply -f https://k8s.io/examples/debug/node-problem-detector.yaml
    

Addon podを使用してNode Problem Detectorを有効化します

カスタムのクラスターブートストラップソリューションを使用していて、デフォルトの設定を上書きする必要がない場合は、Addon Podを利用してデプロイをさらに自動化できます。 node-problem-detector.yamlを作成し、制御プレーンノードのAddon Podのディレクトリ/etc/kubernetes/addons/node-problem-detectorに設定を保存します。

コンフィギュレーションを上書きします

Node Problem Detectorの Dockerイメージをビルドする際に、default configurationが埋め込まれます。

ConfigMap を使用することで設定を上書きすることができます。

  1. config/ にある設定ファイルを変更します

  2. ConfigMap node-problem-detector-configを作成します。

    kubectl create configmap node-problem-detector-config --from-file=config/
    
  3. node-problem-detector.yamlを変更して、ConfigMapを使用するようにします。

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: node-problem-detector-v0.1
      namespace: kube-system
      labels:
        k8s-app: node-problem-detector
        version: v0.1
        kubernetes.io/cluster-service: "true"
    spec:
      selector:
        matchLabels:
          k8s-app: node-problem-detector  
          version: v0.1
          kubernetes.io/cluster-service: "true"
      template:
        metadata:
          labels:
            k8s-app: node-problem-detector
            version: v0.1
            kubernetes.io/cluster-service: "true"
        spec:
          hostNetwork: true
          containers:
          - name: node-problem-detector
            image: registry.k8s.io/node-problem-detector:v0.1
            securityContext:
              privileged: true
            resources:
              limits:
                cpu: "200m"
                memory: "100Mi"
              requests:
                cpu: "20m"
                memory: "20Mi"
            volumeMounts:
            - name: log
              mountPath: /log
              readOnly: true
            - name: config # Overwrite the config/ directory with ConfigMap volume
              mountPath: /config
              readOnly: true
          volumes:
          - name: log
            hostPath:
              path: /var/log/
          - name: config # Define ConfigMap volume
            configMap:
              name: node-problem-detector-config
  4. 新しい設定ファイルでNode Problem Detectorを再作成します。

    # If you have a node-problem-detector running, delete before recreating
    kubectl delete -f https://k8s.io/examples/debug/node-problem-detector.yaml
    kubectl apply -f https://k8s.io/examples/debug/node-problem-detector-configmap.yaml
    

ノード問題検出装置がクラスターアドオンとして実行されている場合、設定の上書きはサポートされていません。 Addon Managerは、ConfigMapをサポートしていません。

Kernel Monitor

Kernel MonitorNode Problem Detectorでサポートされるシステムログ監視デーモンです。 Kernel Monitorはカーネルログを監視し、事前に定義されたルールに従って既知のカーネル問題を検出します。 Kernel Monitorconfig/kernel-monitor.jsonにある一連の定義済みルールリストに従ってカーネルの問題を照合します。 ルールリストは拡張可能です。設定を上書きすることで、ルールリストを拡張することができます。

新しいNodeConditionsの追加

新しいNodeConditionをサポートするには、例えばconfig/kernel-monitor.jsonconditionsフィールド内に条件定義を作成します。

{
  "type": "NodeConditionType",
  "reason": "CamelCaseDefaultNodeConditionReason",
  "message": "arbitrary default node condition message"
}

新たな問題の発見

新しい問題を検出するために、config/kernel-monitor.jsonrulesフィールドを新しいルール定義で拡張することができます。

{
  "type": "temporary/permanent",
  "condition": "NodeConditionOfPermanentIssue",
  "reason": "CamelCaseShortReason",
  "message": "regexp matching the issue in the kernel log"
}

カーネルログデバイスのパスの設定

ご使用のオペレーティングシステム(OS)ディストリビューションのカーネルログパスをご確認ください。 Linuxカーネルのログデバイスは通常/dev/kmsgとして表示されます。 しかし、OSのディストリビューションによって、ログパスの位置は異なります。 config/kernel-monitor.jsonlogフィールドは、コンテナ内のログパスを表します。 logフィールドは、Node Problem Detectorで見たデバイスパスと一致するように設定することができます。

別のログ形式をサポートします

Kernel monitorはTranslatorプラグインを使用して、カーネルログの内部データ構造を変換します。 新しいログフォーマット用に新しいトランスレータを実装することができます。

推奨・制限事項

ノードの健全性を監視するために、クラスターでNode Problem Detectorを実行することが推奨されます。 Node Problem Detectorを実行する場合、各ノードで余分なリソースのオーバーヘッドが発生することが予想されます。

通常これは問題ありません。

  • カーネルログは比較的ゆっくりと成長します。
  • Node Problem Detector にはリソース制限が設定されています。
  • 高負荷時であっても、リソースの使用は許容範囲内です。

詳細はNode Problem Detectorベンチマーク結果を参照してください。

4 - crictlによるKubernetesノードのデバッグ

FEATURE STATE: Kubernetes v1.11 [stable]

crictlはCRI互換のコンテナランタイム用のコマンドラインインターフェースです。

これを使って、Kubernetesノード上のコンテナランタイムやアプリケーションの検査やデバッグを行うことができます。 crictlとそのソースコードはcri-toolsリポジトリにホストされています。

始める前に

crictlにはCRIランタイムを搭載したLinuxが必要です。

crictlのインストール

cri-toolsのリリースページから、いくつかの異なるアーキテクチャ用の圧縮アーカイブcrictlをダウンロードできます。

お使いのKubernetesのバージョンに対応するバージョンをダウンロードしてください。 それを解凍してシステムパス上の/usr/local/bin/などの場所に移動します。

一般的な使い方

crictlコマンドにはいくつかのサブコマンドとランタイムフラグがあります。 詳細はcrictl helpまたはcrictl <subcommand> helpを参照してください。 crictlはデフォルトではunix:///var/run/dockershim.sockに接続します。

他のランタイムの場合は、複数の異なる方法でエンドポイントを設定することができます:

  • フラグ--runtime-endpoint--image-endpointの設定により
  • 環境変数CONTAINER_RUNTIME_ENDPOINTIMAGE_SERVICE_ENDPOINTの設定により
  • 設定ファイル--config=/etc/crictl.yamlでエンドポイントの設定により

また、サーバーに接続する際のタイムアウト値を指定したり、デバッグを有効/無効にしたりすることもできます。 これには、設定ファイルでtimeoutdebugを指定するか、--timeout--debugのコマンドラインフラグを使用します。

現在の設定を表示または編集するには、/etc/crictl.yamlの内容を表示または編集します。

cat /etc/crictl.yaml
runtime-endpoint: unix:///var/run/dockershim.sock
image-endpoint: unix:///var/run/dockershim.sock
timeout: 10
debug: true

crictlコマンドの例

以下の例では、いくつかのcrictlコマンドとその出力例を示しています。

podsの一覧

すべてのポッドをリストアップ:

crictl pods

出力はこのようになります:

POD ID              CREATED              STATE               NAME                         NAMESPACE           ATTEMPT
926f1b5a1d33a       About a minute ago   Ready               sh-84d7dcf559-4r2gq          default             0
4dccb216c4adb       About a minute ago   Ready               nginx-65899c769f-wv2gp       default             0
a86316e96fa89       17 hours ago         Ready               kube-proxy-gblk4             kube-system         0
919630b8f81f1       17 hours ago         Ready               nvidia-device-plugin-zgbbv   kube-system         0

Podを名前でリストアップします:

crictl pods --name nginx-65899c769f-wv2gp

出力はこのようになります:

POD ID              CREATED             STATE               NAME                     NAMESPACE           ATTEMPT
4dccb216c4adb       2 minutes ago       Ready               nginx-65899c769f-wv2gp   default             0

Podをラベルでリストアップします:

crictl pods --label run=nginx

出力はこのようになります:

POD ID              CREATED             STATE               NAME                     NAMESPACE           ATTEMPT
4dccb216c4adb       2 minutes ago       Ready               nginx-65899c769f-wv2gp   default             0

イメージの一覧

すべてのイメージをリストアップします:

crictl images

出力はこのようになります:

IMAGE                                     TAG                 IMAGE ID            SIZE
busybox                                   latest              8c811b4aec35f       1.15MB
k8s-gcrio.azureedge.net/hyperkube-amd64   v1.10.3             e179bbfe5d238       665MB
k8s-gcrio.azureedge.net/pause-amd64       3.1                 da86e6ba6ca19       742kB
nginx                                     latest              cd5239a0906a6       109MB

イメージをリポジトリでリストアップします:

crictl images nginx

出力はこのようになります:

IMAGE               TAG                 IMAGE ID            SIZE
nginx               latest              cd5239a0906a6       109MB

イメージのIDのみをリストアップします:

crictl images -q

出力はこのようになります:

sha256:8c811b4aec35f259572d0f79207bc0678df4c736eeec50bc9fec37ed936a472a
sha256:e179bbfe5d238de6069f3b03fccbecc3fb4f2019af741bfff1233c4d7b2970c5
sha256:da86e6ba6ca197bf6bc5e9d900febd906b133eaa4750e6bed647b0fbe50ed43e
sha256:cd5239a0906a6ccf0562354852fae04bc5b52d72a2aff9a871ddb6bd57553569

List containers

すべてのコンテナをリストアップします:

crictl ps -a

出力はこのようになります:

CONTAINER ID        IMAGE                                                                                                             CREATED             STATE               NAME                       ATTEMPT
1f73f2d81bf98       busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47                                   7 minutes ago       Running             sh                         1
9c5951df22c78       busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47                                   8 minutes ago       Exited              sh                         0
87d3992f84f74       nginx@sha256:d0a8828cccb73397acb0073bf34f4d7d8aa315263f1e7806bf8c55d8ac139d5f                                     8 minutes ago       Running             nginx                      0
1941fb4da154f       k8s-gcrio.azureedge.net/hyperkube-amd64@sha256:00d814b1f7763f4ab5be80c58e98140dfc69df107f253d7fdd714b30a714260a   18 hours ago        Running             kube-proxy                 0

ランニングコンテナをリストアップします:

crictl ps

出力はこのようになります:

CONTAINER ID        IMAGE                                                                                                             CREATED             STATE               NAME                       ATTEMPT
1f73f2d81bf98       busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47                                   6 minutes ago       Running             sh                         1
87d3992f84f74       nginx@sha256:d0a8828cccb73397acb0073bf34f4d7d8aa315263f1e7806bf8c55d8ac139d5f                                     7 minutes ago       Running             nginx                      0
1941fb4da154f       k8s-gcrio.azureedge.net/hyperkube-amd64@sha256:00d814b1f7763f4ab5be80c58e98140dfc69df107f253d7fdd714b30a714260a   17 hours ago        Running             kube-proxy                 0

実行中のコンテナでコマンドの実行

crictl exec -i -t 1f73f2d81bf98 ls

出力はこのようになります:

bin   dev   etc   home  proc  root  sys   tmp   usr   var

コンテナログの取得

すべてのコンテナログを取得します:

crictl logs 87d3992f84f74

出力はこのようになります:

10.240.0.96 - - [06/Jun/2018:02:45:49 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.96 - - [06/Jun/2018:02:45:50 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.96 - - [06/Jun/2018:02:45:51 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"

最新のN行のログのみを取得します:

crictl logs --tail=1 87d3992f84f74

出力はこのようになります:

10.240.0.96 - - [06/Jun/2018:02:45:51 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"

Podサンドボックスの実行

crictlを使ってPodサンドボックスを実行することは、コンテナのランタイムをデバッグするのに便利です。 稼働中のKubernetesクラスターでは、サンドボックスは最終的にKubeletによって停止され、削除されます。

  1. 以下のようなJSONファイルを作成します:

    {
        "metadata": {
            "name": "nginx-sandbox",
            "namespace": "default",
            "attempt": 1,
            "uid": "hdishd83djaidwnduwk28bcsb"
        },
        "logDirectory": "/tmp",
        "linux": {
        }
    }
    
  2. JSONを適用してサンドボックスを実行するには、crictl runpコマンドを使用します:

    crictl runp pod-config.json
    

    サンドボックスのIDが返されます。

コンテナの作成

コンテナの作成にcrictlを使うと、コンテナのランタイムをデバッグするのに便利です。 稼働中のKubernetesクラスターでは、サンドボックスは最終的にKubeletによって停止され、削除されます。

  1. busyboxイメージをプルします:

    crictl pull busybox
    Image is up to date for busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
    
  2. Podとコンテナのコンフィグを作成します:

    Pod config:

    {
        "metadata": {
            "name": "nginx-sandbox",
            "namespace": "default",
            "attempt": 1,
            "uid": "hdishd83djaidwnduwk28bcsb"
        },
        "log_directory": "/tmp",
        "linux": {
        }
    }
    

    Container config:

    {
      "metadata": {
          "name": "busybox"
      },
      "image":{
          "image": "busybox"
      },
      "command": [
          "top"
      ],
      "log_path":"busybox.log",
      "linux": {
      }
    }
    
  3. 先に作成されたPodのID、コンテナの設定ファイル、Podの設定ファイルを渡して、コンテナを作成します。コンテナのIDが返されます。

    crictl create f84dd361f8dc51518ed291fbadd6db537b0496536c1d2d6c05ff943ce8c9a54f container-config.json pod-config.json
    
  4. すべてのコンテナをリストアップし、新しく作成されたコンテナの状態がCreatedに設定されていることを確認します:

    crictl ps -a
    

    出力はこのようになります:

    CONTAINER ID        IMAGE               CREATED             STATE               NAME                ATTEMPT
    3e025dd50a72d       busybox             32 seconds ago      Created             busybox             0
    

コンテナの起動

コンテナを起動するには、そのコンテナのIDをcrictl startに渡します:

crictl start 3e025dd50a72d956c4f14881fbb5b1080c9275674e95fb67f965f6478a957d60

出力はこのようになります:

3e025dd50a72d956c4f14881fbb5b1080c9275674e95fb67f965f6478a957d60

コンテナの状態が「Running」に設定されていることを確認します:

crictl ps

出力はこのようになります:

CONTAINER ID        IMAGE               CREATED              STATE               NAME                ATTEMPT
3e025dd50a72d       busybox             About a minute ago   Running             busybox             0

詳しくはkubernetes-sigs/cri-toolsをご覧ください。

docker cliからcrictlへのマッピング

以下のマッピング表の正確なバージョンは、docker cli v1.40crictl v1.19.0のものです。 この一覧はすべてを網羅しているわけではないことに注意してください。 たとえば、docker cliの実験的なコマンドは含まれていません。

デバッグ情報の取得

mapping from docker cli to crictl - retrieve debugging information
docker clicrictl説明サポートされていない機能
attachattach実行中のコンテナにアタッチ--detach-keys, --sig-proxy
execexec実行中のコンテナでコマンドの実行--privileged, --user, --detach-keys
imagesimagesイメージのリストアップ 
infoinfoシステム全体の情報の表示 
inspectinspect, inspectiコンテナ、イメージ、タスクの低レベルの情報を返します 
logslogsコンテナのログを取得します--details
pspsコンテナのリストアップ 
statsstatsコンテナのリソース使用状況をライブで表示Column: NET/BLOCK I/O, PIDs
versionversionランタイム(Docker、ContainerD、その他)のバージョン情報を表示します 

変更を行います

mapping from docker cli to crictl - perform changes
docker clicrictl説明サポートされていない機能
createcreate新しいコンテナを作成します 
killstop (timeout = 0)1つ以上の実行中のコンテナを停止します--signal
pullpullレジストリーからイメージやリポジトリをプルします--all-tags, --disable-content-trust
rmrm1つまたは複数のコンテナを削除します 
rmirmi1つまたは複数のイメージを削除します 
runrun新しいコンテナでコマンドを実行 
startstart停止した1つまたは複数のコンテナを起動--detach-keys
stopstop実行中の1つまたは複数のコンテナの停止 
updateupdate1つまたは複数のコンテナの構成を更新--restart--blkio-weightとその他

crictlでのみ対応

mapping from docker cli to crictl - supported only in crictl
crictl説明
imagefsinfoイメージファイルシステムの情報を返します
inspectp1つまたは複数のPodの状態を表示します
port-forwardローカルポートをPodに転送します
runp新しいPodを実行します
rmp1つまたは複数のPodを削除します
stopp稼働中の1つまたは複数のPodを停止します

5 - Kubectlを用いたKubernetesノードのデバッグ

このページでは、Kubernetesクラスター上で動作しているノードkubectl debugコマンドを使用してデバッグする方法について説明します。

始める前に

Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:

作業するKubernetesサーバーは次のバージョン以降のものである必要があります: 1.2. バージョンを確認するには次のコマンドを実行してください: kubectl version.

Podを作成し、それらの新しいPodを任意のノードに割り当てる権限が必要です。 また、ホストのファイルシステムにアクセスするPodを作成する権限も必要です。

kubectl debug nodeを用いてノードをデバッグする

kubectl debug nodeコマンドを使用して、トラブルシューティングしたいノードにPodをデプロイします。 このコマンドは、SSH接続を使用してノードにアクセスできないシナリオで役に立ちます。 Podが作成されると、そのPodはノード上で対話型シェルを開きます。 mynodeという名前のノード上で対話型シェルを作成するには、次のように実行します。

kubectl debug node/mynode -it --image=ubuntu
ノードmynode上に、コンテナデバッガーを持つデバッグ用Pod、node-debugger-mynode-pdx84を作成します。
コマンドプロンプトが表示されない場合は、エンターキーを押してみてください。
root@mynode:/#

デバッグコマンドは、情報を収集し、問題をトラブルシューティングするのに役立ちます。 使用する可能性のあるコマンドには、ipifconfigncpingpsなどがあります。 また、mtrtcpdumpcurlなどの他のツールもそれぞれのパッケージマネージャーからインストールすることができます。

デバッグ用のPodは、Pod内の/hostにマウントされたノードのルートファイルシステムにアクセスできます。 kubeletをファイルシステムのネームスペースで実行している場合、デバッグ用のPodはそのネームスペースのルートを見ることになり、ノード全体のルートではありません。 典型的なLinuxノードの場合、関連するログを見つけるために以下のパスを確認できます。

/host/var/log/kubelet.log
ノード上でコンテナを実行する責任があるkubeletからのログです。
/host/var/log/kube-proxy.log
サービスのエンドポイントへのトラフィックを指示する責任があるkube-proxyからのログです。
/host/var/log/containerd.log
ノード上で実行されているcontainerdプロセスからのログです。
/host/var/log/syslog
システムに関する一般的なメッセージや情報です。
/host/var/log/kern.log
カーネルログです。

ノード上でデバッグセッションを作成する際には、以下の点を考慮してください。

  • kubectl debugは、新しいPodの名前をノードの名前に基づいて自動的に生成します。
  • ノードのルートファイルシステムは/hostにマウントされます。
  • コンテナはホストのIPC、ネットワーク、PID Namespaceで実行されますが、Podは特権を持っていません。 これは、一部のプロセス情報の読み取りが失敗する可能性があることを意味します。 その情報へのアクセスはスーパーユーザーに制限されているためです。 例えば、chroot /hostは失敗します。 特権Podが必要な場合は、手動で作成してください。

クリーンアップ

デバッグ用のPodの使用が終了したら、それを削除してください。

kubectl get pods
NAME                          READY   STATUS       RESTARTS   AGE
node-debugger-mynode-pdx84    0/1     Completed    0          8m1s
# Podの名前は適宜変更してください
kubectl delete pod node-debugger-mynode-pdx84 --now
pod "node-debugger-mynode-pdx84" deleted

6 - WindowsデバッグTips

ノードレベルのトラブルシューティング

  1. Podが"Container Creating"と表示されたまま動かなくなったり、何度も再起動を繰り返します

    pauseイメージがWindows OSのバージョンと互換性があることを確認してください。 最新/推奨のpauseイメージや詳細情報については、Pauseコンテナを参照してください。

  2. PodがErrImgPullまたはImagePullBackOffのステータスを表示します

    Podが互換性のあるWindowsノードにスケジュールされていることを確認してください。

    Podに対して互換性のあるノードを指定する方法の詳細については、このガイドを参照してください。

ネットワークのトラブルシューティング

  1. Windows Podがネットワークに接続できません

    仮想マシンを使用している場合は、すべてのVMのネットワークアダプターでMACスプーフィングが有効になっていることを確認してください。

  2. Windows Podから外部リソースにpingできません

    Windows Podには、ICMPプロトコル用にプログラムされたアウトバウンドルールはありません。ただし、TCP/UDPはサポートされています。 クラスター外のリソースへの接続を実証する場合は、ping <IP>を対応するcurl <IP>コマンドに置き換えてください。

    それでも問題が解決しない場合は、cni.confのネットワーク設定に問題がある可能性が高いです。 この静的ファイルはいつでも編集できます。 設定の更新は、新しく作成されたすべてのKubernetesリソースに適用されます。

    Kubernetesのネットワーク要件の1つ(Kubernetesモデルを参照)は、内部でNATせずにクラスター通信が行われることです。 この要件を満たすために、アウトバウンドのNATを発生させたくないすべての通信のためのExceptionListがあります。 ただしこれは、クエリしようとしている外部IPをExceptionListから除外する必要があることも意味します。 そうして初めて、Windows Podからのトラフィックが正しくSNATされ、外部からの応答を受信できるようになります。 この点について、cni.confExceptionListは次のようになります:

    "ExceptionList": [
                    "10.244.0.0/16",  # クラスターのサブネット
                    "10.96.0.0/12",   # Serviceのサブネット
                    "10.127.130.0/24" # 管理(ホスト)のサブネット
                ]
    
  3. WindowsノードがNodePortタイプのServiceにアクセスできません

    ノード自身からのローカルNodePortへのアクセスは失敗します。 これは既知の制限です。 NodePortへのアクセスは、他のノードや外部のクライアントからは動作します。

  4. コンテナのvNICとHNSエンドポイントが削除されています

    この問題はhostname-overrideパラメーターがkube-proxy に渡されていない場合に発生する可能性があります。 これを解決するためには、ユーザーは次のようにkube-proxyにホスト名を渡す必要があります:

    C:\k\kube-proxy.exe --hostname-override=$(hostname)
    
  5. WindowsノードがService IPを使用してサービスにアクセスできません

    これはWindows上のネットワークスタックの既知の制限です。 ただし、Windows PodはService IPにアクセスできます。

  6. kubeletの起動時にネットワークアダプターが見つかりません

    Windowsのネットワーキングスタックでは、Kubernetesネットワーキングが動作するために仮想アダプターが必要です。 (管理者シェルで)次のコマンドを実行しても結果が返されない場合、kubeletが動作するために必要な前提条件である仮想ネットワークの作成に失敗しています。

    Get-HnsNetwork | ? Name -ieq "cbr0"
    Get-NetAdapter | ? Name -Like "vEthernet (Ethernet*"
    

    ホストのネットワークアダプターが"Ethernet"ではない場合、start.ps1スクリプトのInterfaceNameパラメーターを修正することが有益です。 それ以外の場合は、start-kubelet.ps1スクリプトの出力結果を参照して、仮想ネットワークの作成中にエラーが発生していないか確認します。

  7. DNS名前解決が正しく動作しません

    このセクションのWindowsにおけるDNSの制限について確認してください。

  8. kubectl port-forwardが"unable to do port forwarding: wincat not found"で失敗します

    これは、pauseインフラコンテナmcr.microsoft.com/oss/kubernetes/pause:3.6wincat.exeを含める形で、Kubernetes 1.15にて実装されました。 必ずサポートされたKubernetesのバージョンを使用してください。 独自のpauseインフラコンテナをビルドしたい場合は、必ずwincatを含めるようにしてください。

  9. Windows Serverノードがプロキシの背後にあるため、Kubernetesのインストールに失敗しています

    プロキシの背後にある場合は、次のPowerShell環境変数が定義されている必要があります:

    [Environment]::SetEnvironmentVariable("HTTP_PROXY", "http://proxy.example.com:80/", [EnvironmentVariableTarget]::Machine)
    [Environment]::SetEnvironmentVariable("HTTPS_PROXY", "http://proxy.example.com:443/", [EnvironmentVariableTarget]::Machine)
    

Flannelのトラブルシューティング

  1. Flannelを使用すると、クラスターに再参加した後にノードに問題が発生します

    以前に削除したノードがクラスターに再参加すると、flanneldはノードに新しいPodサブネットを割り当てようとします。 ユーザーは、次のパスにある古いPodサブネットの設定ファイルを削除する必要があります:

    Remove-Item C:\k\SourceVip.json
    Remove-Item C:\k\SourceVipRequest.json
    
  2. Flanneldが"Waiting for the Network to be created"と表示されたままになります

    このIssueに関する多数の報告があります; 最も可能性が高いのは、flannelネットワークの管理IPが設定されるタイミングの問題です。 回避策は、start.ps1を再度実行するか、次のように手動で再起動することです:

    [Environment]::SetEnvironmentVariable("NODE_NAME", "<Windows_Worker_Hostname>")
    C:\flannel\flanneld.exe --kubeconfig-file=c:\k\config --iface=<Windows_Worker_Node_IP> --ip-masq=1 --kube-subnet-mgr=1
    
  3. /run/flannel/subnet.envが見つからないためにWindows Podが起動しません

    これはFlannelが正常に起動できなかったことを示しています。 flanneld.exeを再起動するか、Kubernetesマスター上の/run/flannel/subnet.envをWindowsワーカーノード上のC:\run\flannel\subnet.envに手動でコピーして、FLANNEL_SUBNET行を異なる数値に変更します。 例えば、ノードのサブネットを10.244.4.1/24としたい場合は次のようにします:

    FLANNEL_NETWORK=10.244.0.0/16
    FLANNEL_SUBNET=10.244.4.1/24
    FLANNEL_MTU=1500
    FLANNEL_IPMASQ=true
    

さらなる調査

これらの手順で問題が解決しない場合は、下記からKubernetesのWindowsノード上でWindowsコンテナを実行するためのヘルプを得ることができます:

7 - テレプレゼンスを使用したローカルでのサービス開発・デバッグ

Kubernetesアプリケーションは通常、複数の独立したサービスから構成され、それぞれが独自のコンテナで動作しています。これらのサービスをリモートのKubernetesクラスター上で開発・デバッグするには、実行中のコンテナへのシェルを取得してリモートシェル内でツールを実行しなければならず面倒な場合があります。

telepresenceは、リモートKubernetesクラスターにサービスをプロキシしながら、ローカルでサービスを開発・デバッグするプロセスを容易にするためのツールです。 telepresence を使用すると、デバッガーやIDEなどのカスタムツールをローカルサービスで使用でき、ConfigMapやsecret、リモートクラスター上で動作しているサービスへのフルアクセスをサービスに提供します。

このドキュメントでは、リモートクラスター上で動作しているサービスをローカルで開発・デバッグするためにtelepresenceを使用する方法を説明します。

始める前に

  • Kubernetesクラスターがインストールされていること
  • クラスターと通信するために kubectl が設定されていること
  • telepresenceがインストールされていること

リモートクラスター上でシェルの取得

ターミナルを開いて、引数なしでtelepresenceを実行すると、telepresenceシェルが表示されます。 このシェルはローカルで動作し、ローカルのファイルシステムに完全にアクセスすることができます。

このtelepresenceシェルは様々な方法で使用することができます。 例えば、ラップトップでシェルスクリプトを書いて、それをシェルから直接リアルタイムで実行することができます。これはリモートシェルでもできますが、好みのコードエディターが使えないかもしれませんし、コンテナが終了するとスクリプトは削除されます。

終了してシェルを閉じるにはexitと入力してください。

既存サービスの開発・デバッグ

Kubernetes上でアプリケーションを開発する場合、通常は1つのサービスをプログラミングまたはデバッグすることになります。 そのサービスは、テストやデバッグのために他のサービスへのアクセスを必要とする場合があります。 継続的なデプロイメントパイプラインを使用することも一つの選択肢ですが、最速のデプロイメントパイプラインでさえ、プログラムやデバッグサイクルに遅延が発生します。

既存のデプロイメントとtelepresenceプロキシを交換するには、--swap-deployment オプションを使用します。 スワップすることで、ローカルでサービスを実行し、リモートのKubernetesクラスターに接続することができます。 リモートクラスター内のサービスは、ローカルで実行されているインスタンスにアクセスできるようになりました。

telepresenceを「--swap-deployment」で実行するには、次のように入力します。

telepresence --swap-deployment $DEPLOYMENT_NAME

ここで、$DEPLOYMENT_NAMEは既存のDeploymentの名前です。

このコマンドを実行すると、シェルが起動します。そのシェルで、サービスを起動します。 そして、ローカルでソースコードの編集を行い、保存すると、すぐに変更が反映されるのを確認できます。 また、デバッガーやその他のローカルな開発ツールでサービスを実行することもできます。

次の項目

もしハンズオンのチュートリアルに興味があるなら、Google Kubernetes Engine上でGuestbookアプリケーションをローカルに開発する手順を説明したこちらのチュートリアルをチェックしてみてください。

telepresenceには、状況に応じてnumerous proxying optionsがあります。

さらに詳しい情報は、telepresence websiteをご覧ください。

8 - 監査

Kubernetesの監査はクラスター内の一連の行動を記録するセキュリティに関連した時系列の記録を提供します。 クラスターはユーザー、Kubernetes APIを使用するアプリケーション、 およびコントロールプレーン自体によって生成されたアクティビティなどを監査します。

監査により、クラスター管理者は以下の質問に答えることができます:

  • 何が起きたのか?
  • いつ起こったのか?
  • 誰がそれを始めたのか?
  • 何のために起こったのか?
  • それはどこで観察されたのか?
  • それはどこから始まったのか?
  • それはどこへ向かっていたのか?

監査記録のライフサイクルはkube-apiserverコンポーネントの中で始まります。 各リクエストの実行の各段階で、監査イベントが生成されます。 ポリシーに従って前処理され、バックエンドに書き込まれます。 ポリシーが何を記録するかを決定し、 バックエンドがその記録を永続化します。現在のバックエンドの実装はログファイルやWebhookなどがあります。

各リクエストは関連する stage で記録されます。 定義されたステージは以下の通りです:

  • RequestReceived - 監査ハンドラーがリクエストを受信すると同時に生成されるイベントのステージ。 つまり、ハンドラーチェーンに委譲される前に生成されるイベントのステージです。
  • ResponseStarted - レスポンスヘッダーが送信された後、レスポンスボディが送信される前のステージです。 このステージは長時間実行されるリクエスト(watchなど)でのみ発生します。
  • ResponseComplete - レスポンスボディの送信が完了して、それ以上のバイトは送信されません。
  • Panic - パニックが起きたときに発生するイベント。

監査ログ機能は、リクエストごとに監査に必要なコンテキストが保存されるため、APIサーバーのメモリー消費量が増加します。 メモリーの消費量は、監査ログ機能の設定によって異なります。

監査ポリシー

監査ポリシーはどのようなイベントを記録し、どのようなデータを含むべきかについてのルールを定義します。 監査ポリシーのオブジェクト構造は、audit.k8s.io API groupで定義されています。

イベントが処理されると、そのイベントは順番にルールのリストと比較されます。 最初のマッチングルールは、イベントの監査レベルを設定します。

定義されている監査レベルは:

  • None - ルールに一致するイベントを記録しません。
  • Metadata - リクエストのメタデータ(リクエストしたユーザー、タイムスタンプ、リソース、動作など)を記録しますが、リクエストやレスポンスのボディは記録しません。
  • Request - ログイベントのメタデータとリクエストボディは表示されますが、レスポンスボディは表示されません。 これは非リソースリクエストには適用されません。
  • RequestResponse - イベントのメタデータ、リクエストとレスポンスのボディを記録しますが、 非リソースリクエストには適用されません。

audit-policy-fileフラグを使って、ポリシーを記述したファイルを kube-apiserverに渡すことができます。 このフラグが省略された場合イベントは記録されません。 監査ポリシーファイルでは、rulesフィールドが必ず指定されることに注意してください。 ルールがない(0)ポリシーは不当なものとして扱われます。

以下は監査ポリシーファイルの例です:

apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "RequestReceived"
rules:
  # Log pod changes at RequestResponse level
  - level: RequestResponse
    resources:
    - group: ""
      # Resource "pods" doesn't match requests to any subresource of pods,
      # which is consistent with the RBAC policy.
      resources: ["pods"]
  # Log "pods/log", "pods/status" at Metadata level
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods/log", "pods/status"]

  # Don't log requests to a configmap called "controller-leader"
  - level: None
    resources:
    - group: ""
      resources: ["configmaps"]
      resourceNames: ["controller-leader"]

  # Don't log watch requests by the "system:kube-proxy" on endpoints or services
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
    - group: "" # core API group
      resources: ["endpoints", "services"]

  # Don't log authenticated requests to certain non-resource URL paths.
  - level: None
    userGroups: ["system:authenticated"]
    nonResourceURLs:
    - "/api*" # Wildcard matching.
    - "/version"

  # Log the request body of configmap changes in kube-system.
  - level: Request
    resources:
    - group: "" # core API group
      resources: ["configmaps"]
    # This rule only applies to resources in the "kube-system" namespace.
    # The empty string "" can be used to select non-namespaced resources.
    namespaces: ["kube-system"]

  # Log configmap and secret changes in all other namespaces at the Metadata level.
  - level: Metadata
    resources:
    - group: "" # core API group
      resources: ["secrets", "configmaps"]

  # Log all other resources in core and extensions at the Request level.
  - level: Request
    resources:
    - group: "" # core API group
    - group: "extensions" # Version of group should NOT be included.

  # A catch-all rule to log all other requests at the Metadata level.
  - level: Metadata
    # Long-running requests like watches that fall under this rule will not
    # generate an audit event in RequestReceived.
    omitStages:
      - "RequestReceived"

最小限の監査ポリシーファイルを使用して、すべてのリクエストを Metadataレベルで記録することができます。

# Log all requests at the Metadata level.
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata

独自の監査プロファイルを作成する場合は、Google Container-Optimized OSの監査プロファイルを出発点として使用できます。 監査ポリシーファイルを生成するconfigure-helper.shスクリプトを確認することができます。 スクリプトを直接見ることで、監査ポリシーファイルのほとんどを見ることができます。

また、定義されているフィールドの詳細については、Policy` configuration referenceを参照できます。

監査バックエンド

監査バックエンドは監査イベントを外部ストレージに永続化します。 kube-apiserverには2つのバックエンドが用意されています。

  • イベントをファイルシステムに書き込むログバックエンド
  • 外部のHTTP APIにイベントを送信するWebhookバックエンド

いずれの場合も、監査イベントはKubernetes APIaudit.k8s.io API groupで定義されている構造に従います。

ログバックエンド

ログバックエンドは監査イベントをJSONlines形式のファイルに書き込みます。 以下の kube-apiserver フラグを使ってログ監査バックエンドを設定できます。

  • --audit-log-path は、ログバックエンドが監査イベントを書き込む際に使用するログファイルのパスを指定します。 このフラグを指定しないと、ログバックエンドは無効になります。- は標準出力を意味します。
  • --audit-log-maxage は、古い監査ログファイルを保持する最大日数を定義します。
  • audit-log-maxbackupは、保持する監査ログファイルの最大数を定義します。
  • --audit-log-maxsize は、監査ログファイルがローテーションされるまでの最大サイズをメガバイト単位で定義します。

クラスターのコントロールプレーンでkube-apiserverをPodとして動作させている場合は、監査記録が永久化されるように、ポリシーファイルとログファイルの場所にhostPathをマウントすることを忘れないでください。 例えば:

  - --audit-policy-file=/etc/kubernetes/audit-policy.yaml
  - --audit-log-path=/var/log/kubernetes/audit/audit.log

それからボリュームをマウントします:

...
volumeMounts:
  - mountPath: /etc/kubernetes/audit-policy.yaml
    name: audit
    readOnly: true
  - mountPath: /var/log/audit.log
    name: audit-log
    readOnly: false

最後にhostPathを設定します:

...
volumes:
- name: audit
  hostPath:
    path: /etc/kubernetes/audit-policy.yaml
    type: File

- name: audit-log
  hostPath:
    path: /var/log/audit.log
    type: FileOrCreate

Webhookバックエンド

Webhook監査バックエンドは、監査イベントをリモートのWeb APIに送信しますが、 これは認証手段を含むKubernetes APIの形式であると想定されます。

Webhook監査バックエンドを設定するには、以下のkube-apiserverフラグを使用します。

  • --audit-webhook-config-file は、Webhookの設定ファイルのパスを指定します。 webhookの設定は、事実上特化したkubeconfigです。
  • --audit-webhook-initial-backoff は、最初に失敗したリクエストの後、再試行するまでに待つ時間を指定します。 それ以降のリクエストは、指数関数的なバックオフで再試行されます。

Webhookの設定ファイルは、kubeconfig形式でサービスのリモートアドレスと接続に使用する認証情報を指定します。

イベントバッチ

ログバックエンドとwebhookバックエンドの両方がバッチ処理をサポートしています。 webhookを例に、利用可能なフラグの一覧を示します。 ログバックエンドで同じフラグを取得するには、フラグ名のwebhooklogに置き換えてください。 デフォルトでは、バッチングはwebhookでは有効で、logでは無効です。 同様に、デフォルトではスロットリングは webhook で有効で、logでは無効です。

  • --audit-webhook-mode は、バッファリング戦略を定義します。以下のいずれかとなります。
    • batch - イベントをバッファリングして、非同期にバッチ処理します。これがデフォルトです。
    • blocking - 個々のイベントを処理する際に、APIサーバーの応答をブロックします。
    • blocking-strict - blockingと同じですが、RequestReceivedステージでの監査ログに失敗した場合は RequestReceivedステージで監査ログに失敗すると、kube-apiserverへのリクエスト全体が失敗します。

以下のフラグは batch モードでのみ使用されます:

  • --audit-webhook-batch-buffer-sizeは、バッチ処理を行う前にバッファリングするイベントの数を定義します。 入力イベントの割合がバッファをオーバーフローすると、イベントはドロップされます。
  • --audit-webhook-batch-max-sizeは、1つのバッチに入れるイベントの最大数を定義します。
  • --audit-webhook-batch-max-waitは、キュー内のイベントを無条件にバッチ処理するまでの最大待機時間を定義します。
  • --audit-webhook-batch-throttle-qpsは、1秒あたりに生成されるバッチの最大平均数を定義します。
  • --audit-webhook-batch-throttle-burstは、許可された QPS が低い場合に、同じ瞬間に生成されるバッチの最大数を定義します。

パラメーターチューニング

パラメーターは、APIサーバーの負荷に合わせて設定してください。

例えば、kube-apiserverが毎秒100件のリクエストを受け取り、それぞれのリクエストがResponseStartedResponseCompleteの段階でのみ監査されるとします。毎秒≅200の監査イベントが発生すると考えてください。 1つのバッチに最大100個のイベントがあるの場合、スロットリングレベルを少なくとも2クエリ/秒に設定する必要があります。 バックエンドがイベントを書き込むのに最大で5秒かかる場合、5秒分のイベントを保持するようにバッファーサイズを設定する必要があります。

10バッチ、または1000イベントとなります。

しかし、ほとんどの場合デフォルトのパラメーターで十分であり、手動で設定する必要はありません。 kube-apiserverが公開している以下のPrometheusメトリクスや、ログを見て監査サブシステムの状態を監視することができます。

  • apiserver_audit_event_totalメトリックには、エクスポートされた監査イベントの合計数が含まれます。
  • apiserver_audit_error_totalメトリックには、エクスポート中にエラーが発生してドロップされたイベントの総数が含まれます。

ログエントリー・トランケーション

logバックエンドとwebhookバックエンドは、ログに記録されるイベントのサイズを制限することをサポートしています。

例として、logバックエンドで利用可能なフラグの一覧を以下に示します

  • audit-log-truncate-enabledイベントとバッチの切り捨てを有効にするかどうかです。
  • audit-log-truncate-max-batch-sizeバックエンドに送信されるバッチのバイト単位の最大サイズ。
  • audit-log-truncate-max-event-sizeバックエンドに送信される監査イベントのバイト単位の最大サイズです。

デフォルトでは、webhooklogの両方で切り捨ては無効になっていますが、クラスター管理者は audit-log-truncate-enabledまたはaudit-webhook-truncate-enabledを設定して、この機能を有効にする必要があります。

次の項目