はじめに
この記事では,僕がアラートルールの設定中に遭遇したidというラベルの正体について書いています.既に知っている方には新しい情報は少ないと思います.なにそれ!?と思った方や,僕と同じように困っていた方には,役立つかなと思います.
経緯
まず,僕がこのidという存在に困った話をします.
僕は研究室の監視環境を整えるうえで,Kubernetes環境のpodの監視ルールの設定を任されていました.
Cadvisorというコンテナ監視用のexporterを使用して,Prometheusにメトリクスを収集していました.そしてその収集したメトリクスを用いて,PromQLクエリ式でルールを設定していました.
ここで,コンテナ(pod)のメモリ使用率のアラートルールを設定しようとしたところ,次のようなメトリクスの値が取れました
container_memory_usage_bytes{beta_kubernetes_io_arch="amd64", beta_kubernetes_io_instance_type="k3s", beta_kubernetes_io_os="linux", id="/", instance="master", job="kubernetes-nodes", kubernetes_io_arch="amd64", kubernetes_io_hostname="master", kubernetes_io_os="linux", node_kubernetes_io_instance_type="k3s", node_role_kubernetes_io_control_plane="true", node_role_kubernetes_io_master="true"}
これの何が問題なんだと思う方もいると思います.
ここで重要なのは,僕はpodのメモリ使用率を取得しようとしているということです.
本来ほしいのは以下のようなメトリクスの値でした
container_memory_usage_bytes{beta_kubernetes_io_arch="amd64", beta_kubernetes_io_instance_type="k3s", beta_kubernetes_io_os="linux", container="alertmanager", id="/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod6a69032e_6c67_424a_abb6_7f374ef886fe.slice/cri-containerd-59516de8ffbb81b5e3ac6bece07e8f8800d661d2cb08f9fe1bbbe47e2d234250.scope", image="docker.io/prom/alertmanager:latest", instance="core-s4", job="kubernetes-nodes", kubernetes_io_arch="amd64", kubernetes_io_hostname="core-s4", kubernetes_io_os="linux", name="59516de8ffbb81b5e3ac6bece07e8f8800d661d2cb08f9fe1bbbe47e2d234250", namespace="alert", node_kubernetes_io_instance_type="k3s", node_role_kubernetes_io_control_plane="true", node_role_kubernetes_io_etcd="true", node_role_kubernetes_io_master="true", pod="alertmanager-9b5997c44-2s2hr"}
何がいいのかというと,よく見てみるとこっちはpodというラベルやnamespaceというラベルがあります.そのため,どこのnamespaceにあるどのpodなのか特定できます.
一方で一つ目の値だとどうでしょうか.
よく見てみてもpodやnamespaceというラベルが存在しません.
これだとpodの監視ができないじゃないか!
そこでこのメトリクスにある情報を色々見ていたところ,idというものを見つけました.
id="/"
id="/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod6a69032e_6c67_424a_abb6_7f374ef886fe.slice/cri-containerd-59516de8ffbb81b5e3ac6bece07e8f8800d661d2cb08f9fe1bbbe47e2d234250.scope"
なんか階層構造みたいになってそうです.
他にもみていたところ,こういうのもありました.
id="/system.slice/k3s.service"
これはk3sのことをいってそうですね.ちなみにpodやnamespaceのラベルはありませんでした.
ここまでで分かったこと
- idが階層構造になっていそうということ
- idの内容によってpodのものとシステム側のものが分かれていそうということ
これだけだとよく分からないためもっと色々調べてみました.
idの正体
調べた結果,idの値にかなり類似したものを見つけました.
cgroupsというものでした!
cgroupsについては以下のURLで説明されています.
https://valinux.hatenablog.com/entry/20210114
このサイトによると,podやコンテナはKubernetesによってコントローラごとに階層構造で作成しているらしく,それがどんな構造化というと,
/kubepods /<Guaranteed Pod の UID> /<コンテナID> /burstable /<Burstable Pod の UID> /<コンテナID> /besteffort /<BestEffort Pod の UID> /<コンテナID>
というような構造になっているみたいです!
僕が取得した二つ目のメトリクスの値にあったidと比べると,
/kubepods.slice/kubepods-besteffort.slice/
このように,それらしき階層構造になっています.
そもそもcgroupとは何なんでしょう.このサイトによると,
cgroup とは、Linux カーネルの機能の1つであり、プロセスやスレッドが利用するリソースの制限や分離を行うための機能です。 cgroup は名前空間の機能と共に、Linux コンテナの根幹を成す技術の1つでもあります
だそうです.
つまりcgroupによって,kubernetesのpodやコンテナのみならず,ノード全体のリソースの切り分けを行っているみたいです.
結局何がどういうことだったのか
それでは僕が経験した問題について考察してみます.
id="/"
これはkubepodsよりも上位の階層ということになります.つまり,podやk3sのserviceのようなシステムのメモリ使用率も合わせたノード全体を指すのではないでしょうか?
だから,podもnamespaceも無いんじゃないでしょうか?
逆に,以下のidを見てみます
id="/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod6a69032e_6c67_424a_abb6_7f374ef886fe.slice/cri-containerd-59516de8ffbb81b5e3ac6bece07e8f8800d661d2cb08f9fe1bbbe47e2d234250.scope"
これは,kubepods以下の,QOSクラスがbesteffortのpodの,criのコンテナという感じですかね.
ここまでidで表されていれば,podであると判断できるでしょう.
結論
idの正体はcgroupによるpodの階層構造でした.
また,cadvisorが取得したメトリクスには,podだけではなく,ノード自体やk3sサービスのものも含まれていた.そのため,namespaceやpod名が取得できないメトリクスも存在していた.
この情報がお役に立てたなら幸いです.