如何通过命令行创建一个Pod?
摘要:介绍 这篇文章主要涉及到 kubelet 通过 csi 向运行时发送创建请求,运行时发生了什么?pod 网络又是怎么连通的? 对应的流量图 我们将使用 docker 和 linux Bridge 去完成这个 pod 需求 流程描述 kube
介绍
这篇文章主要涉及到 kubelet 通过 csi 向运行时发送创建请求,运行时发生了什么?pod 网络又是怎么连通的?
对应的流量图
我们将使用 docker 和 linux Bridge 去完成这个 pod 需求
流程描述
kubelet 通过 CRI 接口调用运行时(如 containerd)创建 pod。该过程分为两步:
创建 Pod Sandbox:运行时先启动一个轻量的 pause 容器。其核心作用是调用 runc 创建并持有一个独立的 Linux Network Namespace,为 Pod 提供网络沙盒环境。
创建业务容器:运行时随后创建业务容器(如 Nginx),并通过指定 network namespace 路径,使其直接加入 pause 容器所在的 Network Namespace,从而实现网络共享。
Pod 沙盒就绪后,运行时调用 CNI 插件配置网络。插件执行如下操作:
创建 veth pair,一端放入容器命名空间内(命名为 eth0),另一端连接至主机网桥(如 br0)
为容器内的 eth0 分配 IP 并设置路由,网关指向网桥。
配置主机 iptables 规则,实现 SNAT 以使 Pod 能访问外部网络,并设置转发规则。
实际操作
创建网桥
这个网桥充当虚拟交换机,所有 pod 流量都通过该设备传递到物理网卡
# 增加一个网卡设备
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 插件)
我们将手动模拟 CNI(bridge)插件的工作:创建 veth pair,连接容器和网桥,分配 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
为了让流量能进出 Pod,我们需要配置内核转发和 iptables 规则。
