Kubernetes のシステム用に割り当てられるリソースについて整理し、実際の挙動を確認しました。
1. Pod に割り当て可能なリソース
まずは、Kubernetes 上で Pod が使えるリソースについて整理します。
Node 上では OS, Kubernetes が動いており、その上で Pod が動いているため Pod が Node のリソースを全て使用すると問題(OS 全体に影響が出る、Kubernetes 自体が動作しなくなる等)が発生します。 それを回避するため、OS, Kubernetes 用リソース kube-reserved, system-reserved と、Node の最低空きリソース eviction-threshold があります。
Pod に割り当てられるリソースは Node のリソース量から、kube-reserved,system-reserved,eviction-threshold を引いた分になります。
本記事では kube-reserved,system-reserved についてまとめています。eviction-threshold については別の記事でまとめます。
2. cgroup
kube-reserved,system-reserved の説明に cgroup が出てくるため、cgroup について簡単に整理します。
cgroup とは Control Group の略で、プロセスをグループ化し CPU やメモリ等のリソースをグループ毎に制限する Linux カーネルの機能です。
cgroupfs という仮想ファイルシステム上で cgroup を操作します。cgroupfs は /sys/fs/cgroup にマウントされています。
eksctl コマンドで EKS Cluster を作成する - YasuBlog の記事で作成した EKS Node で確認すると cgroupfs が /sys/fs/cgroup にマウントされている事が確認できます。
$ df -h ファイルシス サイズ 使用 残り 使用% マウント位置 devtmpfs 1.9G 0 1.9G 0% /dev tmpfs 1.9G 0 1.9G 0% /dev/shm tmpfs 1.9G 760K 1.9G 1% /run tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup /dev/nvme0n1p1 30G 2.7G 28G 9% / tmpfs 388M 0 388M 0% /run/user/1000 ~省略~ $ mount -l | grep cgroup tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755) cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd) cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory) cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset) cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices) cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct) cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event) cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio) cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids) cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio) cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb) cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
/sys/fs/cgroup 配下のファイルで cgroup を管理しています。
$ ls /sys/fs/cgroup/
blkio cpu cpu,cpuacct cpuacct cpuset devices freezer hugetlb memory net_cls net_cls,net_prio net_prio perf_event pids systemd
例えば、/sys/fs/cgroup/cpu/tasks に記載されたプロセス(PID)の CPU リソース は /sys/fs/cgroup/cpu/cpu.shares に記載された 1024 に制限されます。※ CPU share は CPU の相対値
$ cat /sys/fs/cgroup/cpu/tasks 1 2 3 4 6 8 ~省略~ $ cat /sys/fs/cgroup/cpu/cpu.shares 1024
cgroup を追加する際はディレクトリを作成します。test という cgroup を作成してみます。
$ mkdir /sys/fs/cgroup/cpu/test
ディレクトリを作成するとその配下に自動でファイルが作成されます。
$ ls /sys/fs/cgroup/cpu/test cgroup.clone_children cgroup.procs cpu.cfs_period_us cpu.cfs_quota_us cpu.rt_period_us cpu.rt_runtime_us cpu.shares cpu.stat cpuacct.stat cpuacct.usage cpuacct.usage_all cpuacct.usage_percpu cpuacct.usage_percpu_sys cpuacct.usage_percpu_user cpuacct.usage_sys cpuacct.usage_user notify_on_release tasks
例えば tasks に 2000、cpu.share に 512 を記載すると PID 2000 のプロセスの CPU share を 512 に制限する事になります。
$ cat /sys/fs/cgroup/cpu/test/tasks 2000 $ cat /sys/fs/cgroup/cpu/test/cpu.shares 512
コンテナは OS から見たらただのプロセスなのでこのようにリソースを制限出来ます。
なお、systemd-cgls コマンドで cgroup 階層全体が表示されます。
$ systemd-cgls ├─ 1 /usr/lib/systemd/systemd --switched-root --system --deserialize 21 ├─2913 bpfilter_umh ├─kubepods │ └─burstable │ ├─pod2a7eefa0-6719-4cac-82f4-6b7d58d54635 │ │ ├─510f73e18aa7dac452276e74f7acfd7087f44562eae619e05654bae567f5b460 │ │ │ ├─4276 bash /app/entrypoint.sh │ │ │ ├─4327 ./aws-k8s-agent │ │ │ └─4328 tee -i aws-k8s-agent.log │ │ └─e7101431d6f2cad771a0d30c81101d06475c2b4dad6b033eaf58093e636679a8 │ │ └─3585 /pause │ ├─pode895364f-3e61-48db-93cc-b0f8daefaa55 │ │ ├─c63c43b9ab660f4e2cab66f576e1a3208b6b97d659c0666c7c2c342daeecef8e │ │ │ └─4891 /coredns -conf /etc/coredns/Corefile │ │ └─aa5779e764f7fbfe68948de0ce425e7e03b2c5a2082586f6eb94e9a29b4670a3 │ │ └─4587 /pause │ ├─poddd65f1eb-593a-4882-bb86-9f453fc1a1d2 │ │ ├─0d51784c7ac2cdc9a013d19d79a5617c27c6d4f86c3dfc28c7517f96eb9c8743 │ │ │ └─3637 /pause │ │ └─cb2b42771c6e91de40b0cddde1e57677f5c112fa013fd9c601fa960e2e9d785d │ │ └─3876 kube-proxy --v=2 --config=/var/lib/kube-proxy-config/config │ └─podab6c28cc-525a-4fd2-9a69-07720eeed5ee │ ├─73c143c3c6b7706e3ef2e45b57ca0d6484b9679ba1920c095ba3c1b9025892b2 │ │ └─4626 /pause │ └─8dd43dd500d50180b3d287d96be60c1aa341dff864c9ce1903825dfeae6a7c04 │ └─4925 /coredns -conf /etc/coredns/Corefile ├─user.slice │ └─user-1000.slice │ ├─session-4.scope │ │ ├─28624 sshd: ec2-user [priv] │ │ ├─28655 sshd: ec2-user@pts/1 │ │ ├─28656 -bash │ │ ├─28700 sudo -s │ │ ├─28701 /bin/bash │ │ └─29383 systemd-cgls │ └─session-1.scope │ ├─5724 sshd: ec2-user [priv] │ ├─5779 sshd: ec2-user@pts/0 │ ├─5794 -bash │ ├─7556 sudo -s │ ├─7557 /bin/bash │ ├─8704 systemd-cgls │ └─8705 less └─system.slice ├─rngd.service │ └─1875 /sbin/rngd -f --fill-watermark=0 --exclude=jitter ├─irqbalance.service │ └─1853 /usr/sbin/irqbalance --foreground ├─amazon-ssm-agent.service │ ├─2361 /usr/bin/amazon-ssm-agent │ └─2518 /usr/bin/ssm-agent-worker ├─containerd.service │ ├─2781 /usr/bin/containerd │ ├─3545 /usr/bin/containerd-shim-runc-v2 -namespace moby -id e7101431d6f2c... │ ├─3546 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 0d51784c7ac2c... │ ├─3856 /usr/bin/containerd-shim-runc-v2 -namespace moby -id cb2b42771c6e9... │ ├─4257 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 510f73e18aa7d... │ ├─4528 /usr/bin/containerd-shim-runc-v2 -namespace moby -id aa5779e764f7f... │ ├─4530 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 73c143c3c6b77... │ ├─4826 /usr/bin/containerd-shim-runc-v2 -namespace moby -id c63c43b9ab660... │ └─4844 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 8dd43dd500d50... ├─systemd-udevd.service │ └─1305 /usr/lib/systemd/systemd-udevd ├─system-serial\x2dgetty.slice │ └─serial-getty@ttyS0.service │ └─2377 /sbin/agetty --keep-baud 115200,38400,9600 ttyS0 vt220 ├─docker.service │ └─2870 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.... ├─chronyd.service │ └─1861 /usr/sbin/chronyd ├─auditd.service │ └─1826 /sbin/auditd ├─kubelet.service │ └─3054 /usr/bin/kubelet --cloud-provider aws --config /etc/kubernetes/kub... ├─systemd-journald.service │ └─1284 /usr/lib/systemd/systemd-journald ├─sshd.service │ └─2423 /usr/sbin/sshd -D ├─crond.service │ └─2376 /usr/sbin/crond -n ├─gssproxy.service │ └─1887 /usr/sbin/gssproxy -D ├─rsyslog.service │ └─2367 /usr/sbin/rsyslogd -n ├─rpcbind.service │ └─1851 /sbin/rpcbind -w ├─network.service │ ├─2087 /sbin/dhclient -q -lf /var/lib/dhclient/dhclient--eth0.lease -pf /... │ └─2122 /sbin/dhclient -6 -nw -lf /var/lib/dhclient/dhclient6--eth0.lease ... ├─lvm2-lvmetad.service │ └─1302 /usr/sbin/lvmetad -f ├─postfix.service │ ├─ 2268 /usr/libexec/postfix/master -w │ ├─ 2270 qmgr -l -t unix -u │ └─13892 pickup -l -t unix -u ├─dbus.service │ └─1857 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidf... ├─system-getty.slice │ └─getty@tty1.service │ └─2373 /sbin/agetty --noclear tty1 linux └─systemd-logind.service └─1864 /usr/lib/systemd/systemd-logind
3. kube-reserved/system-reserved
公式ドキュメント Reserve Compute Resources for System Daemons | Kubernetes には以下のように記載されています。(意訳)
項目 | 概要 |
---|---|
kube-reserved | ・kubelet や container runtime, node problem detector などの Kubernetes system daemon 用に確保されるリソース ・Pod として動く system deamon は対象外 ・CPU/メモリ/エフェメラルストレージ/PID 数 を指定可能 ・kubelet フラグ例 --kube-reserved=cpu=100m,memory=100Mi,ephemeral-storage=1Gi,pid=1000 ・Kubernetes system daemon に --kube-reserved を強制するには --enforce-node-allocatable=kube-reserved と --kube-reserved-cgroup=<cgroup> が必要 |
system-reserved | ・sshd や udev などの OS system daemon 用に確保されるリソース ・カーネルメモリは Pod に割り当てられないためカーネル用のメモリも確保した方がよい ・ユーザのログインセッション用リソースを確保する事も推奨(systemd の世界では user.slice) ・CPU/メモリ/エフェメラルストレージ/PID 数 を指定可能 ・kubelet フラグ例 --system-reserved=cpu=100m,memory=100Mi,ephemeral-storage=1Gi,pid=1000 ・OS system daemon に --system-reserved を強制するには --enforce-node-allocatable=system-reserved と --system-reserved-cgroup=<cgroup> が必要 |
「Kubernetes/OS system daemon に --kube-reserved/--system-reserved
を強制するには --enforce-node-allocatable=kube-reserved/system-reserved
と --kube-reserved-cgroup/--systemreserved-cgroup=<cgroup>
が必要」がいまいちピンと来なかったです。
--kube-reserved/--system-reserved
だけでは Kubernetes/OS system daemon 用にリソースが確保されて強制はされない?
他にも、Kubernetes/OS が設定値以上使おうとするとどうなるのか?推奨値はあるのか?
などなど気になる点が多いため検証してみました。
4. 検証
4.1. 検証環境構築
eksctl コマンドで EKS Cluster を作成する - YasuBlog で作成した EKS Cluster を使用します。
4.2. EKS の kube-reserved/system-reserved 設定値
まずは kube-reserved/system-reserved
の確認方法です。Node の情報なので Kubernetes の API サーバから取得できます。
kubectl proxy コマンドでプロキシをローカルに起動すると API サーバにアクセスできます。
$ kubectl proxy Starting to serve on 127.0.0.1:8001
デフォルトでローカルの 8001 ポートでプロキシが起動するので、別ターミナルで http://localhost:8001/api/v1/nodes/<Node 名>/proxy/configz
にアクセスします。json なので jq で整形すると見やすいです。
$ kubectl get node NAME STATUS ROLES AGE VERSION ip-10-0-101-249.ap-northeast-1.compute.internal Ready <none> 2m36s v1.21.5-eks-bc4871b ip-10-0-102-241.ap-northeast-1.compute.internal Ready <none> 2m27s v1.21.5-eks-bc4871b ip-10-0-103-143.ap-northeast-1.compute.internal Ready <none> 2m12s v1.21.5-eks-bc4871b $ curl -sSL "http://localhost:8001/api/v1/nodes/ip-10-0-101-249.ap-northeast-1.compute.internal/proxy/configz" | jq . { "kubeletconfig": { "enableServer": true, "syncFrequency": "1m0s", "fileCheckFrequency": "20s", "httpCheckFrequency": "20s", "address": "0.0.0.0", "port": 10250, "tlsCipherSuites": [ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256" ], "serverTLSBootstrap": true, "authentication": { "x509": { "clientCAFile": "/etc/kubernetes/pki/ca.crt" }, "webhook": { "enabled": true, "cacheTTL": "2m0s" }, "anonymous": { "enabled": false } }, "authorization": { "mode": "Webhook", "webhook": { "cacheAuthorizedTTL": "5m0s", "cacheUnauthorizedTTL": "30s" } }, "registryPullQPS": 5, "registryBurst": 10, "eventRecordQPS": 5, "eventBurst": 10, "enableDebuggingHandlers": true, "healthzPort": 10248, "healthzBindAddress": "127.0.0.1", "oomScoreAdj": -999, "clusterDomain": "cluster.local", "clusterDNS": [ "172.20.0.10" ], "streamingConnectionIdleTimeout": "4h0m0s", "nodeStatusUpdateFrequency": "10s", "nodeStatusReportFrequency": "5m0s", "nodeLeaseDurationSeconds": 40, "imageMinimumGCAge": "2m0s", "imageGCHighThresholdPercent": 85, "imageGCLowThresholdPercent": 80, "volumeStatsAggPeriod": "1m0s", "cgroupRoot": "/", "cgroupsPerQOS": true, "cgroupDriver": "cgroupfs", "cpuManagerPolicy": "none", "cpuManagerReconcilePeriod": "10s", "memoryManagerPolicy": "None", "topologyManagerPolicy": "none", "topologyManagerScope": "container", "runtimeRequestTimeout": "2m0s", "hairpinMode": "hairpin-veth", "maxPods": 17, "podPidsLimit": -1, "resolvConf": "/etc/resolv.conf", "cpuCFSQuota": true, "cpuCFSQuotaPeriod": "100ms", "nodeStatusMaxImages": 50, "maxOpenFiles": 1000000, "contentType": "application/vnd.kubernetes.protobuf", "kubeAPIQPS": 5, "kubeAPIBurst": 10, "serializeImagePulls": false, "evictionHard": { "memory.available": "100Mi", "nodefs.available": "10%", "nodefs.inodesFree": "5%" }, "evictionPressureTransitionPeriod": "5m0s", "enableControllerAttachDetach": true, "protectKernelDefaults": true, "makeIPTablesUtilChains": true, "iptablesMasqueradeBit": 14, "iptablesDropBit": 15, "featureGates": { "RotateKubeletServerCertificate": true }, "failSwapOn": true, "containerLogMaxSize": "10Mi", "containerLogMaxFiles": 5, "configMapAndSecretChangeDetectionStrategy": "Watch", "kubeReserved": { "cpu": "70m", "ephemeral-storage": "1Gi", "memory": "442Mi" }, "enforceNodeAllocatable": [ "pods" ], "volumePluginDir": "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/", "logging": { "format": "text" }, "enableSystemLogHandler": true, "shutdownGracePeriod": "0s", "shutdownGracePeriodCriticalPods": "0s", "enableProfilingHandler": true, "enableDebugFlagsHandler": true } }
104 行目から 108 行目に kube-reserved が表示されています。
kubeReservedCgroup/systemReservedCgroup
が無いため、--kube-reserved-cgroup/--system-reserved-cgroup
が設定されていない事がわかります。
また、enforceNodeAllocatable
は pods のみ設定されています。(kube-reserved/system-reserved
は設定されていない)
なお、API サーバではなく Node にログインして設定ファイルから値を確認する事も可能です。
@node$ cat /etc/kubernetes/kubelet/kubelet-config.json { "kind": "KubeletConfiguration", "apiVersion": "kubelet.config.k8s.io/v1beta1", "address": "0.0.0.0", "authentication": { "anonymous": { "enabled": false }, "webhook": { "cacheTTL": "2m0s", "enabled": true }, "x509": { "clientCAFile": "/etc/kubernetes/pki/ca.crt" } }, "authorization": { "mode": "Webhook", "webhook": { "cacheAuthorizedTTL": "5m0s", "cacheUnauthorizedTTL": "30s" } }, "clusterDomain": "cluster.local", "hairpinMode": "hairpin-veth", "readOnlyPort": 0, "cgroupDriver": "cgroupfs", "cgroupRoot": "/", "featureGates": { "RotateKubeletServerCertificate": true }, "protectKernelDefaults": true, "serializeImagePulls": false, "serverTLSBootstrap": true, "tlsCipherSuites": [ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256" ], "maxPods": 20, "clusterDNS": [ "172.20.0.10" ], "evictionHard": { "memory.available": "100Mi", "nodefs.available": "10%", "nodefs.inodesFree": "5%" }, "kubeReserved": { "cpu": "70m", "ephemeral-storage": "1Gi", "memory": "442Mi" }
インスタンスタイプ毎の設定値を確認してみました。Node のリソース量から自動で計算されているようです。
インスタンスタイプ | kube-reserved | system-reserved | kube-reserved-cgroup | system-reserved-cgroup |
---|---|---|---|---|
t3.small | cpu:70m memory:376Mi ephemeral-storage:1Gi |
なし | なし | なし |
t3.medium | cpu:70m memory:442Mi ephemeral-storage:1Gi |
なし | なし | なし |
m5.large | cpu:80m memory:574Mi ephemeral-storage:1Gi |
なし | なし | なし |
m5.xlarge | cpu:80m memory:893Mi ephemeral-storage:1Gi |
なし | なし | なし |
4.3. 設定値変更
AWS マネージドではないセルフマネージド NodeGroup の場合は以下の通り設定できそうです。
Customizing kubelet configuration - eksctl
AWS マネージドの場合は yaml での設定方法は見つかりませんでした。Node 上の設定ファイル(/etc/kubernetes/kubelet/kubelet-config.json や /etc/systemd/system/kubelet.service)を直接修正する事で設定変更が可能です。 Node 再作成時にも同様に設定されるように、カスタム起動テンプレートかカスタム AMI を使用する必要があります。
Amazon EKS ワーカーノードを設定して特定のディスク使用率でイメージキャッシュをクリーンアップする
個人的には AWS マネージドという事は AWS が良かれと思って設計した値なのでユーザ側がカスタマイズする必要は無いと思っています。
4.4. --enforce-node-allocatable/--kube-reserved-cgroup/--system-reserved-cgroup 無しの場合の制限
EKS のデフォルト状態(--enforce-node-allocatable
と --kube-reserved-cgroup/--system-reserved-cgroup
が設定されていない状態)での制限を確認します。
検証用 Node(t3.medium)の設定値は以下です。
cpu | memory | ephemeral-storage | |
---|---|---|---|
kube-reserved | 70m | 442Mi | 1Gi |
system-reserved | なし | なし | なし |
Kubernetes system daemon 用に cpu 70M, memory 442Mi, ephemeral-storage 1Gi が確保されています。最初に記載した通り、Pod に割り当てられるリソース = Node - (kube-reserved + system-reserved + eviction-threshold)
のため、「確保されている」と言えると思います。
ただし、--enforce-node-allocatable
と --kube-reserved-cgroup/--system-reserved-cgroup
が設定されていないため強制はされていないはずです。
cpu.shares に 70m 、memory.limit_in_bytes に 442Mi が設定されている cgroup の有無を確認しましたが存在しなかったので確かに「強制されていない(リソースを制限していない)」という事がわかります。同様に --system-reserved
を設定して検証しても同じ結果でした。
@node$ find /sys/fs/cgroup/ -type f -name 'cpu.shares' -exec cat {} \; | sort | uniq 102 1024 128 1976 2 25 @node$ find /sys/fs/cgroup/ -type f -name 'memory.limit_in_bytes' -exec cat {} \; | sort | uniq 3135741952 9223372036854771712
つまり、--kube-reserved/--system-reserved
は Kubernetes 用とか OS 用とか関係なく、単純に Pod に割り当てられない領域として確保しているだけという事になります。これは --kube-reserved
と --system-reserved
が同じ意味を表しているという事になるかと思います。※--enforce-node-allocatable
と --kube-reserved-cgroup/--system-reserved-cgroup
が無い場合
マネージドサービスの EKS が --system-reserved
を設定していない理由はこれかと思います。--kube-reserved
一つ設定しておけば Kubernetes/OS 用のリソースとして確保できるからです。(--kube-reserved
と --system-reserved
が同じ意味なので --system-reserved
を設定する必要がない)
当然ですが、リソースを制限しているわけではないので、Kubernetes/OS が --kube-reserved/--system-reserved
に設定されている値より多くのリソースを使用する事が可能です。
4.5. --enforce-node-allocatable/--kube-reserved-cgroup/--system-reserved-cgroup ありの場合の制限
まずは --kube-reserved-cgroup
に設定する cgroup を作成します。プロセスは dockerd を設定します。
@node$ # find /sys/fs/cgroup/ -maxdepth 1 ! -type l -exec mkdir {}/K8s \; mkdir: ディレクトリ `/sys/fs/cgroup//K8s` を作成できません: Read-only file system @node$ pgrep -fl dockerd 2877 dockerd @node$ find /sys/fs/cgroup/ -type d -name K8s -exec sh -c 'echo 2877 > {}/tasks' \; sh: 0 行: echo: 書き込みエラー: No space left on device
systemd-cgls で cgroup を確認します。
@node$ systemd-cgls ├─ 1 /usr/lib/systemd/systemd --switched-root --system --deserialize 21 ├─2986 bpfilter_umh ├─kubepods │ └─burstable │ ├─pode887cc03-8c8a-47fe-94ce-77f75b71b7e2 │ │ ├─5724c33afacf82531d99d78fcea7b5b07b54105d2729b20953eb3e6a3da9dcfb │ │ │ └─3674 /pause │ │ └─b263bef8f5b3aff3df5430cc05551a42d72ffbd93a8e56ed10b3b2e854f2f160 │ │ ├─4309 bash /app/entrypoint.sh │ │ ├─4357 ./aws-k8s-agent │ │ └─4358 tee -i aws-k8s-agent.log │ └─pod637abaec-5fc8-4855-9952-ac08730384df │ ├─1ed3616be7204d70dda58c0ac3a6060fd26b6d595b0a832604cb9b5b777bb91e │ │ └─3629 /pause │ └─f703824f768510f7b8dfd989c8f64d8784cb201d7fe81949a000baed59c869c3 │ └─3911 kube-proxy --v=2 --config=/var/lib/kube-proxy-config/config ├─user.slice │ └─user-1000.slice │ └─session-1.scope │ ├─4928 sshd: ec2-user [priv] │ ├─5012 sshd: ec2-user@pts/0 │ ├─5036 -bash │ ├─5058 sudo -s │ ├─5060 /bin/bash │ ├─5640 systemd-cgls │ └─5641 less ├─system.slice │ ├─rngd.service │ │ └─1866 /sbin/rngd -f --fill-watermark=0 --exclude=jitter │ ├─irqbalance.service │ │ └─1853 /usr/sbin/irqbalance --foreground │ ├─amazon-ssm-agent.service │ │ ├─2363 /usr/bin/amazon-ssm-agent │ │ └─2519 /usr/bin/ssm-agent-worker │ ├─containerd.service │ │ ├─2800 /usr/bin/containerd │ │ ├─3577 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 1ed3616be7204d70dda58c0ac3a6060fd26b6d595b0a832604cb9b5b777bb91e -address /run/containerd/containerd.sock │ │ ├─3578 /usr/bin/containerd-shim-runc-v2 -namespace moby -id 5724c33afacf82531d99d78fcea7b5b07b54105d2729b20953eb3e6a3da9dcfb -address /run/containerd/containerd.sock │ │ ├─3887 /usr/bin/containerd-shim-runc-v2 -namespace moby -id f703824f768510f7b8dfd989c8f64d8784cb201d7fe81949a000baed59c869c3 -address /run/containerd/containerd.sock │ │ └─4279 /usr/bin/containerd-shim-runc-v2 -namespace moby -id b263bef8f5b3aff3df5430cc05551a42d72ffbd93a8e56ed10b3b2e854f2f160 -address /run/containerd/containerd.sock │ ├─systemd-udevd.service │ │ └─1686 /usr/lib/systemd/systemd-udevd │ ├─system-serial\x2dgetty.slice │ │ └─serial-getty@ttyS0.service │ │ └─2375 /sbin/agetty --keep-baud 115200,38400,9600 ttyS0 vt220 │ ├─docker.service │ │ └─2877 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock │ ├─chronyd.service │ │ └─1884 /usr/sbin/chronyd │ ├─auditd.service │ │ └─1827 /sbin/auditd │ ├─kubelet.service │ │ └─3146 /usr/bin/kubelet --cloud-provider aws --config /etc/kubernetes/kubelet/kubelet-config.json --kubeconfig /var/lib/kubelet/kubeconfig --container-runtime docker --network-plugin cni --node-ip=10.0.102.145 --pod-infra-container-image=602401143452.dkr.ecr.ap-northe │ ├─systemd-journald.service │ │ └─1285 /usr/lib/systemd/systemd-journald │ ├─sshd.service │ │ └─2416 /usr/sbin/sshd -D │ ├─crond.service │ │ └─2373 /usr/sbin/crond -n │ ├─gssproxy.service │ │ └─1888 /usr/sbin/gssproxy -D │ ├─rsyslog.service │ │ └─2365 /usr/sbin/rsyslogd -n │ ├─rpcbind.service │ │ └─1867 /sbin/rpcbind -w │ ├─network.service │ │ ├─2087 /sbin/dhclient -q -lf /var/lib/dhclient/dhclient--eth0.lease -pf /var/run/dhclient-eth0.pid eth0 │ │ └─2123 /sbin/dhclient -6 -nw -lf /var/lib/dhclient/dhclient6--eth0.lease -pf /var/run/dhclient6-eth0.pid eth0 │ ├─lvm2-lvmetad.service │ │ └─1301 /usr/sbin/lvmetad -f │ ├─postfix.service │ │ ├─2285 /usr/libexec/postfix/master -w │ │ ├─2286 pickup -l -t unix -u │ │ └─2287 qmgr -l -t unix -u │ ├─dbus.service │ │ └─1860 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation │ ├─system-getty.slice │ │ └─getty@tty1.service │ │ └─2374 /sbin/agetty --noclear tty1 linux │ └─systemd-logind.service │ └─1864 /usr/lib/systemd/systemd-logind └─K8s └─2877 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
dockerd servcie 用 cgroup の K8s が作成されている事がわかります。cgroup K8s のリソースが --kube-reserved
に設定した値で制限されるように etc/systemd/system/kubelet.service
を修正して kubelet を再起動します。
@node$ cat /etc/systemd/system/kubelet.service [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/kubernetes/kubernetes After=docker.service iptables-restore.service Requires=docker.service [Service] ExecStartPre=/sbin/iptables -P FORWARD ACCEPT -w 5 ExecStart=/usr/bin/kubelet --cloud-provider aws \ --config /etc/kubernetes/kubelet/kubelet-config.json \ --kubeconfig /var/lib/kubelet/kubeconfig \ --container-runtime docker \ --network-plugin cni $KUBELET_ARGS $KUBELET_EXTRA_ARGS \ --enforce-node-allocatable=pods,kube-reserved \ --kube-reserved-cgroup=/K8s Restart=always RestartSec=5 KillMode=process [Install] WantedBy=multi-user.target @node$ systemctl daemon-reload @node$ systemctl restart kubelet
kubelet 再起動後に cgroup K8s を確認すると cpu が --kube-reserved
に設定した 70m で制限されていました。
@node$ cat /sys/fs/cgroup/cpu/K8s/cpu.shares
71
--enforce-node-allocatable=kube-reserved,system-reserved
と --kube-reserved-cgroup/--system-reserved-cgroup
を設定する事で、--kube-reserved/--system-reserved
に設定した値で Kubernetes/OS のリソースを制限できる事がわかりました。
マネージドではない手組みの Kubernetes の場合は、Kubernetes/OS 用に cgroup を作成してそれぞれのリソースを制限するという使い方が可能という事かと思います。
なお、cpu.shares は相対値のためリソースに空きがあれば設定された数値より多くのリソースを使用する事が可能です。
5. まとめ
上記の検証結果によるまとめです。
--enforce-node-allocatable=kube-reserved,system-reserved
なし--kube-reserved-cgroup/--system-reserved-cgroup
なしの場合- 特定のプロセス用にリソースを確保しているわけではなく、単純に Pod が使えないリソースというだけ
--kube-reserved
と--system-reserved
は同じ意味(そのため EKS では--kube-reserved
のみ設定)
--enforce-node-allocatable=kube-reserved,system-reserved
あり--kube-reserved-cgroup/--system-reserved-cgroup
ありの場合- 指定した cgroup に対してリソースを制限する事が可能
- どのプロセスをどのようにグループ(cgroup)化し、どれぐらいリソースを割り当てるかという設計が必要
- (個人的には)EKS 等のマネージドサービスの場合はこれらの値を気にしなくて良い(クラウドベンダの設計にまかせて、何か問題が起きた際に考える)
6. 参考
Reserve Compute Resources for System Daemons | Kubernetes
design-proposals-archive/node-allocatable.md at main · kubernetes/design-proposals-archive · GitHub