暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Docker 与 K8S学习笔记(六)—— 容器的资源限制

SET技术干货 2021-10-02
1240

我们在启动Docker容器时,默认情况下容器所使用的资源是没有限制的,这样就会存在部分特别耗资源的容器会占用大量系统资源,从而导致其他容器甚至整个服务器性能降低,为此,Docker提供了一系列参数方便我们对容器的CPU、内存、IO等进行限制。

为了方便演示,我们这里使用progrium/stress镜像,这个镜像内置一个压力测试工具,通过它我们可以很方便进行实验。首先我们拉取此镜像:

    $ sudo docker pull progrium/stress
    Using default tag: latest
    latest: Pulling from progrium/stress
    Image docker.io/progrium/stress:latest uses outdated schema1 manifest format. Please upgrade to a schema2 image for better future compatibility. More information at https://docs.docker.com/registry/spec/deprecated-schema-v1/
    a3ed95caeb02: Pull complete
    871c32dbbb53: Pull complete
    dbe7819a64dd: Pull complete
    d14088925c6e: Pull complete
    58026d51efe4: Pull complete
    7d04a4fe1405: Pull complete
    1775fca35fb6: Pull complete
    5c319e267908: Pull complete
    Digest: sha256:e34d56d60f5caae79333cee395aae93b74791d50e3841986420d23c2ee4697bf
    Status: Downloaded newer image for progrium/stress:latest
    docker.io/progrium/stress:latest

    一、容器内存限制

    与操作系统类似,容器可使用的内存包括两部分:物理内存,Swap交换空间,因此Docker通过以下两个参数对内存资源进行限制:

    • -m或--memroy:设置内存使用限额

    • --memory-swap:设置内存和交换空间总大小,如果只设置-m而不设置此参数,则默认内存和交换空间总大小是-m的两倍

    例如我们按如下配置启动容器:我们设置内存为200M,内存与Swap总共300M,那么Swap就是100M。

      sudo docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M

      这里我们对stress进行设置:

      --vm 1:启动一个工作线程

      --vm-bytes:每个工作线程分配280M内存

        $ sudo docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
        WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
        stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
        stress: dbug: [1] using backoff sleep of 3000us
        stress: dbug: [1] --> hogvm worker 1 [7] forked
        stress: dbug: [7] allocating 293601280 bytes ...
        stress: dbug: [7] touching bytes in strides of 4096 bytes ...
        stress: dbug: [7] freed 293601280 bytes
        stress: dbug: [7] allocating 293601280 bytes ...
        stress: dbug: [7] touching bytes in strides of 4096 bytes ...
        stress: dbug: [7] freed 293601280 bytes
        stress: dbug: [7] allocating 293601280 bytes ...

        我们可以看到stress容器启动后不断在申请内存,释放内存,由于我们设置--vm-bytes 280M,所以它每次会申请280M内存空间,大家可能会注意到,容器启动后有一段告警信息:

        WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.

        这是因为我这边宿主机使用Ubuntu,在Ubuntu上默认是没有开启Swap限制的,这样就会导致容器的swap限制不生效,为了解决这个问题,我们需要先修改/etc/default/grub file 文件:

          $ sudo vim etc/default/grub file

          添加如下内容:

            GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"

            使用 sudo update-grub 更新系统的GRUB,并重启系统。

              $ sudo update-grub
              Sourcing file `/etc/default/grub'
              Sourcing file `/etc/default/grub.d/50-curtin-settings.cfg'
              Generating grub configuration file ...
              Found linux image: boot/vmlinuz-4.15.0-159-generic
              Found initrd image: boot/initrd.img-4.15.0-159-generic
              Found linux image: boot/vmlinuz-4.15.0-158-generic
              Found initrd image: boot/initrd.img-4.15.0-158-generic
              Found linux image: boot/vmlinuz-4.15.0-156-generic
              Found initrd image: /boot/initrd.img-4.15.0-156-generic
              Found linux image: /boot/vmlinuz-4.15.0-154-generic
              Found initrd image: /boot/initrd.img-4.15.0-154-generic
              done

              OK,解决了这个问题后我们继续内存限额的实现,我们这次将vm-bytes设置为310M,看看会有什么样的效果:

                $ sudo docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 310M
                stress: info: [1] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
                stress: dbug: [1] using backoff sleep of 3000us
                stress: dbug: [1] --> hogvm worker 1 [7] forked
                stress: dbug: [7] allocating 325058560 bytes ...
                stress: dbug: [7] touching bytes in strides of 4096 bytes ...
                stress: FAIL: [1] (416) <-- worker 7 got signal 9
                stress: WARN: [1] (418) now reaping child worker processes
                stress: FAIL: [1] (422) kill error: No such process
                stress: FAIL: [1] (452) failed run completed in 0s

                我们可以看到,当线程每次申请的内存大于300M的时候会stress线程报错,容器退出。


                二、容器的CPU限制

                默认情况下,所有容器都可以平等使用宿主机的CPU而没有限制,Docker提供-c或--cpu-share参数用于设置容器的CPU权重,如果不指定则默认为1024。与内存限制不同,-c设置的并不是容器使用CPU的核的数量,而是相对的权重值,某个容器最终能分配到的CPU资源取决于它的cpu share占所有容器cpu share总和的比例,也就是说-c可以决定容器CPU优先级。

                我们首先启动containerA,cpu share为1024:

                  $ sudo docker run --name containerA -it -c 1024 progrium/stress --cpu 2
                  stress: info: [1] dispatching hogs: 2 cpu, 0 io, 0 vm, 0 hdd
                  stress: dbug: [1] using backoff sleep of 6000us
                  stress: dbug: [1] --> hogcpu worker 2 [8] forked
                  stress: dbug: [1] using backoff sleep of 3000us
                  stress: dbug: [1] --> hogcpu worker 1 [9] forked

                  接着启动containerB,cpu share为512:

                    $ sudo docker run --name containerB -it -c 512 progrium/stress --cpu 2
                    stress: info: [1] dispatching hogs: 2 cpu, 0 io, 0 vm, 0 hdd
                    stress: dbug: [1] using backoff sleep of 6000us
                    stress: dbug: [1] --> hogcpu worker 2 [8] forked
                    stress: dbug: [1] using backoff sleep of 3000us
                    stress: dbug: [1] --> hogcpu worker 1 [9] forked

                    PS:注意我们要确保stress容器能够将host的cpu拉满这样才能确保实验效果,所以大家在实验时要注意看自己的宿主机CPU有多少个,例如我的机器cpu为2,所以在启动stress容器时--cpu也设置为2。


                    我们在宿主机上通过top命令能够明显看出效果:containerA消耗的CPU是containerB的两倍:


                    文章转载自SET技术干货,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                    评论