前言

既然這個章節是介紹 Kubernetes Networking 那就先來複習一下之前看過的優質文章吧!

188. Prerequisite - Network Namespaces

list_link_as_ns

▲ 使用 ip netns exec <NAMESPACE> ip link 能以 <NAMESPACE> 的視角查看,或者更快的 ip -n <NAMESPACE> link

list_arp_table

▲ 使用 ip netns exec <NAMESPACE> arp 顯示 namespace 內的 arp table。

list_routuing_table

▲ 使用 ip netns exec <NAMESPACE> route 顯示 namespace 內的 routing table。

add_veth_pair

▲ (上面 ip addr add 漏掉 netmask 了) 這邊講師跟邱牛這篇 Docker 網路入門篇(二) - Bridge 網路模型 做的事情差不多,都是打造 veth pair,只不過邱牛是在 runtime == docker 下解釋,講師則是將 red, blue 這兩個 namespace 從 host OS 透過 ip link add 的方式加在原始路徑裡面。

P.S. 若要刪除 veth pair 的話只需要下達一次 ip -n <NAMESPACE> link del <veth_name> 即可。

veth_connect_to_linux_bridge

▲ 透過 ip link add v-net-0 type bridge && ip link set dev v-net-o up 產生的 bridge 可以把他想像成放在 host 的 virtual switch。

set_ip_to_linux_bridge

▲ 如果想從 host ping 到這四個 namespace 的話只需要將 linux bridge binding IP 即可 (讓 host 有 route table)。

add_gw_to_blue_ns

▲ 我們想從 blue 碰到 192.168.1.3 就必須在 blue namespace 裡面加給他 static route (建議直接用 default gateway) 不過還是沒辦法收到 ping reply (先暴雷,因為要請 host eth0 幫我們做 SNAT 「看到來自 192.168.15.0/24 的封包請幫我用 192.168.1.2 host eth0 的身分送出!」)

iptables_set_masquarade

▲ 如果謹慎一點應該要 iptables -t nat -I POSTROUTING -s 192.168.15.0/24 -i v-net-0 -o eth0 -j MASQUARADE 來限制 --in-interface--out-interface

191. Prerequisite - CNI

container_network_interface

▲ 既然各個 container runtime 都需要在 host 做這些必要事情,CNI 的誕生提供業界標準避免重複造輪。

who_using_cni

Who is using CNI 可以看到一些官方列出的 container runtime,以及第三方 plugins。
CNI 還有提供 library 可以自行開發屬於你自己的 CNI plugins~

cni_specific

▲ CNI 切了兩個責任區,上方是 container runtime 必須要負責的;下方則是 plugin,達成 any runtime should be able to work with any plugins.

2022.08.03 更新:

參加完 2022 COSCUP X KCD 之後 eBPF-based Container Networking#5 當中就有提到 CNI spec 基本要求次要支援目標

coscup2022_ebpf_cni_lin_sir

▲ 原來 IPAM, SNAT, Port mapping 都被歸類在次要目標。

cni_plugins

▲ CNI 自帶一些基本的 plugin,下方是第三方 plugin。延伸閱讀: [Hwchiu]常見 CNI (Container Network Interface) Plugin 介紹 而 docker 並不使用 CNI,而是自身的 CNM (container network model)

k8s_components_port

▲ K8s 各個元件需求的 port,如果是 multi-master 架構的話 etcd 需要額外開啟 2380/tcp 來同步。

官方有提供檢查表 Ports and Protocols

193. Important Note about CNI and CKA Exam

  • 在 LAB 當中考生將被要求安裝 Network Addons (包含 plugin)
  • plugin 將使用 weave-net 作為範例,當然考生可以自由選擇其他 solution
  • 實際考試除非題目指定要求,不然也是自由選擇。
  • 從上方提供的 自由選擇其他 solution 可以發現所有選項點進去都是其官方網站/GitHub,正式考試時只能看官方文件! 好哩加在,小飛機推薦的 CKA Bookmark 有包含官方文件安裝 Weave-net 的方式。 (後來查看,並沒有! 請自行新增 link,或者使用我的 Bookmark)

196. Pod Networking

pod_networking_model

▲ 這個章節主要介紹 pod 在跨 worker node 要怎麼互相碰到。

