kubernetes 集群中 cilium 的實(shí)踐及其網(wǎng)絡(luò)通信解析

Cilium Overview

Cilium 是一個(gè)基于 eBPF 和 XDP 的高性能容器網(wǎng)絡(luò)方案的開源項(xiàng)目,目標(biāo)是為微服務(wù)環(huán)境提供網(wǎng)絡(luò)、負(fù)載均衡、安全功能,主要定位是容器平臺(tái)。

cilium.png

Why Cilium ?

現(xiàn)在應(yīng)用程序服務(wù)的發(fā)展已從單體結(jié)構(gòu)轉(zhuǎn)變?yōu)槲⒎?wù)架構(gòu),微服務(wù)間的的通信通常使用輕量級(jí)的 http 協(xié)議。微服務(wù)應(yīng)用往往是經(jīng)常性更新變化的,在持續(xù)交付體系中為了應(yīng)對(duì)負(fù)載的變化通常會(huì)橫向擴(kuò)縮容,應(yīng)用容器實(shí)例也會(huì)隨著應(yīng)用的更新而被創(chuàng)建或銷毀。

這種高頻率的更新對(duì)微服務(wù)間的網(wǎng)絡(luò)可靠連接帶來了挑戰(zhàn):

  • 傳統(tǒng)的 Linux 網(wǎng)絡(luò)安全連接方式是通過過濾器(例如 iptables )在 IP 地址及端口上進(jìn)行的,但是在微服務(wù)高頻更新的環(huán)境下,應(yīng)用容器實(shí)例的 IP 端口是會(huì)經(jīng)常變動(dòng)。在微服務(wù)應(yīng)用較多的場(chǎng)景下,由于這種頻繁的變動(dòng),成千上萬的 iptables 規(guī)則將會(huì)被頻繁的更新。

  • 出于安全目的,協(xié)議端口(例如 HTTP 流量的 TCP 端口 80)不再用于區(qū)分應(yīng)用流量,因?yàn)樵摱丝谟糜诳绶?wù)的各種消息。

  • 傳統(tǒng)系統(tǒng)主要使用 IP 地址作為標(biāo)識(shí)手段,在微服務(wù)頻繁更新的架構(gòu)中,某個(gè) IP 地址可能只會(huì)存在短短的幾秒鐘,這將難以提供準(zhǔn)確的可視化追蹤痕跡。

Cilium 通過利用 BPF 具有能夠透明的注入網(wǎng)絡(luò)安全策略并實(shí)施的功能,區(qū)別于傳統(tǒng)的 IP 地址標(biāo)識(shí)的方式,Cilium 是基于 service / pod /container 標(biāo)識(shí)來實(shí)現(xiàn)的,并且可以在應(yīng)用層實(shí)現(xiàn) L7 Policy 網(wǎng)絡(luò)過濾??傊?,Cilium 通過解藕 IP 地址,不僅可以在高頻變化的微服務(wù)環(huán)境中應(yīng)用簡(jiǎn)單的網(wǎng)絡(luò)安全策略,還能在支持 L3/L4 基礎(chǔ)上通過對(duì) http 層進(jìn)行操作來提供更強(qiáng)大的網(wǎng)絡(luò)安全隔離。BPF 的使用使 Cilium 甚至可以在大規(guī)模環(huán)境中以高度可擴(kuò)展的方式解決這些挑戰(zhàn)問題。

