yuanxiaojiang
人的放纵是本能,自律才是修行

docker单机网络类型⭐⭐⭐⭐⭐

--network:指定docker容器使用哪个网络进行通信

docker0:docker守护进程启动时,会自动创建一个名为docker0的虚拟网桥(交换机

veth pair:当启动一个docker容器时,docker会创建一个虚拟以太网设备对

NAT(网络地址转换):是一种将私有IP地址转换为公有IP地址,以解决IPv4地址短缺的技术

  容器默认的五种单机网络类⭐⭐⭐⭐⭐

网络模式命令示例描述适用场景
bridge --network bridge 容器连接到 Docker 网桥,有独立 IP,通过 NAT 与外界通信(默认模式) 通用场景,单机部署
host --network host 容器直接使用宿主机的网络,无独立 IP,性能最佳 高性能需求,直接使用宿主机端口
none --network none 不分配任何网络,只有本地回环网络lo 离线任务,最高安全隔离
container --network container:name 新容器与指定容器共享网络命名空间 Sidecar 模式,紧密协作的容器组
自定义网络 --network my-net 自定义网络docker网络类型,需要创建网络,该自定义网络支持基于容器名称访问彼此(相当于内置了DNS) 多容器应用,需要服务发现和网络隔离

 五种网络模式容器网络访问能力对比表⭐⭐

网络类型访问外网访问宿主机IP访问docker01IP访问容器IP容器名解析
none
bridge (默认) ✅ (同网段) ❌ (需手动配置)
host
container
自定义网络 ✅ (自动DNS)

 bridge-桥接模式(默认模式)⭐⭐

Docker 会为容器创建一个虚拟的、独立的网络命名空间,并将其连接到一个名为 docker0 的虚拟网桥上

容器会从 172.17.0.0/16 网段获得一个独立的 IP 地址(例如 172.17.0.2)
容器之间可以通过这个 IP 地址进行通信
容器可以通过 Docker 内置的 DNS 和 NAT 机制访问外部网络(如互联网)
默认情况下,外部网络无法直接通过 IP 地址访问容器内的服务,除非你使用 -p 参数将容器的端口映射到宿主机端口

 host-主机模式⭐⭐

容器不会拥有自己独立的网络命名空间,而是直接使用宿主机的网络栈

容器直接使用宿主机的 IP 地址和端口
容器内监听的端口,会直接在宿主机上被占用
容器与宿主机之间的网络性能最好,几乎没有损耗

 测试

# 查看现有的网络类型
[root@docker01 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
cec4324c5481   bridge    bridge    local
de469a193e4d   host      host      local
155c38d45760   none      null      local
[root@docker01 ~]# docker run -d --name c1-none --network none alpine:latest sleep 3600
[root@docker01 ~]# docker exec c1-none hostname -i  # 返回值为空
[root@docker01 ~]# docker run -d --name c2-bridge --network bridge alpine:latest sleep 3600 [root@docker01 ~]# docker exec c2-bridge hostname -i # 172.17.0.2 [root@docker01 ~]# docker run -d --name c3 alpine:latest sleep 3600 [root@docker01 ~]# docker exec c3 hostname -i # 172.17.0.3
[root@docker01 ~]# docker run -d --name c4-host --network host alpine:latest sleep 3600 [root@docker01 ~]# docker exec c4-host hostname -i 10.0.0.81 172.16.1.81 172.17.0.1 [root@docker01 ~]# hostname -I 10.0.0.81 172.16.1.81 172.17.0.1
[root@docker01 ~]# docker run -d --name c5-container --network container:c3 alpine:latest sleep 3600 # 由于端口冲突导致容器启动失败 [root@docker01 ~]# docker run -d --name c5-container --network container:c3 alpine:latest sleep 3600 [root@docker01 ~]# docker exec c5-container hostname -i # 172.17.0.3

  单机网络环境实现容器通信的三种方法⭐⭐⭐⭐⭐

 手动host解析(不推荐)⭐

# 进入容器手动添加(重启后失效)
docker exec -it c1 bash
echo "172.17.0.3 c2" >> /etc/hosts

 --link(已过时)⭐⭐

# 创建第一个容器
docker run -d --name c1 nginx

# 创建第二个容器并link到c1
docker run -d --name c2 --link c1 nginx

# 在c2中可以直接ping c1,但c1不能ping c2
docker exec c2 ping c1

 自定义网络(推荐)⭐⭐⭐⭐⭐

自定义网络无法直接实现不同宿主机间的容器通信

[root@docker01 ~]# docker network create mynet
[root@docker01 ~]# docker run -it --name c1 --network mynet alpine:latest
[root@docker01 ~]# docker run -it --name c2 --network mynet alpine:latest
    两者之间可以通过容器名互相通信
/ # cat /etc/hosts
172.18.0.2 5164c9931aff  # 容器id映射:容器ip地址 容器id
实现了容器名和容器ID到IP地址的自动解析,让容器间可以通过名称直接通信,无需记忆IP地址

  将多个网络加入到同一个容器⭐⭐⭐⭐⭐

参数全称作用示例值说明
-d --driver 指定网络驱动类型 bridge 桥接网络,容器间可通信,与主机网络隔离
--subnet --subnet 定义网络子网范围 172.21.0.0/16 整个网络地址空间:172.21.0.1 - 172.21.255.254
--gateway --gateway 指定网络网关地址 172.21.0.254 容器与外部通信的出口,必须在子网范围内
--ip-range --ip-range 限制容器IP分配范围 172.21.100.0/24 实际分配给容器的IP:172.21.100.1 - 172.21.100.254
网络名 - 自定义网络名称 linux92 用户定义的网络标识符,用于容器连接

# 创建多个网络
[root@docker01 ~]# docker network create -d bridge  --gateway 172.21.0.254 --ip-range 172.21.100.0/24 --subnet 172.21.0.0/16 customize_network21
[root@docker01 ~]# docker network create -d bridge  --gateway 172.22.0.254 --ip-range 172.22.100.0/24 --subnet 172.22.0.0/16 customize_network22

# 启动容器加入customize_network21/customize_network22网络
[root@docker01 ~]# docker run -d --name c1 --network customize_network21 nginx:latest
[root@docker01 ~]# docker exec c1 hostname -I  # 172.21.100.0
[root@docker01 ~]# docker run -d --name c2 --network customize_network22 nginx:latest
[root@docker01 ~]# docker exec c2 hostname -I  # 172.22.100.0

# 将c1的容器添加一个C2容器相同的网络
[root@docker01 ~]# docker exec c1 hostname -I
172.21.100.0
[root@docker01 ~]# docker network connect customize_network22 c1
[root@docker01 ~]# docker exec c1 hostname -I
172.21.100.0 172.22.100.1

# 将c1的容器去除一个C2容器相同的网络
[root@docker01 ~]# docker network disconnect customize_network22 c1
[root@docker01 ~]# docker exec c1 hostname -I
172.21.100.0

  docker容器端口转发底层原理图⭐⭐⭐⭐⭐

docker容器端口转发底层原理图解

跨主机网络解决方案⭐⭐⭐⭐⭐

  Macvlan实现容器跨主机网络互联⭐⭐⭐

macvlan 技术的核心就是将一块物理网卡虚拟成多块虚拟网卡,每块虚拟网卡都有自己独立的 MAC 地址,使得容器或虚拟机能够直接连接到物理网络

 Macvlan实现容器跨主机网络互联

# 1.两个节点都需要加载Macvlan内核模块
[root@docker01/docker02 ~]# modprobe macvlan  # 动态加载Macvlan内核模块
[root@docker01/docker02 ~]# lsmod | grep macvlan  # 检查Macvlan内核模块是否加载
macvlan                19239  0 
    modprobe:modprobe 是 Linux 中用于动态加载和卸载内核模块的命令
    lsmod:列出所有已加载的内核模块

# 2.两个节点创建同网段的自定义网络类型
[root@docker01/docker02 ~]# docker network create -d macvlan --subnet 172.29.0.0/16 \
--gateway 172.29.0.254 -o parent=eth0 mynet_macvlan
-o:指定驱动选项
    parent:指定父接口网卡(物理网卡)
    eth0:Linux系统中的物理网卡名称
告诉 Docker 使用宿主机的 eth0 物理网卡 作为 macvlan 网络的底层物理接口 # 3.两个节点基于自定义网络启动容器并手动分配IP地址 [root@docker01 ~]# docker run -d -it --name c1 --network mynet_macvlan --ip 172.29.0.81 alpine:latest [root@docker01 ~]# docker exec c1 hostname -i 172.29.0.81 [root@docker02 ~]# docker run -d -it --name c1 --network mynet_macvlan --ip 172.29.0.82 alpine:latest [root@docker02 ~]# docker exec c1 hostname -i 172.29.0.82 # 4.测试两台主机上的容器的连通信、是否可以访问外网 [root@docker01 ~]# docker exec c1 ping 172.29.0.82 -c 3 [root@docker02 ~]# docker exec c1 ping 172.29.0.81 -c 3 # 两台节点使用了该网络模式无法访问外网 [root@docker02/docker02 ~]# docker exec c1 ping www.baidu.com -c 3 # 5.解决macvlan无法访问外网问题 给容器添加一个能访问外网的网络类型 [root@docker01 ~]# docker network connect bridge c1 [root@docker01 ~]# docker exec c1 ping www.baidu.com -c 3 # 访问成功

 

 macvlan优缺点

优点:
  - 1.docker原生支持,无需安装额外插件,配置起来相对简单
  - 2.适合小规模docker环境,例如只有1-3台,如果服务器过多,手动分配IP地址可能会无形之间增加工作量
缺点:
  - 1.需要手动分配IP地址,如果让其自动分配IP地址可能会存在多个主机自动分配的IP地址冲突的情况,到时候还需要人工介入维护
  - 2.相同网络的容器之间相互通信没问题,跨主机之间的容器进行通信也没问题,但容器无法与宿主机之间进行通信,也无法连接到外网;
  - 3.macvlan需要绑定一块物理网卡,若网卡已经被绑定,则无法创建;

温馨提示:
    如果非要使用macvlan,我们需要手动分配IP地址,无法联网的问题,只需要使用"docker network connect"\
重新分配一块能够访问外网的网卡即可解决。

  overlay实现容器跨主机网络互联⭐⭐⭐⭐⭐

  • Consul:自动管理微服务网络并确保它们能相互发现和通信的分布式网络平台
    • 让不同节点上的docker容器能够自动发现彼此,并组成一个跨主机的虚拟大二层网络
    • 虚拟大二层网络:给不同物理服务器搭建虚拟交换机,让其服务器上面的容器感觉在一个局域网里工作
    • 可以将consul理解为共享文件夹
  • cluster-store:通过一个中央数据库地址,确保集群内所有 Docker 主机间的元数据保持一致(共享元数据:网络信息、节点信息、端口信息等)
  • cluster-advertise:声明本机在集群中的“身份名片”,告知其他节点通过哪个地址和端口来访问本机的 Docker 守护进程

image

 环境准备

# 分别在91节点和92节点二进制安装docker-20.10.8
[root@elk91/elk92 ~]# tar xf docker-20.10.8.tgz
[root@elk91/elk92 ~]# cp /root/docker/* /usr/bin/
[root@elk91/elk92 ~]# dockerd

# 拉取consul:1.15.4镜像
[root@elk91 ~]# docker load -i consul_1.15.4.tar
[root@elk91 ~]# docker run -d --network host --restart always --name dev-consul \
-e CONSUL_BIND_INTERFACE=eth0 consul:1.15.4
[root@elk91 ~]# ss -lntup |grep 8500

 部署

# 修改/etc/docker/daemon.json文件
[root@elk91 ~]# cat > /etc/docker/daemon.json << EOF { "cluster-store": "consul://10.0.0.91:8500", "cluster-advertise": "10.0.0.91:6666" } EOF [root@elk91 ~]# dockerd # 重新启动docker容器
[root@elk92 ~]# cat > /etc/docker/daemon.json << EOF { "cluster-store": "consul://10.0.0.91:8500", "cluster-advertise": "10.0.0.92:8888" } EOF [root@elk92 ~]# dockerd # 重新启动docker容器 # 任意一个客户端节点创建网络,其他客户端都会通过consul来实现同步功能 docker network create -d overlay --subnet 172.30.0.0/16 --gateway 172.30.0.254 consul-overlay # 分别在91和92节点基于自定义网络启动容器 [root@elk91 ~]# docker run -d --name c1 --network consul-overlay alpine:latest sleep 3600 [root@elk92 ~]# docker run -d --name c2 --network consul-overlay alpine:latest sleep 3600 [root@elk91 ~]# docker exec c1 hostname -i # 172.30.0.1 [root@elk92 ~]# docker exec c2 hostname -i # 172.30.0.2

 测试

# 测试(以下都能ping通)
[root@elk91 ~]# docker exec c1 ping 172.30.0.2
[root@elk91 ~]# docker exec c1 ping 10.0.0.91
[root@elk91 ~]# docker exec c1 ping www.baidu.com

image

docker底层原理⭐⭐⭐⭐⭐

  chroot技术(容器底层使用了chroot技术)⭐⭐⭐

chroot是一种通过改变进程的根目录来创建隔离文件系统环境的技术

ldd命令用于显示二进制可执行文件或共享库所依赖的所有动态链接库

# 1.创建工作目录
[root@docker02 ~]# mkdir -p /root/yuanxiaojiang
# 2.拷贝bash程序
[root@docker02 ~]# mkdir -p /root/yuanxiaojiang/bin
[root@docker02 ~]# cp /bin/bash /root/yuanxiaojiang/bin/
# 3.拷贝bash程序的依赖环境
[root@docker02 ~]# ldd /bin/bash
    linux-vdso.so.1 =>  (0x00007ffc655cf000)
    libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007f99feae0000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f99fe8dc000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f99fe50e000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f99fed0a000)
[root@docker02 ~]# mkdir -p /root/yuanxiaojiang/lib64
cp /lib64/libtinfo.so.5 /root/yuanxiaojiang/lib64/
cp /lib64/libdl.so.2 /root/yuanxiaojiang/lib64/
cp /lib64/libc.so.6 /root/yuanxiaojiang/lib64/
cp /lib64/ld-linux-x86-64.so.2 /root/yuanxiaojiang/lib64/
# 4.拷贝ls程序及其依赖环境
[root@docker02 ~]# which ls
/usr/bin/ls
[root@docker02 ~]# cp /usr/bin/ls /root/yuanxiaojiang/bin/
[root@docker02 ~]# ldd /root/yuanxiaojiang/bin/ls 
cp /lib64/libselinux.so.1 /root/yuanxiaojiang/lib64/
cp /lib64/libcap.so.2 /root/yuanxiaojiang/lib64/
cp /lib64/libacl.so.1 /root/yuanxiaojiang/lib64/
cp /lib64/libc.so.6 /root/yuanxiaojiang/lib64/
cp /lib64/libpcre.so.1 /root/yuanxiaojiang/lib64/
cp /lib64/libdl.so.2 /root/yuanxiaojiang/lib64/
cp /lib64/ld-linux-x86-64.so.2 /root/yuanxiaojiang/lib64/
cp /lib64/libattr.so.1 /root/yuanxiaojiang/lib64/
cp /lib64/libpthread.so.0 /root/yuanxiaojiang/lib64/

# 5.改变根目录
[root@docker02 ~]# chroot /root/yuanxiaojiang/
bash-4.2# export PATH=/bin:/usr/bin
bash-4.2# ls -l

# 6.启动一个新的容器
[root@docker02 ~]# cp  -r /root/yuanxiaojiang /root/yuanxiaojun
# 启动一个新容器(终端一)
[root@docker02 ~]# chroot /root/yuanxiaojiang/
bash-4.2# echo "xixi" >/xixi.log
bash-4.2# ls -l
-rw-r--r-- 1 0 0   5 Oct 27 13:37 xixi.log
# 启动一个新容器(终端二)
[root@docker02 ~]# chroot /root/yuanxiaojun/
bash-4.2# echo "haha" >/haha.log
bash-4.2# ls -l
-rw-r--r-- 1 0 0   5 Oct 27 13:40 haha.log

# 两个容器数据存放位置(宿主机位置)
[root@docker02 ~]# ls /root/yuanxiaojiang/
bin  lib  lib64  xixi.log
[root@docker02 ~]# ls /root/yuanxiaojun/
bin  haha.log  lib  lib64

  overlayFS(堆叠文件系统)⭐⭐⭐

 overlayFS概述

  • OverlayFS是一种堆叠文件系统,建立在其他文件系统(如ext4、xfs)之上,通过联合挂载技术将多个目录“合并”展示为同一级目录
  • Linux内核为Docker提供的OverlayFS驱动有两种:Overlay和Overlay2。而Overlay2是相对于Overlay的一种改进,在Inode利用率方面比Overlay更有效。
  • Overlay环境需求:
    • Docker版本17.06.02+
    • 宿主机文件系统需要是EXT4或XFS格式

 OverlayFS实现方式⭐⭐⭐

OverlayFS通过三个目录:lower目录、upper目录、以及work目录实现
lower:可以进行只读操作的目录(一般存放的是只读数据upper:可以进行读写操作的目录
work:
  目录为工作基础目录,挂载后会自动创建一个work子目录(实际测试手动卸载后该目录并不会被删除)
  该目录主要是存储一些临时存放的结果中间数据的工作目录

 OverlayFS三层结构⭐⭐⭐

# LowerDir (只读)
    docker镜像的只读层,也就是容器rootfs(根文件系统)的基础部分
    Lowerdir的数量直接等于你构建的Docker镜像所拥有的只读层数
    Lower 包括两个层:
      (1)系统的init
        1)容器在启动以后, 默认情况下lower层是不能够修改内容的, 但是用户有需求需要修改主机名与域名\
          地址, 那么就需要添加init层中的文件(hostname, resolv.conf,hosts,mtab等文件),\
          用于解决此类问题;
        2)修改的内容只对当前的容器生效, 而在docker commit提交为镜像时候,并不会将init层提交。
        3)init文件存放的目录为/var/lib/docker/overlay2/<init_id>/diff
      2)容器的镜像层
        不可修改的数据
