GHOST系统之家 - Windows系统光盘下载网站!
当前位置:GHOST系统之家>系统教程 > Cilium 如何处理 L7 流量

Cilium 如何处理 L7 流量

来源:Ghost系统之家浏览:时间:2023-06-28 08:59:44

Cilium 如何处理 L7 流量

作者:张晓辉 2023-06-13 07:34:10网络 网络管理 Cilium Agent 中运行着大量的 watcher,其中一个就是 CiliumNetworkPolicy watcher。当策略创建或者更新时,Agent 会对策略进行转换并将规则存储到 BPF Map 中。在网络通信时,BPF 程序会对网络流量进行检查并决定应当允许或者拒绝访问。

还记得在使用 Cilium 增强 Kubernetes 网络安全[1]示例中,我们通过设置网络策略限制钛战机tiefighter访问死星deathstar的/v1/exhaust-port端点,但放行着陆请求/v1/request-landing。在提起 Cilium 时,都说其是使用 eBPF 技术推动的用于提供、保护和观察容器工作负载之间的网络连接的开源软件。eBPF 可以处理 L3/4 的数据包,但是对复杂的 L7 的协议处理的成本比较高,并且无法应对 L7 协议策略的灵活性。Cilium 引入Envoy Proxy[2](Cilium 定制的发行版)作为 L7 代理,来处理该场景。

那 Cilium 是如何处理 L7 流量的呢?今天就让我们一探究竟。

注,这篇的内容是基于目前最新的 Cilium 1.13.3 和 proxy 1.23.9,不同版本间会有差异。

在开始之前先搭建先前的“星球大战”环境,或者你也可以直接跳到Debug 阶段[3]。

环境搭建

集群

export INSTALL_K3S_VERSION=v1.27.1+k3s1curl -sfL https://get.k3s.io | sh -s - --disable traefik --disable local-storage --disable metrics-server --disable servicelb --flannel-backend=none --write-kubeconfig-mode 644 --write-kubeconfig ~/.kube/config

安装 Cilium

CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/master/stable.txt)CLI_ARCH=amd64if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; ficurl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sumsudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/binrm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}cilium install

安装示例应用

kubectl apply -n default -f - <设置策略kubectl apply -n default -f - <测试kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port#Access deniedkubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing#Ship landed

查看 pod 信息。

kubectl get po -o wide -n defaultNAME READY STATUSRESTARTS AGE IP NODENOMINATED NODE READINESS GATESdeathstar-7848d6c4d5-58jc8 1/1 Running 06h57m 10.0.0.111 ubuntu-dev3 xwing1/1 Running 06h57m 10.0.0.209 ubuntu-dev3 tiefighter 1/1 Running 06h57m 10.0.0.123 ubuntu-dev3

后面 debug 的操作我们会直接在 cilium 的 agent pod 进行。

agent=$(kubectl get po -l app.kubernetes.io/name=cilium-agent -n kube-system -o jsonpath='{.items[0].metadata.name}')

Debug

先贴上总结的图。

图片

怎么下手呢?

在深入探索 Cilium 的工作机制[4]时,我们对 Cilium 的网络策略处理机制一笔带过:

Cilium Agent 中运行着大量的 watcher,其中一个就是CiliumNetworkPolicywatcher。当策略创建或者更新时,Agent 会对策略进行转换并将规则存储到 BPF Map 中。在网络通信时,BPF 程序会对网络流量进行检查并决定应当允许或者拒绝访问。

实际上这里的处理比较复杂,我们从 watcher 的初始化入手。

#enableK8sWatchers[5]开启一些列的 watcher#ciliumNetworkPoliciesInit[6]开启CiliumNetworkPolicywatcher#PolicyAdd[8]将规则写入Daemon[9]的策略仓库中,实际发PolicyAddEvent到repository-change-queue队列中。#policyAdd[10]对规则进行预处理,并收集与规则相关的 endpoint(需要重新生成 endpoint 的数据,如加载 BPF 程序、更新 map 等),推送PolicyReactionEvent事件EndpointRegenerationEvent#Handle[12]事件的处理过程Endpoint.regenerateBPF[14]重新加载 datapath BPF 程序,刷新 Map。Endpoint.regenerate[13]PolicyReactionEvent.Handle[11]事件处理的过程,依次处理所有策略相关的 endpoint,最后有发出EndpointRegenerationEvent事件#addCiliumNetworkPolicyV2[7]添加CiliumNetworkPolicy的处理