Cilium 的主要功能特性

  • 支持 L3/L4/L7 安全策略,這些策略按照使用方法又可以分為
    基于身份的安全策略(Security identity)
    基于 CIDR 的安全策略
    基于標(biāo)簽的安全策略

  • 支持三層扁平網(wǎng)絡(luò)

    Cilium 的一個(gè)簡(jiǎn)單的扁平 3 層網(wǎng)絡(luò)具有跨多個(gè)群集的能力,可以連接所有應(yīng)用程序容器。通過使用主機(jī)作用域分配器,可以簡(jiǎn)化 IP 分配,這意味著每臺(tái)主機(jī)不需要相互協(xié)調(diào)就可以分配到 IP subnet。

    Cilium 支持以下多節(jié)點(diǎn)的網(wǎng)絡(luò)模型:

    • Overlay 網(wǎng)絡(luò),當(dāng)前支持 Vxlan 和 Geneve ,但是也可以啟用 Linux 支持的所有封裝格式。

    • Native Routing, 使用 Linux 主機(jī)的常規(guī)路由表或云服務(wù)商的高級(jí)網(wǎng)絡(luò)路由等。此網(wǎng)絡(luò)要求能夠路由應(yīng)用容器的 IP 地址。

  • 提供基于 BPF 的負(fù)載均衡
    Cilium 能對(duì)應(yīng)用容器間的流量及外部服務(wù)支持分布式負(fù)載均衡。

  • 提供便利的監(jiān)控手段和排錯(cuò)能力

    可見性和快速的問題定位能力是一個(gè)分布式系統(tǒng)最基礎(chǔ)的部分。除了傳統(tǒng)的 tcpdump 和 ping 命令工具,Cilium 提供了:

    1. 具有元數(shù)據(jù)的事件監(jiān)控:當(dāng)一個(gè) Packet 包被丟棄,這個(gè)工具不會(huì)只報(bào)告這個(gè)包的源 IP 和目的 IP,此工具還會(huì)提供關(guān)于發(fā)送方和接送方所有相關(guān)的標(biāo)簽信息。

    2. 決策追蹤:為何一個(gè) packet 包被丟棄,為何一個(gè)請(qǐng)求被拒絕?策略追蹤框架允許追蹤正在運(yùn)行的工作負(fù)載和基于任意標(biāo)簽定義的策略決策過程。

    3. 通過 Prometheus 暴露 Metrics 指標(biāo):關(guān)鍵的 Metrics 指標(biāo)可以通過 Prometheus 暴露出來到監(jiān)控看板上進(jìn)行集成展示。

    4. Hubble:一個(gè)專門為 Cilium 開發(fā)的可視化平臺(tái)。它可以通過 flow log 來提供微服務(wù)間的依賴關(guān)系,監(jiān)控告警操作及應(yīng)用服務(wù)安全策略可視化。

Cilium 的部署

此處使用外部的 etcd 的部署方式,外部 etcd 安裝 cilium 在較大的運(yùn)行環(huán)境中能夠提供更好的性能。

Requirements

1.  Kubernetes >= 1.9
2.  Linux kernel >= 4.9
3.  ETCD >= 3.1.0
4.  kubernetes 環(huán)境中安裝了 Helm 3
5.  Kubernetes in CNI mode
6.  在所有 worker node 上掛載 BPF 文件系統(tǒng)
7.  推薦:在 kube-controller-manager 上使能 PodCIDR allocation (--allocate-node-cidrs) 

安裝 helm 3

# 下載解壓 helm 安裝包
[root@k8s-master-01 ~]# wget https://get.helm.sh/helm-v3.1.2-linux-amd64.tar.gz
[root@k8s-master-01 ~]# tar -zxvf helm-v3.1.2-linux-amd64.tar.gz
[root@k8s-master-01 ~]# mv linux-amd64/helm /usr/local/bin/

# verify
[root@k8s-master-01 ~]# helm help
The Kubernetes package manager

Common actions for Helm:

- helm search:    search for charts
- helm pull:      download a chart to your local directory to view
- helm install:   upload the chart to Kubernetes
- helm list:      list releases of charts

