【docker集群应用】Docker网络与资源控制

文章目录

Docker 网络

Docker 网络实现原理

Docker 使用 Linux 桥接技术,在宿主机上虚拟一个名为 docker0 的 Docker 容器网桥。当 Docker 启动一个容器时,会根据 docker0 网桥的网段分配给容器一个 IP 地址(Container-IP)。由于同一宿主机内的容器都连接到同一个网桥,因此容器之间可以通过各自的 Container-IP 直接通信。

Docker 网桥是虚拟的,不是真实存在的网络设备,因此外部网络无法直接寻址到它,这意味着外部网络无法直接通过 Container-IP 访问容器。如果希望外部网络能够访问容器,可以通过端口映射将容器端口映射到宿主主机,即使用 docker run 命令的 -p-P 参数。

端口映射示例

bash 复制代码
# 随机映射端口(从32768开始)
docker run -d --name test1 -P nginx

# 指定映射端口
docker run -d --name test2 -p 43000:80 nginx

通过 docker ps -a 可以查看容器的端口映射情况,例如:

bash 复制代码
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                   NAMES
9d3c04f57a68   nginx     "/docker-entrypoint...."   4 seconds ago    Up 3 seconds    0.0.0.0:43000->80/tcp   test2
b04895f870e5   nginx     "/docker-entrypoint...."   17 seconds ago   Up 15 seconds   0.0.0.0:49170->80/tcp   test1

可以通过浏览器访问 http://192.168.80.10:43000http://192.168.80.10:49170 来访问对应的容器。

查看容器的输出和日志信息

使用 docker logs 命令可以查看容器的输出和日志信息:

bash 复制代码
docker logs 容器的ID/名称

Docker 的网络模式

使用 --net--network 选项指定容器的网络模式

  1. Host 模式
    • 相当于 Vmware 中的桥接模式,与宿主机在同一个网络中,但没有独立 IP 地址。
    • 容器与宿主机共享同一个 Network Namespace,使用宿主机的 IP 和端口。
    • 使用 --net=host 指定。
  2. Container 模式
    • 新创建的容器与已存在的容器共享一个 Network Namespace。
    • 共享 IP、端口范围等,但文件系统、进程列表等仍然隔离。
    • 使用 --net=container:NAME_or_ID 指定。
  3. None 模式
    • 容器拥有自己的 Network Namespace,但不进行任何网络配置。
    • 只有 lo 回环网络,没有其他网卡。
    • 无法联网,但保证了容器的安全性。
    • 使用--net=none指定。
  4. Bridge 模式
    • Docker 的默认网络模式。
    • 容器使用独立的 Network Namespace,并连接到 docker0 虚拟网卡。
    • 通过 docker0 网桥和 iptables nat 表配置与宿主机通信。
    • 为每个容器分配 IP,并通过 veth pair 设备与 docker0 网桥连接。
    • 默认设置,可省略或使用 --net=bridge 指定。
  5. 自定义网络
    • 允许用户自定义网络配置,如指定子网、网关等。

    • 可以使用 docker network create 命令创建自定义网络。

    • 示例:

      bash 复制代码
      # 创建自定义网络
      docker network create --subnet=172.18.0.0/16 --opt "com.docker.network.bridge.name"="docker1" mynetwork
      #docker1 为执行 ifconfig -a 命令时,显示的网卡名,如果不使用 --opt 参数指定此名称,那你在使用 ifconfig -a 命令查看网络信息时,看到的是类似 br-110eb56a0b22 这样的名字,这显然不怎么好记。
      #mynetwork 为执行 docker network list 命令时,显示的bridge网络模式名称。
      # 使用指定 IP 运行容器
      docker run -itd --name test4 --net mynetwork --ip 172.18.0.10 centos:7 /bin/bash

查看 Docker 网络列表

使用 docker network lsdocker network list 命令可以查看 Docker 网络列表:

bash 复制代码
docker network ls
# 或
docker network list

示例输出:

bash 复制代码
NETWORK ID     NAME      DRIVER    SCOPE
2b4359d229c6   bridge    bridge    local
0fa580365d39   host      host      local
cc13aa84a223   none      null      local

