Docker资源限制、数据卷和数据卷容器、容器互联、跨主机互联、创建自定义网络、Docker compose简单使用介绍

Docker资源限制

默认情况下,容器没有资源限制,可以使用系统所有资源。docker 通过 docker run 配置容器的内存,cpu, 磁盘io使用量。

其中许多功能都要求内核支持Linux功能。 要检查支持,可以使用docker info命令。 如果内核中禁用了某项功能会在输出结尾处看到警告,如:
WARNING: No swap limit support

内存限制:

对于Linux 主机,如果没有足够的内容来执行重要的系统任务,将会抛出 OOM 或者 Out of Memory Exception(内存溢出、内存泄漏、内存异常), 随后系统会开始杀死进程以释放内存。每个进程都有可能被 kill,包括Dockerd和其它的应用程序。如果重要的系统进程被Kill,会导致整个系统宕机。

产生 OOM 异常时,Docker尝试通过调整Docker守护程序上的OOM优先级来减轻这些风险,以便它比系统上的其他进程更不可能被结束。 容器上的OOM优先级未调整,这使得单个容器被结束的可能性比Docker守护程序或其他系统进程被结束的可能性更大,不推荐通过在守护程序或容器上手动设置–oom-score-adj为极端负数,或通过在容器上设置–oom-kill-disable来绕过这些安全措施。

Docker 可以强制执行硬性内存限制,即只允许容器使用给定的内存大小。
Docker 也可以执行非硬性内存限制,即容器可以使用尽可能多的内存,除非内核检测到主机上的内存不够用了。

内存限制参数:

-m or --memory= :容器可以使用的最大内存量,如果您设置此选项,则允许的最小值为4m (4兆字节)

–memory-swap * :容器可以使用的交换分区大小,要在设置物理内存限制的前提才能设置交换分区的限制

–memory-swappiness :设置容器使用交换分区的倾向性,值越高表示越倾向于使用swap分区,范围为0-100,0为能不用就不用,100为能用就用

–kernel-memory :容器可以使用的最大内核内存量,最小为4m,由于内核内存与用户空间内存隔离,因此无法与用户空间内存直接交换,因此内核内存不足的容器可能会阻塞宿主主机资源,这会对主机和其他容器产生副作用。

–memory-reservation :允许您指定小于–memory的软限制,当Docker检测到主机上的争用或内存不足时会激活该限制,如果使用–memory-reservation,则必须将其设置为低于–memory才能使其优先。 因为它是软限制,所以不能保证容器不超过限制。

–kernel-memory :设置核心内存限制,通过限制核心内存,可以在核心内存使用过多时阻止新进程被创建。不建议使用

–oom-kill-disable:默认情况下,发生OOM时,kernel会杀死容器内进程,但是可以使用–oom-kill-disable参数,可以禁止oom发生在指定的容器上,即 仅在已设置-m / - memory选项的容器上禁用OOM,如果-m 参数未配置,产生OOM时,主机为了释放内存还会杀死系统进程

swap限制:
swap限制参数–memory-swap 只有在设置了 --memory 后才会有意义。使用Swap,可以让容器将超出限制部分的内存置换到磁盘上。WARNING:经常将内存交换到磁盘的应用程序会降低性能

不同的设置会产生不同的效果:
–memory-swap:值为正数, 那么–memory和–memory-swap都必须要设置,–memory-swap表示你能使用的内存和swap分区大小的总和
例如:
–memory=300m, --memory-swap=1g, 那么该容器能够使用 300m 内存和 700m swap,即–memory是实际物理内存大小值不变,而实际的计算方式为(–memory-swap)-(–memory)=容器可用swap

–memory-swap:如果设置为0,则忽略该设置,并将该值视为未设置,即未设置交换分区。

–memory-swap:如果等于–memory的值,并且–memory设置为正整数,容器无权访问swap即也没有设置交换分区

–memory-swap:如果设置为unset,如果宿主机开启了swap,则实际容器的swap值为2x( --memory),即两倍于物理内存大小,但是并不准确。

–memory-swap:如果设置为-1,如果宿主机开启了swap,则容器可以使用主机上swap的最大空间

内存软限制:

docker run -it --rm --oom-kill-disable --memory 128m

验证:
cat /sys/fs/cgroup/memory/docker/容器ID/memory.soft_limit_in_bytes 

内存硬限制:

docker run -it --rm -m 128m lorel/docker-stress-ng --vm 2 --vm-bytes 256M

验证:
cat /sys/fs/cgroup/	/docker/容器ID/memory.limit_in_bytes

交换分区限制:

docker run -it --rm --oom-kill-disable --memory 128m  --memory-swap 192m 

验证:
cat /sys/fs/cgroup/memory/docker/容器ID/memory.memsw.limit_in_bytes

