Skip to content

Kubernetes Pod, Docker container, Linux cgroupの連携

Kenichi Omichi edited this page Jan 12, 2021 · 17 revisions

Kubernetes PodがDocker container, Linux cgroup をベースにどのように実現されているのかをまとめる。

環境

  • Kubernetes: v1.18.10 single-node with Kubespray
  • OS: CentOS 7
  • Container Runtime: Docker-ce

注意点

  • 本資料は docker-ce ランタイムをベースに書かれている。今後、Kubernetesにおいて docker-ce を含んだ dockershim のサポートが廃止される予定であり、crio など他のランタイムを使った場合の調査も必要となる(cgroup については Linux Kernel の機能を使っているため、同様の連携と思われるが念のため)

まとめ

  • kubectl describe pod コマンドの項目「Container ID」から対応する Docker container を特定可能
  • docker inspect コマンドの項目「CgroupParent」から対応する Linux cgroup を特定可能
  • 各 cgroup サブシステムの設定は /sys/fs/cgroup/ 配下のディレクトリ memory, pid などで分割管理されている
  • memory cgroup の場合、/sys/fs/cgroup/memory/kubepods.slice/kubepods-besteffort.slice/{CgroupParent}/docker-{Docker ID}.scope/

詳細1: 実験ベース

シンプルな busybox Pod を起動する。

  • 10.0.2.15のworker node、docker ID: 7e5464e849a2335aed6f321b813c59422a809975b7c88d31b03236b0a6b441b4 で起動していることが分かる。
$ kubectl describe pod pod-busybox
..
Node:         localhost/10.0.2.15
...
Containers:
  mycontainer:
    Container ID:  docker://7e5464e849a2335aed6f321b813c59422a809975b7c88d31b03236b0a6b441b4

次にそのworker nodeにログインし、該当するDocker containerを確認する。

  • Linux PID が 9878 であることが分かる。
