当前位置: 首页 > article >正文

Docker容器网络与通信

文章目录

  • 1、Docker容器默认网络模型
    • 1_原理图
    • 2_名词解释
  • 2、Docker容器默认网络模型工作原理
    • 1_容器访问外网
    • 2_外网访问容器
  • 3、Docker容器四种网络模型
  • 4、Docker容器四种网络模型应用案例
    • 1_查看已有的网络模型
    • 2_创建指定类型的网络模型
      • 1 bridge
      • 2 host
      • 3 none
      • 4 联盟网络
  • 5、跨Docker Host容器间通信探讨
    • 1_跨Docker Host容器间通信必要性
    • 2_跨Docker Host容器间通信实现方案
      • 1 Docker原生方案
      • 2 第三方方案
  • 6、Flannel
    • 1_overlay network介绍
    • 2_Flannel介绍
    • 3_Flannel工作原理
  • 7、ETCD
  • 7.5、下面开始实现跨Docker Host容器间通信
  • 8、ETCD部署
    • 1_主机名称配置
    • 2_主机IP地址配置
    • 3_主机名与IP地址解析
    • 4_开启内核转发
    • 5_Etcd安装
    • 6_Etcd配置
    • 7_启动etcd服务
    • 8_检查端口状态
    • 9_检查Etcd集群是否健康
  • 9、Flannel部署
    • 1_Flannel安装
    • 2_修改Flannel配置文件
    • 3_配置etcd中关于flannel的key
    • 4_启动Flannel服务
    • 5_查看各node中flannel产生的配置信息
  • 10、Docker网络配置
  • 11、跨Docker Host容器间通信验证

1、Docker容器默认网络模型

1_原理图

在这里插入图片描述

2_名词解释

docker0

  • 是一个二层网络设备,即网桥
  • 通过网桥可以将Linux支持的不同的端口连接起来
  • 实现类交换机多对多的通信

veth pair

  • 虚拟以太网(Ethernet)设备
  • 成对出现,用于解决网络命名空间之间的隔离
  • 一端连接 Container network namespace,另一端连接 host network namespace

2、Docker容器默认网络模型工作原理

1_容器访问外网

在这里插入图片描述

图解流程说明

1. 容器

  • 容器内的数据包首先通过容器内部的 eth0 虚拟网络接口。
  • eth0 是容器的网络接口,负责接收和发送容器内的数据包。

2. veth(虚拟以太网设备):

  • 每个容器都会与宿主机建立一对虚拟网络接口,称为 veth pair
  • 容器内的 eth0 通过 veth 与 Docker 主机通信。
  • veth 的另一端连接到宿主机的网络桥 docker0

3. docker0(桥接网络):

  • docker0 是宿主机上由 Docker 创建的虚拟网络桥。
  • 它将容器的网络接口连接起来,使容器可以通过桥接与外部网络通信。

4. SNAT(源地址网络地址转换)

  • 当容器需要与外网通信时,数据包会经过宿主机的 docker0,然后通过宿主机的 eth0 网络接口发送到外部网络。
  • 在此过程中,宿主机会对数据包进行 SNAT,将数据包的源 IP 地址转换为宿主机的 IP 地址,以便能够在外部网络中正确路由。

5.外网:

  • 经过 SNAT 的数据包通过宿主机的 eth0 网络接口到达外部网络。
  • 返回的数据包会通过相反的路径返回到容器内。

创建容器

docker run -d --name web1 -p 8081:80 nginx:latest

检查 NAT 表中 POSTROUTING 链

iptables -t nat -vnL POSTROUTING

输出:

Chain POSTROUTING (policy ACCEPT 7 packets, 766 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE  tcp  --  *      *       172.17.0.2           172.17.0.2           tcp dpt:80

2_外网访问容器

在这里插入图片描述

DNAT:目标地址转换

iptables -t nat -vnL DOCKER

输出:

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     0    --  docker0 *       0.0.0.0/0            0.0.0.0/0           
    0     0 DNAT       6    --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8081 to:172.17.0.2:80

3、Docker容器四种网络模型

在这里插入图片描述

模式使用方法说明
bridge [桥接式网络(Bridge container A)]--network bridge桥接容器,除了有一块本地回环接口(Loopback interface)外,还有一块私有接口(Private interface)通过容器虚拟接口(Container virtual interface)连接到桥接虚拟接口(Docker bridge virtual interface),之后通过逻辑主机接口(Logical host interface)连接到主机物理网络(Physical network interface)。
桥接网卡默认会分配到172.17.0.0/16的IP地址段。
如果我们在创建容器时没有指定网络模型,默认就是(Nat)桥接网络,这也就是为什么我们在登录到一个容器后,发现IP地址段都在172.17.0.0/16网段的原因。
host [开放式容器(Open container)]--network host比联盟式网络更开放,我们知道联盟式网络是多个容器共享网络(Net),而开放式容器(Open contaner)就直接共享了宿主机的名称空间。
因此物理网卡有多少个,那么该容器就能看到多少网卡信息。
我们可以说Open container是联盟式容器的衍生。
none [封闭式网络(Closed container)]--network none封闭式容器,只有本地回环接口(Loopback interface,和咱们服务器看到的lo接口类似),无法与外界进行通信。
container [联盟式网络(Joined container A | Joined container B ]--network container:c1
(容器名称或容器ID)
每个容器都各有一部分名称空间(Mount,PID,User),另外一部分名称空间是共享的(UTS,Net,IPC)。
由于它们的网络是共享的,因此各个容器可以通过本地回环接口(Loopback interface)进行通信。
除了共享同一组本地回环接口(Loopback interface)外,还有一块一块私有接口(Private interface)通过联合容器虚拟接口(Joined container virtual interface)连接到桥接虚拟接口(Docker bridge virtual interface),之后通过逻辑主机接口(Logical host interface)连接到主机物理网络(Physical network interface)。

4、Docker容器四种网络模型应用案例

1_查看已有的网络模型

查看已有的网络模型

[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
60a5207fbd78   bridge    bridge    local
0d19dc861451   host      host      local
682320e20891   none      null      local

查看已有网络模型详细信息

[root@localhost ~]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "60a5207fbd785569cf31650dd88ff7ac8237aea98ff90b3c4ea5c190e2b1795b",
        "Created": "2024-12-07T11:15:50.734476157+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "8365330d68b7ed06db7a842fc25387a0e354147e9829cfa7ab3c52dbfa3bb5dd": {
                "Name": "web1",
                "EndpointID": "743312da194149c307b6d33b875fadf42426601b95cb657096a6cac9cf8cb39f",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

查看 docker 支持的网络模型

[root@localhost ~]# docker info | grep Network
  Network: bridge host ipvlan macvlan null overlay

2_创建指定类型的网络模型

1 bridge

查看创建网络模型的帮助方法

docker network create --help

创建一个名称为mybr0的网络

docker network create -d bridge --subnet "192.168.100.0/24" --gateway "192.168.100.1" -o com.docker.network.bridge.name=docker1 mybr0

查看已创建网络

[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
......
a6a1ad36c3c0   mybr0     bridge    local
......

在 docker host 主机上可以看到多了一个网桥docker1

[root@localhost ~]# ifconfig
docker1: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.100.1  netmask 255.255.255.0  broadcast 192.168.100.255
        ether 02:42:14:aa:f5:04  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20  bytes 1598 (1.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

启动一个容器并连接到已创建mybr0网络

[root@localhost ~]# docker run -it --network mybr0 --rm busybox
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:C0:A8:65:02
          inet addr:192.168.100.2  Bcast:192.168.100.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:18 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:2185 (2.1 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # exit

2 host

查看host类型的网络模型

[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
......
0d19dc861451   host      host      local
......

查看 host 网络模型的详细信息

[root@localhost ~]# docker network inspect host
[
    {
        "Name": "host",
        "Id": "0d19dc861451ad73e194530c11ea2c5cd36fd84185cdbdcbff652b4d86cd49ed",
        "Created": "2024-12-05T09:34:58.338959535+08:00",
        "Scope": "local",
        "Driver": "host",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": null
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

创建容器使用 host 网络模型,并查看其网络信息

[root@localhost ~]# docker run -it --network host --rm busybox
/ # ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:15:BA:C2:F7  
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:15ff:feba:c2f7/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:73477 errors:0 dropped:0 overruns:0 frame:0
          TX packets:145769 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:3022567 (2.8 MiB)  TX bytes:527097953 (502.6 MiB)

docker1   Link encap:Ethernet  HWaddr 02:42:3F:03:1B:E9  
          inet addr:192.168.100.1  Bcast:192.168.100.255  Mask:255.255.255.0
          inet6 addr: fe80::42:3fff:fe03:1be9/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:10 errors:0 dropped:0 overruns:0 frame:0
          TX packets:33 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:678 (678.0 B)  TX bytes:4322 (4.2 KiB)

ens33     Link encap:Ethernet  HWaddr 00:0C:29:A4:42:BD  
          inet addr:192.168.150.145  Bcast:192.168.150.255  Mask:255.255.255.0
          inet6 addr: fe80::20c:29ff:fea4:42bd/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:848483 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1113919 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:586827039 (559.6 MiB)  TX bytes:252189967 (240.5 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:259 errors:0 dropped:0 overruns:0 frame:0
          TX packets:259 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:38326 (37.4 KiB)  TX bytes:38326 (37.4 KiB)

/ # exit

运行Nginx服务

创建用于运行 nginx 应用的容器,使用 host 网络模型

docker run -d --network host nginx:latest

查看容器运行状态

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE          COMMAND                   CREATED          STATUS          PORTS     NAMES
011b218e785c   nginx:latest   "/docker-entrypoint.…"   11 seconds ago   Up 10 seconds             hungry_mahavira

查看docker host 80端口状态

[root@localhost ~]# ss -anput | grep ":80"
tcp   LISTEN 0      511            0.0.0.0:80          0.0.0.0:*     users:(("nginx",pid=1142601,fd=6),("nginx",pid=1142600,fd=6),("nginx",pid=1142599,fd=6),("nginx",pid=1142598,fd=6),("nginx",pid=1142563,fd=6))
tcp   LISTEN 0      511               [::]:80             [::]:*     users:(("nginx",pid=1142601,fd=7),("nginx",pid=1142600,fd=7),("nginx",pid=1142599,fd=7),("nginx",pid=1142598,fd=7),("nginx",pid=1142563,fd=7))

使用curl命令访问 docker host 主机IP地址,验证是否可以对 nginx 进行访问,如可访问,则说明容器与 docker host 共享网络命名空间

[root@localhost ~]# curl http://localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

在这里插入图片描述

3 none

查看none类型的网络模型

[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
......
682320e20891   none      null      local

查看 none 网络模型详细信息

[root@localhost ~]# docker network inspect none
[
    {
        "Name": "none",
        "Id": "682320e2089181ec6561e2c586b6f89e16c1a8e32f6f4db07769cc2a712a5cd9",
        "Created": "2024-12-05T09:34:58.144297386+08:00",
        "Scope": "local",
        "Driver": "null",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": null
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

创建容器使用none网络模型,并查看其网络状态

[root@localhost ~]# docker run -it --network none --rm busybox:latest
/ # ifconfig
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # exit

此类新类似于虚拟机的仅主机模式,是无法上网的,除非自己手动创建虚拟网络设备。

4 联盟网络

创建c1容器,使用默认网络模型

[root@localhost ~]# docker run -it --name c1 --rm busybox:latest
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:17 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2276 (2.2 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

查看c1容器状态

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE            COMMAND   CREATED          STATUS          PORTS     NAMES
92a07e7ef663   busybox:latest   "sh"      20 seconds ago   Up 19 seconds             c1

创建c2容器,与c1容器共享网络命名空间

[root@localhost ~]# docker run -it --name c2 --network container:c1 --rm busybox:latest
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:20 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:2486 (2.4 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

在c2容器中创建文件并开启httpd服务

/ # echo "hello world" >> /tmp/index.html
/ # ls /tmp
index.html
/ # httpd -h /tmp

验证80端口是否打开

/ # netstat -npl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 :::80                   :::*                    LISTEN      10/httpd

在c1容器中进行访问验证

[root@localhost ~]# docker exec c1 wget -O - -q 127.0.0.1
hello world

查看c1容器/tmp目录,发现没有在c2容器中创建的文件,说明c1与c2仅共享了网络命名空间,没有共享文件系统

docker exec c1 ls /tmp

5、跨Docker Host容器间通信探讨

1_跨Docker Host容器间通信必要性

由于Docker容器运行的环境类似于在局域网中运行服务一样,无法直接被外界访问,如果采用在Docker Host利用端口映射方式会导致端口被严重消耗。

能够实现不同的Docker Host方便访问其它Docker Host之上的容器提供的服务

2_跨Docker Host容器间通信实现方案

1 Docker原生方案

overlay

  • 基于VXLAN封装实现Docker原生overlay网络

macvlan

  • Docker主机网卡接口逻辑上分为多个子接口,每个子接口标识一个VLAN,容器接口直接连接Docker Host

网卡接口

  • 通过路由策略转发到另一台Docker Host

2 第三方方案

隧道方案

Flannel

  • 支持UDP和VLAN封装传输方式

Weave

  • 支持UDP和VXLAN

OpenvSwitch

  • 支持VXLAN和GRE协议

路由方案

Calico

  • 支持BGP协议和IPIP隧道
  • 每台宿主机作为虚拟路由,通过BGP协议实现不同主机容器间通信。

6、Flannel

1_overlay network介绍

Overlay 网络是指在不改变现有网络基础设施的前提下,通过某种约定通信协议,把二层报文封装在IP报文之上的新的数据格式。

这样不但能够充分利用成熟的IP路由协议进程数据分发;而且在 Overlay 技术中采用扩展的隔离标识位数,能够突破 VLAN 的4000数量限制支持高达16M的用户,并在必要时可将广播流量转化为组播流量,避免广播数据泛滥。

因此,Overlay 网络实际上是目前最主流的容器跨节点数据传输和路由方案。

2_Flannel介绍

Flannel 是 CoreOS 团队针对 Kubernetes 设计的一个覆盖网络(Overlay Network)工具,其目的在于帮助每一个使用 Kuberentes 的 CoreOS 主机拥有一个完整的子网。

Flannel 通过给每台宿主机分配一个子网的方式为容器提供虚拟网络,它基于Linux TUN/TAP,使用 UDP 封装 IP包来创建 Overlay 网络,并借助 Etcd 维护网络的分配情况。

Flannel is a simple and easy way to configure a layer 3 network fabric designed for Kubernetes.

3_Flannel工作原理

Flannel 是 CoreOS 团队针对 Kubernetes 设计的一个网 络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP地址。

但在默认的 Docker 配置中,每个 Node 的 Docker 服务会分别负责所在节点容器的 IP 分配。

Node 内部的容器之间可以相互访问,但是跨主机(Node)网络相互间是不能通信。

Flannel 设计目的就是为集群中所有节点重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得"同属一个内网"且"不重复的"IP地址,并让属于不同节点上的容器能够直接通过内网 IP 通信。

Flannel 使用 Etcd 存储配置数据和子网分配信息。

Flannel 启动之后,后台进程首先检索配置和正在使用的子网列表,然后选择一个可用的子网,然后尝试去注册它。

Etcd 也存储这个每个主机对应的 IP。

Flannel 使用 Etcd 的 watch 机制监视/coreos.com/network/subnets下面所有元素的变化信息,并且根据它来维护一个路由表。

为了提高性能,Flannel 优化了 Universal TAP/TUN 设备,对 TUN 和 UDP 之间的 IP 分片做了代理。

如下原理图:

在这里插入图片描述

1、数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,这是个 P2P 的虚拟网卡,Flanneld 服务监听在网卡的另外一端。

2、Flannel 通过 Etcd 服务维护了一张节点间的路由表,该张表里保存了各个节点主机的子网网段信息。

3、源主机的 flanneld 服务将原本的数据内容 UDP 封装后根据自己的路由表投递给目的节点的 flanneld 服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡,然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一样的由docker0路由到达目标容器。


7、ETCD

Etcd 是 CoreOS 团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。

Etcd 内部采用raft协议作为一致性算法,Etcd 基于Go语言实现。

Etcd 作为服务发现系统,具有以下特点:

  • 简单:安装配置简单,而且提供了 HTTP API 进行交互,使用也很简单
  • 安全:支持SSL证书验证
  • 快速:根据官方提供的基准测试(benchmarking)数据,单实例支持每秒2k+读操作
  • 可靠:采用 raft 算法,实现分布式系统数据的可用性和一致性

7.5、下面开始实现跨Docker Host容器间通信


8、ETCD部署

主机防火墙及SELINUX需要均关闭。

firewall-cmd --state
sestatus

1_主机名称配置

设置节点1的主机名

hostnamectl set-hostname node1

设置节点2的主机名

hostnamectl set-hostname node2

2_主机IP地址配置

节点1的网络配置

[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens33
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=cc3b99f0-e07f-47cb-a602-a5b3fa13c451
DEVICE=ens33
ONBOOT=yes
IPADDR="192.168.150.131"
NETMASK="255.255.255.0"
GATEWAY="192.168.150.2"
DNS1="192.168.150.2"

节点2的网络配置

[root@localhost ~]# cat /etc/sysconfig/network-scripts/ifcfg-ens33
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=fe08c2ef-0105-42bf-845d-06e108b86420
DEVICE=ens33
ONBOOT=yes
IPADDR="192.168.150.132" 
NETMASK="255.255.255.0"
GATEWAY="192.168.150.2"
DNS1="192.168.150.2"

3_主机名与IP地址解析

在两个节点中都进行IP地址解析操作

vim /etc/hosts

添加如下内容

192.168.150.131 node1
192.168.150.132 node2

4_开启内核转发

所有 Docker Host 中都开启内核转发

echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf

配置生效

sysctl -p

5_Etcd安装

我们要搭建 Etcd 集群,所以在两个节点中都安装

yum -y install etcd

6_Etcd配置

对 Etcd 进行配置,主要是对节点和集群进行配置

vim /etc/etcd/etcd.conf

节点1配置内容如下:

#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/node1.etcd"
#ETCD_WAL_DIR=""
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
ETCD_NAME="node1"
#ETCD_SNAPSHOT_COUNT="100000"
# ........
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.150.131:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.150.131:2379,http://192.168.150.131:4001"
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""
#ETCD_DISCOVERY_SRV=""
ETCD_INITIAL_CLUSTER="node1=http://192.168.150.131:2380,node2=http://192.168.150.132:2380"
#ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

节点2配置内容如下

#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/node2.etcd"
#ETCD_WAL_DIR=""
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
ETCD_NAME="node2"
#ETCD_SNAPSHOT_COUNT="100000"
# ........
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.150.132:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.150.132:2379,http://192.168.150.132:4001"
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""
#ETCD_DISCOVERY_SRV=""
ETCD_INITIAL_CLUSTER="node1=http://192.168.150.131:2380,node2=http://192.168.150.132:2380"
#ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"

7_启动etcd服务

两个节点都启动

systemctl enable etcd
systemctl start etcd

8_检查端口状态

检查

netstat -tnlp | grep -E  "4001|2380"

输出结果:

tcp6       0      0 :::4001                 :::*                    LISTEN      50056/etcd          
tcp6       0      0 :::2380                 :::*                    LISTEN      50056/etcd 

9_检查Etcd集群是否健康

访问集群端口验证集群状态

etcdctl -C http://192.168.150.131:2379 cluster-health

输出:

member adf6f6b228d1577a is healthy: got healthy result from http://192.168.150.131:2379
member baf1f0a8edfe9e89 is healthy: got healthy result from http://192.168.150.132:2379
cluster is healthy

查看成员,可以看到谁是 Leader

etcdctl member list

输出:

adf6f6b228d1577a: name=node1 peerURLs=http://192.168.150.131:2380 clientURLs=http://192.168.150.131:2379,http://192.168.150.131:4001 isLeader=false
baf1f0a8edfe9e89: name=node2 peerURLs=http://192.168.150.132:2380 clientURLs=http://192.168.150.132:2379,http://192.168.150.132:4001 isLeader=true

9、Flannel部署

1_Flannel安装

在两个节点中都安装 flannel

yum -y install flannel

2_修改Flannel配置文件

编辑配置文件

vim /etc/sysconfig/flanneld

节点1、节点2 配置相同:

# Flanneld configuration options  

# etcd url location.  Point this to the server where etcd runs
FLANNEL_ETCD_ENDPOINTS="http://192.168.150.131:2379,http://192.168.150.132:2379"

# etcd config key.  This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_PREFIX="/atomic.io/network"

# Any additional options that you want to pass
FLANNEL_OPTIONS="--logtostderr=false --log_dir=/var/log/ --etcd-endpoints=http://192.168.150.131:2379,http://192.168.150.132:2379 --iface=ens33"

3_配置etcd中关于flannel的key

Flannel 使用 Etcd 进行配置,来保证多个 Flannel 实例之间的配置一致性,所以需要在 Etcd 上进行配置。

使用时 key 的前缀要一致:/atomic.io/network/config 这个key与上面的/etc/sysconfig/flannel中的配置项 FLANNEL_ETCD_PREFIX 是相对应的,不然启动就会出错

[root@node1 ~]# etcdctl mk /atomic.io/network/config '{"Network":"172.21.0.0/16"}'
{"Network":"172.21.0.0/16"}

[root@node1 ~]# etcdctl set /atomic.io/network/config '{"Network":"172.21.0.0/16"}'
{"Network":"172.21.0.0/16"}

由于 Etcd 已经搭建集群,所以可以在其他节点进行查看

[root@node2 ~]# etcdctl get /atomic.io/network/config
{"Network":"172.21.0.0/16"}

该IP网段可以任意设定,随便设定一个网段都可以。

容器的IP就是根据这个网段进行自动分配的,IP 分配后,容器一般是可以对外联网的(网桥模式,只要 Docker Host 能上网即可。)

4_启动Flannel服务

两台主机都启动

systemctl enable flanneld
systemctl start flanneld

5_查看各node中flannel产生的配置信息

注意子网信息

[root@node1 ~]# ls /run/flannel/
docker  subnet.env
[root@node1 ~]# cat /run/flannel/subnet.env
FLANNEL_NETWORK=172.21.0.0/16
FLANNEL_SUBNET=172.21.51.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false
[root@node2 ~]# ls /run/flannel/
docker  subnet.env
[root@node2 ~]# cat /run/flannel/subnet.env
FLANNEL_NETWORK=172.21.0.0/16
FLANNEL_SUBNET=172.21.68.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false

生效前的网络接口信息,注意docker0地址

[root@node1 ~]# ip a s
......
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:02:e0:7b:65 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
7: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN group default qlen 500
    link/none 
    inet 172.21.51.0/16 scope global flannel0
       valid_lft forever preferred_lft forever
    inet6 fe80::3fe9:35df:6225:e948/64 scope link flags 800 
       valid_lft forever preferred_lft foreve
[root@node2 ~]# ip a s
......
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:ee:8f:1e:9d brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
6: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN group default qlen 500
    link/none 
    inet 172.21.68.0/16 scope global flannel0
       valid_lft forever preferred_lft forever
    inet6 fe80::340a:b3d7:5158:1698/64 scope link flags 800 
       valid_lft forever preferred_lft forever

10、Docker网络配置

将 flannel 分配的 FLANNEL_SUBNET 地址配置到 docker 启动服务的配置文件中

--bip=172.21.x.1/24 --ip-masq=true --mtu=1472 放置于启动程序后

vim /usr/lib/systemd/system/docker.service

节点1配置如下,仅修改此行

# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=172.21.51.1/24 --ip-masq=true --mtu=1472

节点2修改

# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=172.21.68.1/24 --ip-masq=true --mtu=1472

存疑:如果fd://与默认的unix:///var/run/docker.sock冲突,可能导致无法监听?

systemctl stop docker.socket
systemctl disable docker.socket

重启 docker,两个节点都执行

systemctl daemon-reload
systemctl restart docker

查看生效后的配置

[root@node1 ~]# ip a s
......
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1472 qdisc noqueue state DOWN group default 
    link/ether 02:42:02:e0:7b:65 brd ff:ff:ff:ff:ff:ff
    inet 172.21.51.1/24 brd 172.21.51.255 scope global docker0
       valid_lft forever preferred_lft forever
7: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN group default qlen 500
    link/none 
    inet 172.21.51.0/16 scope global flannel0
       valid_lft forever preferred_lft forever
    inet6 fe80::3fe9:35df:6225:e948/64 scope link flags 800 
       valid_lft forever preferred_lft foreve
[root@node2 ~]# ip a s
......
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1472 qdisc noqueue state DOWN group default 
    link/ether 02:42:ee:8f:1e:9d brd ff:ff:ff:ff:ff:ff
    inet 172.21.68.1/24 brd 172.21.68.255 scope global docker0
       valid_lft forever preferred_lft forever
6: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN group default qlen 500
    link/none 
    inet 172.21.68.0/16 scope global flannel0
       valid_lft forever preferred_lft forever
    inet6 fe80::340a:b3d7:5158:1698/64 scope link flags 800 
       valid_lft forever preferred_lft forever

11、跨Docker Host容器间通信验证

在节点1的容器中进行测试

[root@node1 ~]# docker run -it --rm busybox:latest
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:15:33:02  
          inet addr:172.21.51.2  Bcast:172.21.51.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1472  Metric:1
          RX packets:7 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:586 (586.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # ping 172.21.68.2 -c 4
PING 172.21.68.2 (172.21.68.2): 56 data bytes
64 bytes from 172.21.68.2: seq=0 ttl=60 time=1.084 ms
64 bytes from 172.21.68.2: seq=1 ttl=60 time=0.888 ms
64 bytes from 172.21.68.2: seq=2 ttl=60 time=0.778 ms
64 bytes from 172.21.68.2: seq=3 ttl=60 time=1.032 ms

--- 172.21.68.2 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.778/0.945/1.084 ms

在节点2的容器中进行测试

[root@node2 ~]# docker run -it --rm busybox:latest
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:15:44:02  
          inet addr:172.21.68.2  Bcast:172.21.68.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1472  Metric:1
          RX packets:7 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:586 (586.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # ping 172.21.51.2 -c 4
PING 172.21.51.2 (172.21.51.2): 56 data bytes
64 bytes from 172.21.51.2: seq=0 ttl=60 time=0.855 ms
64 bytes from 172.21.51.2: seq=1 ttl=60 time=0.673 ms
64 bytes from 172.21.51.2: seq=2 ttl=60 time=0.831 ms
64 bytes from 172.21.51.2: seq=3 ttl=60 time=1.004 ms

--- 172.21.51.2 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.673/0.840/1.004 ms

跨 DockerHost 容器间通信成功



http://www.kler.cn/a/429002.html

相关文章:

  • 锐捷路由器网关RG-NBR6135-E和锐捷交换机 Ruijie Reyee RG-ES224GC 电脑登录web方法
  • 通信协议之多摩川编码器协议
  • java权限修饰符
  • LabVIEW 蔬菜精密播种监测系统
  • nuiapp在APP中的.nvue页面中使用webview展示空白的问题
  • 探索与创作:2024年CSDN平台上的成长与突破
  • mysql备份数据库
  • 8.16DEBUG——DOCKER相关,DOCKER启动异常
  • Python-分析内存进制转换
  • HOC vs Render Props vs Hooks
  • 在Windows下C语言获取当前应用程序运行路径并获取指定目录下所有文件(包括子目录)
  • 决策树:ID3、C4.5和CART特征选择方式
  • Lua使用点号和冒号的区别
  • Selenium是广泛使用的模拟浏览器运行的库
  • 为超越JVM而生?深入理解Kotlin Native的梦想与可能
  • 使用PaddleOCR遇到的问题Bug
  • 机器学习:全面学习路径指南
  • 漫画之家Spring Boot:漫画资源的跨设备访问
  • photoblog解题过程
  • 代码随想录第五十一天
  • 天天 AI-241208:今日热点- OpenAI发布强化微调API,能深度定制超复杂大模型了
  • Linux内核升级操作和 k8s 常见命令
  • Vue3.0中的响应式原理是什么?vue2的响应式原理是什么?
  • LeetCode Hot100 61~70
  • 2024最新qrcode.min.js生成二维码Demo
  • G6基本使用