Environment variables:
+------------------+-----------------------------------------------------------------------------+
| Name             | Description                                                                 |
+------------------+-----------------------------------------------------------------------------+
| $XDG_CACHE_HOME  | set an alternative location for storing cached files.                       |
| $XDG_CONFIG_HOME | set an alternative location for storing Helm configuration.                 |
| $XDG_DATA_HOME   | set an alternative location for storing Helm data.                          |
| $HELM_DRIVER     | set the backend storage driver. Values are: configmap, secret, memory       |
| $HELM_NO_PLUGINS | disable plugins. Set HELM_NO_PLUGINS=1 to disable plugins.                  |
| $KUBECONFIG      | set an alternative Kubernetes configuration file (default "~/.kube/config") |
+------------------+-----------------------------------------------------------------------------+

Helm stores configuration based on the XDG base directory specification, so

- cached files are stored in $XDG_CACHE_HOME/helm
- configuration is stored in $XDG_CONFIG_HOME/helm
- data is stored in $XDG_DATA_HOME/helm

Use "helm [command] --help" for more information about a command.

掛載 BPF 文件系統(tǒng)

在 kubernetes 集群所有 node 上掛載 bpf 文件系統(tǒng)

[root@k8s-master-01 ~]# mount bpffs /sys/fs/bpf -t bpf

# verify
[root@k8s-master-01 ~]# mount |grep bpf
bpffs on /sys/fs/bpf type bpf (rw,relatime)

# persistence configuration, don’t worry that ‘bpffs’ displaying as red, seems bpf was new commer, fastab desen’t update that feature.
[root@k8s-master-01 ~]# echo "bpffs        /sys/fs/bpf      bpf     defaults 0 0" >> /etc/fstab

kubernetes 配置

# 在所有的 kubernetes node 中的 kubelet 配置使用 CNI 模式, kubelet.config 中添加 
--network-plugin=cni

# 在 kube-controller-manager 中使能 PodCIDR, kube-controller-manager.config 中添加
--allocate-node-cidrs=true

cilium 安裝

當(dāng)使用外部 etcd 作為 cilium 的 k-v 存儲(chǔ),etcd 的 IP 地址需要在 cilium 的 configmap 中配置。

使用 helm 安裝 cilium

# 添加 helm cilium repo
[root@k8s-master-01 ~]#  helm repo add cilium https://helm.cilium.io/

# 創(chuàng)建 etcd ssl 證書
[root@k8s-master-01 ~]#  kubectl create secret generic -n kube-system cilium-etcd-secrets \
     --from-file=etcd-client-ca.crt=/etc/etcd/ssl/ca.crt \
     --from-file=etcd-client.key=/etc/etcd/ssl/etcd.key \
     --from-file=etcd-client.crt=/etc/etcd/ssl/etcd.crt

# 安裝 cilium,指定 cilium 版本為 v1.7.1, 開啟 SSL 驗(yàn)證,開啟 prometheus 監(jiān)控,添加 etcd cluster 的 menber endpoints
[root@k8s-master-01 ~]#  helm install cilium cilium/cilium\
  --version 1.7.1\
  --set global.etcd.enabled=true\ 
  --set global.etcd.ssl=true\ 
  --set global.prometheus.enabled=true\
  --set global.etcd.endpoints[0]=https://172.19.50.7:2379\
  --set global.etcd.endpoints[1]=https://172.19.60.32:2379\
  --set global.etcd.endpoints[2]=https://172.19.100.16:2379\
  --namespace kube-system
NAME: cilium
LAST DEPLOYED: Mon Mar 16 16:44:33 2020
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None

# 驗(yàn)證 cilium pod 都安裝成功
[root@k8s-master-01 ~]#  kubectl --namespace kube-system get ds cilium
NAME     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
cilium   4         4         4       4            4           <none>          13h

[root@k8s-master-01 ~]#  kubectl -n kube-system get deployments cilium-operator
NAME              READY   UP-TO-DATE   AVAILABLE   AGE
cilium-operator   1/1     1            1           13h

安裝 cilium 連接測(cè)試用例

