Docker系列---docker cgroup资源管理 | TLS通讯加密 | 详细讲解

前言 - Cgroup

Docker 提供了一种资源控制的方式,即 Cgroup
Cgroup 是 Control group 的简写,是 Linux 内核提供的一种限制所使用物理资源的机制,包括 CPU、内存 和 IO 这三大方面,基本覆盖了常见的资源配额和使用量控制

一、对 CPU 的控制

1.使用 stress 工具测试


mkdir /opt/stress
vim /opt/stress/Dockerfile
FROM centos:7
RUN yum -y install wget
RUN wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo		
'//epel源,可以使用扩展软件包(stress)'
RUN yum -y install stress		'//可以指定产生线程,使用循环语句,测试用'


cd /opt/stress/
systemctl restart docker.service		'//建议重启docker,不然下面的操作可能会失败,卡在wget'
docker build -t centos:stress .		   '//生成镜像'

docker ps -a
docker images 

'//以下可以使用该镜像为基础产生的容器进行测试:'

在这里插入图片描述

2.限制 CPU 使用周期速率

1.查看CPU的资源限制
命令格式:
cat /sys/fs/cgroup/cpu/docker/[容器ID]/cpu.cfs_quota_us

例:
 docker run -itd --name test1 centos:stress /bin/bash

cat /sys/fs/cgroup/cpu/docker/2964d084535d0670cdf79233a0d2e2a99620d1f0c93854ac8ca73944d4affd5e/cpu.cfs_quota_us 
-1
'//-1代表不进行任何限制'

在这里插入图片描述

2.手动修改文件以实现修改CPU限制
echo 20000 > /sys/fs/cgroup/cpu/docker/1a9c837fe4a7fc39b9bcaa21aa3fcf12a49582ebe98e96b82cdab1fae32c3e71/cpu.cfs_quota_us 
cat /sys/fs/cgroup/cpu/docker/1a9c837fe4a7fc39b9bcaa21aa3fcf12a49582ebe98e96b82cdab1fae32c3e71/cpu.cfs_quota_us 
20000


在这里插入图片描述

3.在运行容器的同时指定CPU限制条件
'以下这两个参数一般联合使用,控制容器可以分配到的CPU时钟周期'
'--cpu-period是用来指定容器对CPU的使用要在多长时间内做一次重新分配'
'--cpu-quota是用来指定在这个周期内,最多可以有多少时间来跑这个容器'

例:
'容器进程需要每秒使用单个CPU的0.2秒时间,可以将period设为1000000(1s)'
'若在多核下,允许容器进程完全占用两个CPU,可以将period设置为100000(0.1s)'
docker run -itd --name cpu01 --cpu-period=100000 --cpu-quota=200000 centos:stress

docker exec -it 7c3 bash
cat /sys/fs/cgroup/cpu/cpu.cfs_period_us 
100000
cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us  
200000

在这里插入图片描述

3.多任务比例分享 CPU


当有多个容器任务同时运行时,很难计算 CPU 的使用率,我们可以设置 CPU 按照比例共享 CPU 资源,以实现使用率的动态调整

docker run -itd --name cpu1 --cpu-shares 1024 centos:stress stress -c 10		'//-c 10表示产生10个子线程,测试用'

docker exec -it 624 bash
top		'//查看CPU使用率'

--新开一个终端--
docker run -itd --name cpu1 --cpu-shares 512 centos:stress stress -c 10

docker exec -it 6d3 bash
top		'//对比CPU使用率,是1:2'

在这里插入图片描述

使用【–cpu-shares】,分配两个容器使用CPU资源占用权重为1:2

1.默认情况下,每个Docker容器的CPU份额都是1024,单独一个容器的份额是没有意义的,只有在同时运行多个容器时,容器CPU的加权效果才能体现出来
2.比如以上的两个容器是1:2,在CPU进行时间片分配时,后者比前者多一倍的机会获得CPU的时间片,但是分配的结果取决于当时主机和其他容器的运行状态
3.实际上也无法保证该容器一定获得相应的CPU时间片,因为若是该的进程一直是空闲的,那么cpu1就可以获取比cpu2更多的CPU时间片
4.在极端情况下,例如主机上只运行了一个容器,即使它的CPU份额较小,也是可以独占整个主机的CPU资源的
5.Cgroups只在容器分配的资源紧缺时,即在需要对容器使用的资源进行限制时,才会生效,因此,无法根据某个容器的CPU份额来确定有多少CPU资源分给给它
6.即资源分配的结果取决于同时运行的其他容器CPU分配和容器中进程的运行情况