关闭一个容器的oom机制:

docker run -it --rm --oom-kill-disable --memory 128m lorel/docker-stress-ng --vm 2 --vm-bytes 256M

验证:
cat /sys/fs/cgroup/memory/docker/容器ID/memory.oom_control 

CPU限制

一个宿主机,有几十个核心的CPU,CPU为可压缩资源,但是有成百上千的进程,那么这么多进程怎么执行的?
实时优先级值:0-99
非实时优先级值:-20-19,对应100-139的进程优先级值
Linux kernel进程的调度基于CFS(Completely Fair Scheduler),完全公平调度

CPU密集型的场景:优先级值越低越好,计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力

IO密集型的场景:优先级值高点,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度),比如Web应用,高并发,数据量大的动态网站来说,数据库应该为IO密集型。

默认情况下,每个容器对主机CPU周期的访问权限是不受限制的,但是我们可以设置各种约束来限制给定容器访问主机的CPU周期,大多数用户使用的是默认的CFS调度方式,在Docker 1.13及更高版本中,还可以配置实时优先级。

CPU限制参数:

–cpus= 指定容器可以使用多少可用CPU资源。例如,如果主机有两个CPU,并且您设置了–cpus =“1.5”,那么该容器将保证最多可以访问一个半的CPU。这相当于设置–cpu-period =“100000”和–cpu-quota =“150000”。在Docker 1.13和更高版本中可用。

–cpu-period :设置CPU CFS调度程序周期,它与–cpu-quota一起使用,,默认为100微妙,范围从 100ms~1s,即[1000, 1000000]
–cpu-quota :在容器上添加CPU CFS配额,也就是cpu-quota / cpu-period的值,通常使用–cpus设置此值

–cpuset-cpus 主要用于指定容器运行的CPU编号,也就是我们所谓的绑核。

–cpuset-mem 设置使用哪个cpu的内存,仅对 非统一内存访问(NUMA)架构有效

–cpu-shares 主要用于cfs中调度的相对权重,,cpushare值越高的,将会分得更多的时间片,默认的时间片1024,最大262144

限制容器CPU:

docker run -it --rm  --cpus 2  lorel/docker-stress-ng  --cpu 4 --vm 4

将容器运行到指定的CPU上:

docker run -it --rm  --cpus 2  --cpuset-cpus  1,3 lorel/docker-stress-ng  --cpu 4 --vm 4

基于cpu—shares对CPU进行切分:
启动两个容器,一个—cpu-shares为1000,一个为500,观察最终效果,基本上shares值500的容器对CPU的利用率是shares值为1000容器的一般

docker run -it --rm --cpu-shares 1000 lorel/docker-stress-ng --cpu 4 --vm 4

docker run -it --rm --cpu-shares 500 lorel/docker-stress-ng --cpu 4 --vm 4

验证:
cat /sys/fs/cgroup/cpu/docker/容器ID/cpu.shares 

动态修改CPU shares值:

echo 1000 > /sys/fs/cgroup/cpu/docker/容器ID/cpu.shares 

据卷和数据容器

如果运行中的容器修如果生成了新的数据或者修改了现有的一个已经存在的文件内容,那么新产生的数据将会被复制到读写层进行持久化保存,这个读写层也就是容器的工作目录,此即“写时复制(COW)”机制

Docker 的镜像是分层设计的,底层是只读的,通过镜像启动的容器添加了一层可读写的文件系统,用户写入的数据都保存在这一层当中,如果要将写入的数据永久生效,需要将其提交为一个镜像然后通过这个镜像在启动实例,然后就会给这个启动的实例添加一层可读写的文件系统,目前 Docker 的数据类型分为
两种,一是数据卷,二是数据容器,数据卷类似于挂载的一块磁盘,数据容器是将数据保存在一个容器上。

数据卷

数据卷实际上就是宿主机上的目录或者是文件,可以被直接 mount 到容器当中使用。
实际生成环境中,需要针对不同类型的服务、不同类型的数据存储要求做相应的规划,最终保证服务的可扩展性、稳定性以及数据的安全性。

创建目录文件

mkdir /data/html
echo "test" > /data/html/index.html

启动容器使用-v 参数,将宿主机目录映射到容器内部。

docker run -d --name test1 -v /data/html:/app/html -p 8080:80 nginx:v1

还可以加上ro让目录只读
docker run -d --name test2 -v /data/html:/app/html:ro -p 8081:80 nginx:v1

如果想同时挂载多个文件或目录
docker run -d --name test3 -v /data/html:/app/html:ro -v /data/php:/app/php -p 8082:80 nginx:v1

访问测试效果

http://192.168.1.10:8080/index.html