# Upperdir (读写)
    upperdir则是在lowerdir之上的一层, 为读写层。容器在启动的时候会创建, 所有对容器的修改, \
    都是在这层。比如容器启动写入的日志文件,或者是应用程序写入的临时文件。
# MergedDir (展示)
    merged目录是容器的挂载点,在用户视角能够看到的所有文件,都是从这层展示的。

 overlayFS案例

组件说明
mount -t overlay 挂载一个 overlay 类型的文件系统
overlay 设备名称(overlayfs 通常就用 overlay)
-o 开始指定挂载选项
lowerdir=/path/lower0:/path/lower1:/path/lower2 只读层:多个基础层,用冒号分隔。
优先级:lower2 → lower1 → lower0(从右到左,最右边层级最高)
upperdir=/yuanxiaojiang/upper 可写层:所有修改都会记录在此处
workdir=/yuanxiaojiang/work 工作目录:overlayfs 内部使用,需与 upperdir 在同一文件系统
/yuanxiaojiang/merged/ 挂载点:最终呈现的统一视图
[root@docker02 ~]# mkdir -p /yuanxiaojiang/lower{0..2} /yuanxiaojiang/{upper,work,merged}
[root@docker02 ~]# mount -t overlay overlay -o \
lowerdir=/yuanxiaojiang/lower0:/yuanxiaojiang/lower1:/yuanxiaojiang/lower2,\
upperdir=/yuanxiaojiang/upper,\
workdir=/yuanxiaojiang/work \
/yuanxiaojiang/merged/
[root@docker02 ~]# df -h -t overlay Filesystem Size Used Avail Use% Mounted on overlay 27G 6.5G 21G 24% /yuanxiaojiang/merged # 尝试在lower层写入准备初始数据 [root@docker02 ~]# cp /etc/hosts /yuanxiaojiang/lower0/ [root@docker02 ~]# cp /etc/issue /yuanxiaojiang/lower1/ [root@docker02 ~]# cp /etc/resolv.conf /yuanxiaojiang/lower2/ # 尝试在upper层写入准备初始数据 [root@docker02 ~]# cp /etc/hostname /yuanxiaojiang/upper/ # 尝试在merged目录写入数据,观察数据实际写入的应该是upper层 [root@docker02 ~]# cp /etc/fstab /yuanxiaojiang/merged/ [root@docker02 ~]# ll /yuanxiaojiang/lower0 -rw-r--r-- 1 root root 435 Oct 28 11:05 hosts [root@docker02 ~]# ll /yuanxiaojiang/lower1 -rw-r--r-- 1 root root 23 Oct 28 11:10 issue [root@docker02 ~]# ll /yuanxiaojiang/lower2 -rw-r--r-- 1 root root 72 Oct 28 11:10 resolv.conf [root@docker02 ~]# ll /yuanxiaojiang/upper/ -rw-r--r-- 1 root root 483 Oct 28 11:12 fstab -rw-r--r-- 1 root root 9 Oct 28 11:11 hostname [root@docker02 ~]# ll /yuanxiaojiang/merged/ -rw-r--r-- 1 root root 483 Oct 28 11:12 fstab -rw-r--r-- 1 root root 9 Oct 28 11:11 hostname -rw-r--r-- 1 root root 435 Oct 28 11:05 hosts -rw-r--r-- 1 root root 23 Oct 28 11:10 issue -rw-r--r-- 1 root root 72 Oct 28 11:10 resolv.conf # 重新挂载(不挂载upperdir层) [root@docker02 ~]# umount /yuanxiaojiang/merged [root@docker02 ~]# mount -t overlay overlay \ -o lowerdir=/yuanxiaojiang/lower0:/yuanxiaojiang/lower1:/yuanxiaojiang/lower2,\ workdir=/yuanxiaojiang/work \ /yuanxiaojiang/merged/ [root@docker02 ~]# ll /yuanxiaojiang/merged/ -rw-r--r-- 1 root root 435 Oct 28 11:05 hosts -rw-r--r-- 1 root root 23 Oct 28 11:10 issue -rw-r--r-- 1 root root 72 Oct 28 11:10 resolv.conf [root@docker02 ~]# cp /etc/os-release /yuanxiaojiang/merged/(写入数据失败) cp: cannot create regular file ‘/yuanxiaojiang/merged/os-release’: Read-only file systm

 测试docker底层使用了overlayFS

