Cilium 透明代理注入(Proxy Injection)与独立 Envoy DaemonSet 部署指南
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
Cilium 能够透明地将 Layer 4 代理注入到任何网络连接中,为上层网络策略(如 DNS 策略与 L7 策略)的强制执行提供基础设施。本文以 Documentation/security/network/proxy/index.rst 和 envoy.rst 为主体,结合仓库源码(pkg/proxy、pkg/envoy、install/kubernetes)与 proxylib 架构图,系统讲解 Cilium 代理注入的工作原理、Envoy 作为宿主机代理的两种部署模式(Agent Pod 内嵌与独立 DaemonSet),以及启用和配置cilium-envoyDaemonSet 的完整操作步骤。读完后你将掌握如何在 Kubernetes 集群中选择、启用并运维 Cilium 的 Envoy 代理,从而为 L7 网络策略、Ingress、Gateway API 和 L7 协议可见性提供稳定的代理底座。
一、什么是 Proxy Injection
Cilium 具备将 Layer 4 代理透明注入到任意网络连接的能力。这里的"透明"意味着:应用 Pod 无需感知代理的存在,其发出的流量会被 Cilium 的 datapath 层(BPF)捕获,并转发给代理处理,处理完成后再由代理把流量送达真正的对端。这一机制构成了 Cilium 强制执行更高层网络策略的基础设施,官方文档明确说明它是 DNS 策略 与 L7 策略 的底层支撑。
.. _proxy_injection: Proxy Injection --------------- Cilium is capable of transparently injecting a Layer 4 proxy into any network connection. This is used as the foundation to enforce higher level network policies (see DNS based and l7_policy).目前可以注入的代理类型在文档 toctree 中给出:
.. toctree:: :maxdepth: 1 :glob: envoy即当前唯一被注入的宿主代理是Envoy(见 envoy.rst)。Cilium 将 Envoy 作为宿主机代理,用于执行集群网络策略中规定的 HTTP 及其他 L7 策略。
1.1 proxylib:策略匹配与访问日志的数据面
从文档_static目录中的架构图(proxylib_key_functions.png 与 proxylib_logical_flow.png)可以看到,Cilium 的代理库(proxylib)负责在 Envoy 中解析、匹配与记录代理流量:
- Downstream / Upstream Socket:分别承载客户端与服务器方向的
recv()/send()数据。 <NewProto>Parser.OnData():核心解析器,通过返回PASS/DROP/MORE控制数据流,决定请求放行、丢弃或需要更多数据。Matches():测试请求是否匹配策略映射(Policy Map)中的规则。<NewProto>RuleParser():解析并验证自定义协议规则(如 HTTP/HTTP2),解析结果存入 Policy Map。Inject():当策略判定为DROP时插入错误消息。Log():向 Cilium Access Log 写入访问日志条目,供 L7 协议可见性使用。
从逻辑流程上看(proxylib_logical_flow.png),Cilium Agent 生成 Policy JSON(含 endpointSelector、端口与协议规则),通过 Policy Config 推送给 Envoy;TCP 连接进入 BPF 层后被<NewProto>Parser按策略允许/拒绝,放行流量转发至目标 Pod(如app=newproto-server)。
1.2 数据面与控制面的分离:Cilium Agent ↔ Envoy
在现代 Cilium 代码库中,代理注入的控制面位于 pkg/proxy(redirect.go、proxy.go、dns.go、envoyproxy.go、proxyports.go),而 Envoy 的 xDS 服务器、访问日志服务器与进程管理位于 pkg/envoy。
Cilium Agent 与 Envoy 之间的通信全部通过UNIX domain socket完成,这一点在两种部署模式下保持一致,具体包括:
- 流式传输访问日志(access log,用于 L7 协议可见性):见 pkg/envoy/accesslog_server.go,其中
socketPath使用util.GetAccessLogSocketPath(envoySocketDir),监听类型为unixpacket,并设置 socket 权限0o660(属主与属组可读写)。 - 通过 xDS 协议更新配置:见 pkg/envoy/cell.go,Envoy 的 xDS 服务器(
newXDSServer/newADSServer)在启动后作为后台 job 运行,负责向 Envoy 下发监听器、集群、路由等配置。 - 访问 Envoy admin 接口:见 pkg/envoy/standalone_envoy.go,admin 接口也通过 UNIX socket(
util.GetAdminSocketPath(util.GetSocketDir(config.runDir)))暴露。
xDS(x Discovery Service)是 Envoy 原生的动态配置协议,Cilium 借助它把网络策略翻译成 Envoy 的 Listener / Cluster / Route 配置;admin 接口则用于查询server_info、下发 quit 指令等运维操作(见 pkg/envoy/envoyadminclient.go)。
二、Envoy:Cilium 的宿主机 L7 代理
随 Cilium 一起分发的 Envoy 代理是精简构建的:仅包含最少的 Envoy 扩展,并加入了 Cilium 自定义的策略强制过滤(custom policy enforcement filters)。该代理随 Cilium 镜像一起发布(images/cilium/、images/runtime/等构建产物),作为 Cilium 的宿主代理执行集群网络策略中规定的 HTTP 与其他 L7 策略。
Envoy 版本兼容性矩阵请参考 Cilium Proxy 官方文档(github.com/cilium/proxy#version-compatibility-matrix,原文 envoy.rst 有指向该仓库的说明)。
2.1 何时会启动 Envoy
当以下任一 L7 功能在 Kubernetes 集群中启用或安装时,Cilium Agent 会在 Cilium Agent Pod 内部启动一个独立的 Envoy 进程:
- Ingress(集群入口流量管理)
- Gateway API(基于 Kubernetes Gateway API 的南北向流量治理)
- 含 L7 功能的 Network Policy(如 HTTP/HTTPS/TLS 等七层网络策略)
- L7 协议可见性(L7 Protocol Visibility,通过访问日志展示七层流量)
在该内嵌模式下,这个 Envoy 实例负责代理该节点上所有匹配的 L7 请求。因此,被 L7 策略覆盖的流量依赖于 Cilium Agent Pod 的可用性——Agent 重启或升级期间,代理流量会受影响。
2.2 两种部署模式对比
| 维度 | 内嵌模式(默认) | 独立 DaemonSet(cilium-envoy) |
|---|---|---|
| Envoy 进程位置 | Cilium Agent Pod 内部 | 独立的cilium-envoyDaemonSet |
| 生命周期 | 与 Agent 同生命周期 | 独立生命周期 |
| 通信方式 | UNIX domain socket | UNIX domain socket(与内嵌一致) |
| Agent 重启影响 | 代理流量受影响 | 无影响(Agent 重启不影响 Envoy 代理的在线流量) |
| 资源隔离 | Envoy 与 Agent 共享限制 | CPU/内存限制独立,便于性能隔离 |
| 日志 | 与 Agent 日志混合 | Envoy 应用日志独立 |
| 健康探针 | 内嵌 | 专用健康探针(startup/liveness/readiness,见 install/kubernetes/cilium/templates/_extensions.tpl) |
| 部署时机 | 需要时按需启动 | 安装时显式部署 |
三、部署cilium-envoy独立 DaemonSet
3.1 启用方式
要将 Envoy 代理部署为独立生命周期的 DaemonSet(名为cilium-envoy),在安装 Cilium 时设置 Helm 值envoy.enabled=true:
helm install cilium cilium/cilium \ --namespace kube-system \ --set envoy.enabled=true关于envoy.*前缀的所有可配置键的详细说明,请参见 Helm 参考文档 中envoy.*相关条目。在 install/kubernetes/cilium/README.md 中记录着该值的语义:
envoy.enabled—string—truefor new installation — Enable Envoy Proxy in standalone DaemonSet. This field is enabled by default for new installation.
即:对于新安装,envoy.enabled默认即为true。模板 install/kubernetes/cilium/templates/_helpers.tpl 中的逻辑会根据upgradeCompatibility(升级兼容性配置)决定返回用户显式指定的envoy.enabled值还是默认值,用于兼容旧版本的升级场景。
3.2 两种模式下的通信方式与 SELinux 注意点
无论是内嵌模式还是 DaemonSet 模式,Cilium Agent 与 Envoy 的通信都通过 UNIX domain socket 进行,覆盖:
- 流式访问日志(L7 协议可见性)
- 通过 xDS 更新配置
- 访问 admin 接口
由于使用 UNIX domain socket,当宿主机启用 SELinux 时,Envoy DaemonSet 与 Cilium Agent 需要具有兼容的类型(SELinux type)。在未特别指定其他类型的情况下,两者都使用高特权类型spc_t。Red Hat OpenShift Container Platform 默认启用 SELinux,因此在该平台上运行cilium-envoyDaemonSet 时需要特别注意这一兼容性要求。
3.3 独立 DaemonSet 的潜在收益
采用独立cilium-envoyDaemonSet 模式,可以获得以下收益(原文 envoy.rst 所列,并结合 Helm 模板佐证):
- Cilium Agent 重启(如升级)不影响 Envoy 正在代理的在线流量——代理生命周期与 Agent 解耦,这是最大的收益。
- Envoy 补丁版本升级不影响 Cilium Agent——可以独立滚动升级 Envoy 而不动 Agent。
- Envoy 与 Cilium Agent 拥有独立的 CPU 和内存限制,实现性能隔离。
- Envoy 应用日志不与 Cilium Agent 日志混合,日志排障更清晰。
- Envoy 代理拥有专用的健康探针——install/kubernetes/cilium/templates/_extensions.tpl 中允许为
cilium-envoy容器自定义 startup probe、liveness probe 与 readiness probe。 - 在 Cilium 安装时显式部署 Envoy 代理(相比内嵌模式的按需启动),部署时机更明确、更可控。
3.4 可扩展的部署自定义点
从 Helm 模板 install/kubernetes/cilium/templates/_extensions.tpl 可以看出,cilium-envoyDaemonSet 提供了丰富的打包级自定义入口,包括:lifecycle hooks、init containers、额外启动参数、额外环境变量、额外卷挂载、额外 hostPath 挂载、容器端口、更新策略(update strategy)以及 Pod 亲和性(affinity)。在生产环境中,你可以据此为 Envoy 配置独立的资源配额、节点亲和与滚动更新策略。
另外,若你启用了 Envoy 的 Prometheus 监控,install/kubernetes/cilium/templates/cilium-agent/servicemonitor.yaml 会在envoy.enabled且envoy.prometheus.serviceMonitor.enabled为真时,为 Envoy 生成 ServiceMonitor 供 Prometheus 抓取指标。
四、Agent 与 Envoy 的交互链路(源码视角)
4.1 访问日志:UNIX socket 流式传输
pkg/envoy/accesslog_server.go 中,Cilium Agent 作为服务端在envoySocketDir下创建访问日志 socket:
- 启动时先移除旧的 socket 文件(
os.Remove(s.socketPath),见第 94-95 行),再以net.ListenUnix("unixpacket", ...)监听(第 98 行); - 设置权限
0o660(第 105 行)并将 socket 的属组改为proxyGID(第 109 行); - 每个 Envoy listener 都会在该 socket 上建立独立连接(第 70-72 行注释),Cilium 为每个连接启动 goroutine 并发处理访问日志(第 85 行),支持多连接同时流式上报。
4.2 xDS:动态下发改配置
pkg/envoy/cell.go 中,Cilium 的 xDS 服务器根据配置选择newADSServer(ADS 聚合发现服务)或newXDSServer,并在启动后以后台 job(job.OneShot("xds-server", ...))持续运行。Envoy 通过 xDS 协议从 Agent 获取 Listener/Cluster/Route 等配置,从而将 Cilium Network Policy 中的 L7 规则实时翻译为 Envoy 的转发行为。
4.3 Admin 接口:通过 UNIX socket 运维
pkg/envoy/standalone_envoy.go 中,独立模式下 Envoy 的 admin 接口同样挂载在 UNIX socket 上(util.GetAdminSocketPath(util.GetSocketDir(config.runDir))),并配置Pipe类型的上游集群(第 543-570 行)。Agent 通过 pkg/envoy/envoyadminclient.go 的EnvoyAdminClient访问envoy-admin地址(第 24 行),可执行查询server_info(第 151 行)与下发quit(第 55 行)等管理操作;在优雅关闭流程中,Agent 会先调用admin.quit()再结束 Envoy 进程(第 264 行)。
五、小结
Cilium 的透明代理注入能力是其 L7 网络策略体系的基石:BPF datapath 将流量导向宿主代理,Cilium Agent 通过 UNIX domain socket 与 Envoy 完成配置下发(xDS)、访问日志回流与 admin 运维。当集群中启用 Ingress、Gateway API、L7 Network Policy 或 L7 协议可见性时,Envoy 即以独立进程形式承担该节点全部匹配 L7 请求的代理职责。
对于生产环境,若希望将代理流量与 Agent 生命周期解耦(升级、重启互不影响),可以通过envoy.enabled=true启用cilium-envoy独立 DaemonSet,并利用其独立的资源限制、健康探针、日志与显式部署时机获得更可控的运维体验。需要注意在启用 SELinux 的平台(如 Red Hat OpenShift)上保持 Agent 与 Envoy 使用兼容的 SELinux 类型(默认均为spc_t)。
进一步阅读:
- Proxy Injection 章节文档
- Envoy 部署详解
- Cilium 代理实现源码
- Envoy 控制面实现源码
- Helm 参考(envoy.* 配置键)
【免费下载链接】ciliumeBPF-based Networking, Security, and Observability项目地址: https://gitcode.com/GitHub_Trending/ci/cilium
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考