4.限制 CPU 内核使用


可以通过配置,使得某些程序独享 CPU 内核,以提高其处理速度

cat /sys/fs/cgroup/cpuset/docker/0262a2c1e887/cpuset.cpus
0-7
'//若该服务器有8个核心,那么CPU编号为0-7,表示该容器内的进程在核心上皆可运行,这是默认配置'
'//可查看cat /proc/cpuinfo中的CPU编号(processor)'


docker run -itd --name a1 --cpuset-cpus 0 centos:stress
'//表示创建的容器只能使用0、1两个内核,其后可以使用top命令按1查看CPU使用'


docker exec [容器ID] taskset -c -p 1
'//表示绑定至指定CPU上运行'

在实际使用中,尽量使用绑定内核的方式分配 CPU 资源,然后再配合【–cpu-share】选项来动态调整 CPU 使用资源的比例
住意,这里若是两个容器各自指定不同的CPU内核,则–cpu-share基本没有效果

在这里插入图片描述

二、对内存使用的限制

'与操作系统类似,容器可使用的内存包括两部分:物理内存和 Swap'
'-m 或 --memory:设置内存的使用限额'
'--memory-swap:设置内存+swap 的使用限额'


docker run -itd -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
'//--vm 1:启动1个内存工作线程'
'//--vm-bytes 280M:每个线程分配280M内存'

'相应的Cgroup配置文件:/sys/fs/cgroup/memory/memory.limit_in_bytes'

docker run -itd -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M
'//如果让工作线程分配的内存超过300M,分配的内存超过了限额,stress线程会报错,容器退出'


'注意!一旦容器Cgroup使用的内存超过了限制的容量,Linux内核就会尝试收回这些内存'
'如果仍旧无法控制内存使用在这个设置的范围之内,就会杀死该进程!'

三、对磁盘 IO 资源的限制

如果是在一台服务器上进行容器的混合部署,那么可能会出现同时有几个程序写磁盘数据的情况,那么如何进行限制呢?

bps:byte per second(每秒读写的字节数)
iops:io per second(每秒IO的次数)


1.限制某个程序写入的bps数据量
docker run -d --device-write-bps /dev/sda:30M centos:7

2.限制读取某个程序的bps数据量
docker run -d --device-read-bps /dev/sda:30M centos:7

3.限制读取某个程序的iops次数
--device-read-iops

4.限制写入某个程序的iops次数
--device-write-iops

示例:限制容器写 /dev/sda 的速率为 5MB/s

docker run -it --device-write-bps /dev/sda:5MB centos:7
dd if=/dev/zero of=test bs=1M count=1024 oflag=direct		
'//dd复制,从zero拿文件test,每次拿1MB,写1024次即1GB大小'
'oflag=direct表示指定用direct IO 方式写文件,这样--device-write-bps才能生效'


docker run -it centos:7
dd if=/dev/zero of=test bs=1M count=1024 oflag=direct

默认情况下,所有容器能平等地读写磁盘,可以通过设置--blkio-weight参数来改变容器block 10的优先级。
--blkio-weight与--cpu-shares类似,设置的是相对权重值,默认为500

在下面的例子中,容器A读写磁盘的带宽是容器B的两倍。
docker run-it --name container A--blkio-weight 600 centos:stress
cat /sys/fs/cgroup/blkio/blkio.weight
600
docker run-it --name container B--blkio-weight 300 centos:stress
cat /sys/fs/cgroup/blkio/blkio.weight
300

四、TLS 通讯加密

1.密钥

①对称密钥

是一种加密和解密使用相同密钥的算法,效率较高,可加密内容较大,用来加密会话过程中的消息,适用于大规模生产的环境下使用
就像固定的一道门与一把钥匙一样,但是,对称加密算法在分布式网络系统上使用较为困难,因为密钥管理困难,使用成本较高,还是这个比方,你去收租,几百串钥匙你管的烦不烦?
相对于非对称密钥而言,安全性较差,就像捡到了你的钥匙,那么就可以直接来开你的门了

②非对称密钥

