クラスターのトラブルシューティング
一般的なクラスターの問題をデバッグします。
このドキュメントはクラスターのトラブルシューティングに関するもので、あなたが経験している問題の根本原因として、アプリケーションをすでに除外していることを前提としています。
アプリケーションのデバッグのコツは、アプリケーションのトラブルシューティングガイドをご覧ください。
また、トラブルシューティングドキュメントにも詳しい情報があります。
クラスターのリストアップ
クラスターで最初にデバッグするのは、ノードがすべて正しく登録されているかどうかです。
そして、期待するノードがすべて存在し、それらがすべて Ready
状態であることを確認します。
クラスター全体の健全性に関する詳細な情報を得るには、以下を実行します。
kubectl cluster-info dump
ログの確認
今のところ、クラスターをより深く掘り下げるには、関連するマシンにログインする必要があります。
以下は、関連するログファイルの場所です。
(systemdベースのシステムでは、代わりに journalctl
を使う必要があるかもしれないことに注意してください)
マスターノード
/var/log/kube-apiserver.log
- APIの提供を担当するAPIサーバーのログ/var/log/kube-scheduler.log
- スケジューリング決定責任者であるスケジューラーのログ/var/log/kube-controller-manager.log
- レプリケーションコントローラーを管理するコントローラーのログ
ワーカーノード
/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が立ち上がらない
- kubeletsは到達できなくなりますが、同じ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: k8s.gcr.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: k8s.gcr.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 informationdocker 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 changesdocker 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 crictlcrictl | 説明 |
---|
imagefsinfo | イメージファイルシステムの情報を返します |
inspectp | 1つまたは複数のPodの状態を表示します |
port-forward | ローカルポートをPodに転送します |
runp | 新しいPodを実行します |
rmp | 1つまたは複数のPodを削除します |
stopp | 稼働中の1つまたは複数のPodを停止します |
5 - テレプレゼンスを使用したローカルでのサービス開発・デバッグ
Kubernetesアプリケーションは通常、複数の独立したサービスから構成され、それぞれが独自のコンテナで動作しています。これらのサービスをリモートのKubernetesクラスター上で開発・デバッグするには、get a shell on a running containerしてリモートシェル内でツールを実行しなければならず面倒な場合があります。
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をご覧ください。
6 - 監査
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/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
を設定して、この機能を有効にする必要があります。
次の項目