zoukankan      html  css  js  c++  java
  • 004-docker命令-容器生命周期:run、stop、start、restart、kill、rm、create、exec;容器操作:ps、inspect、top、log,cp,docker配置限制

    一、容器生命周期管理

    1.1、启动命令docker run

      创建一个新的容器并运行一个命令[更多]

      语法:docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

      OPTIONS说明:

    -a stdin: 指定标准输入输出内容类型,可选 STDIN/STDOUT/STDERR 三项;
    -d: 后台运行容器,并返回容器ID;
    -i: 以交互模式运行容器,通常与 -t 同时使用;
    -P: 随机端口映射,容器内部端口随机映射到主机的高端口
    -p: 指定端口映射,格式为:主机(宿主)端口:容器端口
    -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
    --name="nginx-lb": 为容器指定一个名称;
    --dns 8.8.8.8: 指定容器使用的DNS服务器,默认和宿主一致;
    --dns-search example.com: 指定容器DNS搜索域名,默认和宿主一致;
    -h "mars": 指定容器的hostname;
    -e username="ritchie": 设置环境变量;
    --env-file=[]: 从指定文件读入环境变量;
    --cpuset="0-2" or --cpuset="0,1,2": 绑定容器到指定CPU运行;
    -m :设置容器使用内存最大值;
    --net="bridge": 指定容器的网络连接类型,支持 bridge/host/none/container: 四种类型;
    --link=[]: 添加链接到另一个容器;
    --expose=[]: 开放一个端口或一组端口;
    --volume , -v: 绑定一个卷
    --privileged, 容器内root拥有真正的root权限

      示例:

    使用docker镜像nginx:latest以后台模式启动一个容器,并将容器命名为mynginx。
    
    docker run --name mynginx -d nginx:latest
    使用镜像nginx:latest以后台模式启动一个容器,并将容器的80端口映射到主机随机端口。
    
    docker run -P -d nginx:latest
    使用镜像 nginx:latest,以后台模式启动一个容器,将容器的 80 端口映射到主机的 80 端口,主机的目录 /data 映射到容器的 /data。
    
    docker run -p 80:80 -v /data:/data -d nginx:latest
    绑定容器的 8080 端口,并将其映射到本地主机 127.0.0.180 端口上。
    
    $ docker run -p 127.0.0.1:80:8080/tcp ubuntu bash
    使用镜像nginx:latest以交互模式启动一个容器,在容器内执行/bin/bash命令。
    
    runoob@runoob:~$ docker run -it nginx:latest /bin/bash
    root@b8573233d675:/# 
    View Code 

    docker start :启动一个或多个已经被停止的容器

    docker stop :停止一个运行中的容器

    docker restart :重启容器

      示例

    启动已被停止的容器myrunoob:docker start myrunoob
    停止运行中的容器myrunoob:docker stop myrunoob
    重启容器myrunoob:docker restart myrunoob

    docker kill :杀掉一个运行中的容器。

      语法:docker kill [OPTIONS] CONTAINER [CONTAINER...]

       OPTIONS说明:

    -s :向容器发送一个信号

      示例、docker kill -s KILL mynginx

    docker rm :删除一个或多少容器

      语法:docker rm [OPTIONS] CONTAINER [CONTAINER...]

      OPTIONS说明:

    -f :通过SIGKILL信号强制删除一个运行中的容器
    
    -l :移除容器间的网络连接,而非容器本身
    
    -v :-v 删除与容器关联的卷

      示例:

    强制删除容器db01、db02:docker rm -f db01 db02
    移除容器nginx01对容器db01的连接,连接名db:docker rm -l db 
    删除容器nginx01,并删除容器挂载的数据卷:docker rm -v nginx01

    docker pause :暂停容器中所有的进程。

    docker unpause :恢复容器中所有的进程。

      示例

    暂停数据库容器db01提供服务:docker pause db01
    恢复数据库容器db01提供服务:docker unpause db01

    docker create :创建一个新的容器但不启动它

      语法同run 

    docker exec :在运行的容器中执行命令

      OPTIONS说明:

    -d :分离模式: 在后台运行
    
    -i :即使没有附加也保持STDIN 打开
    
    -t :分配一个伪终端

    示例:在容器mynginx中以交互模式执行容器内/root/runoob.sh脚本

        docker exec -it mynginx /bin/sh /root/runoob.sh

      在容器mynginx中开启一个交互模式的终端

        docker exec -i -t mynginx /bin/bash

    2、容器操作

    docker ps : 列出容器

      OPTIONS说明:

    • -a :显示所有的容器,包括未运行的。

    • -f :根据条件过滤显示的内容。 

    • --format :指定返回值的模板文件。

    • -l :显示最近创建的容器。

    • -n :列出最近创建的n个容器。

    • --no-trunc :不截断输出。

    • -q :静默模式,只显示容器编号。

    • -s :显示总的文件大小。

    docker inspect : 获取容器/镜像的元数据。

      OPTIONS说明:

    • -f :指定返回值的模板文件。

    • -s :显示总的文件大小。

    • --type :为指定类型返回JSON。

      示例:mysql 5.6信息:docker inspect mysql:5.6;

        获取正在运行的容器mymysql的 IP:docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mymysql

    docker top :查看容器中运行的进程信息,支持 ps 命令参数。

      语法:docker top [OPTIONS] CONTAINER [ps OPTIONS]

      容器运行时不一定有/bin/bash终端来交互执行top命令,而且容器还不一定有top命令,可以使用docker top来实现查看container中正在运行的进程。

      示例:查看容器mymysql的进程信息:docker top mymysql

        查看所有运行容器的进程信息:for i in `docker ps |grep Up|awk '{print $1}'`;do echo &&docker top $i; done

    docker attach :连接到正在运行中的容器。

      要attach上去的容器必须正在运行,可以同时连接上同一个container来共享屏幕(与screen命令的attach类似)。

      官方文档中说attach后可以通过CTRL-C来detach,但实际上,如果container当前在运行bash,CTRL-C自然是当前行的输入,没有退出;如果container当前正在前台运行进程,如输出nginx的access.log日志,CTRL-C不仅会导致退出容器,而且还stop了。这不是我们想要的,detach的意思按理应该是脱离容器终端,但容器依然运行。好在attach是可以带上--sig-proxy=false来确保CTRL-D或CTRL-C不会关闭容器。

      示例:容器mynginx将访问日志指到标准输出,连接到容器查看访问信息

        docker attach --sig-proxy=false mynginx

    docker events : 从服务器获取实时事件【参看

    docker logs : 获取容器的日志

      OPTIONS说明:

    • -f : 跟踪日志输出

    • --since :显示某个开始时间的所有日志

    • -t : 显示时间戳

    • --tail :仅列出最新N条容器日志

      示例:跟踪查看容器mynginx的日志输出:docker logs -f mynginx

        查看容器mynginx从2016年7月1日后的最新10条日志:docker logs --since="2016-07-01" --tail=10 mynginx

    docker wait : 阻塞运行直到容器停止,然后打印出它的退出代码。

    docker export :将文件系统作为一个tar归档文件导出到STDOUT。

    docker port :列出指定的容器的端口映射,或者查找将PRIVATE_PORT NAT到面向公众的端口。

      示例:查看容器mynginx的端口映射情况:docker port mymysql

    docker cp

      从容器里面拷文件到宿主机

        在宿主机里面执行以下命令:docker cp 容器名:要拷贝的文件在容器里面的路径       要拷贝到宿主机的相应路径

        示例:docker cp testtomcat:/usr/local/tomcat/webapps/test/js/test.js /opt

      从宿主机拷文件到容器里面

        在宿主机里面执行如下命令:docker cp 要拷贝的文件路径 容器名:要拷贝到容器里面对应的路径

        示例:docker cp /opt/test.js testtomcat:/usr/local/tomcat/webapps/test/js

     二、docker资源配置-Docker容器CPU、memory资源限制

      在使用 docker 运行容器时,默认的情况下,docker没有对容器进行硬件资源的限制,当一台主机上运行几百个容器,这些容器虽然互相隔离,但是底层却使用着相同的 CPU、内存和磁盘资源。如果不对容器使用的资源进行限制,那么容器之间会互相影响,小的来说会导致容器资源使用不公平;大的来说,可能会导致主机和集群资源耗尽,服务完全不可用。

      docker 作为容器的管理者,自然提供了控制容器资源的功能。正如使用内核的 namespace 来做容器之间的隔离,docker 也是通过内核的 cgroups 来做容器的资源限制;包括CPU、内存、磁盘三大方面,基本覆盖了常见的资源配额和使用量控制。

      Docker内存控制OOME在linxu系统上,如果内核探测到当前宿主机已经没有可用内存使用,那么会抛出一个OOME(Out Of Memory Exception:内存异常 ),并且会开启killing去杀掉一些进程。

      一旦发生OOME,任何进程都有可能被杀死,包括docker daemon在内,为此,docker特地调整了docker daemon的OOM_Odj优先级,以免他被杀掉,但容器的优先级并未被调整。经过系统内部复制的计算后,每个系统进程都会有一个OOM_Score得分,OOM_Odj越高,得分越高,(在docker run的时候可以调整OOM_Odj)得分最高的优先被kill掉,当然,也可以指定一些特定的重要的容器禁止被OMM杀掉,在启动容器时使用 –oom-kill-disable=true指定。

      启动容器后,可以使用docker 的监控指令查看容器的运行状态

    • docker top 容器名: 查看容器的进程,不加容器名即查看所有
    • docker stats 容器名:查看容器的CPU,内存,IO 等使用信息

    2.1、cgroup简介

    cgroup是Control Groups的缩写,是Linux 内核提供的一种可以限制、记录、隔离进程组所使用的物理资源(如 cpu、memory、磁盘IO等等) 的机制,被LXC、docker等很多项目用于实现进程资源控制。cgroup将任意进程进行分组化管理的 Linux 内核功能。cgroup本身是提供将进程进行分组化管理的功能和接口的基础结构,I/O 或内存的分配控制等具体的资源管理功能是通过这个功能来实现的。这些具体的资源管理功能称为cgroup子系统,有以下几大子系统实现:

    blkio:设置限制每个块设备的输入输出控制。例如:磁盘,光盘以及usb等等。
    cpu:使用调度程序为cgroup任务提供cpu的访问。
    cpuacct:产生cgroup任务的cpu资源报告。
    cpuset:如果是多核心的cpu,这个子系统会为cgroup任务分配单独的cpu和内存。
    devices:允许或拒绝cgroup任务对设备的访问。
    freezer:暂停和恢复cgroup任务。
    memory:设置每个cgroup的内存限制以及产生内存资源报告。
    net_cls:标记每个网络包以供cgroup方便使用。
    ns:命名空间子系统。
    perf_event:增加了对每group的监测跟踪的能力,即可以监测属于某个特定的group的所有线程以及运行在特定CPU上的线程。
    目前docker只是用了其中一部分子系统,实现对资源配额和使用的控制。

    2.2、内存限制

    Docker 提供的内存限制功能有以下几点:

    • 容器能使用的内存和交换分区大小。
    • 容器的核心内存大小。
    • 容器虚拟内存的交换行为。
    • 容器内存的软性限制。
    • 是否杀死占用过多内存的容器。
    • 容器被杀死的优先级

    一般情况下,达到内存限制的容器过段时间后就会被系统杀死。

    内存限制相关的参数

    执行docker run命令时能使用的和内存限制相关的所有选项如下。

    选项描述
    -m,--memory 内存限制,格式是数字加单位,单位可以为 b,k,m,g。最小为 4M
    --memory-swap 内存+交换分区大小总限制。格式同上。必须必-m设置的大
    --memory-reservation 内存的软性限制。格式同上
    --oom-kill-disable 是否阻止 OOM killer 杀死容器,默认没设置
    --oom-score-adj 容器被 OOM killer 杀死的优先级,范围是[-1000, 1000],默认为 0
    --memory-swappiness 用于设置容器的虚拟内存控制行为。值为 0~100 之间的整数
    --kernel-memory 核心内存限制。格式同上,最小为 4M

    2.2.1、用户内存限制

    用户内存限制就是对容器能使用的内存和交换分区的大小作出限制。使用时要遵循两条直观的规则:-m,--memory选项的参数最小为 4 M。--memory-swap不是交换分区,而是内存加交换分区的总大小,所以--memory-swap必须比-m,--memory大。在这两条规则下,一般有四种设置方式。

    你可能在进行内存限制的实验时发现docker run命令报错:WARNING: Your kernel does not support swap limit capabilities, memory limited without swap.

    这是因为宿主机内核的相关功能没有打开。按照下面的设置就行。

    step 1:编辑/etc/default/grub文件,将GRUB_CMDLINE_LINUX一行改为GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"

    step 2:更新 GRUB,即执行$ sudo update-grub

    step 3: 重启系统。

    1. 不设置

    如果不设置-m,--memory--memory-swap,容器默认可以用完宿舍机的所有内存和 swap 分区。不过注意,如果容器占用宿主机的所有内存和 swap 分区超过一段时间后,会被宿主机系统杀死(如果没有设置--00m-kill-disable=true的话)。

    2. 设置-m,--memory,不设置--memory-swap

    -m--memory设置一个不小于 4M 的值,假设为 a,不设置--memory-swap,或将--memory-swap设置为 0。这种情况下,容器能使用的内存大小为 a,能使用的交换分区大小也为 a。因为 Docker 默认容器交换分区的大小和内存相同。

    如果在容器中运行一个一直不停申请内存的程序,你会观察到该程序最终能占用的内存大小为 2a。

    比如$ docker run -m 1G ubuntu:16.04,该容器能使用的内存大小为 1G,能使用的 swap 分区大小也为 1G。容器内的进程能申请到的总内存大小为 2G。

    3. 设置-m,--memory=a--memory-swap=b,且b > a

    -m设置一个参数 a,给--memory-swap设置一个参数 b。a 时容器能使用的内存大小,b是容器能使用的 内存大小 + swap 分区大小。所以 b 必须大于 a。b -a 即为容器能使用的 swap 分区大小。

    比如$ docker run -m 1G --memory-swap 3G ubuntu:16.04,该容器能使用的内存大小为 1G,能使用的 swap 分区大小为 2G。容器内的进程能申请到的总内存大小为 3G。

    4. 设置-m,--memory=a--memory-swap=-1

    -m参数设置一个正常值,而给--memory-swap设置成 -1。这种情况表示限制容器能使用的内存大小为 a,而不限制容器能使用的 swap 分区大小。

    这时候,容器内进程能申请到的内存大小为 a + 宿主机的 swap 大小。

    2.2.2、Memory reservation

      Memory reservation 是一种软性限制,用于节制容器内存使用。给--memory-reservation设置一个比-m小的值后,虽然容器最多可以使用-m使用的内存大小,但在宿主机内存资源紧张时,在系统的下次内存回收时,系统会回收容器的部分内存页,强迫容器的内存占用回到--memory-reservation设置的值大小。

      没有设置时(默认情况下)--memory-reservation的值和-m的限定的值相同。将它设置为 0 会设置的比-m的参数大 等同于没有设置。

      Memory reservation 是一种软性机制,它不保证任何时刻容器使用的内存不会超过--memory-reservation限定的值,它只是确保容器不会长时间占用超过--memory-reservation限制的内存大小。

    例如:

    $ docker run -it -m 500M --memory-reservation 200M ubuntu:16.04 /bin/bash

    如果容器使用了大于 200M 但小于 500M 内存时,下次系统的内存回收会尝试将容器的内存锁紧到 200M 以下。

    例如:

    $ docker run -it --memory-reservation 1G ubuntu:16.04 /bin/bash

    容器可以使用尽可能多的内存。--memory-reservation确保容器不会长时间占用太多内存。

    2.2.3、OOM killer

      默认情况下,在出现 out-of-memory(OOM) 错误时,系统会杀死容器内的进程来获取更多空闲内存。这个杀死进程来节省内存的进程,可以通过设置--oom-kill-disable选项来禁止 OOM killer 杀死容器内进程。但请确保只有在使用了-m/--memory选项时才使用--oom-kill-disable禁用 OOM killer。如果没有设置-m选项,却禁用了 OOM-killer,可能会造成出现 out-of-memory 错误时,系统通过杀死宿主机进程或获取更改内存。

    下面的例子限制了容器的内存为 100M 并禁止了 OOM killer:

    $ docker run -it -m 100M --oom-kill-disable ubuntu:16.04 /bin/bash

    是正确的使用方法。

    而下面这个容器没设置内存限制,却禁用了 OOM killer 是非常危险的:

    $ docker run -it --oom-kill-disable ubuntu:16.04 /bin/bash

    容器没用内存限制,可能或导致系统无内存可用,并尝试时杀死系统进程来获取更多可用内存。

    一般一个容器只有一个进程,这个唯一进程被杀死,容器也就被杀死了。我们可以通过--oom-score-adj选项来设置在系统内存不够时,容器被杀死的优先级。负值更教不可能被杀死,而正值更有可能被杀死。

    2.2.4、核心内存

    核心内存和用户内存不同的地方在于核心内存不能被交换出。不能交换出去的特性使得容器可以通过消耗太多内存来堵塞一些系统服务。核心内存包括:

    • stack pages(栈页面)
    • slab pages
    • socket memory pressure
    • tcp memory pressure

    可以通过设置核心内存限制来约束这些内存。例如,每个进程都要消耗一些栈页面,通过限制核心内存,可以在核心内存使用过多时阻止新进程被创建。

    核心内存和用户内存并不是独立的,必须在用户内存限制的上下文中限制核心内存。

    假设用户内存的限制值为 U,核心内存的限制值为 K。有三种可能地限制核心内存的方式:

    1. U != 0,不限制核心内存。这是默认的标准设置方式
    2. K < U,核心内存时用户内存的子集。这种设置在部署时,每个 cgroup 的内存总量被过度使用。过度使用核心内存限制是绝不推荐的,因为系统还是会用完不能回收的内存。在这种情况下,你可以设置 K,这样 groups 的总数就不会超过总内存了。然后,根据系统服务的质量自有地设置 U。
    3. K > U,因为核心内存的变化也会导致用户计数器的变化,容器核心内存和用户内存都会触发回收行为。这种配置可以让管理员以一种统一的视图看待内存。对想跟踪核心内存使用情况的用户也是有用的。

    例如:

    $ docker run -it -m 500M --kernel-memory 50M ubuntu:16.04 /bin/bash

    容器中的进程最多能使用 500M 内存,在这 500M 中,最多只有 50M 核心内存。

    $ docker run -it --kernel-memory 50M ubuntu:16.04 /bin/bash

    没用设置用户内存限制,所以容器中的进程可以使用尽可能多的内存,但是最多能使用 50M 核心内存。

    2.2.5、Swappiness

    默认情况下,容器的内核可以交换出一定比例的匿名页。--memory-swappiness就是用来设置这个比例的。--memory-swappiness可以设置为从 0 到 100。0 表示关闭匿名页面交换。100 表示所有的匿名页都可以交换。默认情况下,如果不适用--memory-swappiness,则该值从父进程继承而来。

    例如:

    $ docker run -it --memory-swappiness=0 ubuntu:16.04 /bin/bash

    --memory-swappiness设置为 0 可以保持容器的工作集,避免交换代理的性能损失。

    $ docker run -tid —name mem1 —memory 128m ubuntu:16.04 /bin/bash
    $ cat /sys/fs/cgroup/memory/docker/<容器的完整ID>/memory.limit_in_bytes
    $ cat /sys/fs/cgroup/memory/docker/<容器的完整ID>/memory.memsw.limit_in_bytes

    2.3、CPU 限制

      Docker 的资源限制和隔离完全基于 Linux cgroups。对 CPU 资源的限制方式也和 cgroups 相同。Docker 提供的 CPU 资源限制选项可以在多核系统上限制容器能利用哪些 vCPU。而对容器最多能使用的 CPU 时间有两种限制方式:一是有多个 CPU 密集型的容器竞争 CPU 时,设置各个容器能使用的 CPU 时间相对比例。二是以绝对的方式设置容器在每个调度周期内最多能使用的 CPU 时间。

    CPU 限制相关参数

    docker run命令和 CPU 限制相关的所有选项如下:

    选项描述
    --cpuset-cpus="" 允许使用的 CPU 集,值可以为 0-3,0,1
    -c,--cpu-shares=0 CPU 共享权值(相对权重)
    cpu-period=0 限制 CPU CFS 的周期,范围从 100ms~1s,即[1000, 1000000]
    --cpu-quota=0 限制 CPU CFS 配额,必须不小于1ms,即 >= 1000
    --cpuset-mems="" 允许在上执行的内存节点(MEMs),只对 NUMA 系统有效

    其中--cpuset-cpus用于设置容器可以使用的 vCPU 核。-c,--cpu-shares用于设置多个容器竞争 CPU 时,各个容器相对能分配到的 CPU 时间比例。--cpu-period--cpu-quata用于绝对设置容器能使用 CPU 时间。

    --cpuset-mems暂用不上,这里不谈。

    2.3.1、CPU 集

    可以设置容器可以在哪些 CPU 核上运行。

    例如:

    $ docker run -it --cpuset-cpus="1,3" ubuntu:14.04 /bin/bash

    表示容器中的进程可以在 cpu 1 和 cpu 3 上执行。

    $ docker run -it --cpuset-cpus="0-2" ubuntu:14.04 /bin/bash
    $ cat /sys/fs/cgroup/cpuset/docker/<容器的完整长ID>/cpuset.cpus

    表示容器中的进程可以在 cpu 0、cpu 1 及 cpu 3 上执行。

    在 NUMA 系统上,我们可以设置容器可以使用的内存节点。

    例如:

    $ docker run -it --cpuset-mems="1,3" ubuntu:14.04 /bin/bash

    表示容器中的进程只能使用内存节点 1 和 3 上的内存。

    $ docker run -it --cpuset-mems="0-2" ubuntu:14.04 /bin/bash

    表示容器中的进程只能使用内存节点 0、1、2 上的内存。

    2.3.2、CPU 资源的相对限制

      默认情况下,所有的容器得到同等比例的 CPU 周期。在有多个容器竞争 CPU 时我们可以设置每个容器能使用的 CPU 时间比例。这个比例叫作共享权值,通过-c--cpu-shares设置。Docker 默认每个容器的权值为 1024。不设置或将其设置为 0,都将使用这个默认值。系统会根据每个容器的共享权值和所有容器共享权值和比例来给容器分配 CPU 时间。

      假设有三个正在运行的容器,这三个容器中的任务都是 CPU 密集型的。第一个容器的 cpu 共享权值是 1024,其它两个容器的 cpu 共享权值是 512。第一个容器将得到 50% 的 CPU 时间,而其它两个容器就只能各得到 25% 的 CPU 时间了。如果再添加第四个 cpu 共享值为 1024 的容器,每个容器得到的 CPU 时间将重新计算。第一个容器的CPU 时间变为 33%,其它容器分得的 CPU 时间分别为 16.5%、16.5%、33%。

      必须注意的是,这个比例只有在 CPU 密集型的任务执行时才有用。在四核的系统上,假设有四个单进程的容器,它们都能各自使用一个核的 100% CPU 时间,不管它们的 cpu 共享权值是多少。

      在多核系统上,CPU 时间权值是在所有 CPU 核上计算的。即使某个容器的 CPU 时间限制少于 100%,它也能使用各个 CPU 核的 100% 时间。

      例如,假设有一个不止三核的系统。用-c=512的选项启动容器{C0},并且该容器只有一个进程,用-c=1024的启动选项为启动容器C2,并且该容器有两个进程。CPU 权值的分布可能是这样的:

    PID    container    CPU CPU share
    100    {C0}     0   100% of CPU0
    101    {C1}     1   100% of CPU1
    102    {C1}     2   100% of CPU2

    $ docker run -it --cpu-shares=100 ubuntu:14.04 /bin/bash
    $ cat /sys/fs/cgroup/cpu/docker/<容器的完整长ID>/cpu.shares

    表示容器中的进程CPU份额值为100。

    2.3.3、CPU 资源的绝对限制

    Linux 通过 CFS(Completely Fair Scheduler,完全公平调度器)来调度各个进程对 CPU 的使用。CFS 默认的调度周期是 100ms。

    关于 CFS 的更多信息,参考CFS documentation on bandwidth limiting

    我们可以设置每个容器进程的调度周期,以及在这个周期内各个容器最多能使用多少 CPU 时间。使用--cpu-period即可设置调度周期,使用--cpu-quota即可设置在每个周期内容器能使用的 CPU 时间。两者一般配合使用。

    例如:

    $ docker run -it --cpu-period=50000 --cpu-quota=25000 ubuntu:16.04 /bin/bash

    将 CFS 调度的周期设为 50000,将容器在每个周期内的 CPU 配额设置为 25000,表示该容器每 50ms 可以得到 50% 的 CPU 运行时间。

    $ docker run -it --cpu-period=10000 --cpu-quota=20000 ubuntu:16.04 /bin/bash
    $ cat /sys/fs/cgroup/cpu/docker/<容器的完整长ID>/cpu.cfs_period_us
    $ cat /sys/fs/cgroup/cpu/docker/<容器的完整长ID>/cpu.cfs_quota_us

    将容器的 CPU 配额设置为 CFS 周期的两倍,CPU 使用时间怎么会比周期大呢?其实很好解释,给容器分配两个 vCPU 就可以了。该配置表示容器可以在每个周期内使用两个 vCPU 的 100% 时间。

    CFS 周期的有效范围是 1ms~1s,对应的--cpu-period的数值范围是 1000~1000000。而容器的 CPU 配额必须不小于 1ms,即--cpu-quota的值必须 >= 1000。可以看出这两个选项的单位都是 us。

    正确的理解“绝对”

    注意前面我们用--cpu-quota设置容器在一个调度周期内能使用的 CPU 时间时实际上设置的是一个上限。并不是说容器一定会使用这么长的 CPU 时间。比如,我们先启动一个容器,将其绑定到 cpu 1 上执行。给其--cpu-quota--cpu-period都设置为 50000。

    $ docker run --rm --name test01 --cpu-cpus 1 --cpu-quota=50000 --cpu-period=50000 deadloop:busybox-1.25.1-glibc

    调度周期为 50000,容器在每个周期内最多能使用 50000 cpu 时间。

    再用docker stats test01可以观察到该容器对 CPU 的使用率在100%左右。然后,我们再以同样的参数启动另一个容器。

    $ docker run --rm --name test02 --cpu-cpus 1 --cpu-quota=50000 --cpu-period=50000 deadloop:busybox-1.25.1-glibc

    再用docker stats test01 test02可以观察到这两个容器,每个容器对 cpu 的使用率在 50% 左右。说明容器并没有在每个周期内使用 50000 的 cpu 时间。

    使用docker stop test02命令结束第二个容器,再加一个参数-c 2048启动它:

    $ docker run --rm --name test02 --cpu-cpus 1 --cpu-quota=50000 --cpu-period=50000 -c 2048 deadloop:busybox-1.25.1-glibc

    再用docker stats test01命令可以观察到第一个容器的 CPU 使用率在 33% 左右,第二个容器的 CPU 使用率在 66% 左右。因为第二个容器的共享值是 2048,第一个容器的默认共享值是 1024,所以第二个容器在每个周期内能使用的 CPU 时间是第一个容器的两倍。

    2.4、磁盘IO配额控制

    相对于CPU和内存的配额控制,docker对磁盘IO的控制相对不成熟,大多数都必须在有宿主机设备的情况下使用。主要包括以下参数:

    • –device-read-bps:限制此设备上的读速度(bytes per second),单位可以是kb、mb或者gb。
    • –device-read-iops:通过每秒读IO次数来限制指定设备的读速度。
    • –device-write-bps :限制此设备上的写速度(bytes per second),单位可以是kb、mb或者gb。
    • –device-write-iops:通过每秒写IO次数来限制指定设备的写速度。
    • –blkio-weight:容器默认磁盘IO的加权值,有效值范围为10-100。
    • –blkio-weight-device: 针对特定设备的IO加权控制。其格式为DEVICE_NAME:WEIGHT

    存储配额控制的相关参数,可以参考Red Hat文档中blkio这一章,了解它们的详细作用。

    磁盘IO配额控制示例

    blkio-weight

    要使–blkio-weight生效,需要保证IO的调度算法为CFQ。可以使用下面的方式查看:

    root@ubuntu:~# cat /sys/block/sda/queue/scheduler
    noop [deadline] cfq

    使用下面的命令创建两个–blkio-weight值不同的容器:

    docker run -ti –rm –blkio-weight 100 ubuntu:stress
    docker run -ti –rm –blkio-weight 1000 ubuntu:stress

    在容器中同时执行下面的dd命令,进行测试:

    time dd if=/dev/zero of=test.out bs=1M count=1024 oflag=direct

    通过docker官方的blkio-weight doesn’t take effect in docker Docker version 1.8.1 #16173,可以发现这个问题在一些环境上存在,但docker官方也没有给出解决办法。

    device-write-bps

    使用下面的命令创建容器,并执行命令验证写速度的限制。

    docker run -tid –name disk1 –device-write-bps /dev/sda:1mb ubuntu:stress

    可以看到容器的写磁盘速度被成功地限制到了1MB/s。device-read-bps等其他磁盘IO限制参数可以使用类似的方式进行验证。

    容器空间大小限制

    在docker使用devicemapper作为存储驱动时,默认每个容器和镜像的最大大小为10G。如果需要调整,可以在daemon启动参数中,使用dm.basesize来指定,但需要注意的是,修改这个值,不仅仅需要重启docker daemon服务,还会导致宿主机上的所有本地镜像和容器都被清理掉。

    使用aufs或者overlay等其他存储驱动时,没有这个限制。

  • 相关阅读:
    文化因素对商标翻译的影响
    Building An Effective Marketing Plan
    HipHop PHP简介(转)
    关于comet
    TI BSL in python
    剖析 HTTP 协议
    NSIS 打包脚本基础
    图解使用VS的安装项目打包程序
    [Java IO]06_JSON操作
    [Java IO]04_系统标准IO
  • 原文地址:https://www.cnblogs.com/bjlhx/p/10527572.html
Copyright © 2011-2022 走看看