[root@docker02 ~]# docker run -d --name c1 nginx:latest 
[root@docker02 ~]# df -h -t overlay
Filesystem      Size  Used Avail Use% Mounted on
overlay          27G  6.6G   21G  25% /var/lib/docker/overlay2/27ff...e9d4/merged
[root@docker02 ~]# docker inspect -f "{{.GraphDriver.Data.MergedDir}}" c1
/var/lib/docker/overlay2/27ff...e9d4/merged
[root@docker02 ~]# docker inspect -f "{{.GraphDriver.Data.UpperDir}}" c1
/var/lib/docker/overlay2/27ff...e9d4/diff

[root@docker02 ~]# docker exec c1 touch /haha.log  # 在容器中创建一个文件
[root@docker02 ~]# ls /var/lib/docker/overlay2/27ff...e9d4/merged
haha.log
[root@docker02 ~]# ls /var/lib/docker/overlay2/27ff...e9d4/diff/  # 数据被写入到读写层
haha.log

 macvlan和overlay的区别⭐⭐⭐

macvlan和overlay的区别:
  相同点:
    都可以实现网络的互相通信
  不同点:
    - 1.macvlan是内核支持模块,无需安装第三方插件,只需加载模块即可,overlay需要安装第三方插件consul;
    - 2.macvlan需要手动分配IP地址,而overlay网络无需手动分配IP地址;
    - 3.macvlan默认无法访问外网,需要手动配置桥接网络,而overlay默认可以访问外网;
 docker网络不足的总结:
  - 1.docker在网络互联上存在缺陷,比如overlay网络各节点实现IP地址通信,\
      当容器挂掉时,会自动为该容器分配IP地址。若容器重启后,IP地址可能发生变化;
  - 2.若配置文件写的都是IP地址,则容器重启后IP地址发生变化,可能导致服务不可用; 

  namespace-名称空间⭐⭐⭐

