flannel网络拓扑

测试环境创建

在k8s中部署flannel网络插件

https://blog.csdn.net/weixin_64124795/article/details/128894411

参考文章部署k8s集群和flannel网络插件

我的k8s集群物理环境

我的集群中只有两个节点master和node1节点

[root@master sjs]# kubectl get node
NAME     STATUS   ROLES    AGE   VERSION
master   Ready    master   2d    v1.18.0
node1    Ready    <none>   44m   v1.18.0

允许master节点可以调度

kubectl taint nodes master node-role.kubernetes.io/master:NoSchedule-

创建两个pod分别部署到两个节点上

pod.yaml文件

apiVersion: v1  #定义k8s api的版本v1
kind: Pod  #kind资源类型为 Pod
metadata: #元数据声明
  name: nginx # 名称是nginx
  labels:  #标签申明
    app: web  #标签名称是 app:web
spec:   #容器详细信息
  nodeSelector:
    kubernetes.io/hostname: master
  containers:  # 容器信息
    - name: nginx  #容器名称
      imagePullPolicy: Never
      image: app #容器镜像

pod1.yaml文件

apiVersion: v1  #定义k8s api的版本v1
kind: Pod  #kind资源类型为 Pod
metadata: #元数据声明
  name: nginx1 # 名称是nginx
  labels:  #标签申明
    app: web  #标签名称是 app:web
spec:   #容器详细信息
  nodeSelector:
    kubernetes.io/hostname: node1
  containers:  # 容器信息
    - name: nginx  #容器名称
      imagePullPolicy: Never
      image: app #容器镜像

kubectl apply -f pod1.yaml
kubectl apply -f pod.yaml

pod使用的镜像是我自己创建的,在master和node1节点上都执行

  1. 生成可执行文件 aa

    aa.c文件
    
    #include <stdio.h>
    #include <unistd.h>
    int main(){
            while(1) {
            sleep(100000);
            }
    }
    
    编译执行 gcc aa.c -o aa

  2. 编写dockerfile文件

    FROM ubuntu
    RUN apt update && apt install -y git curl net-tools  iputils-ping
    COPY aa .
    CMD ["./aa"]
    

  3. 生成镜像

    docker build -t app .

 

查看测试环境

查看创建的两个pod

可以看到两个pod分别运行在master和node1两个节点上,并且pod的ip不在同一个网段,这是因为在flannel网络插件中是每个节点一个网段的,master上的pod同属于一个网段,node1节点同属于一个网段。

在kube-flannel网络命名空间的kube-flannel-cfg的ConfigMap中全局定义了10.244.0.0/16网段,以后加入k8s的每个节点都会分配一个掩码为24的小网段给节点,比如在我的环境中给master节点分配了10.244.0.0/24网段,给node1分配了10.244.1.0/24的网段

[root@master sjs]# kubectl get pod -owide
NAME     READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
nginx    1/1     Running   0          23m   10.244.0.14   master   <none>           <none>
nginx1   1/1     Running   0          23m   10.244.1.6    node1    <none>           <none>

flannel全局网段10.244.0.0/16

master网段10.244.0.0/24

node1网段10.244.1.0/24

pod互通测试

[root@master home]# kubectl exec -it nginx /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
root@nginx:/# ping 10.244.1.6
PING 10.244.1.6 (10.244.1.6) 56(84) bytes of data.
64 bytes from 10.244.1.6: icmp_seq=1 ttl=62 time=1.41 ms
64 bytes from 10.244.1.6: icmp_seq=2 ttl=62 time=1.10 ms

拓扑图

