kubernetes multi-cni多網卡&vpn設定與應用

Ivan Chiou
The Messiah Code 神碼技術共筆
13 min readAug 11, 2022

新的計畫將是地端與雲端的整合。未來將會陸續碰到網路設定與容器化之間的溝通議題。

眼下會研究兩個議題方向:

  1. 就是透過multi-cni與vpn的設定,讓layer 2的訊息可以互相溝通。

layer 2(Ethernet)為ROS(Robot Operating System)所使用的DDS(Data Distribution Service)所走的資料傳輸協定。

原先在雲端服務所提供的kubernetes虛擬網路環境,都是採用預設layer 3(TCP/IP)虛擬網卡,所以為了讓這些虛擬雲端cluster能夠提供layer 2的介面,必須在其private network安裝另一張虛擬網卡,最多人採用的方式是使用multus-cni。

https://github.com/k8snetworkplumbingwg/multus-cni

多網卡設定在EKS(AWS的K8S)上之複雜,超越我的認知。

藉由以下這篇可以大致了解步驟,但是還不夠。

依照上述文章所述的Prerequisites部分,先把要install的multus相關github準備好,並且要注意的有以下三點:

(1)在使用 Multus CNI 的情況下,會需要額外的在 Worker Node 上配置專門給 Multus CNI 所使用的 Interface。可以透過Lambda function的方式來達成 。

(2) 雖然 Pod 有根據 NetworkAttachmentDefinition 關聯對應的 IP,然而,AWS VPC 卻不知道其背後對應的目標是誰,導致在跨節點訪問上會出現問題。因此需要部署 “aws-ip-management” 來作解決放案。aws-ip-management 是會將 Pod Secondary IP 關聯到對應的 Multus CNI 所使用的 Interface。

(3) 然在推薦 的IPAM 配置是使用 “whereabouts” 插件,來做為 Secondary IP 分配的元件,用以確保cluster間的 IP 不會衝突。如以下設定:

apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: ros-network
spec:
config: '{
"cniVersion": "0.3.0",
"type": "ipvlan",
"master": "eth1",
"mode": "l2",
"ipam": {
"type": "whereabouts",
"datastore": "kubernetes",
"kubernetes": { "kubeconfig": "/etc/cni/net.d/whereabouts.d/whereabouts.kubeconfig" },
"range": "10.10.192.80-10.10.192.100/24",
"routes": [
{ "dst": "0.0.0.0/0" }
],
"log_file" : "/tmp/whereabouts.log",
"log_level" : "debug",
"gateway": "10.10.192.1"
}
}'

但只設定多網卡還不夠,ROS的cluster之間要能夠在EKS的pod之間跨node的溝通,需要設定multicast功能,而AWS VPC預設不支持multicast

因此要透過transit gateway multicast功能來實現,過程如下:

(1) 透過AWS console UI建立transit gateway multicast domain。建立時請注意必須勾選 Multicast support

(2) 等TGW (Transit Gateway)建立完成後,接著建立 transit gateway attachment。選取於第一步建立的 TGW,並選取正確要綁定的EKS cluster所使用的VPC。subnets可依照需求選用多個子網,或其中一個子網。

(3) 待 attachment 建立完成後,切換到 Transit gateway multicast,建立 Multicast domain。接著選取第一步建立的 TGW,並勾選 IGMPv2 support

(4) 建立 Multicast domain 後,關聯子網選擇正確的Multicast domain,接著切換頁籤到 Associations,點選 Create association。選取第二步建立的 attachment,並選取群播的子網(vpc下所有子網)。

(5) 等子網關聯完成後,接著設定 NACL 與 安全組,允許群播的流量,請參考此篇文章。這邊要注意的是群播的IP位置並非設定240.0.0.2,因為在ROS架構下,其預設群播訊息的IP位置為239.255.0.1

(6) 設定完成後,這邊需要手動添加群播組(好像可以有辦法自動添加,但做到這邊已經累了,之後再研究),請參考此篇文章,Group Id 為上述所說的群播IP位址 239.255.0.1。

如此就真的完成了XD。然後進去兩台EKS主機,分別輸入以下指令。

#接收端

iperf -s -u -B 239.255.0.1 -i 1

#發送端

iperf -c 239.255.0.1 -u -T 32 -t 100 -i 10

然後設定你要deploy的app在EKS上,並設定為hostNetwork: true,這樣同樣在EKS POD裡面的multicast也可以互通。

接著就是透過 openvpn access server 來架設VPN,讓地端與雲端的網路環境是在同一網段。確保訊息可以從上述的layer 2 cluster環境傳遞至地端的containers中的APP。

Server端可以這樣設定。

apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: openvpn-server
name: openvpn-server
annotations:
k8s.v1.cni.cncf.io/networks: ros-network
spec:
selector:
matchLabels:
app: openvpn-server
template:
metadata:
labels:
app: openvpn-server
annotations:
k8s.v1.cni.cncf.io/networks: ros-network
spec:
containers:
- name: aws-ip-mgmt
image: aws-ip-manager:0.1
imagePullPolicy: Always
args: [/bin/sh, -c, '/app/script.sh sidecar']
- env:
- name: PUID
value: "1000"
- name: PGID
value: "1004"
- name: TZ
value: Asia/Taipei
- name: INTERFACE
value: eth1
image: ros:foxy
imagePullPolicy: IfNotPresent
name: openvpn-server
command: ["/bin/bash", "-c"]
args: ['apt update && apt -y install ca-certificates wget net-tools gnupg systemctl && wget -qO - https://as-repository.openvpn.net/as-repo-public.gpg | apt-key add - && echo "deb http://as-repository.openvpn.net/as/debian focal main">/etc/apt/sources.list.d/openvpn-as-repo.list && apt update && apt -y install openvpn-as && tail -f /dev/null']
ports:
- containerPort: 1194
name: openvpn-server
protocol: UDP
- containerPort: 943
name: port1
protocol: TCP
- containerPort: 9443
name: port2
protocol: TCP
securityContext:
privileged: true
capabilities:
add:
- NET_ADMIN
privileged: true
volumeMounts:
- mountPath: /usr/local/openvpn_as
name: openvpn-data
- mountPath: /config
name: configs
restartPolicy: Always
volumes:
- name: openvpn-data
persistentVolumeClaim:
claimName: openvpn-server-data-pv-claim
- name: configs
persistentVolumeClaim:
claimName: openvpn-server-pv-claim

同時設定aws-ip-manager將vpn網卡設置至剛創建的第二張網卡上,確保ROS message可以透過layer 2從雲端溝通到地端。並將設定檔attach到外部的volume disk(AWS EBS),做persistent store。

而地端我們一樣有一個k8s cluster,裡面放入openvpn client pod。並將hostNetwork設定成true,代表直接使用該cluster所在主機的網卡當作cluster的網段,並取得host的IP當作openvpn client pod的IP。

apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: openvpn-client
name: openvpn-client
spec:
replicas: 1
selector:
matchLabels:
app: openvpn-client
template:
metadata:
labels:
app: openvpn-client
spec:
hostNetwork: true
containers:
- env:
- name: PUID
value: "1000"
- name: PGID
value: "1004"
- name: TZ
value: Asia/Taipei
- name: INTERFACE
value: eth0
image: ros:foxy
imagePullPolicy: IfNotPresent
name: openvpn-client
command: ["/bin/bash", "-c"]
args: ['apt update && apt install -y curl dnsutils netcat iputils-ping net-tools iproute2 wget && apt install openvpn -y && cd /config && openvpn --config client.ovpn --remote-cert-tls server']
securityContext:
privileged: true
capabilities:
add:
- NET_ADMIN
volumeMounts:
- mountPath: /config
name: configs
restartPolicy: Always
volumes:
- name: configs
persistentVolumeClaim:
claimName: openvpn-client-data-pv-claim

記得將openvpn的client.ovpn與auth-user-pass的conf file放置相對openvpn-client-data-pv-claim的hostpath中。

如此串連後,所有在雲端EKS中的pod兩張網卡IP就完全與地端的IP走layer 2串連在一起。而可以互通ROS協定訊息。

要注意,openvpn access server free版本因為最多只允許同時兩個client connect,所以在多地端不同branch的site的狀況下,就需要考慮其他3rd party vpn軟體,而softether vpn(open source)是可以做為另外的考量。

一旦VPN已串連起來,要做port forwarding方便使用proxy的外部IP來連進來內部主機的服務就不是問題了。

socat TCP4-LISTEN:99999,fork TCP4:192.168.xxx.x:22

透過socat把public ip的99999 port指定到私有網路192.168.xxx.x的22,就可以ssh進來地端的機器。還有傳送tcp/udp的資料。

vpn+tcp+udp的溝通好處在於設定可用於任何網路環境,傳輸的反應於網路的架構一致,但缺點也是每個網路環境的設定很難SOP化,以至於未來很難一鍵設定完成,難以快速建置新的環境。

如此,非常複雜的網路行為終於搞定。

2. 透過mqtt讓雲端與地端相互溝通 — AWS的 IoT Greengrass solution。

使用mqtt(一種message broker)的溝通好處在於可於各種裝置設定,不論其網路狀況,方便設定部署程式的自動化。但壞處是mqtt server(透過Greengrass solution可以serverless)的maintain與設定,較為依賴於服務且訊息必集中於雲端,有可能對地端的延遲較高。

下回分解

--

--

Ivan Chiou
The Messiah Code 神碼技術共筆

Rich experience in multimedia integration, cross-functional collaboration, and dedicated to be a mentor for young developers.