image

 namespace介绍⭐⭐⭐

docker底层用到了namespace做资源隔离 

Linux Namespace是Linux系统提供的一种 资源隔离机制
可实现系统资源隔离的列表如下:
    IPC: 用于隔离进程间通信
    MNT: 用于隔离文件系统和提供硬盘挂载点
    NET: 用于隔离网络
    PID: 用于隔离进程ID
    User: 用于隔离用户和用户组
    UTS: 用于隔离HostName(主机名)和DomianName(域名)

 NET网络名称空间测试案例⭐

# 1.创建一个名称为"linux_yuan"的网络名称空间
[root@docker01 ~]# ip netns add linux_yuan
[root@docker01 ~]# ll /var/run/netns/
-r--r--r-- 1 root root 0 Oct 30 13:36 linux_yuan

# 2.启动"linux_yuan"的网络名称空间的lo网卡 
[root@docker01 ~]# ip netns exec linux_yuan ping 127.0.0.1  # 未启动网卡,不饿能ping通
[root@docker01 ~]# ip netns exec linux_yuan ifconfig lo up  # 启动lo网卡
[root@docker01 ~]# ip netns exec linux_yuan ping 127.0.0.1  # 可以ping通

# 3.宿主机创建网络设备对
[root@docker01 ~]# ip link add veth100 type veth peer name veth200
[root@docker01 ~]# ip address  # 会多出来2块网卡,即veth100,veth200