根据拓扑图来分析网络流量的流程

  1. 假设nginx访问nginx1,流量的过程 ping 10.244.1.6

  2. 首先查看nginx的pod里面的路由情况,匹配到默认路由,网关是10.244.0.1即是master节点的cni0

    root@nginx:/# route -n
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    0.0.0.0         10.244.0.1      0.0.0.0         UG    0      0        0 eth0
    10.244.0.0      0.0.0.0         255.255.255.0   U     0      0        0 eth0
    10.244.0.0      10.244.0.1      255.255.0.0     UG    0      0        0 eth0
    

  3. 因此访问nginx1的时候首先到达cni0,然后将报文送入master节点协议栈的网络层即ip_recv函数中,会经过netfilter点的prerouting(没有更改),经过master节点的路由判定发现ip地址10.244.1.6不是本机的地址,因此走转发流程即netfilter的forward的hook点,前面在进行路由匹配的时候已经知道了网关是10.244.1.0和出口flannel.1网卡,因此会将报文发到flannel网卡,进入后会组装报文的目的mac地址,那么网关10.244.1.0的mac地址是什么哪,下面可以看出,会将e6:1a:63:79:93:46组装入报文作为目的mac地址。

    [root@master home]# route -n
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    0.0.0.0         192.168.202.2   0.0.0.0         UG    0      0        0 ens33
    0.0.0.0         192.168.40.1    0.0.0.0         UG    100    0        0 ens38
    0.0.0.0         192.168.100.1   0.0.0.0         UG    101    0        0 ens37
    10.244.0.0      0.0.0.0         255.255.255.0   U     0      0        0 cni0
    10.244.1.0      10.244.1.0      255.255.255.0   UG    0      0        0 flannel.1
    172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
    192.168.40.0    0.0.0.0         255.255.255.0   U     100    0        0 ens38
    192.168.100.0   0.0.0.0         255.255.255.0   U     101    0        0 ens37
    192.168.202.0   0.0.0.0         255.255.255.0   U     0      0        0 ens33
    
    [root@master home]# ip neigh show dev flannel.1
    10.244.1.0 lladdr e6:1a:63:79:93:46 PERMANENT
    

  4. 因为flannel.1是vxlan口,接下来需要进行vxlan封装了,需要知道外层的ip地址是啥,这个是根据fdb表来根据mac地址查询的,查询出的ip地址是192.168.202.131

    [root@master home]# bridge fdb show flannel.1|grep e6:1a:63:79:93:46
    e6:1a:63:79:93:46 dev flannel.1 dst 192.168.202.131 self permanent

  5. 由于vxlan是将二层的报文封装到udp里,所有这里内核会将报文传入到传输层,进行port封装,再到网络层,将刚才查到的ip封装,然后进行路由从指定的网卡发出

  6. 在master的ens33上抓包

    tcpdump -i ens33 'udp[39]=1' -nv -w aa.cap

手动构建flannel拓扑

master节点配置

brctl addbr cni0                        #创建网桥名字为br0
ifconfig cni0 192.168.10.1/24 up

#创建两个网络命名空间
ip netns add vm1
ip netns add vm2

# 创建两对veth pair
ip link add veth0 type veth peer name veth1
ip link add veth00 type veth peer name veth11

ifconfig veth1 up
ifconfig veth11 up

# 将veth pair的一端放入网络命名空间
ip link set veth0 netns vm1
ip link set veth00 netns vm2

# 设置网络命名空间的网卡ip
ip netns exec vm1 ip addr add 192.168.10.2/24 dev veth0
ip netns exec vm2 ip addr add 192.168.10.3/24 dev veth00
ip netns exec vm1 ip link set veth0 up
ip netns exec vm2 ip link set veth00 up

# 设置网络命名空间的默认路由,192.168.10.1是cni0的网卡
ip netns exec vm1 ip route add default via 192.168.10.1 dev veth0
ip netns exec vm2 ip route add default via 192.168.10.1 dev veth00

# 将veth pair的一端放入到cni0
brctl addif  cni0 veth1               #将eth1网口和br0网口创建联系
brctl addif  cni0 veth11              #将eth2网口和br0网口创建联系

# 创建vxlan口,并指定出口网卡
ip link add flannel.1 type vxlan id 100 remote 192.168.202.130 dstport 4789 dev ens33   
ip link set flannel.1 up                        #开启vxlan接口
ip addr add 192.168.10.0/24 dev flannel.1        #为网桥配置ip地址

# 添加路由将流量引入到flannel.1网卡
route add -net 192.168.20.0/24  dev flannel.1
route add -net 192.168.20.0/24 gw 192.168.20.0 dev flannel.1

#添加vxlan对端的mac地址
ip neigh add 192.168.20.0 lladdr 9a:0c:28:83:52:e2 dev flannel.1

node节点

brctl addbr cni0                        #创建网桥名字为br0
ifconfig cni0  192.168.20.1/24 up

ip netns add vm1
ip netns add vm2

ip link add veth0 type veth peer name veth1
ip link add veth00 type veth peer name veth11

ifconfig veth1 up
ifconfig veth11 up

ip link set veth0 netns vm1
ip link set veth00 netns vm2

ip netns exec vm1 ip addr add 192.168.20.2/24 dev veth0
ip netns exec vm2 ip addr add 192.168.20.3/24 dev veth00
ip netns exec vm1 ip link set veth0 up
ip netns exec vm2 ip link set veth00 up

ip netns exec vm1 ip route add default via 192.168.20.1 dev veth0
ip netns exec vm2 ip route add default via 192.168.20.1 dev veth00


brctl addif  cni0 veth1               #将eth1网口和br0网口创建联系
brctl addif  cni0 veth11              #将eth2网口和br0网口创建联系