其原理是加密密钥与解密密钥不同,形成一个密钥对,其中一个密钥加密的结果,可以用另一个密钥来解密
加密和解密使用不同的密钥,一个密钥公开,称公钥,一个密钥保密,称私钥,相对而言,效率不高,但是安全性高
比如,大家一起去食堂吃饭,付款码就像公钥,每个人都可以看到(使用),私钥就代表着个人身份信息,用自己的私钥去验证,最终成功付款,才能干饭

③混合密钥(对称+非对称)

只用对称密钥进行信息传输,效率虽快,但是安全性差一点,被截胡怎么办?而用非对称密钥,安全性相对而言是有一定保障,但若是传输的信息量较大,光是去加密就需要耗费大量的时间,导致效率低下

因此,聪明人可能就想到了,我们就不能将其混合使用吗,各取所长:对要发送的明文(数据量较大)进行对称加密生成密文,然后对这个加密过程中生成的对称密钥进行非对称加密(私钥加密)

这就像,你用一把钥匙锁起来了一大箱金银财宝,然后将这把钥匙又用一个小匣子单独锁了起来,安全性更强!还要对其进行一个签名,即这个小匣子中还代表着你的身份信息

还有一个步骤,将明文在加密之前进行哈希算法产生一个哈希值,主要是为了验证数据的完整性,从而得知这个数据传过去有无被中间人篡改

最后,将密文、加密后的密钥、哈希值这三样一起传递给对方,对方将加密后的密钥用公钥解密后获取私钥,将密文解密成明文,然后比对哈希值,检查数据有无被篡改(若不同则丢弃)

2.签名
前面有提到过,签名代表着你的身份信息
打个比方,你扫二维码付款,收款商家能够得知是谁付的款,这个对象就是你的身份信息

3.数据完整性
这个前文也有提高过,使用哈希算法确保数据完整性
即这个数据在传输过程结束后能够最终检测其一致性

4.证书
组成:密钥+身份信息+哈希算法等,统统在其中,就像容器一样
格式:x509,国际标准
证书是需要被颁发的(证书颁发机构:CA),拿到 ca 证书后才能去找 CA 给自己颁发服务器证书(server,包含公钥),还需要有客户端证书(给客户端的,包含私钥)。

五、Docker 启用 TLS 进行加密通讯

1.TLS 概述

TLS(传输层安全协议)用于在两个通信应用程序之间提供保密性和数据完整性,该协议由两层组成:TLS 记录协议(TLS Record)和 TLS 握手协议(TLS Handshake)
TLS 协议采用主从式架构模型,用于在两个应用程序间透过网络创建起安全的连线,防止在交换数据时受到窃听及篡改
TLS 协议的优势是与高层的应用层协议(如 HTTP、FTP 等)无耦合;应用层协议能透明地运行在 TLS 协议之上,由 TLS 协议进行创建加密通道需要的协商和认证;应用层协议传送的数据在通过TLS协议时都会被加密,从而保证通信的私密性

2.TLS 原理

TLS 协议是可选的,必须配置客户端和服务器才能使用。主要有两种方式实现这一目标:一个是使用统一的 TLS 协议通信端口(例如:用于 HTTPS 的 443 端口);另一个是客户端请求服务器连接到 TLS 时使用特定的协议机制

一旦客户端和服务器都同意使用 TLS 协议,他们通过使用一个握手过程协商出一个有状态的连接以传输数据。通过握手,客户端和服务器协商各种参数用于创建安全连接:

当客户端连接到支持 TLS 协议的服务器要求创建安全连接并列出了受支持的密码组合(加密密码算法和加密哈希函数),握手开始
服务器从该列表中决定加密和散列函数,并通知客户端
服务器发回其数字证书,此证书通常包含服务器的名称、受信任的证书颁发机构(CA)和服务器的公钥
客户端确认其颁发的证书的有效性
为了生成会话密钥用于安全连接,客户端使用服务器的公钥加密随机生成的密钥,并将其发送到服务器,只有服务器才能使用自己的私钥解密
利用随机数,双方生成用于加密和解密的对称密钥。这就是 TLS 协议的握手,握手完毕后的连接是安全的,直到连接(被)关闭。如果上述任何一个步骤失败,TLS 握手过程就会失败,并且断开所有的连接

2.部署步骤

'//服务端主机'
--开局优化--
mkdir /tls
cd /tls/
hostnamectl set-hostname server
su
'//设置主机名称,便于识别'
 cat >> /etc/hosts << EOF