数据卷的特点:
1.数据卷是目录或者文件,并且可以在多个容器之间共同使用。
2.对数据卷更改数据容器里面会立即更新。
3.数据卷的数据可以持久保存,即使删除使用使用该容器卷的容器也不影响。
4.在容器里面的写入数据不会影响到镜像本身。
文件挂载用于很少更改文件内容的场景,比如 nginx 的配置文件、tomcat 的配置文件等。

数据卷使用场景:
1.日志
2.静态web页面
3.应用配置文件
4.多容器间目录或文件共享

数据卷容器

数据卷容器最大的功能是可以让数据在多个 docker 容器之间共享,即可以让B 容器访问 A 容器的内容,而容器 C 也可以访问 A 容器的内容,即先要创建一个后台运行的容器作为 Server,用于卷提供,这个卷可以为其他容器提供数据存储服务,其他使用此卷的容器作为 client 端。

先启动一个容器挂载需要共享的宿主机目录当做Server

docker run -d --name test1 -v /data/html:/app/html -p 8080:80 nginx:v1

启动端 容器Client

docker run -d --name test2 -p 8081:80 --volumes-from test1 nginx:v1

访问测试

http://192.168.1.10:8081/index.html

在当前环境下,即使把提供卷的容器 Server 删除,已经运行的容器 Client 依然可以使用挂载的卷,因为容器是通过挂载访问数据的,但是无法创建新的卷容器客户端,但是再把卷容器 Server 创建后即可正常创建卷容器 Client,此方式可以用于线上数据库、共享数据目录等环境,因为即使数据卷容器被删除了,其他已经运行的容器依然可以挂载使用

数据卷容器可以作为共享的方式为其他容器提供文件共享,类似于 NFS 共享,可以在生产中启动一个实例挂载本地的目录,然后其他的容器分别挂载此容器的目录,即可保证各容器之间的数据一致性。

容器互联

在同一个宿主机上的容器之间可以通过自定义的容器名称相互访问,比如一个业务前端静态页面是使用 nginx,动态页面使用的是 tomcat,由于容器在启动的时候其内部 IP 地址是 DHCP 随机分配的,所以如果通过内部访问的话,自定义名称是相对比较固定的,因此比较适用于此场景。

先创建第一个容器

docker run -d --name test1 -p 8080:80 nginx:v1

查看host
cat /etc/hosts
127.0.0.1  localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 d245c8f3s5bd

创建第二个容器链接到第一个容器

docker run -d --name test2 --link test1 -p 8080:80 nginx:v1

查看第二个容器的host
cat /etc/hosts
127.0.0.1  localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 test1 d245c8f3s5bd #第一个容器的名称和 ID,只会添加到本地不会添加到对方
172.17.0.3 a381c1c9ed97
自定义别名

自定义的容器名称可能后期会发生变化,那么一旦名称发生变化,程序之间也要随之发生变化,比如程序通过容器名称进行服务调用,但是容器名称发生变化之后再使用之前的名称肯定是无法成功调用,每次都进行更改的话又比较麻烦,因此可以使用自定义别名的方式解决,即容器名称可以随意更,只要不更改别名即可。

命令格式:
docker run -d --name 容器名称 --link 目标容器名称:自定义别名 -p 本地端口:容器端口 镜像名称 命令

示例:

docker run -d --name test3 --link test1:testweb -p 8080:80 nginx:v1

查看容器的host
cat /etc/hosts
127.0.0.1  localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 testweb d245c8f3s5bd test1
172.17.0.4 g38211c9ehd7

跨主机互联

Docker 的网络有四种类型,可使用–net=参数指定,下面将介绍每一种类型的具体工作方式

Bridge 模式

–net=bridge ,默认就是 bridge 模式。也是使用比较多的模式,此模式创建的容器会为每一个容器分配自己的网络 IP 等信息,并将容器连接到一个虚拟网桥与外界通信。

Host 模式

–net=host 指定

启动的容器如果指定了使用 host 模式,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和 IP 地址,因此在容器里面查看到的 IP 信息就是宿主机的信息,访问容器的时候直接使用宿主机 IP+容器端口即可,不过容器的其他资源们必须文件系统、系统进程等还是和宿主机保持隔离。
此模式的网络性能最高,但是各容器之间端口不能相同,适用于运行容器端口比较固定的业务。

示例:
先确认主机端口没有占用 80 端口,接下来启动一个新容器,并指定网络模式为 host

docker run -d --name net_host --net=host nginx-test:v1 nginx

none 模式

–net=none 指定
在使用 none 模式后,Docker 容器不会进行任何网络配置,其没有网卡、没有 IP也没有路由,因此默认无法与外界通信,需要手动添加网卡配置 IP 等,所以极少使用。

Container模式

