创建pod
resources:
limits:
cpu: "4"
memory: 4Gi
nvidia.com/gpu: "1"
requests:
cpu: "4"
memory: 4Gi
nvidia.com/gpu: "1"
# cat /sys/fs/cgroup/memory/memory.limit_in_bytes
4294967296 / 4G
1 |
|
可见变量占用字节数: 64 + 8*(n-1)
# cat /sys/fs/cgroup/memory/memory.limit_in_bytes
4294967296
# cat /sys/fs/cgroup/memory/memory.usage_in_bytes
78319616
理论上可以申请的数组长度n =((4294967296 - 78319616) - 64)/8 + 1 = 527080953
用这个值指导数组长度的创建
>>> my_list = [0]*526000000
>>> import sys
>>> print(sys.getsizeof(my_list))
4208000056
# cat /sys/fs/cgroup/memory/memory.usage_in_bytes
4294369280
容器剩余的内存字节byte
4294967296 - 4294369280 = 598016 字节
理论上可再创建的数组长度是(598016 - 64 )/8 + 1 = 74745
个
创建长度为10w的数组,进程因为oom而被杀死。
>>> my_list5 = [0]*100000
Killed
在容器中查看memory控制组管理的进程, 均为容器中启动的进程。从而可以控制整个容器所使用的系统资源
# cat /sys/fs/cgroup/memory/tasks
1
11
12
15
26
64
75
157
212
root@ruike-gpu-instance-1698738579-jqri0boj-557db69f4c-z95w2:/sys/fs/cgroup/memory# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:49 ? 00:00:00 /bin/bash /start.sh
root 11 1 0 07:49 ? 00:00:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 s
root 12 1 0 07:49 ? 00:00:01 /usr/bin/python3 /usr/local/bin/jupyter-lab --Se
root 15 11 0 07:50 ? 00:00:00 sshd: root@pts/0
root 26 15 0 07:50 pts/0 00:00:00 -bash
root 64 11 0 07:56 ? 00:00:00 sshd: root@pts/1
root 75 64 0 07:56 pts/1 00:00:00 -bash
root 157 0 0 12:31 pts/2 00:00:00 bash
root 216 157 0 13:05 pts/2 00:00:00 ps -ef
当在容器中执行top/free等命令时,容器侧和host侧看到的信息事一致的,这是因为
在调用libcontaienr
库时将/proc
、/dev
、/dev/shm
、/sys
目录以只读方式挂载(bind mount)到容器中,同时还会建立以下几个链接:
/proc/self/fd->/dev/fd
/proc/self/fd/0->/dev/stdin
/proc/self/fd/1->/dev/stdout
/proc/self/fd/2->/dev/stder
这样做的道理事保证系统 IO 不会出现问题,容器运行的进程和系统运行的进程查看操作系统事等价的。
而像free,top等命令会调用该挂在的目录, 所以呈现事一致的。
# strace free
execve("/usr/bin/free", ["free"], [/* 66 vars */]) = 0
...
statfs("/sys/fs/selinux", 0x7ffec90733a0) = -1 ENOENT (No such file or directory)
statfs("/selinux", 0x7ffec90733a0) = -1 ENOENT (No such file or directory)
open("/proc/filesystems", O_RDONLY) = 3
...
open("/sys/devices/system/cpu/online", O_RDONLY|O_CLOEXEC) = 3
...
open("/proc/meminfo", O_RDONLY) = 3
总结
1、Docker 是利用 CGroups 实现资源限制的,只能限制资源消耗的最大值,而不能隔绝其他程序占用自己的资源;
2、Namespace 的6项隔离看似完整,实际上依旧没有完全隔离 Linux 资源,比如/proc 、/sys 、/dev/sd*等目录未完全隔离,SELinux、time、syslog 等所有现有 Namespace 之外的信息都未隔离。
3. 内存是不可压缩资源,超过会出发oom将进程killed。其他进程还活着,而cpu是可压缩资源,超过不会被killed.
note
k8s | docker | 作用 |
---|---|---|
requests.cpu | –cpu-shares | 当一个宿主机上有多个容器发生 CPU资源竞争时这个参数就会生效,参数值越大,越容易被分配到 CPU |
requests.memory | 没有使用 | 在 Kubernetes 的资源 QoS 管理时使用 |
limits.cpu | –cpu-quota | 另外一个参数–cpu-period 默认设置为100000,通过这两个参数限制容器最多能够使用的CPU核数 |
limits.memory | –memory | 限制容器内存 |
查看容器真实使用的资源
1、读取容器 CPU 核数
# 这个值除以100000得到的就是容器核数
~# cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us
400000
2、获取容器内存使用情况(USAGE / LIMIT)
~ # cat /sys/fs/cgroup/memory/memory.usage_in_bytes
4289953792
~ # cat /sys/fs/cgroup/memory/memory.limit_in_bytes
4294967296
3、获取容器是否被设置了 OOM,是否发生过 OOM
~ # cat /sys/fs/cgroup/memory/memory.oom_control
4、获取容器磁盘I/O
~ # cat /sys/fs/cgroup/blkio/blkio.throttle.io_service_bytes
5、获取容器虚拟网卡入/出流量
~ # cat /sys/class/net/eth0/statistics/rx_bytes
10167967741
~ # cat /sys/class/net/eth0/statistics/tx_bytes
15139291335