此用例將會(huì)部署一系列的 deployment,它們會(huì)使用多種路徑來相互訪問,連接路徑包括帶或者不帶服務(wù)負(fù)載均衡和各種網(wǎng)絡(luò)策略的組合。

部署的 podName 表示連接方式,readiness/liveness 探針則可指示連接是否成功。

[root@k8s-master-01 ~]# kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/HEAD/examples/kubernetes/connectivity-check/connectivity-check.yaml -n app-service

[root@k8s-master-01 ~]# kubectl get pods -o wide -n app-service
NAME                                                     READY   STATUS    RESTARTS   AGE     IP               NODE            NOMINATED NODE   READINESS GATES
echo-a-58dd59998d-n9g9p                                  1/1     Running   0          9m13s   10.244.1.50      k8s-master-02   <none>           <none>
echo-b-669ccc7765-lzqn7                                  1/1     Running   0          9m13s   10.244.2.50      k8s-master-03   <none>           <none>
host-to-b-multi-node-clusterip-6fb94d9df6-rbjwz          1/1     Running   3          9m13s   192.168.66.226   k8s-master-02   <none>           <none>
host-to-b-multi-node-headless-7c4ff79cd-hm6sr            1/1     Running   3          9m13s   192.168.66.226   k8s-master-02   <none>           <none>
pod-to-a-5c8dcf69f7-gldq9                                1/1     Running   3          9m13s   10.244.2.30      k8s-master-03   <none>           <none>
pod-to-a-allowed-cnp-75684d58cc-tf9nn                    1/1     Running   1          9m13s   10.244.2.239     k8s-master-03   <none>           <none>
pod-to-a-external-1111-669ccfb85f-7r4j8                  1/1     Running   0          9m13s   10.244.2.251     k8s-master-03   <none>           <none>
pod-to-a-l3-denied-cnp-7b8bfcb66c-wd4nj                  1/1     Running   0          9m13s   10.244.2.134     k8s-master-03   <none>           <none>
pod-to-b-intra-node-74997967f8-ml5ps                     1/1     Running   3          9m13s   10.244.2.95      k8s-master-03   <none>           <none>
pod-to-b-multi-node-clusterip-587678cbc4-4qcb2           1/1     Running   3          9m13s   10.244.1.28      k8s-master-02   <none>           <none>
pod-to-b-multi-node-headless-574d9f5894-tmfwn            1/1     Running   3          9m13s   10.244.1.138     k8s-master-02   <none>           <none>
pod-to-external-fqdn-allow-google-cnp-6dd57bc859-l49z2   1/1     Running   0          9m12s   10.244.2.62      k8s-master-03   <none>           <none>

安裝 hubble https://github.com/cilium/hubble

hubble 是一個(gè)用于云原生工作負(fù)載的完全分布式網(wǎng)絡(luò)和安全可視化平臺(tái)。它建立在 Cilium 和 eBPF 的基礎(chǔ)上,以完全透明的方式深入了解服務(wù)以及網(wǎng)絡(luò)基礎(chǔ)結(jié)構(gòu)的通信和行為。

[root@k8s-master-01 ~]# git clone https://github.com/cilium/hubble.git
[root@k8s-master-01 ~]# cd hubble/install/kubernetes
[root@k8s-master-01 ~]# helm install hubble ./hubble \
    --namespace kube-system \
    --set metrics.enabled="{dns,drop,tcp,flow,port-distribution,icmp,http}" \
    --set ui.enabled=true

hubble 對(duì)前面安裝的測(cè)試用例監(jiān)控信息

image.png

Cilium 的網(wǎng)絡(luò)通信解析

cilium 在 kubernetes 集群中安裝好后,此處我們來探究一下在不同 node 上 pod 間的 vxlan 通信方式。

image.png

cilium 安裝完后,cilium agent 會(huì)在 node 上創(chuàng)建 cilium_netcilium_host 一對(duì) veth pair 及用于跨宿主機(jī)通信的 cilium_vxlan,然后在 cilium_host 上配置其管理的 CIDR IP 作為網(wǎng)關(guān)。