pod_networking_example_0

▲ 範例有三個 worker node,首先要先解決同 worker node 內互連的問題: (1) 建立一個 bridge (2) veth pair 接上 bridge <=> container (3) 為 bridge 與 container 設定 IP。

pod_networking_example_1

▲ 想從 bluepod 去找位在 node2 的 purple pod 10.244.2.2,卻發現 ping 不到,原因是沒有路由。手動增加一筆靜態路由 (非永久) ip route add 10.244.2.2/32 via 192.168.1.12 請 node1 的 eth0 幫我們送件~

eth0 收到之後會向 L2 domain 發送 broadcast 「誰有 10.244.2.2 呀,請給我他的 MAC address 謝謝」

two_node_ping_bridge_arp

▲ 實際做一次實驗 Eric_minikube 192.168.199.62 eth0 收到 arp broadcast 之後就單獨回覆 (unicast) 192.168.199.63 說 「我有,挖來出力!」
因為該 network 是本身就有的,無論是否開啟 net.ipv4.ip_forward =1 都能送達。

pod_networking_example_2

▲ 接著在每一個 worker node 都加上一筆 static route。

pod_networking_example_3

實際上不會這樣一筆一筆加,太麻煩了。直接給整個網段一個 gateway 就好!

pod_networking_example_4

kubelet 會從 --cni-conf-dir 找到設定的 .json 然後 pass 給 --cni-bin-dir 執行,創造屬於該 container 的 network namespace。

197. CNI in kubernetes

kubelet_networking_0

--cni-bin-dir 下面有可供使用的 plugin binary file。

kubelet_networking_1

isGateway 代表是否要給 bridge binding 一個 IP address,好讓它變成 gateway 的角色;ipMasq 是否要在 host 針對這個 network 做 NAT。詳細 Container Network Interface (CNI) Specification

198. CNI weave

waeve_cni_0

▲ Weave (CNI) 運作的方式就是在各個 worker node 部屬一個 agent,每個 agent 會告知彼此身上有哪些路由 (聽起來有點像 BGP),並且重新封裝 (encapsulation) 把原始封包變成它的 payload

waeve_cni_1

不管 CNI 為何,container 內的 routing table 都必須存在。

Understanding Weave Net

waeve_peer_network

  • Weave Network 各個節點稱做 peer。
  • 每個 peer 都會自己的名子 (預設是 MAC address) 方便人類辨識,即使 restart 也會保留唯一會改變的是 UID
  • Weave 透過 TCP 連線來執行交握 (perform a protocol handshake) 並且 交換網路拓譜 (topology),通訊過程是可以被設定加密的。
  • Weave 透過 UDP 「連線」來傳輸 payload (來自 container 的原始封包),全雙工而且穿透防火牆
  • Weave 會建立 network bridge 在各個 worker node 身上,並且有 IPAM 功能。
  • Weave 傳輸封包的方式有兩種: (1) fast data path 完全在 kernel space 處理 packet。 (2) sleeve mode,封包目的若是 non-local container 的話會被 kernel 捕捉,並且交由位於 user space 的 Weave Net router 處理。

waeve_cni_2

▲ Deploy Weave via kubectl

waeve_cni_3

▲ 如果安裝方式是 kubeadm 的話可以使用 kubectl logs weave-net -n kube-system -c weave 來查詢 log (通常用於 debug)

199. Practice Test - Explore CNI Weave

Q: kubelet 使用何種 CNI Plugin ?
A: ps -aux | grep 'kubelet' | grep -i 'network'

Q: CNI plugin binary 在哪裡 ?
A: ps -aux | grep 'kubelet' | grep -i 'cni' 沒有找到 --cni-bin-dir => 預設在 /opt/cni/bin 底下。

Q: 有哪些 CNI binary 可以使用 ?
A: ls -al /opt/cni/bin

Q: 哪一個 CNI plugin config 被使用 ?
A: ll /etc/cni/net.d/

Q: 該 config 預設使用哪個 bin file ?
A: less /etc/cni/net.d/10-flannel.conflisttype 欄位。

(可能要背喔!) 201. Practice Test - Deploy Network Solution

若要更改 Weave 預設使用的 IP 範圍必須使用 kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')&env.IPALLOC_RANGE=10.50.0.0/16"

