blog

Kubernetesチュートリアル:PIDからPod名を取得する

クラスタを管理する過程で、よくこのような状況に遭遇します。あるノードで、あるプロセスが高いリソースを使用していることがわかりますが、どのプロセスがどのコンテナに入っているのかわかりません。PIDに基づ...

Jan 7, 2021 · 6 min. read
シェア

Kubernetesクラスタを管理していると、リソース使用量の多いノードでプロセスを見つけたものの、それがどのコンテナに入っているのかわからないという状況によく遭遇します。PIDからポッド名を素早く見つける方法はありますか?

今、PIDが.のプロメテウス・プロセスがあるとします:

さらに情報を掘り起こすには、PIDに対応するコンテナの情報を掘り起こす方法と、PIDに対応するポッドの情報を掘り起こす方法があります。

Container ID

コンテナの ID を取得するには、PID に対応する cgroup 情報を表示します:

$ cat /proc/14338/cgroup
11:blkio:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1abcf1/d6f24b62eaf7bc06f98de083cc3389cdac:cpuset:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1abcf1/d6f24b62eaf7bc06f98de083cc3389cdac:freezer:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1abcf1/d6f24b62eaf7bc06f98de083cc3389cdac:hugetlb:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1abcf1/d6f24b62eaf7bc06f98de083cc3389cdac:perf_event:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1abcf1/d6f24b62eaf7bc06f98de083cc3389cdac:cpuacct,cpu:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1abcf1/d6f24b62eaf7bc06f98de083cc3389cdac:pids:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1abcf1/d6f24b62eaf7bc06f98de083cc3389cdac:devices:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1abcf1/d6f24b62eaf7bc06f98de083cc3389cdac:net_prio,net_cls:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1abcf1/d6f24b62eaf7bc06f98de083cc3389cdac:memory:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1abcf1/d6f24b62eaf7bc06f98de083cc3389cdac:name=systemd:/kubepods/burstable/pod8e018a8e-4aaa-4ac6-986a-1abcf1/d6f24b62eaf7bc06f98de083cc3389cdacc

このプロセスに対応するコンテナIDがd6f24b62であることがわかります。上記のコマンドを最適化して、コンテナ ID を直接取得することができます:

$ CID=$(cat /proc/14338/cgroup | awk -F '/' '{print $5}')
$ echo ${CID:0:8}
d6f24b62

最後のステップは、コンテナIDに基づいてPod名を取得することです。 コンテナランタイムがcontainerdまたはcrioの場合は、crictlを使用してコンテナ情報を取得できます:

# Go Template
$ crictl inspect -o go-template --template='{{index .status.labels "io.kubernetes.pod.name"}}' d6f24b62
prometheus-k8s-0
# jq
$ crictl inspect d6f24b62|jq '.status.labels["io.kubernetes.pod.name"]'
"prometheus-k8s-0"

お好みに応じて、Goテンプレートまたはjqを使用してポッド名を取得できます。

コンテナランタイムがDockerの場合は、コマンドラインツールのdockerを使って上記と同様の方法で取得できます。

Pod UID

まずPIDに基づいてPod UIDを直接取得する2番目の方法を見てみましょう:

$ cat /proc/14338/mountinfo | grep "etc-hosts" | awk -F / {'print $6'}
8e018a8e-4aaa-4ac6-986a-1abcf1

次に、Pod UIDに基づいてPod名を取得します:

$ crictl ps -o json | jq '.[][].labels | select (.["io.kubernetes.pod.uid"] == "8e018a8e-4aaa-4ac6-986a-1abcf1") | .["io.kubernetes.pod.name"]'|uniq
"prometheus-k8s-0"

統合

方法はあるのですが、すべてのステップを1つにまとめ、1つのステップでPod名を取得するにはどうすればよいでしょうか?シェル関数を~/.bashrcに追加して、上記の方法1を選択し、goテンプレートでフォーマットします:

podinfo() {
 CID=$(cat /proc/$1/cgroup | awk -F '/' '{print $5}')
 CID=$(echo ${CID:0:8})
 crictl inspect -o go-template --template='{{index .status.labels "io.kubernetes.pod.name"}}' $CID
}

以下のコマンドを実行すると、変更が即座に反映されます:

$ source ~/.bashrc

次に、この関数を使用してPod名を取得できます:

$ podinfo 14338
prometheus-k8s-0

一つ上げて三つ逆

Kubernetesの多くのコンポーネントは、kubeletのようなHTTPSプロトコル経由でメトリクスを公開しています。

prometheusのようなコンテナを選び、そのPIDを見つけることから始めます:

$ ps -ef|grep "/bin/prometheus"
  :02 /bin/prometheus --web.console.templates=/etc/prometheus/consoles --web.console.libraries=/etc/prometheus/console_libraries --config.file=/etc/prometheus/config_out/prometheus.env.yaml --storage.tsdb.path=/prometheus --storage.tsdb.retention.time=24h --web.enable-lifecycle --storage.tsdb.no-lockfile --web.route-prefix=/
  :10 /bin/prometheus-config-reloader --log-format=logfmt --reload-url=http://:90/-/ad --config-file=/etc/prometheus/config/prometheus.yaml.gz --config-envsubst-file=/etc/prometheus/config_out/prometheus.env.yaml
root  18:19 pts/0  grep --color=auto /bin/prometheus

PIDに基づいてPod UIDを検索します:

$ cat /proc/14338/mountinfo | grep "etc-hosts" | awk -F / {'print $6'}
8e018a8e-4aaa-4ac6-986a-1abcf1

Pod UIDに基づいて、サービスアカウントのトークンマウンティングディレクトリを検索します:

$ ll /var/lib/kubelet/pods/8e018a8e-4aaa-4ac6-986a-1abcf1/volumes/kubernetes.io~secret/prometheus-k8s-token-p7bgb/
総使用量 0
lrwxrwxrwx 1 root root  21:24 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root  21:24 namespace -> ..data/namespace
lrwxrwxrwx 1 root root  21:24 token -> ..data/token

トークン情報を取得します:

$ export TOKEN=$(cat /var/lib/kubelet/pods/8e018a8e-4aaa-4ac6-986a-1abcf1/volumes/kubernetes.io~secret/prometheus-k8s-token-p7bgb/token)

curl経由でメトリクスに直接アクセス:

$ curl -s -H "Authorization: Bearer $TOKEN" --cacert /var/lib/kubelet/pods/8e018a8e-4aaa-4ac6-986a-1abcf1/volumes/kubernetes.io~secret/prometheus-k8s-token-p7bgb/ca.crt --insecure https://...://or

もちろん、クラスタ管理者の認証情報、鍵、CA証明書が見つかれば、それを直接使ってアクセスすることもできます。

実に見事なトリック。

Kubernetesは、ホスト名がPodの名前に対応するようにコンテナを作成しますが、この考え方に沿って、より巧妙な方法を得ることができます!これは、nsenterツールの助けを借りて行うことができます:

$ nsenter -t 14338 --uts hostname
prometheus-k8s-0

一見すると、上記の方法よりもずっとエレガントですが、この方法にはちょっとした問題があります。 コンテナがHostNetworkモードで実行されている場合、ホスト名はホストマシンのホスト名なので、この方法ではPod名を取得できません。一般的な方法ではありませんが、nsenterを使ってホスト名を取得する以外に、環境変数を使ってホスト名を取得することもできます:

$ xargs -0 -L1 -a /proc/14338/environ | grep HOSTNAME
HOSTNAME=prometheus-k8s-0

これらのパラメータについて説明してください:

  • -0: 区切り文字として null を使用することを示します。
  • -L: コマンドライン引数として何行指定するかを示します。-xargs は標準入力をコマンドライン引数に変換するために使用され、 xargs の後に実際に実行されるコマンドが続かない場合、デフォルトの echo を使用することを意味します。
  • -a: 標準入力ではなく、ファイルから内容を読み込みます。

それでも理解できないのなら、私はベストを尽くしたつもりです。

最後に、すべてのコンテナのPIDと対応するPod情報を検索する別のプロジェクトをお勧めします:。

Kubernetes 1.18.2 1.17.5 1.16.9 1.15.12 オフラインインストーラが リリースされました。 最新版のsealos v3.3.6を使用しています。 ホスト名解決設定の最適化、ブートipvsのロード問題を解決するためのlvscareマウント/ lib /モジュール、修正lvscareコミュニティnetlinkと3.10カーネル非互換性の問題、証明書の世紀のsealos生成やその他の機能を行いました。より多くの機能 .ピングループに参加するには、以下のQRコードをスキャンするために歓迎 , ピングループは、統合されたsealosロボットリアルタイムsealosのダイナミックを見ることができます。

Read next

Vueのソースコードに隠されたトリックを掘り起こす!

まえがき\n最近、Vueのスキルの記事が非常にホットで、私も書いたことがありますが、この記事のスキルはVueのドキュメントのトレースで見つけることができますが、いくつかの記事では、Vueのドキュメントのスキルはトレースで見つけることができないと言います!なぜでしょうか?\nというと

Jan 7, 2021 · 10 min read