至此我们 apply 的网络策略被写入到 map 中。

接下来看下 ebpf 程序有任何使用该策略。

eBPF

还记得在Kubernetes 网络学习之 Cilium 与 eBPF[15]中我们分析容器发出的数据包,被LXC BPF Ingress程序处理。这里不再赘述,处理流程可以看那篇文章。

我们先查看死星的 endpoint id 和 identity 分别为863和2033。

kubectl get ciliumendpoint -n defaultNAME ENDPOINT ID IDENTITY ID INGRESS ENFORCEMENT EGRESS ENFORCEMENT VISIBILITY POLICY ENDPOINT STATE IPV4 IPV6tiefighter 221629439 ready10.0.0.123deathstar-7848d6c4d5-58jc8 863 2033 ready10.0.0.111xwing775 5513ready10.0.0.209

使用 endpoint id 通过通过命令查看为死星配置的网络策略,可以看到其中的两条 ingress 的策略,其代理端口19313,这个端口就是 Cilium 中 L7 代理的监听端口。

kubectl exec $agent -n kube-system -c cilium-agent -- cilium bpf policy get 863POLICY DIRECTION LABELS (source:key[=value])PORT/PROTO PROXY PORT BYTES PACKETSAllowIngress reserved:hostANYNONE 0 0 reserved:kube-apiserverAllowIngress k8s:app.kubernetes.io/name=deathstar 80/TCP 193130 0 k8s:class=deathstar k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default k8s:io.cilium.k8s.policy.cluster=default k8s:io.cilium.k8s.policy.serviceaccount=default k8s:io.kubernetes.pod.namespace=default k8s:org=empireAllowIngress k8s:app.kubernetes.io/name=tiefighter80/TCP 193130 0 k8s:class=tiefighter k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default k8s:io.cilium.k8s.policy.cluster=default k8s:io.cilium.k8s.policy.serviceaccount=default k8s:io.kubernetes.pod.namespace=default k8s:org=empireAllowEgressreserved:unknown ANYNONE 0 0

BPF 程序处理流量在检查策略时bpf_lxc.c#L1842[16],检查配置的策略带有代理端口执行POLICY_ACT_PROXY_REDIRECT将流量重定向给代理(端口19313,地址为主机地址)。

Cilium Proxy

Cilium agent 提供了 xds server 实现,通过 Unix Domain Socket/var/run/cilium/xds.sock与 proxy 进行通信,下发配置。

我们参考cilium-bugtool的dump 源码[17],dump 代理的配置。

kubectl exec $agent -n kube-system -c cilium-agent -- curl -s --unix-socket /var/run/cilium/envoy-admin.sock http://admin/config_dump?include_eds

从配置 config.json 中可以看到 Cilium 在 envoy proxy 中实现了如下三个不同类型的过滤器(Filter):

listener filterfilterhttp filter

监听器过滤器

监听器过滤器(Listener Filter)`cilium.BpfMetadata`[18]会从几个数据源中准备元数据:策略、监听器设置、请求方的标识等。数据源包括 xds 配置、BPF mapcilium_ipcache、cilium_ct4_global(ct:connection tracking。当然还包括 ct6 相关的 map)。