# 4.将"veth200"设备关联到咱们自定义的"linux_yuan"网络名称空间
[root@docker01 ~]# ip link set veth200 netns linux_yuan
[root@docker01 ~]# ip address  # 发现宿主机的veth200网卡不见了

# 5.将"veth200"设备配置IP地址
[root@docker01 ~]# ip netns exec linux_yuan ip address
[root@docker01 ~]# ip netns exec linux_yuan ifconfig veth200 172.31.100.200/24 up
[root@docker01 ~]# ip netns exec linux_yuan ip address

# 6.宿主机veth100也配置IP地址
[root@docker01 ~]# ifconfig veth100 172.31.100.100/24 up
[root@docker01 ~]# ifconfig veth100
[root@docker01 ~]# ping 173.31.100.200  # 能ping通

# 7.测试
[root@docker01 ~]# ip netns exec linux_yuan ping 172.31.100.100  # 能ping通
[root@docker01 ~]# ip netns exec linux_yuan ping 10.0.0.81  # 未添加网关,无法ping通
[root@docker01 ~]# ip netns exec linux_yuan route add default gw 172.31.100.100  # 将veth100配置为默认网关
[root@docker01 ~]# ip netns exec linux_yuan ping 10.0.0.81  # 添加网关后,可能ping通

# ping外网无法ping通
[root@docker01 ~]# ip netns exec linux_yuan www.baidu.com  # 不能ping通
[root@docker01 ~]# ip netns exec linux_yuan 10.0.0.82  # 不能ping通
[root@docker01 ~]# ip netns exec linux_yuan 110.242.68.4  # 不能ping通