总结

  • Host:容器使用宿主机的 IP 和端口。
  • Container:容器与另一个指定容器共享 IP 和端口范围。
  • None:关闭容器的网络功能。
  • Bridge :默认模式,为每个容器分配 IP 并连接到 docker0 虚拟网桥。
  • 自定义网络:允许用户自定义网络配置。

Docker 容器网络命名空间示例

创建并运行容器
bash 复制代码
docker run -itd --name test1 centos:7 /bin/bash  # 创建名为 test1 的容器
查看容器列表
bash 复制代码
docker ps -a

输出示例:

CONTAINER ID   IMAGE      COMMAND       CREATED      STATUS       PORTS     NAMES
3ed82355f811   centos:7   "/bin/bash"   5 days ago   Up 6 hours             test1
查看容器进程号
bash 复制代码
docker inspect -f '{{.State.Pid}}' 3ed82355f811  # 查看 test1 容器的进程号

输出示例:

25945
查看容器的命名空间编号
bash 复制代码
ls -l /proc/25945/ns  # 查看 test1 容器的进程、网络、文件系统等命名空间编号

输出示例:

lrwxrwxrwx 1 root root 0 1月   7 11:29 ipc -> ipc:[4026532572]
lrwxrwxrwx 1 root root 0 1月   7 11:29 mnt -> mnt:[4026532569]
lrwxrwxrwx 1 root root 0 1月   7 11:27 net -> net:[4026532575]
lrwxrwxrwx 1 root root 0 1月   7 11:29 pid -> pid:[4026532573]
lrwxrwxrwx 1 root root 0 1月   7 12:22 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 1月   7 11:29 uts -> uts:[4026532570]
创建并运行共享网络命名空间的容器
bash 复制代码
docker run -itd --name test2 --net=container:3ed82355f811 centos:7 /bin/bash  # 创建名为 test2 的容器,并与 test1 共享网络命名空间
查看容器列表
bash 复制代码
docker ps -a

输出示例:

CONTAINER ID   IMAGE      COMMAND       CREATED          STATUS          PORTS     NAMES
ff96bc43dd27   centos:7   "/bin/bash"   48 seconds ago   Up 46 seconds             test2
3ed82355f811   centos:7   "/bin/bash"   58 minutes ago   Up 58 minutes             test1
查看容器进程号
bash 复制代码
docker inspect -f '{{.State.Pid}}' ff96bc43dd27  # 查看 test2 容器的进程号

输出示例:

27123
查看容器的命名空间编号
bash 复制代码
ls -l /proc/27123/ns  # 查看 test2 容器的进程、网络、文件系统等命名空间编号

输出示例:

lrwxrwxrwx 1 root root 0 1月   7 12:27 ipc -> ipc:[4026532692]
lrwxrmxrwx 1 root root 0 1月   7 12:27 mnt -> mnt:[4026532690]
lrwxrwxrwx 1 root root 0 1月   7 12:27 net -> net:[4026532575]
lrwxrwxrwx 1 root root 0 1月   7 12:27 pid -> pid:[4026532693]
lrwxrwxrwx 1 root root 0 1月   7 12:27 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 1月   7 12:27 uts -> uts:[4026532691]

Docker 资源控制

Docker 通过 Cgroups(Control Groups)机制来控制和限制容器使用的资源,包括 CPU、内存和磁盘 IO。以下是对这些资源控制的详细解释和示例。

1. CPU 资源控制

1.1 设置 CPU 使用率上限

  • CFS(Completely Fair Scheduler):Linux 使用CFS来调度各个进程对CPU的使用,CFS默认的调度周期是100ms。
  • --cpu-period:设置CPU调度周期(微秒),有效范围是1ms到1s(1000到1000000)。
  • --cpu-quota :设置每个周期内容器能使用的CPU时间(微秒),值必须大于等于1000。
    示例:
bash 复制代码
docker run -itd --name test6 --cpu-quota 50000 centos:7 /bin/bash
bash 复制代码
docker ps -a
CONTAINER ID   IMAGE      COMMAND       CREATED      STATUS       PORTS     NAMES
3ed82355f811   centos:7   "/bin/bash"   5 days ago   Up 6 hours             test5
bash 复制代码
cd /sys/fs/cgroup/cpu/docker/3ed82355f81151c4568aaa6e7bc60ba6984201c119125360924bf7dfd6eaa42b/
cat cpu.cfs_quota_us 
-1
bsh 复制代码
cat cpu.cfs_period_us 
100000

这将使容器 test6 在每个CFS周期中最多使用50%的CPU时间。
相关参数
cpu.cfs_period_us:cpu分配的周期(微秒,所以文件名中用 us 表示),默认为100000。
cpu.cfs_quota_us:表示该cgroups限制占用的时间(微秒),默认为-1,表示不限制。 如果设为50000,表示占用50000/100000=50%的CPU。

进行CPU压力测试
bash 复制代码
docker exec -it 3ed82355f811 /bin/bash

vim /cpu.sh
#!/bin/bash
i=0
while true
do
let i++
done

chmod +x /cpu.sh
./cpu.sh

top	#可以看到这个脚本占了很多的cpu资源

设置50%的比例分配CPU使用时间上限

bash 复制代码
docker run -itd --name test6 --cpu-quota 50000 centos:7 /bin/bash#可以重新创建一个容器并设置限额

cd /sys/fs/cgroup/cpu/docker/3ed82355f81151c4568aaa6e7bc60ba6984201c119125360924bf7dfd6eaa42b/
echo 50000 > cpu.cfs_quota_us
docker exec -it 3ed82355f811 /bin/bash
./cpu.sh
bash 复制代码
top	#可以看到cpu占用率接近50%,cgroups对cpu的控制起了效果

在多核情况下,如果允许容器进程完全占用两个 CPU, 则可以将 cpu-period 设置为 100000( 即 0.1 秒), cpu-quota设置为 200000(0.2 秒)。

1.2 设置 CPU 资源占用比

  • --cpu-shares :指定CPU份额,默认值为1024,值为1024的倍数。当多个容器竞争CPU资源时,份额高的容器获得CPU时间片的几率更高。
    示例:
bash 复制代码
#创建两个容器为 c1 和 c2,若只有这两个容器,设置容器的权重,使得c1和c2的CPU资源占比为1/3和2/3。
docker run -itd --name c1 --cpu-shares 1024 centos:7
docker run -itd --name c2 --cpu-shares 2048 centos:7

这将使容器 c2 在CPU资源竞争中获得比容器 c1 多一倍的机会。

bash 复制代码
#分别进入容器,进行压力测试
yum install -y epel-release
yum install -y stress
stress -c 4				#产生四个进程,每个进程都反复不停的计算随机数的平方根
bash 复制代码
#查看容器运行状态(动态更新)
docker stats
CONTAINER ID   NAME             CPU %     MEM USAGE / LIMIT     MEM %     NET I/O          BLOCK I/O         PIDS
c3ee18e65852   c2               66.50%    5.5MiB / 976.3MiB     0.56%     20.4MB / 265kB   115MB / 14.2MB    4
bb02d3b345d8   c1               32.68%    2.625MiB / 976.3MiB   0.27%     20.4MB / 325kB   191MB / 12.7MB    4
  • 可以看到在 CPU 进行时间片分配的时候,容器 c2 比容器 c1 多一倍的机会获得 CPU 的时间片。
  • 但分配的结果取决于当时主机和其他容器的运行状态, 实际上也无法保证容器 c1 一定能获得 CPU 时间片。比如容器 c1 的进程一直是空闲的,那么容器 c2 是可以获取比容器 c1 更多的 CPU 时间片的。极端情况下,例如主机上只运行了一个容器,即使它的 CPU 份额只有 50,它也可以独占整个主机的 CPU 资源。
  • Cgroups 只在容器分配的资源紧缺时,即在需要对容器使用的资源进行限制时,才会生效。因此,无法单纯根据某个容器的 CPU 份额来确定有多少 CPU 资源分配给它,资源分配结果取决于同时运行的其他容器的 CPU 分配和容器中进程运行情况。