使用参数 –net=container:名称或 ID 指定
使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和主机共享网,新创建的容器不会创建自己的网卡也不会配置自己的 IP,而是和一个已经存在的被指定的容器东西 IP 和端口范围,因此这个容器的端口不能和被指定的端口冲突,除了网络之外的文件系统、进程信息等仍然保持 相互隔
离,两个容器的进程可以通过 lo 网卡社保通信。

示例:

先启动一个容器
docker run -d --name test1 nginx-test:v1

启动container模式的容器
docker run -d --name container --net=container:test1 nginx-test:v1 nginx

简单实现跨主机互联

跨主机互联是说 A 宿主机的容器可以访问 B 主机上的容器,但是前提是保证各主机之间的网络是可以相互通信的,然后各容器才可以通过主机访问到对方的容器,实现原理是在宿主机做一个网络路由就可以实现 A 宿主机的容器访问 B 主机的容器的目的,复杂的网络或者大型的网络可以使用 google 开源的k8s 进行互联。

1.修改各宿主机网段
Docker 的默认网段是 172.17.0.x/24,而且每个宿主机都是一样的,因此要做路由的前提就是各个主机的网络不能一致。
为避免影响,先在各服务器删除之前创建的所有容器。

docker rm -f `docker ps -a -q`

2.修改主机A的容器网段

vim /usr/lib/systemd/system/docker.service
在ExecStart后面添加参数
ExecStart=/usr/bin/dockerd-current --bip=172.16.10.1/24

重启服务查看网段
systemctl daemon-reload
systemctl restart docker

3.修改主机B的容器网段

vim /usr/lib/systemd/system/docker.service
在ExecStart后面添加参数
ExecStart=/usr/bin/dockerd-current --bip=172.16.20.1/24

重启服务查看网段

4.添加路由规则
现在IP情况如下
主机A的IP:192.168.1.10
容器IP:172.16.10.1
主机B的IP:192.168.1.20
容器IP:172.16.20.1

在主机A上添加路由规则
route add -net 172.16.20.0/24 gw 192.168.1.20

在主机B上添加路由规则
route add -net 172.16.10.0/24 gw 192.168.1.10

启动容器用ping测试

创建自定义网络

使用 docker 命令创建自定义网络可以自定义IP范围和网关等信息,一般很少用到手动创建网络

示例:

docker network create --subnet 172.20.0.0 --gateway 172.20.0.1 test-net

docker network create --subnet IP--gateway 网关 网络名称随便起

其他参数可用命令查看
docker network create --help
使用自定义网络
docker run -it --network test-net centos bash

Docker compose简单使用介绍

Docker compose是 docker 容器的一种编排服务,可管理多个容器。
比如可以解决容器之间的依赖关系,就像启动一个 web 就必须得先把数据库服务先启动一样,docker compose 完全可以替代 docker run 启动容器。

github 地址 https://github.com/docker/compose

这里直接用yum安装

yum install docker-compose -y
从docker compose 启动容器

这里实验需要用到镜像仓库,可参照这篇文章

Harbor介绍和使用

1.创建目录

mkdir docker-com

2.编写yml文件

vim nginx-test.yml

web1: #名称,不是镜像名称
  image:192.168.1.10/nginx/nginx-test:v1 #指定镜像
  container_name:web1-nginx #容器名称
  expose: #暴露端口
    - 80
    - 443
  ports: #主机端口映射
    - 80:80
    - 443:443

如果有多个容器要启动可以直接在后面加
web2:
  image:192.168.1.10/nginx/nginx-test:v1
  container_name:web2-nginx
  expose: 
    - 8080
    - 4430
  ports: #主机端口映射
    - 8080:8080
    - 4430:4430

3.启动测试
注意:需要在yml文件所在的目录启动

docker-compose start

如果是第一次启动,需要用这条命令
docker-compose up
加-d参数在后台运行
数据卷挂载

在yml文件中定义数据卷挂载

web1: #名称,不是镜像名称
  image:192.168.1.10/nginx/nginx-test:v1 #指定镜像
  container_name:web1-nginx #容器名称
  expose: #暴露端口
    - 80
    - 443
  ports: #主机端口映射
    - 80:80
    - 443:443
  volumes:
    - /app/nginx/nginx.conf:/etc/nginx/nginx.conf
    - /data/nginx/html:/data/html
链接其他容器

跟docker的 --link 参数效果一样

vim nginx-test.yml

web1: #名称,不是镜像名称
  image:192.168.1.10/nginx/nginx-test:v1 #指定镜像
  container_name:web1-nginx #容器名称
  expose: #暴露端口
    - 80
    - 443
  ports: #主机端口映射
    - 80:80
    - 443:443
  links: #链接其他容器
    - web2


web2:
  image:192.168.1.10/nginx/nginx-test:v1
  container_name:web2-nginx
  expose: 
    - 8080
    - 4430
  ports: #主机端口映射
    - 8080:8080
    - 4430:4430
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值