目录

cilium-chain和ClusterIP

概述

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
// bpf/bpf_lxc.c

测试案例

 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%E5%92%8Cclusterip/img.png

总结

cilium-chain 的 ClusterIP 的实现跟 Cilium 本身没有本质的区别,区别主要是在于后端绑定的 Pod IP 是 cilium-chain 的主网卡还是 Cilium 自行创建的。

参考资料

  1. Cilium相关命令解读
警告
本文最后更新于 2023年11月12日,文中内容可能已过时,请谨慎参考。