1.3 设置容器绑定指定的 CPU

  • --cpuset-cpus :允许容器在指定的CPU上运行。
    示例:
bash 复制代码
docker run -itd --name test7 --cpuset-cpus 1,3 centos:7 /bin/bash

这将使容器 test7 只能在CPU 1和CPU 3上运行。

#进入容器,进行压力测试
yum install -y epel-release
yum install stress -y
stress -c 4

然后退出容器,执行 top 命令再按 1 查看CPU使用情况。

2. 内存使用限制

  • -m 或 --memory:限制容器可以使用的最大内存。

示例

bash 复制代码
docker run -itd --name test8 -m 512m centos:7 /bin/bash
docker stats
  • --memory-swap :正常情况下,--memory-swap 的值包含容器可用内存和可用 swap。
    如果 --memory-swap 设置为 0 或者 不设置,则容器可以使用的 swap 大小为 -m 值的两倍。
    如果 --memory-swap 的值和 -m 值相同,则容器不能使用 swap。
    如果 --memory-swap 值为 -1,它表示容器程序使用的内存受限,而可以使用的 swap 空间使用不受限制(宿主机有多少 swap 容器就可以使用多少)。
    强调一下,--memory-swap 是必须要与 --memory 一起使用的。

示例 :容器 test8 最大使用512M内存,容器 test8_swap 可以使用300M内存和700M swap。

bash 复制代码
docker run -itd --name test8 -m 512m centos:7 /bin/bash
docker run -itd --name test8_swap -m 300m --memory-swap=1g centos:7 /bin/bash

所以 -m 300m --memory-swap=1g 的含义为:容器可以使用 300M 的物理内存,并且可以使用 700M(1G - 300)的 swap。

3. 磁盘 IO 配额控制

  • --device-read-bps:限制某个设备上的读速度(bps),单位可以是kb、mb或gb。
  • --device-write-bps(在Docker 25版本之后已无效):限制某个设备上的写速度(bps)。
  • --device-read-iops:限制读某个设备的IOPS(每秒读次数)。
  • --device-write-iops :限制写入某个设备的IOPS(每秒写次数)。
    示例:
bash 复制代码
docker run -itd --name test9 --device-read-bps /dev/sda:1M centos:7 /bin/bash
docker run -it --name test10 --device-write-iops /dev/sda:1000 centos:7 /bin/bash

这将使容器 test9 对设备 /dev/sda 的读速度限制为1MB/s,容器 test10 对设备 /dev/sda 的写IOPS限制为1000次/秒。

通过dd来验证写速度

bash 复制代码
dd if=/dev/zero of=test.out bs=1M count=10 oflag=direct#添加oflag参数以规避掉文件系统cache
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 10.0025 s, 1.0 MB/s

清理 Docker 占用的磁盘空间

使用 docker system prune -a 命令可以清理关闭的容器、无用的数据卷和网络,释放磁盘空间。

bash 复制代码
docker system prune -a
相关推荐
蜗牛丨30 分钟前
Go Vue3 CMS管理后台(前后端分离模式)
mysql·docker·go·vue3·axios·gin·jwt·分页·跨域·ant design vue·log·gorm·otp动态码登录·validator·模型绑定·权限判断
菜鸟小灰灰1 小时前
搭建私有docker仓库
运维·docker·容器
一只小菜鸡1 小时前
python+django5.1+docker实现CICD自动化部署springboot 项目前后端分离vue-element
python·docker·自动化
炽天使1 小时前
aws rds-mysql不支持性能详情监控
linux·数据库·mysql·云计算·aws·rds
csdn_金手指1 小时前
docker 通过Dockerfile自定义的镜像部署Springboot项目
spring boot·docker·容器
Allen Bright1 小时前
Redis主从架构
数据库·redis·架构
ZHOU西口2 小时前
MySQL系列之远程管理(安全)
数据库·mysql·安全·tls·加密连接·require_secure
梦游钓鱼2 小时前
pyshark安装使用,ubuntu:20.04
linux·运维·ubuntu
Jacket Li2 小时前
Kubeadm 安装 Kubernetes 高可用集群 v1.30.0
云原生·容器·kubernetes