若考試沒有給 Weave Config 的選項的話 &env.IPALLOC_RANGE= 必須背起來!!
若考試沒有給 Weave Config 的選項的話 &env.IPALLOC_RANGE= 必須背起來!!
若考試沒有給 Weave Config 的選項的話 &env.IPALLOC_RANGE= 必須背起來!!

203. IP Address Management - Weave

cni_ipam

▲ CNI plugin 自帶 DHCP 與 host-local 兩種 IPAM type,host-local 就是將 IP 使用狀態存在一個 file@local。延伸閱讀: [HWchiu Day13] 初探 CNI 的 IP 分配問題 (IPAM)

206. Service Networking

上面幾個章節都是在介紹 pod networking,這個章節要介紹的是 service networking。

service_networking_0

kubelet 會去詢問 api-server 有沒有新任務;kube-proxy 也一樣只不過他的任務是詢問是否有 service 被建立。

先前我們在 CKA_Note_Section_2_Core_Concepts#18. Kube Proxy 就有提到 service 並不實體存在 worker node 身上,他只是一個紀錄 service 資訊的地方。
以 ClusterIP type 的 service 為例,當 service 被建立時會拿到一個 IP (含 port number),其 IP address range 被設定在 api-server config。同時在 worker node 上面建立 routing rule。

service_networking_1

kube-proxy 可以透過 userspace, iptables (預設), ipvs 來建立 routing rules。

service_networking_2

service IP address range 被設定在 api-server

service_networking_3

iptables 規則就會被 kube-proxy 增加一條 「所有要去 (dst) 10.103.132.104 3306/TCP packet 全部 DNAT 去 10.244.1.2 3306/TCP,也就是 pod 的 IP address」

service_networking_4

kube-proxy 的變動可以在 /var/log/kube-proxy.log 底下查看。

service_networking_5

▲ 如果是 kubeadm 安裝的話可以 透過 kubectl logs -n kube-system kube-proxy 查看

209. DNS in kubernetes

這個章節會講到:

  • 哪些元件會被分配到 DNS domain name
  • service DNS record
  • pod DNS record

dns_in_k8s

▲ FQDN 就是 Hostname + Namespace + Type + Root Domain 串在一起。 其中 pod create 時並不會自動被產生 DNS record 除非另外設定。

註: 同一個 Namespace 可以透過 Hostname 碰到彼此,不需要完整 FQDN。

210. CoreDNS in Kubernetes

coredns_in_k8s_0

▲ CoreDNS 被以 Deployment 的形式部屬。

coredns_configmap

▲ CoreDNS (kube-dns) 需要一個 “Corefile” 的設定檔,通常會被弄成 configMaps。更多資訊: CoreDNS ConfigMap options

coredns_in_k8s_1

▲ 橘字的部分被稱為 plugin,kubernetes 就是其中一個! cluster.local 設定前面提到的 Root domain 為何。

我聽不懂講師講的 pod insecure 到底在幹嘛,所以就自己去翻書 (CoreDNS-Kubernetes) 了~

pods 主要設定該怎麼處裡 IP-based 的 A record,舉例: 1-2-3-4.ns.pod.cluster.local => A 1.2.3.4
這關係到使用 HTTPS (會用到 TLS cert) 直接與 pod 通訊的安全性

  • disable: 預設選項,直接不處理、直接回 NXDOMAIN 「沒有這個人啦!」。這也是為什麼前面提到 「pod create 時並不會自動被產生 DNS record 除非另外設定」的原因,設定就在這裡。
  • insecre: 不向 K8s 檢查 pod 是否存在,直接回對應的 A record。
  • verified: 先向 K8s 詢問確認有這個 pod 存在後才回復對映 A record,不過這會使用更高的記憶體。

coredns_in_k8s_2

kubelet 負責設定 pod 使用的 DNS server 為何,使用者不必自己手動加入。

coredns_in_k8s_3

▲ 在 /etc/resolv.conf 當中定義 search,使得我們直接打 dig web-service 可能找到正確的 FQDN。

coredns_in_k8s_4

不過僅限 service (原因就是在 /etc/resolv.conf search 裡面沒有 pod 呀!)

213. Ingress

請參考 CKAD Note Section 7 Service and Networking#94. Ingress Networking