ip link add flannel.1 type vxlan id 100 remote 192.168.202.129 dstport 4789 dev ens33   
ip link set flannel.1 up                        #开启vxlan接口
ip addr add 192.168.20.0/24 dev flannel.1        #为网桥配置ip地址

route add -net 192.168.10.0/24  dev flannel.1
route add -net 192.168.10.0/24 gw 192.168.10.0 dev flannel.1

#添加vxlan对端的mac地址
ip neigh add 192.168.10.0 lladdr a6:e0:77:01:e4:17 dev flannel.1

验证

  1. node1的vm1 ping master的vm1

    [root@node1 ~]# ip netns exec vm1 ping 192.168.10.2
    PING 192.168.10.2 (192.168.10.2) 56(84) bytes of data.
    64 bytes from 192.168.10.2: icmp_seq=1 ttl=62 time=0.991 ms
    64 bytes from 192.168.10.2: icmp_seq=2 ttl=62 time=2.32 ms
    64 bytes from 192.168.10.2: icmp_seq=3 ttl=62 time=4.42 ms
    

  2. node1的vm1 ping node1的flanneld.1

    [root@node1 ~]# ip netns exec vm1 ping 192.168.20.1
    PING 192.168.20.1 (192.168.20.1) 56(84) bytes of data.
    64 bytes from 192.168.20.1: icmp_seq=1 ttl=64 time=0.036 ms
    64 bytes from 192.168.20.1: icmp_seq=2 ttl=64 time=0.044 ms
    64 bytes from 192.168.20.1: icmp_seq=3 ttl=64 time=0.094 ms
    

  3. node1的vm1 ping node1的vm2

    [root@node1 ~]# ip netns exec vm1 ping 192.168.20.3
    PING 192.168.20.3 (192.168.20.3) 56(84) bytes of data.
    64 bytes from 192.168.20.3: icmp_seq=1 ttl=64 time=0.034 ms
    64 bytes from 192.168.20.3: icmp_seq=2 ttl=64 time=0.067 ms
    64 bytes from 192.168.20.3: icmp_seq=3 ttl=64 time=0.104 ms
    

  4. node1的vm1 ping master的flannel.1

    [root@node1 ~]# ip netns exec vm1 ping 192.168.10.1
    PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data.
    64 bytes from 192.168.10.1: icmp_seq=1 ttl=63 time=0.821 ms
    64 bytes from 192.168.10.1: icmp_seq=2 ttl=63 time=0.992 ms
    64 bytes from 192.168.10.1: icmp_seq=3 ttl=63 time=2.15 ms
    64 bytes from 192.168.10.1: icmp_seq=4 ttl=63 time=1.33 ms
    

  5. node1的vm1 ping node1的其他网卡

    [root@node1 ~]# ip netns exec vm1 ping 192.168.100.200
    PING 192.168.100.200 (192.168.100.200) 56(84) bytes of data.
    64 bytes from 192.168.100.200: icmp_seq=1 ttl=64 time=0.065 ms
    64 bytes from 192.168.100.200: icmp_seq=2 ttl=64 time=0.079 ms
    64 bytes from 192.168.100.200: icmp_seq=3 ttl=64 time=0.101 ms
    

  6. node1的vm1 ping外部网络,没ping通,这是因为vm1的ip是一个内部ip

    [root@node1 ~]# ip netns exec vm1 ping 192.168.100.1
    PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
    
    
    

  7. 在外部网络的192.168.100.1网卡上抓包是能够收到报文的,只是返回的时候找不到路所有访问不通

  8. 那么怎么解决访问不通的问题,可以想到使用snat可以实现,将源ip地址是192.168.20.0/24的转换为192.168.100.200

  9. 在node1上执行

    iptables -t nat -A POSTROUTING  -s 192.168.20.0/24  -j SNAT --to-source 192.168.100.200

  10. 在master执行

    iptables -t nat -A POSTROUTING  -s 192.168.10.0/24  -j SNAT --to-source 192.168.100.100

  11. 再从node1的vm1 ping外部网络

    [root@node1 ~]# ip netns exec vm1 ping 192.168.100.1
    PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
    64 bytes from 192.168.100.1: icmp_seq=1 ttl=127 time=0.484 ms
    64 bytes from 192.168.100.1: icmp_seq=2 ttl=127 time=0.818 ms
    64 bytes from 192.168.100.1: icmp_seq=3 ttl=127 time=0.789 ms
    64 bytes from 192.168.100.1: icmp_seq=4 ttl=127 time=0.785 ms
    

  12. 抓包查看

https://zhuanlan.zhihu.com/p/550273312?utm_id=0

https://blog.csdn.net/qq_36963950/article/details/130542890?spm=1001.2014.3001.5506

  • 21
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值