Kubernetes - CNI
网络分类
Type | Desc |
---|---|
CNI |
Pod 到 Pod 的网络,Node 到 Pod 的网络 |
kube-proxy |
通过 Service 访问 |
Ingress |
入站 流量 |
基础原则
- 所有
Pod
能够不通过NAT
就能互相访问 - 所有
Node
能够不通过NAT
就能互相访问 - 容器内看到的 IP 地址和外部组件看到的
容器 IP
是一样的
补充说明
- 在 Kubernetes 集群,
IP 地址
是以Pod
为单位进行分配的,每个 Pod 拥有一个独立的 IP 地址 - 一个 Pod 内部的
所有容器
共享一个网络栈
,即宿主上的一个Network Namespace
- Pod 内的
所有容器
能够通过localhost:port
来连接对方 - 在 Kubernetes 中,提供一个
轻量
的通用
容器网络接口CNI
Container Network Interface
,用来设置和删除容器的网络连通性
Container Runtime
通过CNI
调用网络插件
来完成容器的网络设置
插件分类
下面的 Plugin 均由
ContainerNetworking
组维护
IPAM -> Main -> Meta
IPAM
- IP address allocation - 解决IP 分配
的问题
Plugin | Value |
---|---|
dhcp |
Runs a daemon on the host to make DHCP requests on behalf of the container |
host-local |
Maintains a local database of allocated IPs |
static |
Allocate a single static IPv4/IPv6 address to container |
Main
- interface-creating - 解决网络互通
的问题
容器
和主机
的互通同一主机
的容器互通跨主机
的容器互通 -CNI
在原先容器网络的基础上的新增能力
Plugin | Desc |
---|---|
bridge |
Creates a bridge, adds the host and the container to it |
ipvlan |
Adds an ipvlan interface in the container |
loopback |
Set the state of loopback interface to up |
macvlan |
Creates a new MAC address, forwards all traffic to that to the container |
ptp |
Creates a veth pair |
vlan |
Allocates a vlan device |
host-device |
Move an already-existing device into a container |
dummy |
Creates a new Dummy device in the container |
Meta - other plugins
Plugin | Desc |
---|---|
tuning |
Tweaks sysctl parameters of an existing interface |
portmap |
An iptables-based portmapping plugin. Maps ports from the host’s address space to the container |
bandwidth |
Allows bandwidth-limiting through use of traffic control tbf (ingress/egress) |
sbr |
A plugin that configures source based routing for an interface (from which it is chained) |
firewall |
A firewall plugin which uses iptables or firewalld to add rules to allow traffic to/from the container |
运行机制
Container Runtime
在启动
时从CNI
的配置目录读取JSON
格式的配置文件(多个文件,按字典序
选择第 1 个)
1 CNI + N CSI
关于容器网络管理,
Container Runtime
一般需要配置两个参数:--cni-bin-dir
和--cni-conf-dir
特殊情况:使用
kubelet
内置的Dockershim
作为Container Runtime
时
由kubelet
来查找CNI
插件,运行插件为容器设置网络,因此这两个参数应该设置为kubelet
Key | Value | Parameters |
---|---|---|
配置文件 | /etc/cni/net.d |
--cni-conf-dir |
可执行文件 | /opt/cni/bin |
--cni-bin-dir |
配置文件
1 | $ ll /etc/cni/net.d |
ipam
- calico-ipammain
- calicometa
- bandwidth + portmap
1 | { |
编译好的
可执行
文件 - Kubernetes调用 CNI 插件
,本质上是运行本地的可执行文件
1 | $ ll /opt/cni/bin |
设计考量
- Container Runtime 必须在
调用任何 CNI 插件之前
为容器创建一个新的Network Namespace
Network Namespace
挂在SandBox
- Container Runtime 执行
RunPodSandBox
后,才去调用 CNI 插件
- Container Runtime 必须要决定
容器
属于哪些网络
,针对每个网络,哪些插件
必须要执行 - Container Runtime 必须加载
配置文件
,并确定设置网络
时哪些插件
必须被执行 - 网络配置采用
JSON
格式 - Container Runtime 必须按
顺序执行
配置文件里相应的插件
- 在完成
容器生命周期
后,Container Runtime 必须按照与执行添加容器相反的顺序
执行CNI 插件
- 为了将容器与网络
断开连接
- 为了将容器与网络
- Container Runtime 被
同一容器
调用时不能并行
操作,但被不同容器
调用时,允许并行
操作 - Container Runtime 针对
一个容器
必须按顺序
执行ADD
和DEL
操作- ADD 对应 Container Runtime 的
SetUpPodNetwork
,CNI 的AddNetwork
- ADD 后总是跟着相应的 DEL
- DEL 可能跟着额外的 DEL,CNI 插件应该允许处理多个 DEL
- ADD 对应 Container Runtime 的
容器
必须由ContainerID
来唯一标识- 需要
存储状态
的插件需要使用网络名称
、容器 ID
、网络接口
组成的主 Key
来索引
- 需要
- Container Runtime 针对
同一网络
、同一容器
、同一网络接口
,不能连续调用两次
ADD 命令1 ADD + N DEL
Container Runtime 通过
环境变量
的方式,将参数传递给 calico 的二进制可执行文件
主机网络
- Kubernetes 需要
标准的 CNI 插件
,最低版本为 0.2.0 - 网络插件除了支持设置和清理
Pod
的网络接口外,还需要支持iptables
- 如果
kube-proxy
工作在iptables
模式,网络插件需要确保容器流量
能使用iptables
转发 - 如果网络插件将容器连接到
Linux 网桥
,需要将net.bridge.bridge-nf-call-iptables
设置为 1- Linux 网桥上的数据包将
遍历 iptables 规则
- Linux 网桥上的数据包将
- 如果网络插件不使用 Linux 网桥,应确保容器流量被正确设置了
路由
- 如果
数据链路
- Container Runtime 调用
CNI 插件
配置网络(chain: ipam -> main -> meta
) - Container Runtime 将配置结果返回给
kubelet
kubelet
将相关信息上报给API Server
,此时通过get po -owide
就能查看到对应的Pod IP
信息
跨主机互通
跨主机互通
的 2 种方式
Tunnel 模式
- 封包解包:
IPinIP
(IP +IP
) /VXLAN
(IP +UDP
)
- 封包解包:
动态路由
- Node 之间
交换路由信息
,最终 Node A 会知道 Node B 的路由信息,相当于有一个全景地图
- Node 之间
Plugin
Flannel / Weave / Calico / Cilium,其中
Calico
和Cilium
是完整
的解决方案
Flannel
基于
Tunnel
实现,封包解包的性能开销
大致为10%
Flannel 本身
没有完备的生态
(如对NetworkPolicy
的支持)
- Flannel 由 CoreOS 开发,是 CNI 插件的早期入门产品,
简单易用
- Flannel 使用 Kubernetes 集群
现有的 etcd 集群
来存储其状态信息
- 不需要提供专用的数据存储,只需要在每个
Node
上运行flanneld
守护进程(DaemonSet
)
- 不需要提供专用的数据存储,只需要在每个
- 每个
Node
都被分配一个子网
,为该 Node 上的Pod
分配 IP 地址 同一 Node
内的 Pod 可以使用网桥
进行通信- 而
不同 Node
上的 Pod 将通过flanneld
将其流量封装在UDP
包中并路由
到目的地 -VXLAN
- 而
- 封装方式使用
VXLAN
- 优点 -
性能良好
- 缺点 -
流量难以跟踪
- 优点 -
Calico
概述
性能
更佳 +功能
更全(网络策略
)
- 对于
同网段
通信,基于3 层
,Calico 使用BGP 路由协议
在Node
之间路由
数据包BGP
- 数据包在 Node 之间移动不需要包装在额外的封装层
- 对于
跨网段
通信,基于IPinIP
使用虚拟网卡设备tunl0
- 用一个 IP 数据包封装另一个 IP 数据包
外层 IP 数据包头
的源地址
为隧道入口设备
的 IP 地址,目标地址
为隧道出口设备
的 IP 地址
网络策略
- Calico 最受欢迎的功能之一- 使用
ACLs
和kube-proxy
来创建iptables
过滤规则,从而实现隔离容器网络
的目的
- 使用
- Calico 可以与
Istio
集成- 在
Service Mesh
层和网络基础结构
层上解释和实施集群中工作负载的策略 - 即:可以配置
功能强大的规则
来描述Pod
应该如何发送和接收流量
,提高安全性
和加强对网络环境的控制
- 在
- Calico 是
完全分布式
的横向扩展
结构,可以快速和平稳地扩展部署规模
社区提供的是
通用
方案,Pod 网络不强绑定
底层基础网络,在底层基础网络默认是没法为 Pod 网络路由
felix agent - 配置网络
BIRD
agent -BGP
Daemon
初始化
CNI 二进制文件和配置文件是
由 initContainer 从容器拷贝到主机上
1 | $ k get ds -A |
DaemonSet -
k get ds -n calico-system calico-node -oyaml
CALICO_NETWORKING_BACKEND
- 当前运行在bird
模式
The BIRD project aims to develop a fully functional
dynamic IP routing
daemon primarily targeted on (but not limited to) Linux, FreeBSD and other UNIX-like systems and distributed under the GNU General Public License.
BIRD
是一个开源的BGP Deamon
,不同的 IDC 之间可以通过 BGP交换路由信息
1 | apiVersion: apps/v1 |
initContainers - 将
Calico
的文件(10-calico.conflist)拷贝到主机
上的 CNI 目录(/etc/cni/net.d)
然后 Container Runtime 就能读到 CNI 插件对应的文件
即 CRI 使用 CNI 的可执行文件和配置文件,那 CNI 的某个 initContainer 先将这些文件拷贝到主机上
VXLAN
封包解包
类似与 Flannel 的
flannelId
1 | $ ip a |
CRD
1 | $ k get crd |
IPPool
定义一个集群的预定义 IP 段
1 | $ k get ippools.projectcalico.org |
ipipMode: Never
- 没有开启IPinIP
blockSize: 26
- 每个Node
可以分配多大的 IP 段2^(26-16) ≈ 1024
个Node
,每个 Node 上可分配2^(32 - 26) ≈ 64
个IP
1 | apiVersion: projectcalico.org/v3 |
IPAMBlock
定义每个 Node 预分配的 IP 段
1 | $ k get ipamblocks.crd.projectcalico.org |
1 | apiVersion: crd.projectcalico.org/v1 |
IPAMHandle
记录 IP 分配的具体细节
1 | $ k run --image=nginx nginx |
1 | apiVersion: crd.projectcalico.org/v1 |
新增记录
1 | apiVersion: v1 |
网络连通
1 | apiVersion: apps/v1 |
1 | $ k apply -f centos.yaml |
容器内执行,数据包会到 Mac 地址
EE:EE:EE:EE:EE:EE
1 | $ k exec -it centos-67dd9d8678-bxxdv -- bash |
宿主上 veth 对应的 Mac 地址也为
ee:ee:ee:ee:ee:ee
宿主上发现
192.168.185.16
对应的是本机上的calic440f455693
veth
1 | $ ip a |
进入另一个 Pod 确认
1 | $ sudo crictl ps |
sudo crictl inspect 7d6ad449ae76b
1 | { |
1 | $ sudo nsenter -t 106728 -n ip a |
跨主机路由
IDC -> Node
- 每个
Node
会运行一个bird
Deamon - 不同的 Node 上的 bird 会保持一个
长连接
,然后交换路由信息
(将 Node 模拟成一个路由器
)
对比
生产:
Calico
/Cilium
网络策略 | IPV6 | 网络层级 | 部署方式 | 命令行 | |
---|---|---|---|---|---|
Flannel | N | N | L2 - VXLAN |
DaemonSet |
|
Weave | Y | Y | L2 - VXLAN | DaemonSet | |
Calico |
Y |
Y | L3 - IPinIP / VXLAN / BGP |
DaemonSet |
calicoctl |
Cilium |
Y | Y | L3/L4 + L7(filtering) | DaemonSet | cilium |