クラスターのトラブルシューティング
一般的なクラスターの問題をデバッグします。
このドキュメントはクラスターのトラブルシューティングに関するもので、あなたが経験している問題の根本原因として、アプリケーションをすでに除外していることを前提としています。
アプリケーションのデバッグのコツは、アプリケーションのトラブルシューティングガイドをご覧ください。
また、トラブルシューティングドキュメントにも詳しい情報があります。
kubectlのトラブルシューティングについては、kubectlのトラブルシューティングを参照してください。
クラスターのリストアップ
クラスターで最初にデバッグするのは、ノードがすべて正しく登録されているかどうかです。
以下を実行します。
そして、期待するノードがすべて存在し、それらがすべて Ready
状態であることを確認します。
クラスター全体の健全性に関する詳細な情報を得るには、以下を実行します。
kubectl cluster-info dump
例: ダウンあるいは到達不能なノードのデバッグ
デバッグを行う際、ノードの状態を見ることが有用なことがあります。
たとえば、そのノード上で動作しているPodが奇妙な挙動を示している場合や、なぜPodがそのノードにスケジュールされないのかを知りたい場合などです。
Podと同様に、kubectl describe node
やkubectl get node -o yaml
を使用してノードに関する詳細情報を取得できます。
例えば、ノードがダウンしている(ネットワークから切断されている、またはkubeletが停止して再起動しないなど)場合に見られる状況は以下の通りです。
ノードがNotReadyであることを示すイベントに注意し、また、Podが動作していないことにも注意してください(NotReady状態が5分間続くとPodは追い出されます)。
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または物理マシン)のシャットダウン
- ネットワークパーティション
- その結果
- パーティション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のデータディレクトリーなど)が消失
-
対処法: 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についての詳しい情報はそちらをご覧ください。
備考:
メトリクス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 - リソース監視のためのツール
アプリケーションを拡張し、信頼性の高いサービスを提供するために、デプロイ時にアプリケーションがどのように動作するかを理解する必要があります。
コンテナ、Pod、Service、クラスター全体の特性を調べることにより、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 Detector
はDaemonSet
として、あるいはスタンドアロンデーモンとして実行することができます。
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 Detector
をAddonとして有効にしている場合があります。
また、kubectl
を使ってNode Problem Detector
を有効にするか、Addon pod
を作成することで有効にできます。
kubectlを使用してNode Problem Detectorを有効化します
kubectl
はNode Problem Detector
を最も柔軟に管理することができます。
デフォルトの設定を上書きして自分の環境に合わせたり、カスタマイズしたノードの問題を検出したりすることができます。
例えば:
-
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/
備考:
システムログのディレクトリが、お使いのOSのディストリビューションに合っていることを確認する必要があります。
-
Node Problem Detector
をkubectl
で起動します。
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
を使用することで設定を上書きすることができます。
-
config/
にある設定ファイルを変更します
-
ConfigMap
node-problem-detector-config
を作成します。
kubectl create configmap node-problem-detector-config --from-file=config/
-
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
-
新しい設定ファイルで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
備考:
この方法は kubectl
で起動された Node Problem Detector にのみ適用されます。
ノード問題検出装置がクラスターアドオンとして実行されている場合、設定の上書きはサポートされていません。
Addon Manager
は、ConfigMap
をサポートしていません。
Kernel Monitor
Kernel MonitorはNode Problem Detector
でサポートされるシステムログ監視デーモンです。
Kernel Monitorはカーネルログを監視し、事前に定義されたルールに従って既知のカーネル問題を検出します。
Kernel Monitorはconfig/kernel-monitor.json
にある一連の定義済みルールリストに従ってカーネルの問題を照合します。
ルールリストは拡張可能です。設定を上書きすることで、ルールリストを拡張することができます。
新しいNodeConditionsの追加
新しいNodeCondition
をサポートするには、例えばconfig/kernel-monitor.json
のconditions
フィールド内に条件定義を作成します。
{
"type": "NodeConditionType",
"reason": "CamelCaseDefaultNodeConditionReason",
"message": "arbitrary default node condition message"
}
新たな問題の発見
新しい問題を検出するために、config/kernel-monitor.json
のrules
フィールドを新しいルール定義で拡張することができます。
{
"type": "temporary/permanent",
"condition": "NodeConditionOfPermanentIssue",
"reason": "CamelCaseShortReason",
"message": "regexp matching the issue in the kernel log"
}
カーネルログデバイスのパスの設定
ご使用のオペレーティングシステム(OS)ディストリビューションのカーネルログパスをご確認ください。
Linuxカーネルのログデバイスは通常/dev/kmsg
として表示されます。
しかし、OSのディストリビューションによって、ログパスの位置は異なります。
config/kernel-monitor.json
のlog
フィールドは、コンテナ内のログパスを表します。
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_ENDPOINT
とIMAGE_SERVICE_ENDPOINT
の設定により
- 設定ファイル
--config=/etc/crictl.yaml
でエンドポイントの設定により
また、サーバーに接続する際のタイムアウト値を指定したり、デバッグを有効/無効にしたりすることもできます。
これには、設定ファイルでtimeout
やdebug
を指定するか、--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
コマンドとその出力例を示しています。
警告:
実行中のKubernetesクラスターにcrictl
を使ってポッドのサンドボックスやコンテナを作成しても、Kubeletは最終的にそれらを削除します。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
イメージの一覧
すべてのイメージをリストアップします:
出力はこのようになります:
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
イメージをリポジトリでリストアップします:
出力はこのようになります:
IMAGE TAG IMAGE ID SIZE
nginx latest cd5239a0906a6 109MB
イメージのIDのみをリストアップします:
出力はこのようになります:
sha256:8c811b4aec35f259572d0f79207bc0678df4c736eeec50bc9fec37ed936a472a
sha256:e179bbfe5d238de6069f3b03fccbecc3fb4f2019af741bfff1233c4d7b2970c5
sha256:da86e6ba6ca197bf6bc5e9d900febd906b133eaa4750e6bed647b0fbe50ed43e
sha256:cd5239a0906a6ccf0562354852fae04bc5b52d72a2aff9a871ddb6bd57553569
List containers
すべてのコンテナをリストアップします:
出力はこのようになります:
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によって停止され、削除されます。
-
以下のようなJSONファイルを作成します:
{
"metadata": {
"name": "nginx-sandbox",
"namespace": "default",
"attempt": 1,
"uid": "hdishd83djaidwnduwk28bcsb"
},
"logDirectory": "/tmp",
"linux": {
}
}
-
JSONを適用してサンドボックスを実行するには、crictl runp
コマンドを使用します:
crictl runp pod-config.json
サンドボックスのIDが返されます。
コンテナの作成
コンテナの作成にcrictl
を使うと、コンテナのランタイムをデバッグするのに便利です。
稼働中のKubernetesクラスターでは、サンドボックスは最終的にKubeletによって停止され、削除されます。
-
busyboxイメージをプルします:
crictl pull busybox
Image is up to date for busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
-
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": {
}
}
-
先に作成されたPodのID、コンテナの設定ファイル、Podの設定ファイルを渡して、コンテナを作成します。コンテナのIDが返されます。
crictl create f84dd361f8dc51518ed291fbadd6db537b0496536c1d2d6c05ff943ce8c9a54f container-config.json pod-config.json
-
すべてのコンテナをリストアップし、新しく作成されたコンテナの状態がCreated
に設定されていることを確認します:
出力はこのようになります:
CONTAINER ID IMAGE CREATED STATE NAME ATTEMPT
3e025dd50a72d busybox 32 seconds ago Created busybox 0
コンテナの起動
コンテナを起動するには、そのコンテナのIDをcrictl start
に渡します:
crictl start 3e025dd50a72d956c4f14881fbb5b1080c9275674e95fb67f965f6478a957d60
出力はこのようになります:
3e025dd50a72d956c4f14881fbb5b1080c9275674e95fb67f965f6478a957d60
コンテナの状態が「Running」に設定されていることを確認します:
出力はこのようになります:
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.40
とcrictl v1.19.0
のものです。
この一覧はすべてを網羅しているわけではないことに注意してください。
たとえば、docker cli
の実験的なコマンドは含まれていません。
備考:
CRICTLの出力形式はDocker CLIと似ていますが、いくつかのCLIでは列が欠けています。
デバッグ情報の取得
mapping from docker cli to crictl - retrieve debugging information
docker cli |
crictl |
説明 |
サポートされていない機能 |
attach |
attach |
実行中のコンテナにアタッチ |
--detach-keys , --sig-proxy |
exec |
exec |
実行中のコンテナでコマンドの実行 |
--privileged , --user , --detach-keys |
images |
images |
イメージのリストアップ |
|
info |
info |
システム全体の情報の表示 |
|
inspect |
inspect , inspecti |
コンテナ、イメージ、タスクの低レベルの情報を返します |
|
logs |
logs |
コンテナのログを取得します |
--details |
ps |
ps |
コンテナのリストアップ |
|
stats |
stats |
コンテナのリソース使用状況をライブで表示 |
Column: NET/BLOCK I/O, PIDs |
version |
version |
ランタイム(Docker、ContainerD、その他)のバージョン情報を表示します |
|
変更を行います
mapping from docker cli to crictl - perform changes
docker cli |
crictl |
説明 |
サポートされていない機能 |
create |
create |
新しいコンテナを作成します |
|
kill |
stop (timeout = 0) |
1つ以上の実行中のコンテナを停止します |
--signal |
pull |
pull |
レジストリーからイメージやリポジトリをプルします |
--all-tags , --disable-content-trust |
rm |
rm |
1つまたは複数のコンテナを削除します |
|
rmi |
rmi |
1つまたは複数のイメージを削除します |
|
run |
run |
新しいコンテナでコマンドを実行 |
|
start |
start |
停止した1つまたは複数のコンテナを起動 |
--detach-keys |
stop |
stop |
実行中の1つまたは複数のコンテナの停止 |
|
update |
update |
1つまたは複数のコンテナの構成を更新 |
--restart 、--blkio-weight とその他 |
crictlでのみ対応
mapping from docker cli to crictl - supported only in crictl
crictl |
説明 |
imagefsinfo |
イメージファイルシステムの情報を返します |
inspectp |
1つまたは複数のPodの状態を表示します |
port-forward |
ローカルポートをPodに転送します |
runp |
新しいPodを実行します |
rmp |
1つまたは複数の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:/#
デバッグコマンドは、情報を収集し、問題をトラブルシューティングするのに役立ちます。
使用する可能性のあるコマンドには、ip
、ifconfig
、nc
、ping
、ps
などがあります。
また、mtr
、tcpdump
、curl
などの他のツールもそれぞれのパッケージマネージャーからインストールすることができます。
備考:
デバッグコマンドは、デバッグ用のPodが使用しているイメージに基づいて異なる場合があり、これらのコマンドをインストールする必要があるかもしれません。
デバッグ用の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が必要な場合は、手動で作成するか、--profile=sysadmin
を使用してください。
- デバッグ用のPodにデバッグプロファイルを適用することで、securityContextなどの特定のプロパティを設定できます。
クリーンアップ
デバッグ用のPodの使用が終了したら、それを削除してください。
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
備考:
ノードがダウンしている場合(ネットワークから切断されている、kubeletが停止して再起動しないなど)、
kubectl debug node
コマンドは機能しません。
その場合は、
ダウンあるいは到達不能なノードのデバッグを確認してください。
6 - WindowsデバッグTips
ノードレベルのトラブルシューティング
-
Podが"Container Creating"と表示されたまま動かなくなったり、何度も再起動を繰り返します
pauseイメージがWindows OSのバージョンと互換性があることを確認してください。
最新/推奨のpauseイメージや詳細情報については、Pauseコンテナを参照してください。
備考:
コンテナランタイムとしてcontainerdを使用している場合、pauseイメージはconfig.toml設定ファイルのplugins.plugins.cri.sandbox_image
フィールドで指定されます。
-
PodがErrImgPull
またはImagePullBackOff
のステータスを表示します
Podが互換性のあるWindowsノードにスケジュールされていることを確認してください。
Podに対して互換性のあるノードを指定する方法の詳細については、このガイドを参照してください。
ネットワークのトラブルシューティング
-
Windows Podがネットワークに接続できません
仮想マシンを使用している場合は、すべてのVMのネットワークアダプターでMACスプーフィングが有効になっていることを確認してください。
-
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.conf
のExceptionList
は次のようになります:
"ExceptionList": [
"10.244.0.0/16", # クラスターのサブネット
"10.96.0.0/12", # Serviceのサブネット
"10.127.130.0/24" # 管理(ホスト)のサブネット
]
-
WindowsノードがNodePort
タイプのServiceにアクセスできません
ノード自身からのローカルNodePortへのアクセスは失敗します。
これは既知の制限です。
NodePortへのアクセスは、他のノードや外部のクライアントからは動作します。
-
コンテナのvNICとHNSエンドポイントが削除されています
この問題はhostname-override
パラメーターがkube-proxy
に渡されていない場合に発生する可能性があります。
これを解決するためには、ユーザーは次のようにkube-proxyにホスト名を渡す必要があります:
C:\k\kube-proxy.exe --hostname-override=$(hostname)
-
WindowsノードがService IPを使用してサービスにアクセスできません
これはWindows上のネットワークスタックの既知の制限です。
ただし、Windows PodはService IPにアクセスできます。
-
kubeletの起動時にネットワークアダプターが見つかりません
Windowsのネットワーキングスタックでは、Kubernetesネットワーキングが動作するために仮想アダプターが必要です。
(管理者シェルで)次のコマンドを実行しても結果が返されない場合、kubeletが動作するために必要な前提条件である仮想ネットワークの作成に失敗しています。
Get-HnsNetwork | ? Name -ieq "cbr0"
Get-NetAdapter | ? Name -Like "vEthernet (Ethernet*"
ホストのネットワークアダプターが"Ethernet"ではない場合、start.ps1
スクリプトのInterfaceNameパラメーターを修正することが有益です。
それ以外の場合は、start-kubelet.ps1
スクリプトの出力結果を参照して、仮想ネットワークの作成中にエラーが発生していないか確認します。
-
DNS名前解決が正しく動作しません
このセクションのWindowsにおけるDNSの制限について確認してください。
-
kubectl port-forward
が"unable to do port forwarding: wincat not found"で失敗します
これは、pauseインフラコンテナmcr.microsoft.com/oss/kubernetes/pause:3.6
にwincat.exe
を含める形で、Kubernetes 1.15にて実装されました。
必ずサポートされたKubernetesのバージョンを使用してください。
独自のpauseインフラコンテナをビルドしたい場合は、必ずwincatを含めるようにしてください。
-
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のトラブルシューティング
-
Flannelを使用すると、クラスターに再参加した後にノードに問題が発生します
以前に削除したノードがクラスターに再参加すると、flanneldはノードに新しいPodサブネットを割り当てようとします。
ユーザーは、次のパスにある古いPodサブネットの設定ファイルを削除する必要があります:
Remove-Item C:\k\SourceVip.json
Remove-Item C:\k\SourceVipRequest.json
-
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
-
/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で定義されている構造に従います。
備考:
パッチの場合、リクエストボディはパッチ操作を含むJSON配列であり、適切なKubernetes APIオブジェクトを含むJSONオブジェクトではありません。
例えば、以下のリクエストボディは/apis/batch/v1/namespaces/some-namespace/jobs/some-job-name
に対する有効なパッチリクエストです。
[
{
"op": "replace",
"path": "/spec/parallelism",
"value": 0
},
{
"op": "remove",
"path": "/spec/template/spec/containers/0/terminationMessagePolicy"
}
]
ログバックエンド
ログバックエンドは監査イベントを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を例に、利用可能なフラグの一覧を示します。
ログバックエンドで同じフラグを取得するには、フラグ名のwebhook
をlog
に置き換えてください。
デフォルトでは、バッチングは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件のリクエストを受け取り、それぞれのリクエストがResponseStarted
とResponseComplete
の段階でのみ監査されるとします。毎秒≅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
バックエンドに送信される監査イベントのバイト単位の最大サイズです。
デフォルトでは、webhook
とlog
の両方で切り捨ては無効になっていますが、クラスター管理者は audit-log-truncate-enabled
またはaudit-webhook-truncate-enabled
を設定して、この機能を有効にする必要があります。
次の項目