目录

cilium-chain和物理网卡

概述

查看 Cilium 是什么情况下,会给物理网卡绑定 eBPF 程序,下面以 v1.14.4 的代码进行源码的解析。

代码分析

只要不开启以下的特性,Cilium 就不会将 eBPF 程序挂载到物理网卡上。

  1. EnableNodePort
  2. EnableHostFirewall
  3. EnableBandwidthManager
  4. EnableWireguard
  5. EnableHighScaleIPcache
  6. EnableL2Announcements
1
2
3
4
5
6
7
// pkg/option/config.go 
// AreDevicesRequired returns true if the agent needs to attach to the native
// devices to implement some features.
func (c *DaemonConfig) AreDevicesRequired() bool {
	return c.EnableNodePort || c.EnableHostFirewall || c.EnableBandwidthManager ||
		c.EnableWireguard || c.EnableHighScaleIPcache || c.EnableL2Announcements
}

Loader.reloadHostDatapath 这个方法会负责根据不同情况,对物理网卡进行 eBPF 程序的附着,下面的代码省略了关于 cilium_host 和 cilium_net 的部分。

 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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// pkg/datapath/loader/loader.go
// reloadHostDatapath (re)attaches BPF programs to:
// - native devices: ingress and (optionally) egress if certain features require it
func (l *Loader) reloadHostDatapath(ctx context.Context, ep datapath.Endpoint, objPath string) error {
    ...

	// Replace programs on physical devices.
	for _, device := range option.Config.GetDevices() {
		if _, err := netlink.LinkByName(device); err != nil {
			log.WithError(err).WithField("device", device).Warn("Link does not exist")
			continue
		}

		netdevObjPath := path.Join(ep.StateDir(), hostEndpointNetdevPrefix+device+".o")
		if err := patchHostNetdevDatapath(ep, objPath, netdevObjPath, device,
			node.GetMasqIPv4AddrsWithDevices(), node.GetMasqIPv6AddrsWithDevices()); err != nil {
			return err
		}

		progs := []progDefinition{
			{progName: symbolFromHostNetdevEp, direction: dirIngress},
		}

		// 这里就是上面提到的,如果不开启某些特性,宿主机网卡是不会加载eBPF程序的
		if option.Config.AreDevicesRequired() &&
			// Attaching bpf_host to cilium_wg0 is required for encrypting KPR
			// traffic. Only ingress prog (aka "from-netdev") is needed to handle
			// the rev-NAT xlations.
			device != wgTypes.IfaceName {

			progs = append(progs, progDefinition{symbolToHostNetdevEp, dirEgress})
		} else {
			// Remove any previously attached device from egress path if BPF
			// NodePort and host firewall are disabled.
			err := RemoveTCFilters(device, netlink.HANDLE_MIN_EGRESS)
			if err != nil {
				log.WithField("device", device).Error(err)
			}
		}

		// replaceDatapath本质上是调用tc在宿主机上进行eBPF的程序的加载和卸载
		finalize, err := replaceDatapath(ctx, device, netdevObjPath, progs, "")
		if err != nil {
			scopedLog := ep.Logger(Subsystem).WithFields(logrus.Fields{
				logfields.Path: objPath,
				logfields.Veth: device,
			})
			if ctx.Err() == nil {
				scopedLog.WithError(err).Warningf("JoinEP: Failed to load program for physical device %s", device)
			}
			return err
		}
		defer finalize()
	}

	return nil
}

下面再看看,Cilium 是如何给网卡编译和加载对应的 eBPF 程序的,重点是如何 compile 以及 attach 这两个过程。

梳理流程

从上面的分析中,可以将 Cilium 中是否在宿主机的网卡上加载 eBPF 程序的逻辑整理如下。

/cilium-chain%E5%92%8C%E7%89%A9%E7%90%86%E7%BD%91%E5%8D%A1/img.png

测试和验证

测试集群开启了 kube-proxy-replacement,并且设置 enable-node-portenable-host-firewall 为 false。

1
2
3
kube-proxy-replacement: partial
enable-node-port: "false"
enable-host-firewall: "false"

cilium-agent 启动,创建一个 Pod,运行一段时间之后检查 bond0 和 bond0.212 上是否有 ingress/egress。

/cilium-chain%E5%92%8C%E7%89%A9%E7%90%86%E7%BD%91%E5%8D%A1/img_1.png

创建 CiliumNetworkPolicy,再次检查 bond0 和 bond0.212 上是否有 ingress/egress。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "l4-rule"
spec:
  endpointSelector:
    matchLabels:
      app: network-multitool
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: network-multitool
    toPorts:
    - ports:
      - port: "80"
        protocol: TCP
/cilium-chain%E5%92%8C%E7%89%A9%E7%90%86%E7%BD%91%E5%8D%A1/img_2.png

参考资料

  1. 链式CNI插件与portmap端口映射
  2. 支持hostPort
  3. Cilium 1.6: 无KVstore操作、百分之百kube-proxy替换、基于套接字的负载均衡
  4. Tutorial: How to Use Cilium Hubble for Observability in CNI Chaining Mode (Part 1)
  5. Kubernetes Security — Explore Cilium host firewall and host policies
  6. cilium中的datapath简解
警告
本文最后更新于 2023年11月12日,文中内容可能已过时,请谨慎参考。