• Docker安全配置


    Docker安全及日志管理

    资源列表

    操作系统配置主机名IP
    CentOS 7.92C4Gmaster192.168.93.165
    CentOS 7.92C4Gclient192.168.93.166

    基础环境

    • 关闭防火墙
    systemctl stop firewalld
    systemctl disable firewalld
    
    • 关闭安全内核机制
    setenforce 0
    sed -i "s/^SELINUX=.*/SELINUX=disabled/g" /etc/selinux/config
    
    • 修改主机名
    hostnamectl set-hostname master
    hostnamectl set-hostname client
    
    • 绑定映射关系
    cat >> /etc/hosts << EOF
    192.168.93.165 master
    192.168.93.166 client
    EOF
    

    一、Docker安全相关介绍

    1.1、Docker容器与虚拟机的区别

    1.1.1、隔离与共享
    • 虚拟机通过添加Hypervisor层,虚拟出网卡、内存、CPU等虚拟硬件,再在其上建立虚拟机,每个虚拟机都有自己的系统内核。而Docker容器则是通过隔离的方式,将文件系统、进程、设备、网络等资源进行隔离,再对权限、CPU资源等进行控制,最终让容器之间互不影响,容器无法影响宿主机。容器与宿主机共享内核、文件系统、硬件等资源
    1.1.2、性能与损耗
    • 与虚拟机相比,容器资源损耗要少。同样的宿主机下,能够建立容器的数量要比虚拟机多。但是,虚拟机的安全性要比容器稍好,要从虚拟机攻破宿主机或其他虚拟机,需要先攻破Hypervisor层,这是极其困难的。而docker容器与宿主机共享内核、文件系统等资源,更有可能对其他容器、宿主机产生影响

    1.2、Docker存在的安全问题

    1.2.1、Docker自身漏洞
    • 作为一款应用Docker本身实现上会有代码缺陷。CVE官方记录Docker历史版本公有超过20项漏洞,可参见Docker官方网站。黑客常用的攻击手段主要有代码执行、权限提升、信息泄露、权限绕过等。目前Docker版本更迭非常快,Docker用户最好将Docker升级为最新的版本
    1.2.2、Docker源码问题

    Docker提供了Docker hub,可以让用户上传创建的镜像,以便其他用户下载,快速搭建环境。但同时也带来了一些安全问题。例如下面三种方式:

    (1)、客户上传恶意镜像

    • 如果有客户在制作的镜像中植入木马】后门等恶意软件,那么环境从一开始就已经不安全了,后续更没有什么安全可言

    (2)、镜像使用有漏洞的软件

    • Docker hub上能下载的镜像里面,75%的镜像都安装了有漏洞的软件。所以下载镜像后,需要检查里面软件的版本信息,对应的版本是否存在漏洞,并及时更新打上补丁

    (3)中间人攻击篡改镜像

    • 镜像在传输的过程中可能被篡改,目前新版本的Docker已经提供了相应的校验机制来预防这个问题

    1.3、Docker架构缺陷与安全机制

    Docker本身的架构与机制就可能产生问题,例如这样一种攻击场景,黑客已经控制了宿主机上的一些容器,或者获得了通过在公有云上建立容器的方式,然后对宿主机或其他容器发起攻击

    1.3.1、容器之间的局域网攻击
    • 主机上的容器之间可以构成局域网,因此针对局域网的ARP欺骗】嗅探、广播风暴等攻击方式更可以用上。所以,在一个主机上部署多个容器需要合理的配置网络,设置iptables规则
    1.3.2、DDos攻击耗尽资源
    • Cgroup安全机制就是要防止此类攻击的,不要为单一的容器分配过多的资源即可避免类似问题
    1.3.3、有漏洞的系统调用
    • Docker与虚拟机的一个重要的区别就是Docker与宿主机公有一个操作系统内核。一旦宿主机内核存在可以越权或者提权漏洞,尽管Docker使用普通用户执行,在容器被入侵时,攻击者还可以利用内核漏洞跳到宿主机做更多的事情
    1.3.4、共享root用户权限
    • 如果以root用户权限运行容器,容器内的root用户也就拥有了宿主机的root权限

    1.4、Docker安全基线标准

    • 根据Docker官方文档整理,下面从内核、主机、网络、镜像、容器以及其他等6个方面总结Docker安全基线标准
    1.4.1、内核级别
    • 及时更新内核
    • UserNameSpace(容器内的root权限在容器之外处于非高权限状态)
    • Cgroups(对资源的配额和度量)
    • SElinux/AppArmor/GRSEC(控制文件访问权限)
    • Capability(权限划分)
    • Seccomp(限定系统调用)
    • 禁止将容器的命令空间与宿主机进程命令空间共享
    1.4.2、主机级别
    • 为容器创建独立分区

    • 仅运行必要的服务

    • 禁止将宿主机上敏感目录映射到容器

    • 对Docker守护进程、相关文件和目录进行审计

    • 设置适当的默认文件描述符数

    • 用户权限为root的Docker相关文件的访问权限应该为644或者更低权限

    • 周期性检查每个主机的容器清单,并清理不必必要的容器

    1.4.3、网络级别
    • 通过iptables设定规则实现禁止或允许容器之间网络流量
    • 允许Docker修改iptables
    • 禁止将Docker绑定到其他IP/Port或者UnixSocket
    • 禁止在容器上映射特权端口
    • 容器上只开放所需要的端口
    • 禁止在容器上使用主机网络模式(host)
    1.4.4、镜像级别
    • 创建本地镜像仓库服务器
    • 镜像中软件都为最新版本
    • 使用可信镜像文件,并通过安全通道下载
    • 重新构建镜像而非对容器和镜像打补丁
    • 合理管理镜像标签,及时移除不再使用的镜像
    • 使用镜像扫描
    • 使用镜像签名
    1.4.5、容器级别
    • 容器最小化,操作系统镜像最小集
    • 容器以单一主进程的方式运行
    • 禁止privileged标记使用特权容器
    • 禁止在容器上运行ssh服务
    • 以只读的方式挂载容器的根目录系统
    • 明确定义属于容器的数据盘符
    • 通过设置no-failure限制容器尝试重启的次数
    • 限制容器中可用的进程数,以方式fork bomb
    1.4.6、其他设置
    • 定期对宿主机系统及容器进行安全审计
    • 使用最少资源和最低权限运行容器
    • 避免在同一宿主机上部署大量容器,维持一个能够管理的数量
    • 监控Docker容器的使用,性能以及其他各项指标
    • 增加实时 威胁检测和事件响应功能
    • 使用中心和远程日志收集服务

    实例:容器相关的常用安全配置方法

    一、Docker TLS通信安全

    • 按照Docker官方的说法,为了防止链劫持、会话劫持等问题导致Docker通信时被中间人攻击,c/s两端应该通过加密的方式通讯

    1.1、创建密钥

    hostnamectl set-hostname master
    [root@master ~]# mkdir /tls
    [root@master ~]# cd /tls/
    [root@master tls]# echo "127.0.0.1 master" >> /etc/hosts
    # 使用OpenSSL创建CA、服务器的端口段密钥
    [root@master tls]# openssl genrsa -aes256 -out ca-key.pem 4096
    Generating RSA private key, 4096 bit long modulus
    ...................++
    ...........................................................................................................................++
    e is 65537 (0x10001)
    Enter pass phrase for ca-key.pem:	 # 密码123123
    Verifying - Enter pass phrase for ca-key.pem:   # 确定密码
    
    [root@master tls]# openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
    Enter pass phrase for ca-key.pem:	# 输入刚刚的密码123123
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [XX]:CN
    State or Province Name (full name) []:HN
    Locality Name (eg, city) [Default City]:ZhengZhou
    Organization Name (eg, company) [Default Company Ltd]:kgc
    Organizational Unit Name (eg, section) []:kgc
    Common Name (eg, your name or your server's hostname) []:master
    Email Address []:
    
    [root@master tls]# openssl genrsa -out server-key.pem 4096
    Generating RSA private key, 4096 bit long modulus
    ......................................................................................................++
    ..................................................................................................................++
    e is 65537 (0x10001)
    
    [root@master tls]# openssl req -subj "/CN=master" -sha256 -new -key server-key.pem -out server.csr
    
    # 由于可以通过IP地址贺DNS名称进行TLS连接,因此IP地址需要在创建证书时指定,例如,允许连接的IP为127.0.0.1、192.168.93.166
    [root@master tls]# echo subjectAltName = DNS:master,IP:192.168.93.165,IP:127.0.0.1 >> extfile.cnf
    # 将Docker守护程序密钥的扩展用法属性设置为仅用于服务器身份验证
    [root@master tls]# echo extendedKeyUsage = serverAuth >> extfile.cnf
    
    # 生成签名证书
    [root@master tls]# openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf
    Signature ok
    subject=/CN=master
    Getting CA Private Key
    Enter pass phrase for ca-key.pem:
    
    [root@master tls]# openssl genrsa -out key.pem 4096
    Generating RSA private key, 4096 bit long modulus
    .....................................................................................................................................................++
    ...........................................................................................................................................................................................................................................................................................++
    e is 65537 (0x10001)
    
    [root@master tls]# openssl req -subj '/CN=client' -new -key key.pem -out client.csr
    [root@master tls]# echo extendedKeyUsage = clientAuth > extfile-client.cnf
    
    # 生成签名证书
    [root@master tls]# openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile-client.cnf
    Signature ok
    subject=/CN=client
    Getting CA Private Key
    Enter pass phrase for ca-key.pem:
    
    # 生成后,可以安全地删除两个证书签名请求贺扩展配置文件
    [root@master tls]# rm -rf client.csr server.csr extfile.cnf extfile-client.cnf
    
    # 为了数据的安全,进行对密钥的权限更改
    [root@master tls]# chmod -v 0400 ca-key.pem key.pem server-key.pem
    [root@master tls]# chmod -v 0444 ca.pem server-cert.pem cert.pem
    
    # 把密钥上传到client
    [root@master tls]# scp ca.pem root@192.168.93.166:/etc/docker/
    [root@master tls]# scp cert.pem root@192.168.93.166:/etc/docker/
    [root@master tls]# scp key.pem root@192.168.93.166:/etc/docker/
    
    # 重新启动docker开启TLS认证加密
    ## 方法1:
    [root@master tls]# vim /lib/systemd/system/docker.service 
    ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/tls/ca.pem --tlscert=/tls
    /server-cert.pem --tlskey=/tls/server-key.pem -H tcp://0.0.0.0:2376 -H unix:/
    //var/run/docker.sock
    #ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
    [root@master tls]# systemctl daemon-reload 
    [root@master tls]# systemctl restart docker
    
    ## 方法2:
    [root@master tls]# systemctl stop docker
    [root@master tls]# dockerd --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H=0.0.0.0:2376
    
    

    1.2、client连接

    hostnamectl set-hostname client
    [root@client ~]# vim /etc/hosts
    192.168.93.165 master
    [root@client ~]# cd /etc/docker/
    # 使用密钥连接master并查看master的docker版本
    [root@client docker]# docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=master:2376 version
    Client: Docker Engine - Community
     Version:           26.1.2
     API version:       1.45
     Go version:        go1.21.10
     Git commit:        211e74b
     Built:             Wed May  8 14:01:02 2024
     OS/Arch:           linux/amd64
     Context:           default
    
    Server: Docker Engine - Community
     Engine:
      Version:          26.1.2
      API version:      1.45 (minimum version 1.24)
      Go version:       go1.21.10
      Git commit:       ef1912d
      Built:            Wed May  8 13:59:55 2024
      OS/Arch:          linux/amd64
      Experimental:     false
     containerd:
      Version:          1.6.31
      GitCommit:        e377cd56a71523140ca6ae87e30244719194a521
     runc:
      Version:          1.1.12
      GitCommit:        v1.1.12-0-g51d5e94
     docker-init:
      Version:          0.19.0
      GitCommit:        de40ad0
    
    

    二、容器最小化

    • 如果仅在容器中运行必要的服务,像SSH等服务是不能轻易开启去连接容器的。通常使用以下方式来进入容器
    [root@master ~]# docker exec -it 容器名称 bash
    

    三、Docker RemoteAPI访问控制

    • Docker的远程调用API接口存在未授权访问漏洞,至少应显示外网访问。建议使用Socket方式访问
    # docker.scok是daemon监听的套接字,容器中的进程可以通过它与docker daemon通信
    [root@master ~]# dockerd -H unix:///var/run/docker.sock[root@master ~]# vim /usr/lib/systemd/system/docker.service
    # 进行修改即可
    ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://192.168.93
    .165:2375
    [root@master ~]# systemctl daemon-reload 
    [root@master ~]# systemctl restart docker
    [root@master ~]# netstat -anpt | grep docker
    tcp        0      0 192.168.93.165:2375     0.0.0.0:*               LISTEN      13281/dockerd
    
    • 然后在宿主机的firewalld上做IP访问控制即可。(source address 是客户端地址)
    [root@master ~]# systemctl start firewalld
    
    # 添加防火墙富规则
    [root@master ~]# firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.93.166" port protocol="tcp" port="2375" accept"
    success
    
    # 刷新防火墙
    [root@master ~]# firewall-cmd --reload
    success
    
    • 然后在客户端192.168.93.166上即授权访问控制
    # 在客户端控制服务端拉去一个nginx镜像
    [root@client ~]# docker -H=tcp://192.168.93.165:2375 pull nginx
    
    # 在服务端查看是否有nginx镜像
    [root@master ~]# docker images
    REPOSITORY   TAG       IMAGE ID       CREATED      SIZE
    nginx        latest    4f67c83422ec   3 days ago   188MB
    

    四、限制流量转向

    • 使用防火墙过滤器限制Docker容器的源IP地址范围与外界通信
    # 拒绝10.0网段的主机与服务器通信
    [root@master ~]# firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.10.0/24" reject"
    

    五、DockerBenchforSecurity介绍

    • Docker Bench for Security是一个脚本,它是在生产环境中常见的检测检查部署Docker容器的最佳安全实现,测试都是自动化的,受CIS Docker 1.13基准的启发而来
    • 要使用docker-slim,从Github下载其二进制文件。二进制文件可用于Linux和Mac。下载二进制文件后,将其添加到环境变量PATH中
    [root@master ~]# yum -y install git
    [root@master ~]# git clone https://github.com/docker/docker-bench-security.git
    Cloning into 'docker-bench-security'...
    remote: Enumerating objects: 2726, done.
    remote: Counting objects: 100% (804/804), done.
    remote: Compressing objects: 100% (242/242), done.
    remote: Total 2726 (delta 611), reused 634 (delta 554), pack-reused 1922
    Receiving objects: 100% (2726/2726), 4.46 MiB | 1.50 MiB/s, done.
    Resolving deltas: 100% (1889/1889), done.
    [root@master ~]# cd docker-bench-security/
    [root@master docker-bench-security]# sh docker-bench-security.sh
    ##################################################################
    # --------------------------------------------------------------------------------------------
    # Docker Bench for Security v1.6.0
    #
    # Docker, Inc. (c) 2015-2024
    #
    # Checks for dozens of common best-practices around deploying Docker containers in production.
    # Based on the CIS Docker Benchmark 1.6.0.
    # --------------------------------------------------------------------------------------------
    
    Initializing 2024-06-02T06:50:17-04:00
    
    
    Section A - Check results
    
    [INFO] 1 - Host Configuration
    [INFO] 1.1 - Linux Hosts Specific Configuration
    [DEPRECATION NOTICE]: API is accessible on http://192.168.93.165:2375 without encryption.
             Access to the remote API is equivalent to root access on the host. Refer
             to the 'Docker daemon attack surface' section in the documentation for
             more information: https://docs.docker.com/go/attack-surface/
    In future versions this will be a hard failure preventing the daemon from starting! Learn more at: https://docs.docker.com/go/api-security/
    [WARN] 1.1.1 - Ensure a separate partition for containers has been created (Automated)
    [INFO] 1.1.2 - Ensure only trusted users are allowed to control Docker daemon (Automated)
    [INFO]       * Users: 
    [WARN] 1.1.3 - Ensure auditing is configured for the Docker daemon (Automated)
    
    Section C - Score
    
    [INFO] Checks: 86
    [INFO] Score: -2
    # 部分内容省略
    ##################################################################
    
    # 输出结果中,带有不同的级别,说明问题的严重程度,最后会给出整体检查结果和评分
    1、标红[WARN]是需要调整
    2、标绿[PASS]表示通过检测
    3[INFO]可根据实际需要确定是否进行调整
    # 一般要尽量避免出现WARN或以上的问题
    

    六、Cgroup资源配置方法

    • Docker通过Cgroup来控制容器使用的资源配额,包括CPU、内存、磁盘三大方面,基本覆盖了常见的资源配额和使用量控制
    • Cgroup是ControlGroups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组所使用的物理资源(如CPU、内存、磁盘IO等等)的机制,被LXC、docker等很多项目用于实现进程资源控制。Cgroup本身是提供将进程分组话管理的功能和接口的基础结构,I/O或内存的分配控制等具体的资源管理是通过该功能来实现的。这些具体的资源管理功能称为Cgroup子系统

    6.1、子系统实现

    • 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上的线程

    6.2、使用Stress工具测试CPU和内存

    • 使用Dockerfile来创建一个基于CentOS的stress工具镜像
    root@master ~]# docker pull centos:7
    [root@master ~]# mkdir /root/stress
    [root@master ~]# cat /root/stress/Dockerfile
    FROM centos:7
    MAINTAINER Wzh
    RUN yum -y install wget
    RUN wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
    RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
    RUN yum -y install stress
    [root@master ~]# cd /root/stress/
    [root@master stress]# docker build -t centos:stress .
    
    • 使用如下命令创建容器,命令中的–cpu-shares参数值不能保证可以获得1个vcpu或者多少GHz的CPU资源,它仅是一个弹性的加权值,值越大或者分配的资源就越多
    [root@master stress]# docker run -itd --cpu-shares 100 centos:stress
    
    • Cgroups只在容器分配的资源紧缺时,即在需要对容器的资源进行限制时,才会生效。因此,无法单纯根据某个容器的CPU份额来确定有多少CPU资源分配给它,资源分配结果取决于同时运行的其他容器的CPU分配和容器中进程运行情况
    • 可以通过cpushare可以设置容器使用CPU的优先级,比如启动了两个容器及运行查看CPU百分比
     # stress -c 10向容器中开启10个进程用于测试
    [root@master stress]# docker run -itd --name cpu512 --cpu-shares 512 centos:stress stress -c 10
    
    # 进入容器使用top查看资源咱占用情况
    [root@master ~]# docker exec -it cpu512 bash
    [root@5a30bc38e2d9 /]# top
    top - 11:26:33 up 10 min,  0 users,  load average: 7.89, 2.69, 0.98
    Tasks:  13 total,  11 running,   2 sleeping,   0 stopped,   0 zombie
    %Cpu(s): 98.8 us,  1.2 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0
    KiB Mem :  3861260 total,  2380572 free,   312972 used,  1167716 buff/cache
    KiB Swap:  4063228 total,  4063228 free,        0 used.  3302036 avail Mem 
    
       PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
         9 root      20   0    7312     96      0 R  20.3  0.0   0:17.46 stress 
        12 root      20   0    7312     96      0 R  20.3  0.0   0:17.62 stress 
        13 root      20   0    7312     96      0 R  20.3  0.0   0:18.17 stress 
         6 root      20   0    7312     96      0 R  19.9  0.0   0:17.96 stress 
         7 root      20   0    7312     96      0 R  19.9  0.0   0:17.58 stress 
         8 root      20   0    7312     96      0 R  19.9  0.0   0:17.66 stress 
        15 root      20   0    7312     96      0 R  19.9  0.0   0:17.59 stress 
        10 root      20   0    7312     96      0 R  19.6  0.0   0:17.47 stress 
        11 root      20   0    7312     96      0 R  19.6  0.0   0:17.58 stress 
        14 root      20   0    7312     96      0 R  19.6  0.0   0:18.16 stress 
         1 root      20   0    7312    624    528 S   0.0  0.0   0:00.01 stress 
        16 root      20   0   11828   1896   1492 S   0.0  0.0   0:00.01 bash   
        30 root      20   0   56192   2012   1444 R   0.0  0.1   0:00.00 top    
    
    
    • 下面设置CPU资源份额翻倍
    [root@master ~]# docker run -itd --name cpu1024 --cpu-shares 1024 centos:stress stress -c 10
    [root@master ~]# docker exec -it cpu1024 bash
    [root@dc64e7513c1f /]# top
    top - 11:28:19 up 12 min,  0 users,  load average: 13.22, 5.74, 2.24
    Tasks:  13 total,  11 running,   2 sleeping,   0 stopped,   0 zombie
    %Cpu(s):100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0
    KiB Mem :  3861260 total,  2369580 free,   323532 used,  1168148 buff/cache
    KiB Swap:  4063228 total,  4063228 free,        0 used.  3291300 avail Mem 
    
       PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
         7 root      20   0    7312     92      0 R  14.2  0.0   0:03.71 stress 
        13 root      20   0    7312     92      0 R  14.2  0.0   0:03.68 stress 
        15 root      20   0    7312     92      0 R  14.2  0.0   0:03.50 stress 
        14 root      20   0    7312     92      0 R  13.9  0.0   0:03.51 stress 
         9 root      20   0    7312     92      0 R  12.9  0.0   0:03.32 stress 
        10 root      20   0    7312     92      0 R  12.6  0.0   0:03.32 stress 
        12 root      20   0    7312     92      0 R  12.6  0.0   0:03.29 stress 
        11 root      20   0    7312     92      0 R  12.3  0.0   0:03.31 stress 
        16 root      20   0    7312     92      0 R  12.3  0.0   0:03.33 stress 
         8 root      20   0    7312     92      0 R  11.9  0.0   0:03.31 stress 
         1 root      20   0    7312    620    528 S   0.0  0.0   0:00.01 stress 
        17 root      20   0   11828   1904   1496 S   0.0  0.0   0:00.01 bash   
        31 root      20   0   56192   2012   1444 R   0.0  0.1   0:00.00 top    
    
    # 可以看容器512CPU占用率要比1024高
    

    七、CPU周期限制

    Docker提供了–cpu-period、–cpu-quota两个参数控制容器可以分配到CPU时钟周期

    • –cpu-period:是用来指定容器对CPU的使用要在多长事件内做一次重新分配

    • –cpu-quota:是用来指定在这个周期内,最多可以有多少时间跑这个容器。与–cpu-shares不同的是,这种配置是指定一个绝对值,容器对CPU资源的使用绝对不会超过配置的值

    • cpu-period和cpu-quota的单位为微秒(us)。cpu-period的最小值为1000微妙,最大值为1秒。默认值为0.1秒。cpu-quota的值默认为-1,表示不做控制。cpu-period和cpu-quota参数一般联合使用

    # 例如:容器进程需要每1秒使用单个CPU的0.2秒时间,可以将cpu-period设置为1000000(即1秒),cpu-quota设置为200000(0.2秒)
    [root@master ~]# docker run -itd --cpu-period 1000000 --cpu-quota 200000 centos:stress 
    [root@master ~]# docker exec -it condescending_spence bash
    [root@3d0f9e29cc61 /]# cat /sys/fs/cgroup/cpu/cpu.cfs_period_us 
    1000000
    [root@3d0f9e29cc61 /]# cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us 
    200000
    

    八、CPUCore控制

    • 对于多核CPU的服务器,Docker还可以控制容器运行使用哪些CPU内核,即使用–cpuset-cpus参数,这对具有多CPU的服务器尤其有用,可以对需要高性能计算的容器进行性能最优的配置
    # 只允许这个容器使用0、1两个内核
    [root@master ~]# docker run -itd --name cpu1 --cpuset-cpus 0-1 centos:stress
    [root@master ~]# docker exec -it cpu1 bash
    [root@ea4cd6c80f5e /]# cat /sys/fs/cgroup/cpuset/cpuset.cpus
    0-1
    
    

    九、CPU配额控制参数的混合使用

    • 通过cpuset-cpus参数指定容器A使用CPU内核0,容器B使用CPU内核1
    [root@master ~]# docker run -itd --name cpu3 --cpuset-cpus 1 --cpu-shares 512 centos:stress stress -c 1
    [root@master ~]# docker exec -it cpu3 bash
    [root@3a197567bf58 /]# top
    top - 11:52:58 up 37 min,  0 users,  load average: 20.67, 20.14, 16.51
    Tasks:   4 total,   2 running,   2 sleeping,   0 stopped,   0 zombie
    %Cpu(s):100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0
    KiB Mem :  3861260 total,  2333408 free,   357196 used,  1170656 buff/cache
    KiB Swap:  4063228 total,  4063228 free,        0 used.  3256448 avail Mem 
    
       PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
         7 root      20   0    7312     96      0 R  54.8  0.0   0:32.37 stress 
         1 root      20   0    7312    424    344 S   0.0  0.0   0:00.00 stress 
         8 root      20   0   11828   1900   1496 S   0.0  0.0   0:00.01 bash   
        22 root      20   0   56192   2000   1444 R   0.0  0.1   0:00.00 top  
        
        
        
    [root@master ~]# docker run -itd --name cpu4 --cpuset-cpus 1 --cpu-shares 1024 centos:stress stress -c 1
    [root@master ~]# docker exec -it cpu4 bash
    [root@080ee5432922 /]# top
    top - 11:56:33 up 40 min,  0 users,  load average: 21.80, 20.81, 17.52
    Tasks:   4 total,   2 running,   2 sleeping,   0 stopped,   0 zombie
    %Cpu(s):100.0 us,  0.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0
    KiB Mem :  3861260 total,  2325228 free,   364704 used,  1171328 buff/cache
    KiB Swap:  4063228 total,  4063228 free,        0 used.  3248516 avail Mem 
    
       PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
         7 root      20   0    7312     96      0 R  66.7  0.0   0:16.50 stress 
         1 root      20   0    7312    424    344 S   0.0  0.0   0:00.01 stress 
         8 root      20   0   11828   1896   1496 S   0.0  0.0   0:00.01 bash   
        22 root      20   0   56192   1964   1428 R   0.0  0.1   0:00.00 top   
    # 上面的centos:stress镜像安装了stress工具,用来测试CPU和内存的负载。通过在两个容器上分别执行stress -c 1命令,将会给系统一个随机负载,产生1个进程,这个进程都反复不停的计算有rand()产生随机数的平方根,知道资源耗尽
    

    十、内存限额

    与操作系统类似,容器可使用的内存包括两部分:物理内存和Swap。Docker通过下面两组参数来控制容器内存的使用量

    • -m或–memory:设置内存的使用限额,例如100M、1024M
    • –memory-swap:设置内存+swap的使用限额
    # 执行如下命令允许该容器最多使用200M的内存和不能超过300的swap(swap100内存)
    [root@master ~]# docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
    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: 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 ...
    --vm 1:启动1个内存工作线程
    --vm-bytes 280M:每个线程分配280内存
    
    # 默认情况下,容器可以使用主机上的所有空闲内存。与CPU的cgroups配置类似,Docker会自动为容器在目录/sys/fs/cgroup/memory/docker<容器的完整长度 ID>中创建相应cgroup配置文件
    
    # 因为280M在可分配的范围(300M)内,所以工作线程能够正常工作,其工作过程是
    分配280M内存
    释放280M内存
    再分配280M内存
    再释放280M内存
    一直循环
    
    # 如果让工作线程分配的内存超过300M,分配的内存超过限制,stress线程报错,容器退出
    [root@master ~]# 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
    

    十一、Blocklo的限制

    • 默认情况下,所有容器能平等地读写磁盘,可以通过设置–blkio-weight参数来改变容器的vlock IO的优先级
    • –blkio-weigit与–cpu-shares类似,设置的是相对权重值,默认为500。在下面的例子中,容器A读写磁盘的宽带是容器B的两倍
    [root@master ~]# docker run -it --name IO_A --blkio-weight 600 centos:stress [root@c3d24510ba18 /]# cat /sys/fs/cgroup/blkio/blkio.weight
    600
    
    [root@master ~]# docker run -it --name IO_B --blkio-weight 300 centos:stress
    [root@5f98b4ad5a2a /]# cat /sys/fs/cgroup/blkio/blkio.weight
    300
    

    十二、bps和iops的限制

    • bps是byte per second,每秒读写的数据量。iops是io per second,每秒的IO的次数
    • 可以通过以下参数控制容器的bps和iops
    --device-read-bps:限制读某个设备的bps
    --device-write-bsp:限制写某个设备的bps
    --device-read-iops:限制某个设备的iops
    --device-write-iops:限制写某个设备的iops
    
    # 下面的示例是显示容器写/dev/sda的速率为5MB/s
    [root@master ~]# docker run -it --device-write-bps /dev/sda:5MB centos:stress
    # 输出完时间为20秒左右
    [root@4775b55a6f0b /]# dd if=/dev/zero of=test bs=1M count=100 oflag=direct 
    100+0 records in
    100+0 records out
    104857600 bytes (105 MB) copied, 20.0017 s, 5.2 MB/s
    
    
    # 不限速,不限速时间还没1秒就输出完毕了
    [root@master ~]# docker run -it centos:stress
    [root@ee280332da35 /]# dd if=/dev/zero of=test bs=1M count=100 oflag=direct
    100+0 records in
    100+0 records out
    104857600 bytes (105 MB) copied, 0.0775017 s, 1.4 GB/s
    
    
    # 通过dd命令测试在容器中写磁盘的速度。因为容器的文件系统是在host/dev/sda上的,在容器中写文件相当于对host/dev/sda进行写操作。另外,oflag=direct指定用direct IO方式写文件,这样--device-weite-bps才能生效
    
  • 相关阅读:
    华为机试 - 目录删除
    提高 Python 代码可读性的 5 个基本技巧
    数据栅格化
    小白学Java
    一文速学 - PHP7特性
    leetcode695 岛屿的最大面积
    【Nginx28】Nginx学习:代理模块(二)缓存与错误处理
    07-SDRAM :FIFO控制模块
    【FPGA教程案例42】图像案例2——通过verilog实现图像二值化处理,通过MATLAB进行辅助验证
    零基础自学游戏开发和软件开发先学什么知识点或课程?
  • 原文地址:https://blog.csdn.net/weixin_73059729/article/details/139401639