从数据源中获取的数据保存在 socket option 中(proxy 源码bpf_metadata.cc#L364[19]),作为上下文元数据的在其他的过滤器中使用。

元数据数据源

xds filter 配置,这里提供了 bpf map 的根目录/sys/fs/bpf,以及is_ingress: true表示当前 filter 是在入口监听器上(ingress listener):

{ "name": "cilium.bpf_metadata", "typed_config": {"@type": "type.googleapis.com/cilium.BpfMetadata","bpf_root": "/sys/fs/bpf","is_ingress": true }

xds network policy 配置(截取了 proxy 的部分配置),从配置中可以找到 endpoint 的 IP 和 id,以及前面我们设置的规则[20]:

{ "@type": "type.googleapis.com/cilium.NetworkPoliciesConfigDump", "networkpolicies": [{ "endpoint_ips": ["10.0.0.111" ], "endpoint_id": "863", "ingress_per_port_policies": [{ "port": 80, "rules": [{ "http_rules": {"http_rules": [ {"headers": [ {"name": ":method","safe_regex_match": { "google_re2": {}, "regex": "POST"} }, {"name": ":path","safe_regex_match": { "google_re2": {}, "regex": "/v1/request-landing"} }] }] }} ]} ], "egress_per_port_policies": [{} ], "conntrack_map_name": "global"},...}

Mapcilium_ipcache,可以通过连接信息中的 IP 地址获取身份标识,如死星的`identity`[21]为2033(见 proxy 源码bpf_metadata.cc#L165[22]):

kubectl exec $agent -n kube-system -c cilium-agent -- cilium bpf ipcache listIP PREFIX/ADDRESS IDENTITY10.0.0.67/32identity=1 encryptkey=0 tunnelendpoint=0.0.0.0 nodeid=010.0.0.111/32 identity=2033 encryptkey=0 tunnelendpoint=0.0.0.0 nodeid=010.0.0.123/32 identity=29439 encryptkey=0 tunnelendpoint=0.0.0.0 nodeid=010.0.0.243/32 identity=4 encryptkey=0 tunnelendpoint=0.0.0.0 nodeid=010.0.0.160/32 identity=19608 encryptkey=0 tunnelendpoint=0.0.0.0 nodeid=010.0.0.209/32 identity=5513 encryptkey=0 tunnelendpoint=0.0.0.0 nodeid=0192.168.1.13/32 identity=1 encryptkey=0 tunnelendpoint=0.0.0.0 nodeid=00.0.0.0/0 identity=2 encryptkey=0 tunnelendpoint=0.0.0.0 nodeid=0

Mapcilium_ct4_global,从连接跟踪(connection tracking)中获取请求方的identity(SourceSecurityID 29439,钛战机的标识):

cilium bpf ct list globalTCP OUT 10.0.0.123:48954 -> 10.0.0.111:80 expires=58774 RxPackets=4 RxBytes=435 RxFlagsSeen=0x1b LastRxReport=58764 TxPackets=6 TxBytes=522 TxFlagsSeen=0x1b LastTxReport=58764 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=4 SourceSecurityID=29439 IfIndex=0TCP IN 10.0.0.67:33988 -> 10.0.0.111:80 expires=58776 RxPackets=6 RxBytes=659 RxFlagsSeen=0x1b LastRxReport=58766 TxPackets=4 TxBytes=386 TxFlagsSeen=0x1b LastTxReport=58766 Flags=0x0013 [ RxClosing TxClosing SeenNonSyn ] RevNAT=0 SourceSecurityID=29439 IfIndex=0TCP IN 10.0.0.123:48954 -> 10.0.0.111:80 expires=80364 RxPackets=6 RxBytes=522 RxFlagsSeen=0x1b LastRxReport=58764 TxPackets=0 TxBytes=0 TxFlagsSeen=0x00 LastTxReport=0 Flags=0x0051 [ RxClosing SeenNonSyn ProxyRedirect ] RevNAT=0 SourceSecurityID=29439 IfIndex=0

过滤器

过滤器(Filter)`cilium.NetworkFilter`[23]工作在 L4,用于处理已建立的链接,应用端口级的策略,即 L4 策略。

从上下文元数据中保存的 endpoint 相关的策略中查找与目标端口相关的策略,检查请求方证书中的 sni 和请求方的身份标识 identity 是否在白名单中,见 proxy 源码network_filter.cc#L169[24]。

假如策略上设置了 L7 的协议,会使用 Golang 编写的解析器对 L7 的数据进行解析。

在本示例中并未使用 L4 的策略。

HTTP 过滤器

HTTP 过滤器(HTTP Filter)`cilium.L7Policy`[25]是本文的重点,但相对其他两个过滤器来说逻辑就简单多了。

"http_filters": [ {"name": "cilium.l7policy","typed_config": { "@type": "type.googleapis.com/cilium.L7Policy", "access_log_path": "/var/run/cilium/access_log.sock"} }

在过滤器对 HTTP 请求头进行解码时(见 proxy 源码l7policy.cc#L97[26]),依然是从上下文元数据中获取策略等内容。拿到策略后,与请求方(对于这里 ingress 的场景检查请求方,如果是 egress 的场景,检查上游的标识)的标识、请求头的信息进行比对,决定放行还是拒绝请求。

总结

整篇看下来,Cilium 在处理 L7 流量上的实现还是比较复杂的,牵扯多个组件协同。eBPF 在 L3/L4 流量处理上有着优异的性能优势,但是对 L7 流量处理仍然无法脱离 sidecar 代理(不论 sidecar 是 per pod 还是 per node)。而 L7 流量处理也恰恰有着非常多的使用场景,不仅仅是 HTTP 协议。

参考资料

[1]使用 Cilium 增强 Kubernetes 网络安全:https://atbug.com/enhance-kubernetes-network-security-with-cilium/

[2]Envoy Proxy:https://github.com/cilium/proxy

[3]Debug 阶段:#debug

[4]深入探索 Cilium 的工作机制:https://atbug.com/deep-dive-into-cilium/#网络策略

[5]#enableK8sWatchers:https://github.com/cilium/cilium/blob/f9bdd00c4910bfe3bac3b208fdfbb9452487e776/pkg/k8s/watchers/watcher.go#L525

[6]#ciliumNetworkPoliciesInit:https://github.com/cilium/cilium/blob/f9bdd00c4910bfe3bac3b208fdfbb9452487e776/pkg/k8s/watchers/cilium_network_policy.go#L85

[7]#addCiliumNetworkPolicyV2:https://github.com/cilium/cilium/blob/f9bdd00c4910bfe3bac3b208fdfbb9452487e776/pkg/k8s/watchers/cilium_network_policy.go#L159

[8]#PolicyAdd:https://github.com/cilium/cilium/blob/f9bdd00c4910bfe3bac3b208fdfbb9452487e776/daemon/cmd/policy.go#L224

[9]Daemon:https://atbug.com/deep-dive-into-cilium/#agent

[10]#policyAdd:https://github.com/cilium/cilium/blob/f9bdd00c4910bfe3bac3b208fdfbb9452487e776/daemon/cmd/policy.go#L249

[11]PolicyReactionEvent.Handle:https://github.com/cilium/cilium/blob/f9bdd00c4910bfe3bac3b208fdfbb9452487e776/daemon/cmd/policy.go#L454

[12]EndpointRegenerationEvent#Handle:https://github.com/cilium/cilium/blob/f9bdd00c4910bfe3bac3b208fdfbb9452487e776/pkg/endpoint/events.go#L27

[13]Endpoint.regenerate:https://github.com/cilium/cilium/blob/f9bdd00c4910bfe3bac3b208fdfbb9452487e776/pkg/endpoint/policy.go#L286

[14]Endpoint.regenerateBPF:https://github.com/cilium/cilium/blob/f9bdd00c4910bfe3bac3b208fdfbb9452487e776/pkg/endpoint/bpf.go#L584

[15]Kubernetes 网络学习之 Cilium 与 eBPF:https://atbug.com/learn-cilium-and-ebpf/#第-2-步pod1-lxc-bpf-ingress

[16]bpf_lxc.c#L1842:https://github.com/cilium/cilium/blob/f9bdd00c4910bfe3bac3b208fdfbb9452487e776/bpf/bpf_lxc.c#L1842

[17]dump 源码:https://github.com/cilium/cilium/blob/f9bdd00c4910bfe3bac3b208fdfbb9452487e776/bugtool/cmd/root.go#L505

[18]cilium.BpfMetadata:https://github.com/cilium/proxy/blob/v1.23/cilium/bpf_metadata.cc

[19]bpf_metadata.cc#L364:https://github.com/cilium/proxy/blob/v1.23/cilium/bpf_metadata.cc#L364

[20]规则:#设置策略

[21]identity:https://atbug.com/deep-dive-into-cilium/#端点-endpoint

[22]bpf_metadata.cc#L165:https://github.com/cilium/proxy/blob/v1.23/cilium/bpf_metadata.cc#L165

[23]cilium.NetworkFilter:https://github.com/cilium/proxy/blob/v1.23/cilium/network_filter.cc

[24]network_filter.cc#L169:https://github.com/cilium/proxy/blob/v1.23/cilium/network_filter.cc#L169

[25]cilium.L7Policy:https://github.com/cilium/proxy/blob/v1.23/cilium/l7policy.cc

[26]l7policy.cc#L97:https://github.com/cilium/proxy/blob/v1.23/cilium/l7policy.cc#L97

责任编辑:武晓燕 来源:云原生指北 CiliumL7流量

推荐系统

  • 电脑公司Ghost Win8.1 x32 精选纯净版2022年7月(免激活) ISO镜像高速下载

    电脑公司Ghost Win8.1 x32 精选纯净版2022年7月(免激活) ISO镜像高速下载

    语言:中文版系统大小:2.98GB系统类型:Win8

    电脑公司Ghost Win8.1x32位纯净版V2022年7月版本集成了自2022流行的各种硬件驱动,首次进入系统即全部硬件已安装完毕。电脑公司Ghost Win8.1x32位纯净版具有更安全、更稳定、更人性化等特点。集成最常用的装机软件,精心挑选的系统维护工具,加上绿茶独有

  • 微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载

    语言:中文版系统大小:5.13GB系统类型:Win11

    微软Win11原版22H2下载_Win11GHOST 免 激活密钥 22H2正式版64位免费下载系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Win11 64位 Office办公版(免费)优化  1、保留 Edge浏览器。  2、隐藏“操作中心”托盘图标。  3、保留常用组件(微软商店,计算器,图片查看器等)。  5、关闭天气资讯。 

  • Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    Win11 21H2 官方正式版下载_Win11 21H2最新系统免激活下载

    语言:中文版系统大小:4.75GB系统类型:Win11

    Ghost Win11 21H2是微软在系统方面技术积累雄厚深耕多年,Ghost Win11 21H2系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。Ghost Win11 21H2是微软最新发布的KB5019961补丁升级而来的最新版的21H2系统,以Windows 11 21H2 22000 1219 专业版为基础进行优化,保持原汁原味,系统流畅稳定,保留常用组件

  • windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    windows11中文版镜像 微软win11正式版简体中文GHOST ISO镜像64位系统下载,微软win11发布快大半年了,其中做了很多次补丁和修复一些BUG,比之前的版本有一些功能上的调整,目前已经升级到最新版本的镜像系统,并且优化了自动激活,永久使用。windows11中文版镜像国内镜像下载地址微软windows11正式版镜像 介绍:1、对函数算法进行了一定程度的简化和优化

  • 微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载

    语言:中文版系统大小:5.31GB系统类型:Win11

    微软windows11正式版GHOST ISO镜像 win11下载 国内最新版渠道下载,微软2022年正式推出了win11系统,很多人迫不及待的要体验,本站提供了最新版的微软Windows11正式版系统下载,微软windows11正式版镜像 是一款功能超级强大的装机系统,是微软方面全新推出的装机系统,这款系统可以通过pe直接的完成安装,对此系统感兴趣,想要使用的用户们就快来下载

  • 微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    微软windows11系统下载 微软原版 Ghost win11 X64 正式版ISO镜像文件

    语言:中文版系统大小:0MB系统类型:Win11

    微软Ghost win11 正式版镜像文件是一款由微软方面推出的优秀全新装机系统,这款系统的新功能非常多,用户们能够在这里体验到最富有人性化的设计等,且全新的柔软界面,看起来非常的舒服~微软Ghost win11 正式版镜像文件介绍:1、与各种硬件设备兼容。 更好地完成用户安装并有效地使用。2、稳定使用蓝屏,系统不再兼容,更能享受无缝的系统服务。3、为

  • 雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载

    语言:中文版系统大小:4.75GB系统类型:

    雨林木风Windows11专业版 Ghost Win11官方正式版 (22H2) 系统下载在系统方面技术积累雄厚深耕多年,打造了国内重装系统行业的雨林木风品牌,其系统口碑得到许多人认可,积累了广大的用户群体,雨林木风是一款稳定流畅的系统,一直以来都以用户为中心,是由雨林木风团队推出的Windows11国内镜像版,基于国内用户的习惯,做了系统性能的优化,采用了新的系统

  • 雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO

    语言:中文版系统大小:5.91GB系统类型:Win7

    雨林木风win7旗舰版系统下载 win7 32位旗舰版 GHOST 免激活镜像ISO在系统方面技术积累雄厚深耕多年,加固了系统安全策略,雨林木风win7旗舰版系统在家用办公上跑分表现都是非常优秀,完美的兼容各种硬件和软件,运行环境安全可靠稳定。win7 32位旗舰装机版 v2019 05能够帮助用户们进行系统的一键安装、快速装机等,系统中的内容全面,能够为广大用户