# Docker核心技术(二)cgroup资源使用限制

Docker核心技术-cgroup资源使用限制

cgroup(linux control group)

在了解了通过namespace可以实现在linux上对于资源隔离的管控,那么还有一个问题就是,我们即使通过namespace将不同进程隔离开,那么加入其中一个进程耗尽了主机的所有CPU和内存资源,那么其他进程即使通过ns进行了隔离,但因为主机没有可用的CPU和内存,那么也是无法工作的,另外我们也知道docker可以控制容器所使用的CPU和内存等资源,那么是怎么做到的呢?带着这些问题我们来看看linux是怎么通过cgroup来实现资源的控制和限制的。

cgroup示例

在linux中一切皆是文件,那么cgroup对于资源的限制肯定也是通过文件来实现的,我们可以在/sys/fs/cgroup目录中看到限制的对象。

[root@i-l7l18s0l cgroup]# pwd
/sys/fs/cgroup
[root@i-l7l18s0l cgroup]# ls cpu
cgroup.clone_children  cgroup.procs          cpuacct.stat   cpuacct.usage_percpu  cpu.cfs_quota_us  cpu.rt_runtime_us  cpu.stat  notify_on_release  system.slice  user.slice
cgroup.event_control   cgroup.sane_behavior  cpuacct.usage  cpu.cfs_period_us     cpu.rt_period_us  cpu.shares         docker    release_agent      tasks
[root@i-l7l18s0l cgroup]#
复制代码

查看cpu下的文件可以看到cfs_period_us和cfs_quota_us,通过组合使用这两个参数可以实现,限制进程在cfs_period_us的一段时间,只能被分配到总量为cfs_quota_us的CPU,下面我们通过一个示例来演示如何限制。

在/sys/fs/cgroup/cpu下新建一个new-cpu-limit目录, 同时查看目录可以看到对应的限制文件也会自动进行创建。

[root@i-l7l18s0l cpu]# mkdir new_cpu_limit
[root@i-l7l18s0l cpu]# ls
cgroup.clone_children  cgroup.procs          cpuacct.stat   cpuacct.usage_percpu  cpu.cfs_quota_us  cpu.rt_runtime_us  cpu.stat  new_cpu_limit      release_agent  tasks
cgroup.event_control   cgroup.sane_behavior  cpuacct.usage  cpu.cfs_period_us     cpu.rt_period_us  cpu.shares         docker    notify_on_release  system.slice   user.slice
[root@i-l7l18s0l cpu]#
[root@i-l7l18s0l cpu]# ls new_cpu_limit/
cgroup.clone_children  cgroup.procs  cpuacct.usage         cpu.cfs_period_us  cpu.rt_period_us   cpu.shares  notify_on_release
cgroup.event_control   cpuacct.stat  cpuacct.usage_percpu  cpu.cfs_quota_us   cpu.rt_runtime_us  cpu.stat    tasks
[root@i-l7l18s0l cpu]#
复制代码

写一个死循环占满CPU

[root@docker cpu]# while : ; do : ; done &
[1] 9240
[root@docker cpu]# top
复制代码

查看进程CPU使用率 image.png 查看new_cpu_limit目录下cfs_quota_us和cfs_period_us默认值

[root@docker cpu]# cd new_cpu_limit/
[root@docker new_cpu_limit]# cat cpu.cfs_quota_us
-1
[root@docker new_cpu_limit]# cat cpu.cfs_period_us
100000
[root@docker new_cpu_limit]#
复制代码

cpu.cfs_quota_us值为-1代表没有任何限制,cpu.cfs_period_us则是默认的100ms(100000us),接下来将new_cpu_limit控制组的cpu.cfs_quota_us文件写入50ms(50000),这表示在100ms周期内,cpu最多使用50%,同时将该进程的pid=9240写入对应的tasks文件,表示对pid=9240进程限制:

[root@docker new_cpu_limit]# echo 50000 > cpu.cfs_quota_us
[root@docker new_cpu_limit]# echo 9240 > tasks
复制代码

再次查看CPU使用率,检查是否cgroup控制生效,通过下面截图可以看到进程的cpu使用率降到了50%,也就是说我们的配置生效了 image.png 通过以上例子可以知道linux是怎么限制进程的资源使用情况的。

docker容器资源限制

上面的示例讲解了linux对于资源的限制,那么我们接下来看下docker对于容器资源的限制是怎么做的。 通过命令docker inspect $containerId --format {{}}