# 8.测试完成后,删除名称空间
ll /var/run/netns/   # 可以先查看挂载点文件是否存在
ip netns del linux_yuan  # 删除名称空间
ip link del veth100    # 删除宿主机的虚拟网卡

 测试docker使用net namespace⭐

[root@docker01 ~]# docker run -d --name c1 alpine:latest sleep 3600
[root@docker01 ~]# ip address
  1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
  2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast 
  3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast 
  4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue 
  40: vethfe02329@if39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 
[root@docker01 ~]# docker exec c1 ip a
  1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
  39: eth0@if40: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 

[root@docker01 ~]# docker run -d --name c2 alpine:latest sleep 3600
[root@docker01 ~]# ip address
  1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
  2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast 
  3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast 
  4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue 
  40: vethfe02329@if39: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 
  42: veth7083571@if41: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
[root@docker01 ~]# docker exec c2 ip a
  1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
  41: eth0@if42: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 

 两个容器共享网络名称空间案例⭐

# 1. 启动两个容器
[root@docker01 ~]# docker run -d --name c1 alpine:latest sleep 3600
[root@docker01 ~]# docker run -d --name c2 --network container:c1 alpine:latest sleep 3600

# 2.查看c1和c2的进程ID对应的网络名称空间
[root@docker01 ~]# docker inspect -f "{{.State.Pid}}" c1    # 12239
[root@docker01 ~]# docker inspect -f "{{.State.Pid}}" c2    # 12609
[root@docker01 ~]# ll /proc/12239/ns
lrwxrwxrwx 1 root root 0 Oct 30 16:40 net -> net:[4026532503]
[root@docker01 ~]# ll /proc/12609/ns/
lrwxrwxrwx 1 root root 0 Oct 30 16:46 net -> net:[4026532503]
  # 两个进程(12239 和 12609)共享同一个网络命名空间(net:[4026532503])
[root@docker01 ~]# docker exec c1 ifconfig
[root@docker01 ~]# docker exec c2 ifconfig
  # 两个容器显示的网络信息相同

# c1和c2对应的net的存储地址是相同的,因此c1和c2能够看到相同的网络信息

  cgoups⭐⭐⭐

 cgoups介绍

Linux CGroup全称Linux Control Group,是Linux内核的一个功能
用于限制、控制、分离进程组所使用的物理资源

cgroups在Linux系统中能够控制的资源列表
  cpu: 主要限制进程的cpu使用率
  cpuacct: 可以统计cgroups中的进程的cpu使用报告
  cpuset: 可以为cgroups中的进程分配单独的cpu节点或者内存节点
  memory: 可以限制进程的memory使用量
  blkio: 可以限制进程的块设备io
  devices: 可以控制进程能够访问某些设备
  net_cls: 可以标记cgroups中进程的网络数据包,然后可以使用tc模块对数据包进行控制
  net_prio: 这个子系统用来设计网络流量的优先级
  freezer: 可以挂起或者恢复cgroups中的进程
  ns: 可以使不同cgroups下面的进程使用不同的namespace
  hugetlb: 这个子系统主要针对于HugeTLB系统进行限制,这是一个大页文件系统

 CPU资源限制案例

image

# 1.挂载cgroup文件系统,以便通过文件接口管理控制组
[root@docker01 ~]# mount -t cgroup
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu

# 2.进入到CPU的挂载路径,并创建自定义的资源限制组
[root@docker01 ~]# cd /sys/fs/cgroup/cpu && mkdir linux_yuan && ls linux_yuan
cgroup.clone_children    cgroup.procs  cpuacct.usage    cpu.cfs_period_us 
    系统会默认在linux_yuan目录下创建文件

# 3.使用stree进行压力测试
[root@docker01 ~]# yum install -y stress
[root@docker01 ~]# stree -c 4 -v -t 20m

# 4.限制CPU的使用率在30%
[root@docker01 ~]# cd /sys/fs/cgroup/cpu/linux_yuan/ && echo 30000 > cpu.cfs_quota_us

# 5.将任务的ID加入自定义限制组
[root@docker01 ~]# ps -ef |grep stress |grep -v grep
root 13607 2223 0 17:14 pts/0 00:00:00 stress -c 4 -v -t 20m
root 13608 13607 17 17:14 pts/0 00:02:03 stress -c 4 -v -t 20m
root 13609 13607 17 17:14 pts/0 00:02:01 stress -c 4 -v -t 20m
root 13610 13607 17 17:14 pts/0 00:02:06 stress -c 4 -v -t 20m
root 13611 13607 17 17:14 pts/0 00:02:07 stress -c 4 -v -t 20m

[root@docker01 ~]# cd /sys/fs/cgroup/cpu/linux_yuan/
[root@docker01 linux_yuan]# echo 13608 >> tasks
[root@docker01 linux_yuan]# echo 13609 >> tasks
[root@docker01 linux_yuan]# echo 13610 >> tasks
[root@docker01 linux_yuan]# echo 13611 >> tasks

# 6.删除自定义限制组
[root@docker01 ~]# rmdir /sys/fs/cgroup/cpu/linux_yuan/

 docker使用cgroup实现资源限制⭐⭐⭐⭐⭐

# 1.部署测试容器
[root@docker02 ~]# docker load -i /root/stress-image.tar 
[root@docker02 ~]# docker run -d --cpu-quota 30000 --memory 200m --name c1 polinux/stress:1.0.4 sleep 3600
[root@docker02 ~]# docker run -d --name c2 polinux/stress:1.0.4 sleep 3600

# 2.压测CPU和内存
[root@docker02 ~]# docker exec c1 stress -c 4 -v -t 20m
[root@docker02 ~]# docker stats c1
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT   MEM %     NET I/O     BLOCK I/O   PIDS
cfddae493235   c1        30.03%    160KiB / 200MiB     0.08%     656B / 0B   0B / 0B     6

[root@docker02 ~]# docker exec c2 stress -c 4 -v -t 20m
[root@docker02 ~]# docker stats c2
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT   MEM %     NET I/O     BLOCK I/O   PIDS
31cd95ff5382   c2        69.60%    160KiB / 972.3MiB   0.02%     656B / 0B   0B / 0B     6 

 对已运行的容器实现资源限制⭐⭐⭐⭐⭐

# 1.容器实例准备
[root@docker02 ~]# docker run -d --name c1 polinux/stress:1.0.4 sleep 3600

# 2.压力测试
[root@docker02 ~]# docker exec c1 stress --cpu 8 --io 4 --vm 2 --vm-bytes 128M --timeout 10m --vm-keep
    --cpu 8: 生成8个CPU密集型工作进程
    --io 4: 生成4个I/O密集型工作进程
    --vm 2: 生成2个内存工作进程
    --vm-bytes 128M: 每个内存工作进程分配128MB内存
    --timeout 10m: 测试持续10分钟
    --vm-keep: 关键参数 - 保持内存分配,不重复释放和重新分配

# 3.限制前的状态
[root@docker02 ~]# docker stats c1 --no-stream 
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O     BLOCK I/O     PIDS
dff33327d3b5   c1        99.51%    256.2MiB / 972.3MiB   26.35%    656B / 0B   0B / 54.3kB   16

# 4.限制容器的资源使用
[root@docker02 ~]# docker container update --cpu-quota 20000 --memory 300m --memory-swap 300m c1

# 5.限制之后的状态
[root@docker02 ~]# docker stats c1 --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
dff33327d3b5 c1 19.80% 225.2MiB / 300MiB 75.07% 656B / 0B 4.59GB / 2.36GB 16

多机环境(需要其他方案)

如果容器分布在 不同的物理机/虚拟机

 
 
如果是不同宿主机上面的容器,我想问问,用这种方法可以吗
 

不可以用! 这三种方法在跨宿主机的场景下完全无效。

为什么不行?

1. 网络隔离

  • 每台宿主机有自己独立的 Docker 网络环境

  • 自定义网络、--link、hosts 修改都只在当前宿主机内

 
 
自定以网络可以实现不同宿主机之间的容器间的通信吗
 

不可以! 自定义网络无法直接实现不同宿主机间的容器通信。

原因分析

1. 网络范围限制

bash
# 在主机A上创建网络
docker network create mynet
# 网络范围:172.18.0.0/16

# 在主机B上创建网络
docker network create mynet  
# 网络范围:172.19.0.0/16(完全不同)
  • 每台主机的 Docker 网络都是独立的

  • 网络地址段不互通