> 192.168.78.11 server
> 192.168.78.22 client
> EOF		'//添加映射'
'//切换至client客户端'
hostnamectl set-hostname client
su
cat >> /etc/hosts << EOF
> 192.168.126.16 server
> 192.168.126.17 client
> EOF
ping server
'//测试能否互相ping通'
ping client

--server端--

1.创建CA密钥
openssl genrsa -aes256 -out ca-key.pem 4096		'//输入密钥,123123(确认)'
'//genrsa:非对称密钥;-aes256:256位密钥长度'
'//-out输出名为ca-key.pem,为证书名称,结尾固定为.pem,文件大小为4096(默认)'
ls
ca-key.pem

2.创建CA证书
openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -subj "/CN=*" -out ca.pem		'//输入123123(CA密钥)'
'//req:请求;-new创建一个新的证书,-x509为证书标准规格'
'//-days:证书有效期为1000天;使用到之前生成的CA密钥文件'
'//使用哈希;项目名称;-out产生一个CA证书'
ls
ca-key.pem  ca.pem		'//证书和密钥是一对,相互之间是不可分割的'

3.创建服务器私钥
openssl genrsa -out server-key.pem 4096
'//生成服务端密钥,长度为4096,这里是空密码生成'
ls
ca-key.pem  ca.pem  server-key.pem
'//有兴趣的同学可以进去看看,空也是一个字符,能对其加密'

4.签名服务器私钥(添加身份信息)
openssl req -subj "/CN=*" -sha256 -new -key server-key.pem -out server.csr
'//请求的名称;哈希校验;生成新文件;引用服务器私钥'
'签名文件都是以.csr为结尾'
ls
ca-key.pem  ca.pem  server.csr  server-key.pem

5.使用CA证书与私钥证书签名,制作server端证书
openssl x509 -req -days 1000 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
'//-in输入server端签名,CA证书,CA密钥'
'//使用CA证书颁发,生成服务端证书'
 ls		'//'
ca-key.pem  ca.pem  ca.srl  server-cert.pem  server.csr  server-key.pem

6.生成客户端密钥
 openssl genrsa -out key.pem 4096

7.签名客户端
openssl req -subj "/CN=client" -new -key key.pem -out client.csr
ls
ca-key.pem  ca.srl      key.pem          server.csr
ca.pem      client.csr  server-cert.pem  server-key.pem

8.创建配置文件
 echo extendedKeyUsage=clientAuth > extfile.cnf
'//扩展性的密钥使用是使用客户端密钥的方式,生成这个配置文件,生成客户端时需要使用此文件(后一步)'

9.签名证书,需要(签名客户端,ca证书,ca密钥)
openssl x509 -req -days 1000 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf
'//生成客户端证书'
 ls
ca-key.pem  ca.srl    client.csr   key.pem          server.csr
ca.pem      cert.pem  extfile.cnf  server-cert.pem  server-key.pem

10.删除多余文件
 rm -rf ca.srl client.csr extfile.cnf server.csr
'//签名文件在过程中产生,也可以说是多余的'
ls		'//可以看到留下来的都是证书'
ca-key.pem  ca.pem  cert.pem  key.pem  server-cert.pem  server-key.pem

11.配置docker
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
'//注释第13行,在下面添加以上语句'
'//使用/usr/bin/dockerd(该进程)启动;--tlsverify:安全加密通讯'
'//tls中的匹配证书...;server端的证书及密钥'
'//监听任意地址,从端口2376来进行访问;通讯文件进程'

12.重启进程(服务/配置文件)及docker服务
systemctl daemon-reload && systemctl restart docker
 netstat -natp|grep 2376
tcp6       0      0 :::2376                 :::*                    LISTEN      101431/dockerd      

13.远程传输CA证书、客户端证书、客户端密钥至client端
scp ca.pem root@192.168.78.22:/etc/docker/
scp cert.pem root@192.168.78.22:/etc/docker/
scp key.pem root@192.168.78.22:/etc/docker/

14.本地验证
docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H tcp://server:2376 version
'//docker[...]version,本地使用证书进行验证,注意是使用相对路径'


--client端--
'//切至客户端'
cd /etc/docker/
ls
ca.pem  cert.pem  daemon.json  key.json  key.pem
 docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H tcp://server:2376 version
'//验证tls安全加密,注意这里server不要换成ip地址'

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值