$ sudo docker ps
CONTAINER ID        IMAGE                                           COMMAND                  CREATED             STATUS              PORTS                    NAMES
7e5464e849a2        busybox                                         "sleep 3600"             4 minutes ago       Up 4 minutes                                 k8s_mycontainer_pod-busybox_default_4640f0a9-7443-449c-af2f-8a7d1b928a8c_0
...
$
$ sudo docker inspect 7e5464e849a2 
[
    {
        "Id": "7e5464e849a2335aed6f321b813c59422a809975b7c88d31b03236b0a6b441b4",
        "Created": "2021-01-06T18:06:39.994555047Z",
        "Path": "sleep",
        "Args": [
            "3600"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 9878,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2021-01-06T18:06:40.160559308Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
...
        "HostConfig": {
            "CgroupParent": "kubepods-besteffort-pod4640f0a9_7443_449c_af2f_8a7d1b928a8c.slice",
...

関連 namespaces の確認コマンドとして lsns がある。

  • /proc/{pid}/ns で表示される内容と一致。
$ sudo lsns
        NS TYPE  NPROCS   PID USER   COMMAND
..
4026532600 mnt        1  9878 root   sleep 3600
4026532601 uts        1  9878 root   sleep 3600
4026532602 pid        1  9878 root   sleep 3600
$
$ sudo ls -l /proc/9878/ns
total 0
lrwxrwxrwx. 1 root root 0 Jan  6 13:19 ipc -> ipc:[4026532530]
lrwxrwxrwx. 1 root root 0 Jan  6 13:19 mnt -> mnt:[4026532600]
lrwxrwxrwx. 1 root root 0 Jan  6 13:19 net -> net:[4026532533]
lrwxrwxrwx. 1 root root 0 Jan  6 13:19 pid -> pid:[4026532602]
lrwxrwxrwx. 1 root root 0 Jan  6 13:19 user -> user:[4026531837]
lrwxrwxrwx. 1 root root 0 Jan  6 13:19 uts -> uts:[4026532601]
$

lscgroup など cgroup 確認コマンドを利用するため、libcgroup-tools をインストール。

$ sudo yum install libcgroup-tools
...

docker inspect の結果(kubepods-besteffort-pod4640f0a9_7443_449c_af2f_8a7d1b928a8c.slice) から /sys/fs/cgroup/pids/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod4640f0a9_7443_449c_af2f_8a7d1b928a8c.slice に 当該 PID namespace がマウントされていることが分かる。 そのディレクトリ配下に docker ID(7e5464e849a2335..) のサブディレクトリができている。

# cd /sys/fs/cgroup/pids/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod4640f0a9_7443_449c_af2f_8a7d1b928a8c.slice
#
# ls
cgroup.clone_children  cgroup.procs                                                                   docker-7e5464e849a2335aed6f321b813c59422a809975b7c88d31b03236b0a6b441b4.scope  pids.current  tasks
cgroup.event_control   docker-11fbb3af903839440ba6df00452f616b29370e656cc3697630274df6d4b0e6ba.scope  notify_on_release                                                              pids.max
#
# cd docker-7e5464e849a2335aed6f321b813c59422a809975b7c88d31b03236b0a6b441b4.scope
# ls
cgroup.clone_children  cgroup.event_control  cgroup.procs  notify_on_release  pids.current  pids.max  tasks

で、その PID namespace の cgroup には自分(Linux PID: 9878) しかいないことが分かる。

# cat tasks 
9878
# cat cgroup.procs 
9878
# cat pids.current 
1
#

同様に Memory namespace の cgroup も同じ構成のディレクトリパスにマウントされている。

  • 同じ PID が登録されていることが分かる。
# pwd
/sys/fs/cgroup/memory/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod4640f0a9_7443_449c_af2f_8a7d1b928a8c.slice/docker-7e5464e849a2335aed6f321b813c59422a809975b7c88d31b03236b0a6b441b4.scope
#
# ls
cgroup.clone_children  memory.kmem.limit_in_bytes          memory.kmem.tcp.usage_in_bytes  memory.memsw.max_usage_in_bytes  memory.soft_limit_in_bytes  tasks
cgroup.event_control   memory.kmem.max_usage_in_bytes      memory.kmem.usage_in_bytes      memory.memsw.usage_in_bytes      memory.stat
cgroup.procs           memory.kmem.slabinfo                memory.limit_in_bytes           memory.move_charge_at_immigrate  memory.swappiness
memory.failcnt         memory.kmem.tcp.failcnt             memory.max_usage_in_bytes       memory.numa_stat                 memory.usage_in_bytes
memory.force_empty     memory.kmem.tcp.limit_in_bytes      memory.memsw.failcnt            memory.oom_control               memory.use_hierarchy
memory.kmem.failcnt    memory.kmem.tcp.max_usage_in_bytes  memory.memsw.limit_in_bytes     memory.pressure_level            notify_on_release
#
# cat cgroup.procs 
9878
$ cat tasks 
9878
#

詳細2: 設定調査

Kubespray のコードレビューの過程で、dockerd プロセスの起動オプションで cgroup の制御方法を指定する方法があることが分かった。 --exec-opt native.cgroupdriver=systemd で systemd を指定している。systemd 以外に cgroupfs が指定可能である。 上記詳細1の実験の通り、結局は cgroupfs に必要な設定を施しているだけのはずなので、systemd は cgroupfs を容易に設定するための仕組みとして使っている? この仮説を確認する。

  • この仮説の結論: 正しくない。cgroupfs は cgroup v1 を、systemd は cgroup v2 をそれぞれ管理している。詳細は次の調査で行う。

Kubernetesとしての説明は以下にある。 https://kubernetes.io/ja/docs/setup/production-environment/container-runtimes/#cgroup%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90%E3%83%BC

これはDockerから来ており、Dockerのオプションの説明は以下の通り。 https://docs.docker.com/engine/reference/commandline/dockerd/

The native.cgroupdriver option specifies the management of the container’s cgroups.
You can only specify cgroupfs or systemd.
If you specify systemd and it is not available, the system errors out.
If you omit the native.cgroupdriver option, cgroupfs is used on cgroup v1 hosts,
systemd is used on cgroup v2 hosts with systemd available.

この説明によると cgroup v1 と cgroup v2 が存在し、 cgroupfs は cgroup v1 を systemd は cgroup v2 をそれぞれ管理するツールのように見える。 そうなると前述の詳細1では cgroup v1 を使って cgroup を管理しているように見える。 上記が正しいのか、また cgroup v1 と cgroup v2 の違いを調査する。

systemd vs. cgroupfs

ここでは systemd と cgroupfs、またそれらが管理すると思われる cgroup v1 と cgroup v2 について調べる。 LWN に適切なページがあった。 https://lwn.net/Articles/679786/

Clone this wiki locally