2. DNS 解析局限

  • 自定义网络的 DNS 解析只在本机有效

  • 主机A的容器无法解析到主机B的容器名称

跨主机通信解决方案

1. Docker Swarm(推荐)

bash
# 创建 Swarm 集群
docker swarm init
# 在其他主机上执行加入命令

# 创建 overlay 网络
docker network create -d overlay mynet

# 服务会自动在集群中调度,跨主机通信
docker service create --network mynet --name web nginx

2. 第三方网络插件

bash
# 使用 Weave Net
weave launch
docker run --net=weave -d --name c1 nginx

# 使用 Calico
# 使用 Flannel

3. 手动配置

  • VPN:在容器间建立 VPN 隧道

  • 端口映射 + 服务发现:通过暴露端口配合服务注册发现

  • 云服务商网络:AWS VPC、Azure VNet 等

4. Kubernetes

yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-a
spec:
  containers:
  - name: container-a
    image: nginx

Kubernetes 的 CNI 网络插件自动处理跨主机通信

总结

 
方案适用场景复杂度
自定义网络 单机容器通信 简单
Docker Swarm 中小规模集群 中等
Kubernetes 大规模生产环境 复杂
第三方插件 特定网络需求 中等

对于跨主机需求,建议使用 Docker Swarm 或 Kubernetes

本回答由 AI 生成,内容仅供参考,请仔细甄别。
 
 
# 查看现有的网络类型 [root@docker01 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE cec4324c5481 bridge bridge local de469a193e4d host host local 155c38d45760 none null local [root@docker01 ~]# docker run -d --name c1-none --network none alpine:latest sleep 3600 [root@docker01 ~]# docker exec c1-none hostname -i # 返回值为空 [root@docker01 ~]# docker run -d --name c2-bridge --network bridge alpine:latest sleep 3600 [root@docker01 ~]# docker exec c2-bridge hostname -i # 172.17.0.2 [root@docker01 ~]# docker run -d --name c3 alpine:latest sleep 3600 [root@docker01 ~]# docker exec c3 hostname -i # 172.17.0.3 [root@docker01 ~]# docker run -d --name c4-host --network host alpine:latest sleep 3600 [root@docker01 ~]# docker exec c4-host hostname -i 10.0.0.81 172.16.1.81 172.17.0.1 [root@docker01 ~]# hostname -I 10.0.0.81 172.16.1.81 172.17.0.1 [root@docker01 ~]# docker run -d --name c5-container --network container:c3 alpine:latest sleep 3600 # 由于端口冲突导致容器启动失败 [root@docker01 ~]# docker run -d --name c5-container --network container:c3 alpine:latest sleep 3600 [root@docker01 ~]# docker exec c5-container hostname -i # 172.17.0.3 这四种情况下,是不是除了none方式访问不了外网,宿主机ip,docker01网卡地址,其余的都可以
 

你的理解基本正确,但需要更精确的分析:

网络类型详细分析

1. none 网络 (c1-none)

bash
docker exec c1-none hostname -i  # 返回值为空

网络能力:

  • ❌ 无法访问外网

  • ❌ 无法访问宿主机

  • ❌ 无法访问其他容器

  • ✅ 只有 loopback (127.0.0.1)

2. bridge 网络 (c2-bridgec3)

bash
docker exec c2-bridge hostname -i  # 172.17.0.2
docker exec c3 hostname -i         # 172.17.0.3

网络能力:

  • ✅ 可以访问外网 (通过 NAT)

  • ✅ 可以访问宿主机 (172.17.0.1)

  • ✅ 容器间可以互相访问 (172.17.0.x)

  • ✅ 可以访问 docker01 网卡地址

3. host 网络 (c4-host)

bash
docker exec c4-host hostname -i    # 10.0.0.81 172.16.1.81 172.17.0.1
hostname -I                         # 10.0.0.81 172.16.1.81 172.17.0.1

网络能力:

  • ✅ 完全共享宿主机的网络栈

  • ✅ 可以直接访问所有宿主机网络接口

  • ✅ 无 NAT,性能最好

  • ✅ 可以访问外网、宿主机、其他容器

4. container 网络 (c5-container)

bash
docker exec c5-container hostname -i  # 172.17.0.3

网络能力:

  • 与 c3 容器共享网络命名空间

  • 网络能力完全等同于 c3 容器

  • ✅ 可以访问外网

  • ✅ 可以访问宿主机

  • ✅ 可以访问其他容器

总结表格

 
网络类型外网访问宿主机访问容器间访问docker01网卡
none
bridge
host
container

结论: 只有 none 网络完全隔离,其他三种网络类型都可以访问外网、宿主机和 docker01 网卡地址。

 
 
就是将自定义网络类型也加进去,然后将表格返回给我
 

Docker 网络类型完整对比表格

 
网络类型外网访问宿主机访问容器间访问docker01网卡容器名解析隔离性性能
none 最高 -
bridge (默认) ✅ (同网段) ❌ (需手动配置) 中等 中等
host 最低 最佳
container
自定义网络 ✅ (自动DNS) 可配置 中等
posted on 2025-10-27 21:46  猿小姜  阅读(11)  评论(0)    收藏  举报

levels of contents