Ensp 模擬 Calico 跨網(wǎng)段 Bgp 網(wǎng)絡(luò)
之前詳細(xì)介紹了calico的ipip、vxlan、bgp模式, 但是所有的k8s節(jié)點都是同網(wǎng)段的, 本篇使用ensp和workstation在自己家里就可以模擬測試跨網(wǎng)段k8s集群calico方案的純bgp模式。
架構(gòu)搭建
本測試搭建的是"每機柜獨立自治系統(tǒng)"架構(gòu), 參考:The *AS Per Rack* model[1]
跨網(wǎng)段k8s集群架構(gòu)
整個架構(gòu)分為ensp部分和workstation部分, ensp部分主要是搭建出R1和R2的ebgp關(guān)系以及分別在R1和R2上添加各自網(wǎng)段內(nèi)的k8s節(jié)點的bgp peer,workstation部分為構(gòu)建跨網(wǎng)端的k8s集群。因為192.168.219.0/24網(wǎng)段的主機加入集群需要依賴ensp中的路由, 操作的順序是先搭建出ensp的網(wǎng)絡(luò)部分再將新節(jié)點加到k8s中繼而配置bgp?,F(xiàn)有k8s集群有三臺服務(wù)器均通過橋接聯(lián)網(wǎng), 一臺master節(jié)點兩臺普通節(jié)點, 分別如下
- k8s-master:10.30.81.127
- k8s-node1:10.30.81.128
- k8s-node2:10.30.81.130
ensp配置
按照上圖搭建出ensp部分的網(wǎng)絡(luò)設(shè)備連接拓?fù)洌?然后分別配置R1、R2和兩朵云, R1和R2上配置如下
- :'
- R1上配置
- '
- # 接口ip配置
- int g0/0/0
- ip a 20.20.20.10 24
- int g0/0/1
- ip a 10.30.81.118 24
- int g0/0/2
- ip a 30.30.30.10 24
- # 設(shè)置靜態(tài)路由, 跳到下一個網(wǎng)段
- ip route-static 192.168.219.0 24 20.20.20.20
- ip route-static 192.168.219.0 24 30.30.30.20
- # bgp配置, 把同AS內(nèi)的ibgp peer也配置了
- bgp 64512
- peer 10.30.81.127 as-number 64512
- peer 10.30.81.128 as-number 64512
- peer 10.30.81.130 as-number 64512
- peer 192.168.219.10 as-number 64513
- peer 192.168.219.10 ebgp-max-hop 5
- peer 192.168.219.10 connect-interface g0/0/1
- peer 10.30.81.127 reflect-client
- peer 10.30.81.128 reflect-client
- peer 10.30.81.130 reflect-client
- display bgp peer
- display bgp ip-routing
- display ip interface br
- display ip routing-table
- :'
- R2上配置
- '
- # 接口ip配置
- int g0/0/0
- ip a 192.168.219.10 24
- int g0/0/1
- ip a 20.20.20.20 24
- int g0/0/2
- ip a 30.30.30.20 24
- # 設(shè)置靜態(tài)路由, 跳到下一個網(wǎng)段
- ip route-static 10.30.81.0 24 20.20.20.10
- ip route-static 10.30.81.0 24 30.30.30.10
- # bgp配置, 把同AS內(nèi)的ibgp peer也配置了
- bgp 64513
- peer 10.30.81.118 as-number 64512
- peer 10.30.81.118 ebgp-max-hop 5
- peer 10.30.81.118 connect-interface g0/0/0
- peer 192.168.219.20 as-number 64513
- peer 192.168.219.40 as-number 64513
- peer 192.168.219.20 reflect-client
- peer 192.168.219.40 reflect-client
- display bgp peer
- display bgp ip-routing
- display ip interface br
- display ip routing-table
按如上配置好后R1和R2, 并且配置好兩朵云后, 在R2上ping 10.30.81.118是可以成功的了, 并且我們也可以觀察到R1和R2已經(jīng)建立起了EBGP關(guān)系。但是從R2上ping k8s集群的任何一臺主機都不通, 而是會報host unreachable, 因為k8s節(jié)點主機上并沒有回程路由, 它們并不知道將icmp的replay包發(fā)往往R1, 因此需要在三臺主機上添加路由
- # 此時添加如下路由也不會有效, 因為從R2上發(fā)出來的ping包源ip不是192.1168.219.0/24網(wǎng)段的
- route add -n 192.168.219.0/24 gw 10.30.81.118 dev ens33
- echo route add -n 192.168.219.0/24 gw 10.30.81.118 dev ens33 >> /etc/rc.local
- ip route add 192.168.219.0/24 via 10.30.81.118 dev ens33
- # 添加如下路由才會在R2上ping通現(xiàn)有k8s集群節(jié)點。 可以在ping通后刪除掉, 因為R2只是中間節(jié)點而已
- route add -n 20.20.20.0/24 gw 10.30.81.118 dev ens33
- route add -n 30.30.30.0/24 gw 10.30.81.118 dev ens33
在k8s所有節(jié)點添加了如上的路由就可以在R2上ping通所有的k8s節(jié)點了
新機器加入k8s集群
創(chuàng)建虛機并配置它的網(wǎng)絡(luò)為nat模式,配置它們的網(wǎng)卡和路由, 注意不要讓它們有10.30.81.0/24網(wǎng)段的路由指向vmnet8。網(wǎng)卡配置如下
- # 網(wǎng)卡配置如下
- [root@k8s-node4 ~]# cat ifcfg-ens33
- TYPE=Ethernet
- DNS1=8.8.8.8
- IPADDR=192.168.219.40
- NETMASK=255.255.255.0
- GATEWAY=192.168.219.10
- BOOTPROTO=static
- DEFROUTE=yes
- IPV4_FAILURE_FATAL=no
- NAME=ens33
- UUID=6ef9b5bf-31c1-43b9-89d6-b8e89ab3c9c3
- DEVICE=ens33
- ONBOOT=yes
- # 下面的路由可以不加
- route add -net 10.30.81.0/24 gw 192.168.219.10 dev ens33
之后就是節(jié)點加入k8s的準(zhǔn)備
系統(tǒng)配置, 如下
- echo "Stop Firewalld"
- systemctl stop firewalld
- systemctl disable firewalld
- sed -ie 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
- setenforce 0
- echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
- echo "net.bridge.bridge-nf-call-ip6tables = 1" >>/etc/sysctl.conf
- echo "net.bridge.bridge-nf-call-iptables = 1" >>/etc/sysctl.conf
- echo "net.bridge.bridge-nf-call-arptables = 1" >>/etc/sysctl.conf
- swapoff -a
- echo swapoff -a >> /etc/rc.local
- sysctl -p
從已k8s集群節(jié)點中將kubeadm、kubelet、kubectl的二進制文件拷貝到/usr/bin目錄下,設(shè)置kubelet開機自啟,kubelet的配置如下
- [Unit]
- Description=kubelet: The Kubernetes Node Agent
- Documentation=https://kubernetes.io/docs/
- Wants=network-online.target
- After=network-online.target
- [Service]
- ExecStart=/usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --network-plugin=cni --pod-infra-container-image=k8s.gcr.io/pause:3.2 --fail-swap-on=false
- Restart=always
- StartLimitInterval=0
- RestartSec=10
- [Install]
- WantedBy=multi-user.target
安裝docker
從已有k8s集群節(jié)點中將calico相關(guān)的容器鏡像、kube-proxy鏡像導(dǎo)出并給導(dǎo)入到新節(jié)點中。集群已經(jīng)存在了, k8s控制平面的apiserver、etcd、controller-manager、scheduler鏡像可以不拷到新節(jié)點。
使用kubeadm將新節(jié)點加入k8s集群
驗證跨網(wǎng)段之間的通信是走了ensp網(wǎng)絡(luò)的, 從k8s-master上跟蹤到k8s-node3的路由路徑, 下一跳中存在20.20.20.20為R2的接口
- [root@k8s-master ~]# traceroute 192.168.219.20
- traceroute to 192.168.219.20 (192.168.219.20), 30 hops max, 60 byte packets
- 1 10.30.81.118 (10.30.81.118) 18.396 ms 79.412 ms 79.396 ms
- 2 20.20.20.20 (20.20.20.20) 79.387 ms 79.380 ms 83.814 ms
- 3 k8s-node3 (192.168.219.20) 108.104 ms 112.777 ms 117.847 ms
通過如上搭建出了5節(jié)點的跨網(wǎng)段k8s集群, 如下
- [root@k8s-node4 ~]# kubectl get node -o wide
- NAME STATUS ROLES AGE VERSION INTERNAL-IP
- k8s-master Ready control-plane,master 45d v1.20.0 10.30.81.127
- k8s-node1 Ready <none> 45d v1.20.0 10.30.81.128
- k8s-node2 Ready <none> 9d v1.20.0 10.30.81.130
- k8s-node3 Ready <none> 20h v1.20.0 192.168.219.20
- k8s-node4 Ready <none> 20h v1.20.0 192.168.219.40
calico配置bgp
配置bgp需要使用calicoctl工具, 自己準(zhǔn)備好, 配置bgp主要分為以下步驟
- 確認(rèn)calico部署是純BGP模式
- 關(guān)閉BGP默認(rèn)的full mesh模式
- 修改指定主機k8s-node3和k8s-node4的bgp as number值為64513
- 給所有主機打標(biāo)簽進行bgp as分組, 滿足bpg peer選擇特定的peer對等體
- 創(chuàng)建bgp peer, 通過第四步打的標(biāo)簽讓rr client與rr建立ibgp關(guān)系
確認(rèn)calico-node的如下兩個配置為Never
- - name: CALICO_IPV4POOL_IPIP
- value: "Never"
- - name: CALICO_IPV4POOL_VXLAN
- value: "Never"
calico的bgp模式默認(rèn)是full mesh的, 將其關(guān)閉
- calicoctl get bgpconfiguration default -o yaml
- apiVersion: projectcalico.org/v3
- items:
- - apiVersion: projectcalico.org/v3
- kind: BGPConfiguration
- metadata:
- creationTimestamp: "2021-09-05T06:23:50Z"
- name: default
- resourceVersion: "555583"
- uid: 9438105f-cdd8-4315-8694-6d4885c76c85
- spec:
- logSeverityScreen: Info
- nodeToNodeMeshEnabled: false # 修改為false后calicoctl apply -f bgpconfiguration.yaml
- kind: BGPConfigurationList
- metadata:
- resourceVersion: "580613"
將calico節(jié)點k8s-node3和k8s-node4的bgp as number設(shè)置為64513
- calicoctl get node k8s-node3 -o yaml > node3.yaml
- apiVersion: projectcalico.org/v3
- kind: Node
- metadata:
- annotations:
- projectcalico.org/kube-labels: '{"beta.kubernetes.io/arch":"amd64","beta.kubernetes.io/os":"linux","kubernetes.io/arch":"amd64","kubernetes.io/hostname":"k8s-node3","kubernetes.io/os":"linux"}'
- creationTimestamp: "2021-09-04T14:03:35Z"
- labels:
- beta.kubernetes.io/arch: amd64
- beta.kubernetes.io/os: linux
- kubernetes.io/arch: amd64
- kubernetes.io/hostname: k8s-node3
- kubernetes.io/os: linux
- name: k8s-node3
- resourceVersion: "580885"
- uid: 64f44ad1-f537-43f3-9f0e-d5d5b80adba2
- spec:
- addresses:
- - address: 192.168.219.20/24
- type: CalicoNodeIP
- - address: 192.168.219.20
- type: InternalIP
- bgp:
- asNumber: 64513 # 添加這一行
- ipv4Address: 192.168.219.20/24
- orchRefs:
- - nodeName: k8s-node3
- orchestrator: k8s
- status:
- podCIDRs:
- - 10.244.4.0/24
給節(jié)點打標(biāo)簽
- :'
- 給as64512的節(jié)點打標(biāo)簽
- '
- kubectl label nodes k8s-master as-group=as64512
- kubectl label nodes k8s-master as-id=as64512
- kubectl label nodes k8s-node1 as-group=as64512
- kubectl label nodes k8s-node1 as-id=as64512
- kubectl label nodes k8s-node2 as-group=as64512
- kubectl label nodes k8s-node2 as-id=as64512
- :'
- 給as64513的節(jié)點打標(biāo)簽
- '
- kubectl label nodes k8s-node3 as-group=as64513
- kubectl label nodes k8s-node3 as-id=as64513
- kubectl label nodes k8s-node4 as-group=as64513
- kubectl label nodes k8s-node4 as-id=as64513
- :'
- 后面部署pod測試跨網(wǎng)段節(jié)點的pod間的通信使用
- '
- kubectl label nodes k8s-master node=master
- kubectl label nodes k8s-node4 node=node4
- kubectl label nodes k8s-node3 node=node3
- kubectl label nodes k8s-node2 node=node2
- kubectl label nodes k8s-node1 node=node1
創(chuàng)建calico的bgp peer實例, 因為在ensp配置部分已經(jīng)在R1、R2上配置好了RR模式。在RR模式下我們選擇將所有的k8s節(jié)點都作為rr的client, 因此同意as下的k8s節(jié)點間不需要再建立ibgp對等體關(guān)系,剩下的則讓各自as的k8s節(jié)點分別和R1與R2建立ibgp關(guān)系即可
- :'
- 區(qū)域as64513的k8s節(jié)點與R2建立rr關(guān)系
- '
- vim as64513_r2_peer.yaml
- apiVersion: projectcalico.org/v3
- kind: BGPPeer
- metadata:
- name: as64513-to-r2-peer ## 給BGPPeer取一個名稱,方便識別
- spec:
- nodeSelector: rr-id == 'as64513' ## 通過節(jié)點選擇器添加有rr-id == 'as64513'標(biāo)簽的節(jié)點
- peerIP: 192.168.219.10
- asNumber: 64513
- :'
- 區(qū)域as64512的k8s節(jié)點與R1建立rr關(guān)系
- '
- vim as64512_r1_peer.yaml
- apiVersion: projectcalico.org/v3
- kind: BGPPeer
- metadata:
- name: as64512-to-r1-peer ## 給BGPPeer取一個名稱,方便識別
- spec:
- nodeSelector: rr-id == 'as64512' ## 通過節(jié)點選擇器添加有rr-id == 'as64512'標(biāo)簽的節(jié)點
- peerIP: 10.30.81.118
- asNumber: 64512
- calicoctl apply -f as64512_r1_peer.yaml
- calicoctl apply -f as64513_r2_peer.yaml
驗證bgp路由宣告和pod間通信
使用標(biāo)簽在各個節(jié)點行創(chuàng)建pod, 然后找跨網(wǎng)端的兩臺主機的pod進行ping通信并抓包。創(chuàng)建pod
- mkdir test_pod
- cd test_pod
- vim master.yaml
- apiVersion: v1
- kind: Pod
- metadata:
- name: master
- spec:
- containers:
- - name: master
- image: larioy/nettool:latest
- imagePullPolicy: IfNotPresent
- nodeSelector:
- node: master
- sed s/master/node1/g master.yaml > node1.yaml
- sed s/master/node2/g master.yaml > node2.yaml
- sed s/master/node3/g master.yaml > node3.yaml
- sed s/master/node4/g master.yaml > node4.yaml
- ls -l | grep -v grep | grep yaml | awk '{print $9}' | xargs -I {} kubectl apply -f {}
看看創(chuàng)建出來的pod的分布情況
- [root@k8s-master ~]# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE
- master 1/1 Running 0 4h17m 10.244.235.192 k8s-master
- node1 1/1 Running 0 4h17m 10.244.36.64 k8s-node1
- node2 1/1 Running 0 4h17m 10.244.169.129 k8s-node2
- node3 1/1 Running 0 4h17m 10.244.107.192 k8s-node3
- node4 1/1 Running 0 4h17m 10.244.122.64 k8s-node4
在bird客戶端看看學(xué)習(xí)到的bgp路由, 在k8s-master節(jié)點上操作, 其自身pod子網(wǎng)段為:10.244.235.192/26
rr路由宣告
在ensp網(wǎng)絡(luò)的R1上其應(yīng)該能學(xué)習(xí)到所有k8s節(jié)點的pod子網(wǎng)對應(yīng)的子網(wǎng)段路由
R1學(xué)習(xí)的bgp路由
接著通過跨網(wǎng)段節(jié)點的pod間通信抓包驗證, as64512的k8s-master節(jié)點的pod master與as64513的k8s-node3的pod node3間通信抓包, 在R2上抓包
- [root@k8s-master ~]# kubectl get pod -o wide | grep -E "node3|master"
- master 1/1 Running 0 29m 10.244.235.192 k8s-master
- node3 1/1 Running 0 29m 10.244.107.192 k8s-node3
- [root@k8s-master ~]# kubectl exec -it master -- ping 10.244.107.192
- PING 10.244.107.192 (10.244.107.192): 56 data bytes
- 64 bytes from 10.244.107.192: seq=0 ttl=60 time=49.314 ms
- 64 bytes from 10.244.107.192: seq=1 ttl=60 time=28.744 ms
- 64 bytes from 10.244.107.192: seq=2 ttl=60 time=48.422 ms
- 64 bytes from 10.244.107.192: seq=3 ttl=60 time=39.144 ms
- 64 bytes from 10.244.107.192: seq=4 ttl=60 time=32.472 ms
R2抓包
如上跨節(jié)點k8s集群基于bgp實現(xiàn)了pod間的通信
手動維護bgp
實驗過程中在ENSP部分有關(guān)R1/R2的bgp配置都是手工進行維護的, 針對每機架一個AS的部署模式, 怎么監(jiān)控到一個AS內(nèi)的主機的上下線, 然后自動的更新RR上client的信息。
bgp架構(gòu)的思考
在本篇測試中只建立了"每機架作為一個獨立as"架構(gòu)的測試,該架構(gòu)中最上層是采用交換機連接, 因此要求所有不同網(wǎng)段中的RR要建立其ebgp關(guān)系, 不一定要全互聯(lián)但是要保證每個RR都可以從某一個RR學(xué)到其他剩余的RR宣告的BGP路由。"每機架作為一個獨立AS"架構(gòu)的另一種為最上層為路由器, 他們與所有RR都建立EBGP關(guān)系,這樣在RR之間就不需要再建立BGP關(guān)系了。另外就是考慮路由條目變多后, 哪種架構(gòu)更合適, 暫未涉及。
問題記錄
- ensp使用云無法找到vmnet8網(wǎng)卡問題, 重裝winPcap,重裝ensp, 路由和同網(wǎng)段主機突然不通了可能是網(wǎng)卡找不到...
- ensp路由設(shè)備無效問題:見ensp界面右上角菜單查找?guī)椭謨裕?刪掉頁面上的所有設(shè)備重新注冊, 還是失敗考慮重裝ensp...
- workstation在nat模式下無法連接虛機:先查主機上vmnet8網(wǎng)卡的ip地址,在虛擬網(wǎng)絡(luò)編輯器中設(shè)置nat時, 設(shè)置的nat范圍需要和vmnet8的ip地址在同一網(wǎng)段且網(wǎng)關(guān)設(shè)置為vmnet8的ip
- 新增k8s節(jié)點在安裝必備的工具時可以先切換回橋接聯(lián)網(wǎng),然后再切換回nat, 然后在加入k8s集群
- ensp部分網(wǎng)絡(luò)配置不通可以直接在路由器R1和R2的兩端接口處抓包, 分析哪段不通, 哪段接到請求但是沒有響應(yīng)
本文為原創(chuàng)投稿文章,文章原文:https://larioy.gst.monster/2021/09/05/k8s-ji-chong-cni-fang-an-jie-xi/calico/ensp-mo-ni-calico-kua-wang-duan-bgp-wang-luo/
參考資料
[1]The AS Per Rack model: https://docs.projectcalico.org/reference/architecture/design/l3-interconnect-fabric