通過(guo)命令模擬pod創(chuang)建
介紹
這篇文章主要(yao)涉及到 kubelet 通(tong)過 csi 向運(yun)行時發(fa)送創建(jian)請求,運(yun)行時發(fa)生了什么?pod 網(wang)絡(luo)又(you)是(shi)怎(zen)么連通(tong)的(de)?
對應的流量圖

我們將使用 docker 和(he) linux Bridge 去完成這(zhe)個 pod 需求(qiu)
流程描述
kubelet 通(tong)過 CRI 接口調(diao)用運行時(如 containerd)創建(jian) pod。該過程分為(wei)兩步:
- 創建 Pod Sandbox:運行時先啟動一個輕量的 pause 容器。其核心作用是調用 runc 創建并持有一個獨立的 Linux Network Namespace,為 Pod 提供網絡沙盒環境。
- 創建業務容器:運行時隨后創建業務容器(如 Nginx),并通過指定 network namespace 路徑,使其直接加入 pause 容器所在的 Network Namespace,從而實現網絡共享。
Pod 沙盒就緒后(hou),運(yun)行時調用 CNI 插件(jian)配(pei)置(zhi)網絡。插件(jian)執行如(ru)下操作:
- 創建 veth pair,一端放入容器命名空間內(命名為 eth0),另一端連接至主機網橋(如 br0)
- 為容器內的 eth0 分配 IP 并設置路由,網關指向網橋。
- 配置主機 iptables 規則,實現 SNAT 以使 Pod 能訪問外部網絡,并設置轉發規則。
實際操作
創建網橋
這個網橋充當虛擬交換(huan)機,所有 pod 流量都通過該設備傳遞到物理網卡(ka)
# 增加一個網卡設備
ip link add name br0 type bridge
# 向網卡設備添加地址
ip addr add 10.0.0.1/24 dev br0
# 設置網卡啟動
ip link set dev br0 up
# 驗證
ip a
啟動 pod 外殼并劫持網絡空間
# 創建pod外殼容器
docker run -itd --name my-pod --network=none docker.1ms.run/rancher/mirrored-pause:3.9
# 劫持容器網絡命名空間
mkdir -p /var/run/netns
ln -sf /var/run/docker/netns/ce39ddc16db1 /var/run/netns/my-pod
# 驗證
ip netns

配置 pod 網絡(模擬 CNI 插件)
我們將(jiang)手(shou)動模(mo)擬 CNI(bridge)插件的工作:創建 veth pair,連接(jie)容器和網橋,分配 IP,設置路由
# 創建一對虛擬以太網設備(veth pair)
# veth-pod:將留在主機默認命名空間的一端
# veth-cont:將留在容器命名空間的一端
ip link add veth-pod type veth peer name veth-cont
# 將veth-cont 放到容器命名空間內部
ip link set veth-cont netns my-pod
# 重命名veth-cont,將其改成符合容器的標準名稱eth0
ip netns exec my-pod ip link set veth-cont name eth0
# 啟動容器內命名空間網卡
ip netns exec my-pod ip link set eth0 up
# 為容器命名空間內的網卡配置地址要和剛才網關網卡地址一致
ip netns exec my-pod ip addr add 10.0.0.2/24 dev eth0
# 添加到網關的路由
ip netns exec my-pod ip route add default via 10.0.0.1
# 給外面這一端網卡綁定master
ip link set veth-pod master br0
# 啟動外面這一端網卡
ip link set veth-pod up
# 驗證容器網絡命名空間內網絡環境
ip netns exec my-pod ip addr show
ip netns exec my-pod route -n
ip netns exec my-pod ping 10.0.0.1

創建業務容器
docker run -itd --name nginx-pod --network container:my-pod nginx:alpine
配置主機網絡和 iptables 模擬 kubeporxy
為了讓流量能(neng)進出 Pod,我(wo)們需(xu)要配置內核轉發和 iptables 規則。
# 開啟內核轉發功能
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
# 配置SNAT
# 解析:
# 10.244.1.0/24(Pod網段),且要從主機的物理網卡(假設是eth0)出去的流量,將其源IP偽裝成主機自己的IP。
# 這樣,外部網絡回包時才知道送回給哪個主機
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
# 添加一條 iptables DNAT 規則,將端口轉發到業務網絡命名空間內
# -t nat: 操作 nat 表
# -A PREROUTING: 在數據包剛到達時就進行規則判斷
# -p tcp --dport 30080: 匹配協議為 TCP,且目標端口是 30080 的流量
# -j DNAT: 進行目標地址轉換(DNAT)
# --to-destination 10.0.0.2:80: 將目標地址改為 Pod 的 IP 和端口
iptables -t nat -D PREROUTING -p tcp --dport 30080 -j DNAT --to-destination 10.0.0.2:80
iptables -t nat -D OUTPUT -d 127.0.0.1/32 -p tcp --dport 30080 -j DNAT --to-destination 10.0.0.2:80
iptables -t nat -I PREROUTING 1 -p tcp --dport 30080 -j DNAT --to-destination 10.0.0.2:80
iptables -t nat -I OUTPUT 1 -p tcp --dport 30080 -j DNAT --to-destination 10.0.0.2:80
# 驗證規則
iptables -t nat -L POSTROUTING -n -v
# 驗證訪問
curl -v //192.168.1.114:30080


清理環境
# 刪除容器
docker stop 4728aeef69f8
docker stop 3041747824eb
docker rm 3041747824eb
docker rm 4728aeef69f8
重啟主機
重啟后(hou)所有規則默認刪除