如上圖示中,通過抓包分析 Container A 與 Container B 之前的通信路徑。

Container A ping Container B (以下稱 Container A -> CA , Container B -> CB)

進(jìn)入 Node01 上 CA 內(nèi) (10.244.1.154),ping CB ip 地址 10.224.6.11

[root@Node01 ~]# docker exec -it 5eb8b6605c64 bash
root@voyager-client-8769496c4-ttzsj:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.244.1.154  netmask 255.255.255.255  broadcast 0.0.0.0
        ether 02:16:7a:1d:0c:7e  txqueuelen 0  (Ethernet)
        RX packets 1518748  bytes 139582792 (133.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1377417  bytes 286246722 (272.9 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

root@voyager-client-8769496c4-ttzsj:/# ping 10.244.6.11
PING 10.244.6.11 (10.244.6.11) 56(84) bytes of data.
64 bytes from 10.244.6.11: icmp_seq=1 ttl=63 time=0.664 ms
64 bytes from 10.244.6.11: icmp_seq=2 ttl=63 time=1.58 ms
64 bytes from 10.244.6.11: icmp_seq=3 ttl=63 time=0.574 ms
64 bytes from 10.244.6.11: icmp_seq=4 ttl=63 time=0.493 ms
64 bytes from 10.244.6.11: icmp_seq=5 ttl=63 time=0.587 ms
64 bytes from 10.244.6.11: icmp_seq=6 ttl=63 time=0.460 ms
64 bytes from 10.244.6.11: icmp_seq=7 ttl=63 time=0.551 ms

進(jìn)入 Node01 上 cilium agent 容器內(nèi),查看 CA 容器作為 cilium endpoint 的信息

[root@Node01 ~]# docker exec -it 7c0ce8909d21 bash

# 通過 cilium bpf endpoint 可看到在宿主機(jī) Node01 上 CA 容器 attach 的網(wǎng)卡 mac 地址 F2:19:FC:0E:0A:8c
root@cilium-agent:~# cilium bpf endpoint list
IP ADDRESS         LOCAL ENDPOINT INFO
10.96.0.10:0       (localhost)
192.168.66.226:0   (localhost)
10.102.101.239:0   (localhost)
10.101.126.212:0   (localhost)
10.99.24.234:0     (localhost)
10.244.1.4:0       id=1928  flags=0x0000 ifindex=10  mac=26:84:C5:50:4D:F9 nodemac=C6:AB:F1:63:C1:FE
10.99.146.112:0    (localhost)
10.96.0.1:0        (localhost)
10.110.33.8:0      (localhost)
10.244.1.208:0     (localhost)
10.111.30.67:0     (localhost)
10.108.89.187:0    (localhost)
10.107.23.171:0    (localhost)
10.244.1.183:0     id=3023  flags=0x0000 ifindex=48  mac=7E:DB:15:12:77:78 nodemac=CA:DE:51:6C:3B:6E
10.244.1.18:0      id=3047  flags=0x0000 ifindex=322 mac=92:BB:35:0B:64:DD nodemac=96:2D:AE:BD:78:6D
10.244.1.154:0     id=3432  flags=0x0000 ifindex=336 mac=02:16:7A:1D:0C:7E nodemac=F2:19:FC:0E:0A:8C
10.244.1.106:0     id=2222  flags=0x0000 ifindex=310 mac=02:EF:1A:74:99:36 nodemac=CE:12:20:E1:99:98

# 在宿主機(jī)上可看到對(duì)應(yīng)的網(wǎng)卡為 lxc8b528e748ff4(lxcxxA)
[root@Node01 ~]# ifconfig
cilium_host: flags=4291<UP,BROADCAST,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet 10.244.1.208  netmask 255.255.255.255  broadcast 0.0.0.0
        inet6 fe80::b814:51ff:fe6e:3ec0  prefixlen 64  scopeid 0x20<link>
        ether ba:14:51:6e:3e:c0  txqueuelen 1000  (Ethernet)
        RX packets 28524536  bytes 4348528855 (4.0 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1583  bytes 107646 (105.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

cilium_net: flags=4291<UP,BROADCAST,RUNNING,NOARP,MULTICAST>  mtu 1500
        inet6 fe80::cd4:62ff:fe16:2c7c  prefixlen 64  scopeid 0x20<link>
        ether 0e:d4:62:16:2c:7c  txqueuelen 1000  (Ethernet)
        RX packets 1583  bytes 107646 (105.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 28524536  bytes 4348528855 (4.0 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

cilium_vxlan: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::f4ee:12ff:fe6e:c46f  prefixlen 64  scopeid 0x20<link>
        ether f6:ee:12:6e:c4:6f  txqueuelen 1000  (Ethernet)
        RX packets 24633319  bytes 3811772734 (3.5 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 24389802  bytes 6318433970 (5.8 GiB)
        TX errors 0  dropped 46 overruns 0  carrier 0  collisions 0

.......
lxc8b528e748ff4: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::f019:fcff:fe0e:a8c  prefixlen 64  scopeid 0x20<link>
        ether f2:19:fc:0e:0a:8c  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
.......

CA 容器 ping 出的 icmp 包將會(huì)經(jīng)過網(wǎng)卡 lxc8b528e748ff4 (lxcxxA) 路由到 cilium_host 網(wǎng)關(guān),路由方式與傳統(tǒng)的通過 Linux bridge 這樣的二層設(shè)備轉(zhuǎn)發(fā)不一樣,cilium 在每個(gè)容器相關(guān)聯(lián)的虛擬網(wǎng)卡上都附加了 bpf 程序,通過連接到 TC ( traffic control ) 入口鉤子的 bpf 程序?qū)⑺芯W(wǎng)絡(luò)流量路由到主機(jī)端虛擬設(shè)備上,由此 cilium 便可以監(jiān)視和執(zhí)行有關(guān)進(jìn)出節(jié)點(diǎn)的所有流量的策略,例如 pod 內(nèi)的 networkPolicy 、L7 policy、加密等規(guī)則。

# CA 容器內(nèi)的默認(rèn)路由指向 cilium_host 網(wǎng)關(guān)地址 10.244.1.208
root@voyager-client-8769496c4-ttzsj:/#  ip route
default via 10.244.1.208 dev eth0 mtu 1450
10.244.1.208 dev eth0 scope link

CA 容器內(nèi)的流量要跨宿主機(jī)節(jié)點(diǎn)路由到 CB 容器,則需要 cilium_vxlan VTEP 設(shè)備對(duì)流量包進(jìn)行封裝轉(zhuǎn)發(fā)到 Node02 上。bpf 程序會(huì)查詢 tunnel 規(guī)則并將流量發(fā)送給 cilium_vxlan,在 cilium agent 容器內(nèi)可查看到 bpf 的 tunnel 規(guī)則

[root@Node01 ~]# docker exec -it 7c0ce8909d21 bash
root@cilium-agent:~# cilium bpf tunnel list
TUNNEL         VALUE
10.244.3.0:0   192.168.66.196:0
10.244.2.0:0   192.168.66.194:0
10.244.6.0:0   192.168.66.221:0 # CB 容器 ip 為 10.244.6.11, tunnel 對(duì)端地址為 192.168.66.221,即為 Node02 主機(jī)節(jié)點(diǎn)地址

在 Node01 上對(duì) cilium_vxlan 抓包,可看到 CA 容器對(duì) icmp 包經(jīng)過了 cilium_vxlan

[root@Node01 ~]# tcpdump -i cilium_vxlan icmp -n -vv
tcpdump: listening on cilium_vxlan, link-type EN10MB (Ethernet), capture size 262144 bytes
15:54:23.550645 IP (tos 0x0, ttl 64, id 18157, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 497, seq 509, length 64
15:54:23.551123 IP (tos 0x0, ttl 64, id 12892, offset 0, flags [none], proto ICMP (1), length 84)
    10.244.6.11 > 10.244.1.154: ICMP echo reply, id 497, seq 509, length 64
15:54:24.574575 IP (tos 0x0, ttl 64, id 18805, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 497, seq 510, length 64
15:54:24.574999 IP (tos 0x0, ttl 64, id 13181, offset 0, flags [none], proto ICMP (1), length 84)
    10.244.6.11 > 10.244.1.154: ICMP echo reply, id 497, seq 510, length 64
15:54:25.598625 IP (tos 0x0, ttl 64, id 19388, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 497, seq 511, length 64
15:54:25.599107 IP (tos 0x0, ttl 64, id 13587, offset 0, flags [none], proto ICMP (1), length 84)

再對(duì) Node01 上的 eth0 抓包,可看到 cilium_vxlan 已將 CA 的流量進(jìn)行 vxlan 封包,src ip 改為本機(jī) node ip 192.168.66.226, dst ip 改為 192.168.66.221

[root@Node01 ~]# tcpdump -i eth0 -n dst 192.168.66.221 and udp -vv
17:48:38.398691 IP (tos 0x0, ttl 64, id 58330, offset 0, flags [none], proto UDP (17), length 134)
    192.168.66.226.60971 > 192.168.66.221.otv: [no cksum] OTV, flags [I] (0x08), overlay 0, instance 27634
IP (tos 0x0, ttl 64, id 35369, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 1878, length 64
17:48:39.422639 IP (tos 0x0, ttl 64, id 58509, offset 0, flags [none], proto UDP (17), length 134)
    192.168.66.226.60971 > 192.168.66.221.otv: [no cksum] OTV, flags [I] (0x08), overlay 0, instance 27634
IP (tos 0x0, ttl 64, id 36202, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 1879, length 64
17:48:40.446630 IP (tos 0x0, ttl 64, id 59226, offset 0, flags [none], proto UDP (17), length 134)
    192.168.66.226.60971 > 192.168.66.221.otv: [no cksum] OTV, flags [I] (0x08), overlay 0, instance 27634
IP (tos 0x0, ttl 64, id 37119, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 1880, length 64
17:48:41.470617 IP (tos 0x0, ttl 64, id 60174, offset 0, flags [none], proto UDP (17), length 134)
    192.168.66.226.60971 > 192.168.66.221.otv: [no cksum] OTV, flags [I] (0x08), overlay 0, instance 27634
IP (tos 0x0, ttl 64, id 37830, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 1881, length 64

到 Node02 上對(duì) eth0 抓包,可看到 CA 容器的流量包已到 Node02 上

[root@Node02 ~]# tcpdump -i eth0 -n src 192.168.66.226 and udp -vv
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
05:55:08.542658 IP (tos 0x0, ttl 64, id 52637, offset 0, flags [none], proto UDP (17), length 134)
    192.168.66.226.60971 > 192.168.66.221.otv: [no cksum] OTV, flags [I] (0x08), overlay 0, instance 27634
IP (tos 0x0, ttl 64, id 33378, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 2259, length 64
05:55:09.566806 IP (tos 0x0, ttl 64, id 52888, offset 0, flags [none], proto UDP (17), length 134)
    192.168.66.226.60971 > 192.168.66.221.otv: [no cksum] OTV, flags [I] (0x08), overlay 0, instance 27634
IP (tos 0x0, ttl 64, id 34260, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 2260, length 64
05:55:10.567877 IP (tos 0x0, ttl 64, id 53331, offset 0, flags [none], proto UDP (17), length 134)
    192.168.66.226.60971 > 192.168.66.221.otv: [no cksum] OTV, flags [I] (0x08), overlay 0, instance 27634
IP (tos 0x0, ttl 64, id 34318, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 2261, length 64
05:55:11.614841 IP (tos 0x0, ttl 64, id 54206, offset 0, flags [none], proto UDP (17), length 134)
    192.168.66.226.60971 > 192.168.66.221.otv: [no cksum] OTV, flags [I] (0x08), overlay 0, instance 27634
IP (tos 0x0, ttl 64, id 35300, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 2262, length 64

對(duì) cilium_vxlan 抓包即可看到 CA 容器過來對(duì)流量包已被解封

[root@Node02 ~]# tcpdump -i cilium_vxlan -n dst 10.244.6.11 -vv
tcpdump: listening on cilium_vxlan, link-type EN10MB (Ethernet), capture size 262144 bytes
05:59:22.494598 IP (tos 0x0, ttl 64, id 25390, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 2507, length 64
05:59:23.518736 IP (tos 0x0, ttl 64, id 26363, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 2508, length 64
05:59:24.542563 IP (tos 0x0, ttl 64, id 26951, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 2509, length 64
05:59:25.566736 IP (tos 0x0, ttl 64, id 27503, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 2510, length 64
05:59:26.590731 IP (tos 0x0, ttl 64, id 28392, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 2511, length 64
05:59:27.614648 IP (tos 0x0, ttl 64, id 28548, offset 0, flags [DF], proto ICMP (1), length 84)
    10.244.1.154 > 10.244.6.11: ICMP echo request, id 502, seq 2512, length 64

至此,CA 容器對(duì)流量已到達(dá) cilium 創(chuàng)建的虛擬網(wǎng)卡。

我們知道 Linux 內(nèi)核本質(zhì)上是事件驅(qū)動(dòng)的(the Linux Kernel is fundamentally event-driven), cilium 創(chuàng)建的虛擬網(wǎng)卡接收到流量包將會(huì)觸發(fā)連接到 TC ( traffic control ) ingress 鉤子的 bpf 程序,對(duì)流量包進(jìn)行相關(guān)策略對(duì)處理。

查看 cilium 官方給出的 ingress/egress datapath,可大致驗(yàn)證上述 cilium 的網(wǎng)絡(luò)通信路徑。

首先是 egress datapath,圖中橙黃色標(biāo)簽為 cilium component,有 cilium 在宿主機(jī)上創(chuàng)建的 bpf 程序(對(duì)應(yīng)著紅色標(biāo)簽的 kernel bpf 鉤子),若使用 L7 Policy 則還有 cilium 創(chuàng)建的 iptables 規(guī)則。流量從某個(gè)容器 endpoint 通過容器上的 veth pair 網(wǎng)卡 lxcxxx 出發(fā),即會(huì)觸發(fā) bpf_sockops.c / bpf_redir.c bpf 程序,若使用了 L7 Policy 則進(jìn)入用戶空間進(jìn)行 L7 層的數(shù)據(jù)處理,若沒有使能 L7 Policy 則將觸發(fā) TC egress 鉤子,bpf_lxc 對(duì)數(shù)據(jù)進(jìn)行處理(若使能 L3 加密,則觸發(fā)其他 bpf 鉤子),數(shù)據(jù)最終被路由到 cilium_host 網(wǎng)關(guān)處,再根據(jù) overlay 模式(vxlan 等)將數(shù)據(jù)發(fā)送出去。

image.png

在 cilium ingress datapath 中,數(shù)據(jù)流量進(jìn)入主機(jī)網(wǎng)絡(luò)設(shè)備上,cilium 可根據(jù)相關(guān)配置,對(duì)數(shù)據(jù)流量進(jìn)行預(yù)處理(prefilter/L3 加解密/ 負(fù)載均衡/ L7 Policy 處理)或直接路由到 cilium_host 觸發(fā)相應(yīng)到 bpf 程序,再到最終的 endpoint 處。

image.png

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容