概述
Cilium v1.14.4 默认安装不会设置 kubeProxyReplacement
参数,默认情况下只会开启 ClusterIP,也就是可以部分支持 Service 的功能,如果还需要 NodePort 功能,还需要单独设置。
1
2
3
4
5
6
7
8
9
10
|
# helm get values cilium
USER-SUPPLIED VALUES:
cni:
chainingMode: generic-veth
configMap: cni-configuration
customConf: true
enableIPv4Masquerade: false
k8sServiceHost: 192.168.1.200
k8sServicePort: 6443
routingMode: native
|
本文主要分析 Cilium 是如何实现 ClusterIP 功能,以及分析 Flannel 结合 cilium-chain 下,ClusterIP 是如何于其他 CNI 合作。
配置信息
查看 cilium-agent 内部的一些信息(省略了跟Service无关的部分)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
# cilium status --verbose
Kubernetes: Ok 1.20 (v1.20.3) [linux/amd64]
KubeProxyReplacement: False
CNI Chaining: generic-veth
Cilium: Ok 1.14.4 (v1.14.4-87dd2b64)
IPAM: IPv4: 1/254 allocated from 10.0.2.0/24,
KubeProxyReplacement Details:
Status: False
Socket LB: Disabled
Socket LB Tracing: Disabled
Socket LB Coverage: Full
Session Affinity: Disabled
Graceful Termination: Enabled
NAT46/64 Support: Disabled
Services:
- ClusterIP: Enabled
- NodePort: Disabled
- LoadBalancer: Disabled
- externalIPs: Disabled
- HostPort: Disabled
BPF Maps: dynamic sizing: on (ratio: 0.002500)
Name Size
Auth 524288
Non-TCP connection tracking 65536
TCP connection tracking 131072
Endpoint policy 65535
IP cache 512000
IPv4 masquerading agent 16384
IPv6 masquerading agent 16384
IPv4 fragmentation 8192
IPv4 service 65536
IPv6 service 65536
IPv4 service backend 65536
IPv6 service backend 65536
IPv4 service reverse NAT 65536
IPv6 service reverse NAT 65536
Metrics 1024
NAT 131072
Neighbor table 131072
Global policy 16384
Session affinity 65536
Sock reverse NAT 65536
Tunnel 65536
|
代码框架
cilium-agent 会 watch Kubernetes 关于 Service/Endpoint/EndpointSlice 等资源,然后根据这些资源的变化,对 eBPF 的 Service LB 的 Map 做 CRUD。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
d.k8sWatcher.RunK8sServiceHandler() //daemon/cmd/daemon.go
|-k8s.UpdateService //pkg/k8s/watchers/watcher.go
|-K8sWatcher.addK8sSVCs //pkg/k8s/watchers/watcher.go
|-k.svcManager.UpsertService(p) //pkg/k8s/watchers/watcher.go
|-s.upsertService(params) //pkg/service/service.go
|-s.upsertServiceIntoLBMaps //pkg/service/service.go
|-s.lbmap.AddBackend //pkg/service/service.go
|-LBBPFMap.AddBackend //pkg/maps/lbmap/lbmap.go
|-updateBackend //pkg/maps/lbmap/lbmap.go
|-backend.Map().OpenOrCreate() //pkg/maps/lbmap/lbmap.go
|-s.lbmap.UpsertService(p) //pkg/service/service.go
|-upsertServiceProto //pkg/maps/lbmap/lbmap.go
|-LBBPFMap.UpsertService //pkg/maps/lbmap/lbmap.go
|-updateServiceEndpoint //pkg/maps/lbmap/lbmap.go
|-Update //pkg/bpf/map_linux.go
|- Update //vendor/github.com/cilium/ebpf/map.go
|- MapUpdateElem
|- BPF(cmd Cmd, attr unsafe.Pointer, size uintptr)
|- unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size) //系统调用
|
Service IP到Pod IP
这里的 Pod IP 是指 Service 关联的 Endpoint,也可以理解成是 Service 的后端 Pod IP。
测试案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: kube-system
name: nm-test
spec:
selector:
matchLabels:
app: nm-test
template:
metadata:
labels:
app: nm-test
spec:
nodeSelector:
kubernetes.io/os: linux
os-type: openeuler
kubernetes.io/hostname: 10.189.212.124
containers:
- name: nm-test
image: runzhliu/network-multitool:latest
command: ["/bin/bash", "-c", "sleep infinity"]
securityContext:
privileged: true
EOF
|
可用范围
从上面的分析可以知道,Cilium 之所以声称可以完全的 kube-proxy free,是因为 cilium-agent 在节点层面上,维护了一个 lbMap 的结构,这个结构会将 Service 的 ClusterIP 和后端的 Endpoint 的 IP 完成映射,并且一直会 watch 整个集群内部的 Service 等相关的资源的变化情况。
因此在没有部署 cilium-agent 的节点上,也包括 Kubernetes 集群外,Service 的 ClusterIP 是无法使用的,因为节点上没有相关的 lbMap 结构来完成 Service IP 到 Endpoint 的映射。
另外关于一些开源组件的 webhook 等应用,在当前我们的 Kubernetes 架构上也无法直接使用,本质原因是我们集群的 kube-apiserver 是独立部署,而不是用静态 Pod 这些形式搭建的,也就是说 kube-apiserver 的节点上,同样是没有 cilium-agent,因此如果需要使用 webhook 等功能,还是需要像之前的集群那样,通过注册 VGW 等形式曲线实现。
总结
cilium-chain 的 ClusterIP 的实现跟 Cilium 本身的没有本质的区别,区别主要是在于后端绑定的 Pod IP 是 cilium-chain 的主网卡还是 Cilium 自行创建的。
参考资料
- Cilium相关命令解读
警告
本文最后更新于 2023年11月12日,文中内容可能已过时,请谨慎参考。