[root@docker ~]# docker inspect 583d44c9ac18
[root@docker ~]# docker inspect 583d44c9ac18
[
    {
        "Id": "583d44c9ac18f0134be6529b448539196c895b137db2aa77b54317a22e3f9f51",
        "Created": "2022-01-29T07:53:17.061823755Z",
        "Path": "./go-gin",
        "Args": [],
        "State": {
            ...
        },
        "Image": ...,
        "LogPath": "",
        "Name": "/relaxed_meninsky",
        "RestartCount": 0,
        "Driver": "overlay2",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": [
            "96e6e59418b86d5241733d6cb66e9f3872ad72ae30c1da0aa6789fab8ecce61b"
        ],
        "HostConfig": {
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "journald",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {},
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "Dns": ...,
            "ShmSize": 67108864,
            "Runtime": "docker-runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": null,
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DiskQuota": 0,
            "KernelMemory": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": -1,
            "OomKillDisable": false,
            "PidsLimit": 0,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0
        },
        "GraphDriver": {
            "Name": "overlay2",
            "Data": ...
            }
        },
        "Mounts": [],
        "Config": {
            "Hostname": "583d44c9ac18",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "8888/tcp": {}
            },
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": false,
            "Env": ...,
            "Cmd": null,
            "ArgsEscaped": true,
            "Image": "13227829078/gogin:v1.0",
            "Volumes": null,
            "WorkingDir": "/app",
            "Entrypoint": [
                "./go-gin"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",,
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    ...
                }
            }
        }
    }
]
复制代码

在{{.HosConfig}}中可以看到对于容器资源的限制,如图显示默认没有配置资源的限制,这是时候我们查看下对应的cgroup下文件是不是这样的。

[root@docker cpu]# pwd
/sys/fs/cgroup/cpu
[root@docker cpu]# ls
aegis   cgroup.clone_children  cgroup.procs          cpuacct.stat   cpuacct.usage_percpu  cpu.cfs_quota_us  cpu.rt_runtime_us  cpu.stat       notify_on_release  system.slice  user.slice
assist  cgroup.event_control   cgroup.sane_behavior  cpuacct.usage  cpu.cfs_period_us     cpu.rt_period_us  cpu.shares         new_cpu_limit  release_agent      tasks
[root@docker cgroup]# cat cpu/system.slice/docker-583d44c9ac18f0134be6529b448539196c895b137db2aa77b54317a22e3f9f51.scope/cpu.cfs_period_us
100000
[root@docker cgroup]# cat cpu/system.slice/docker-583d44c9ac18f0134be6529b448539196c895b137db2aa77b54317a22e3f9f51.scope/cpu.cfs_quota_us
-1
复制代码

可以看到在目录重新启动一个容器cpu/system.slice/docker-583d44c9ac18f0134be6529b448539196c895b137db2aa77b54317a22e3f9f51.scope下,确实有对应的限制文件,也是cgroup的默认参数。那么我们在重新启动一个容器,添加上对于cpu的限制再次查看

[root@docker cpu]# docker run -it -d --cpu-quota=50000 --cpu-period=120000 --name gogin 13227829078/gogin:v1.0
23cd79c0b5d73a395c2c6bfd2358c120523680ce047f447a867b8e51698ec31c
[root@docker cpu]# docker ps
CONTAINER ID        IMAGE                    COMMAND             CREATED             STATUS              PORTS               NAMES
23cd79c0b5d7        13227829078/gogin:v1.0   "./go-gin"          2 seconds ago       Up 2 seconds        8888/tcp            gogin
583d44c9ac18        13227829078/gogin:v1.0   "./go-gin"          2 hours ago         Up 2 hours          8888/tcp            relaxed_meninsky
[root@docker cpu]# ls
aegis   cgroup.clone_children  cgroup.procs          cpuacct.stat   cpuacct.usage_percpu  cpu.cfs_quota_us  cpu.rt_runtime_us  cpu.stat       notify_on_release  system.slice  user.slice
assist  cgroup.event_control   cgroup.sane_behavior  cpuacct.usage  cpu.cfs_period_us     cpu.rt_period_us  cpu.shares         new_cpu_limit  release_agent      tasks
[root@docker cpu]# docker inspect 23cd79c0b5d7
复制代码

可以看到添加的限制已经被使用 image.png 查看对应的cpu限制文件内容也是我们设置的值

[root@docker cgroup]# cat cpu/system.slice/docker-23cd79c0b5d73a395c2c6bfd2358c120523680ce047f447a867b8e51698ec31c.scope/cpu.cfs_quota_us
50000
[root@docker cgroup]# cat cpu/system.slice/docker-23cd79c0b5d73a395c2c6bfd2358c120523680ce047f447a867b8e51698ec31c.scope/cpu.cfs_period_us
120000
复制代码

到这里我们也清楚了docker通过cgroup可以实现对于资源用量的限制,关于更多的docker资源限制的设置可以通过docker run --help来进行查看。

猜你喜欢

转载自juejin.im/post/7068910469850873886
今日推荐