在Docker Swarm中,有两种方式可以实现内部的负载均衡:Service VIP和Routing Mesh

主机规划

$ sudo docker node ls
ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
r0tfqjhih73qyy43ja34501mf *   node1      Ready     Active         Leader           24.0.2
8w00ahq3ltzcmfejx7j6d755p     node2      Ready     Active                          24.0.2

在这里插入图片描述

创建overlay网络

node1上创建一个名为mynetoverlay网络

$ sudo docker network create -d overlay mynet
obrrvzltlp46ydu4zqq56md6a

只有自定义网络支持service name解析vip(类似于DNS服务)。

service创建

创建一个service,名为web通过p端口映射出来:

$ sudo docker service create --name web --network mynet -p 8080:80 --replicas 2 containous/whoami
128itvcw5ejqv832g9hw791a6
overall progress: 2 out of 2 tasks
1/2: running   [==================================================>]
2/2: running   [==================================================>]
verify: Service converged

我们使用镜像containous/whoami是一个简单web服务,能返回服务器hostname,和基本网络信息比如IP地址。

查询service

$ sudo docker service ps web
ID             NAME      IMAGE                      NODE      DESIRED STATE   CURRENT STATE            ERROR     PORTS
dvihg8lgiw03   web.1     containous/whoami:latest   node2     Running         Running 23 seconds ago
fb45l99kx767   web.2     containous/whoami:latest   node1     Running         Running 23 seconds ago

创建一个client

创建一个client用来访问service

$ sudo docker service create --name client --network mynet centos:7 ping 8.8.8.8
ohgc2y9t9ztb086j1e5n777b8
overall progress: 1 out of 1 tasks
1/1: running   [==================================================>]
verify: Service converged

查看client服务:

~$ sudo docker service ls
ID             NAME      MODE         REPLICAS   IMAGE                      PORTS
ohgc2y9t9ztb   client    replicated   1/1        centos:7
128itvcw5ejq   web       replicated   2/2        containous/whoami:latest   *:8080->80/tcp

$ sudo docker service ps client
ID             NAME       IMAGE      NODE      DESIRED STATE   CURRENT STATE            ERROR     PORTS
ebrpzyvsz7jm   client.1   centos:7   node1     Running         Running 16 seconds ago

client中访问service

查询client的容器ID为d200af28b981

$ sudo docker container ps
CONTAINER ID   IMAGE                      COMMAND          CREATED              STATUS              PORTS     NAMES
d200af28b981   centos:7                   "ping 8.8.8.8"   About a minute ago   Up About a minute             client.1.ebrpzyvsz7jmszwd5dmnihfyw
694fd2d1f0a4   containous/whoami:latest   "/whoami"        About a minute ago   Up About a minute   80/tcp    web.2.fb45l99kx7674pvzd44ow3ubf

client中访问service:

$ sudo docker container exec -it d200af28b981 curl web
Hostname: 0914dead5a9c
IP: 127.0.0.1
IP: 10.0.1.3
IP: 172.20.0.3
IP: 10.0.0.5
RemoteAddr: 10.0.1.5:47794
GET / HTTP/1.1
Host: web
User-Agent: curl/7.29.0
Accept: */*

$ sudo docker container exec -it d200af28b981 curl web
Hostname: 694fd2d1f0a4
IP: 127.0.0.1
IP: 10.0.0.6
IP: 172.18.0.3
IP: 10.0.1.4
RemoteAddr: 10.0.1.5:36370
GET / HTTP/1.1
Host: web
User-Agent: curl/7.29.0
Accept: */*

可以发现两个web容器的IP分别为10.0.1.310.0.1.4

client容器中去ping web这个service name:

$ sudo docker container exec -it d200af28b981 ping web -c 3
PING web (10.0.1.2) 56(84) bytes of data.
64 bytes from 10.0.1.2 (10.0.1.2): icmp_seq=1 ttl=64 time=0.032 ms
64 bytes from 10.0.1.2 (10.0.1.2): icmp_seq=2 ttl=64 time=0.047 ms
64 bytes from 10.0.1.2 (10.0.1.2): icmp_seq=3 ttl=64 time=0.062 ms

--- web ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2022ms
rtt min/avg/max/mdev = 0.032/0.047/0.062/0.012 ms

通过ping获取到的IP是10.0.1.2,而不是web容器的实际IP,那么这个IP是谁的IP呢?

查看mynet网络详情

首先10.0.1.0/24这个网段是mynet网络的,所以这个地址肯定是连在了mynet上。

所以我们来查看一下mynet的网络详情:

$ sudo docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "obrrvzltlp46ydu4zqq56md6a",
        "Created": "2023-11-29T11:02:29.924112625Z",
        "Scope": "swarm",
        "Driver": "overlay",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.1.0/24",
                    "Gateway": "10.0.1.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "694fd2d1f0a471630d755743a39ae28ecf4c38d20a30b45f145d55110d038882": {
                "Name": "web.2.fb45l99kx7674pvzd44ow3ubf",
                "EndpointID": "60ffd2a92a9b8e6603668c1922774d572512c88ecc1899e8bb2a6890a0569998",
                "MacAddress": "02:42:0a:00:01:04",
                "IPv4Address": "10.0.1.4/24",
                "IPv6Address": ""
            },
            "d200af28b98158a90a2ba110477e6cff17170b059c89f07b389f8a40a9debca6": {
                "Name": "client.1.ebrpzyvsz7jmszwd5dmnihfyw",
                "EndpointID": "05cb7d2aecfb35c5aa38a0713cb3c989290f9dcdb6db819bc3e6bdd57731ae5d",
                "MacAddress": "02:42:0a:00:01:08",
                "IPv4Address": "10.0.1.8/24",
                "IPv6Address": ""
            },
            "lb-mynet": {
                "Name": "mynet-endpoint",
                "EndpointID": "7bf814a43e5c733914694cddeaed0ec91ff2522b430a2e75567b0f5d5e7a09bc",
                "MacAddress": "02:42:0a:00:01:05",
                "IPv4Address": "10.0.1.5/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.driver.overlay.vxlanid_list": "4097"
        },
        "Labels": {},
        "Peers": [
            {
                "Name": "de473f8d81e5",
                "IP": "172.19.177.14"
            },
            {
                "Name": "138b78fdca53",
                "IP": "172.19.188.123"
            }
        ]
    }
]

发现有一个叫lb-mynet的容器连在了mynet上。

lb-mynet网络命名空间详情

这个lb-mynet其实并不是一个容器,而是一个网络命名空间(network namespace), 我们可以通过下面的方式进入到这个命名空间

先查看mynet网络的ID为obrrvzltlp46

$ sudo docker network ls | grep mynet
obrrvzltlp46   mynet             overlay   swarm

再在/run/docker/netns/目录下寻找lb_开头+obrrvzltlp46前缀文件

$ sudo ls /run/docker/netns/
05bd5279bd2a  1-lly92pzjok  1-obrrvzltlp  c035f61daf3b  ingress_sbox  lb_obrrvzltl

找到lb-mynet对应命名空间文件lb_obrrvzltl

通过nsenter命令进入到lb_obrrvzltl这个命名空间里查看IP地址:

$ sudo nsenter --net="/run/docker/netns/lb_obrrvzltl" ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
157: eth0@if158: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
    link/ether 02:42:0a:00:01:05 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.0.1.5/24 brd 10.0.1.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 10.0.1.2/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet 10.0.1.7/32 scope global eth0
       valid_lft forever preferred_lft forever

可以看到网卡eth0的IP中有一个IP地址为10.0.1.2,这个IP称之为虚拟IP(VIP)。

lb-mynet网络命名空间对流量处理

我们client容器中根据service name访问web这个service时,Docker Swarm内置的DNS解析器会将web这个service name解析10.0.1.2这个IP,也就是流量会进入到lb-mynet这个网络命名空间内,下面来看下lb-mynet网络命名空间会流量处理

ingress网络一样,查看iptables规则

$ sudo nsenter --net="/run/docker/netns/lb_obrrvzltl" iptables -nvL -t mangle
Chain PREROUTING (policy ACCEPT 43 packets, 3771 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain INPUT (policy ACCEPT 31 packets, 2253 bytes)
 pkts bytes target     prot opt in     out     source               destination
   31  2253 MARK       all  --  *      *       0.0.0.0/0            10.0.1.2             MARK set 0x111
    0     0 MARK       all  --  *      *       0.0.0.0/0            10.0.1.7             MARK set 0x112

Chain FORWARD (policy ACCEPT 12 packets, 1518 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 34 packets, 2517 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 43 packets, 3771 bytes)
 pkts bytes target     prot opt in     out     source               destination

可以看到目标IP为10.0.1.2流量会被MARK为0x111,也就是十进制的273。

再来看ipvd的负载均衡规则

$ sudo nsenter --net="/run/docker/netns/lb_obrrvzltl" ipvsadm
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
FWM  273 rr
  -> 10.0.1.3:0                   Masq    1      0          0
  -> 10.0.1.4:0                   Masq    1      0          0
FWM  274 rr
  -> 10.0.1.8:0                   Masq    1      0          0

ipvs会将MARK为273的流量轮询(RR)转发给10.0.1.3和10.0.1.4,从而实现负载均衡

原文地址:https://blog.csdn.net/u022812849/article/details/134707580

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_18739.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注