前言
今天我们进入 Cilium 安全相关主题, 介绍 CiliumNetworkPolicies 相比于 Kubernetes 网络策略最大的不同: 7 层网络策略能力.
CiliumNetworkPolicy 7 层能力
CiliumNetworkPolicy 与标准 NetworkPolicy 的最大区别之一是支持 L7 协议感知规则。在 Cilium 中,可以为不同的协议(包括 HTTP、Kafka 和 DNS)制定特定于协议的 L7 策略。
第 7 层策略规则扩展了第 4 层策略的 toPorts
部分,可用于 Ingress 和 Egress.
📝Notes
<networkpolicy.io> 目前只支持 L3/L4 策略的编辑和制作, 可以先用可视化编辑器制作 L4 的 CiliumNetworkPolicy, 再根据需求扩展为 L7 的 CiliumNetworkPolicy YAML。
第 7 层策略规则属性因 Cilium 支持的不同协议而异。特定协议的属性有 详细的文档 说明,后续主要以 HTTP 为例进行介绍。
L7 HTTP 策略
当节点上运行的任何端点的任何 L7 HTTP 策略处于活动状态时,该节点上的 Cilium Agent 将启动一个嵌入式本地 HTTP Agent 服务(基于 Envoy, 二进制包为 cilium-envoy
),并指示 eBPF 程序将数据包转发到该本地 HTTP 代理。HTTP 代理负责解释 L7 网络策略规则,并酌情进一步转发数据包。此外,一旦 HTTP 代理就位,你就可以在 Hubble 流量中获得 L7 可观察性,我们将在后续介绍。
在编写 L7 HTTP 策略时,HTTP 代理可以使用几个字段来匹配网络流量:
- PATH: 与 URL 请求的常规路径相匹配的扩展 POSIX regex。如果省略或为空,则允许所有路径。
- Method: 请求的方法,如 GET、POST、PUT、PATCH、DELETE。如果省略或为空,则允许使用所有方法。
- Host: 与请求的主机标头匹配的扩展 POSIX regex。如果省略或为空,则允许使用所有主机。
- Headers: 请求中必须包含的 HTTP 头信息列表。如果省略或为空,则无论是否存在标头,都允许请求。
下面的示例使用了几个具有 regex 路径定义的 L7 HTTP 协议规则,以扩展 L4 策略,限制所有带有 app=myService
标签的端点只能使用 TCP 在 80 端口接收数据包。在此端口上通信时,只允许使用以下 HTTP API 端点:
GET /v1/path1
: 精确匹配 “/v1/path1”PUT /v2/path2.*
: 匹配所有以 “/v2/path2” 开头的 pathsPOST .*/path3
: 这将匹配所有以 “/path3” 结尾的路径,并附加 HTTP 标头X-My-Header
必须设为true
的限制条件:
具体策略如下:
apiVersion: "cilium.io/v2" kind: CiliumNetworkPolicy metadata: name: "l7-rule" spec: endpointSelector: matchLabels: app: myService ingress: - toPorts: - ports: - port: '80' protocol: TCP rules: http: - method: GET path: "/v1/path1" - method: PUT path: "/v2/path2.*" - method: POST path: ".*/path3" headers: - 'X-My-Header: true' YAML |
该规则块包含扩展 L4 Ingress 策略的 L7 策略逻辑。您只需在 toPorts
列表中添加相应的规则块作为属性,就可以从 L4 策略开始,提供细粒度的 HTTP API 支持。
L7 策略示例
可以再看几个 L7 策略示例:
第一个, HTTP L7 策略: 允许来自 env=prod
的实体使用 HTTP GET app=service
pod 的 /public
apiVersion: "cilium.io/v2" kind: CiliumNetworkPolicy metadata: name: "rule1" spec: description: "Allow HTTP GET /public from env=prod to app=service" endpointSelector: matchLabels: app: service ingress: - fromEndpoints: - matchLabels: env: prod toPorts: - ports: - port: "80" protocol: TCP rules: http: - method: "GET" path: "/public" YAML |
第二个, Kafka L7 策略: 使《星球大战》中的帝国总部(app: empire-hq
)能够生成 (produce) 帝国公告(empire-announce)和死星计划(deathstar-plans)主题消息。
📝Notes
Cilium 用于演示 CiliumNetworkPolicy 能力的 Demo 程序, 借用了《星球大战》帝国和反抗军的概念。
apiVersion: "cilium.io/v2" kind: CiliumNetworkPolicy metadata: name: "rule1" spec: description: "enable empire-hq to produce to empire-announce and deathstar-plans" endpointSelector: matchLabels: app: kafka ingress: - fromEndpoints: - matchLabels: app: empire-hq toPorts: - ports: - port: "9092" protocol: TCP rules: kafka: - role: "produce" topic: "deathstar-plans" - role: "produce" topic: "empire-announce" YAML |
第三个, DNS L7 策略: “tofqdn-dns-visibility”
apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: "tofqdn-dns-visibility" spec: endpointSelector: matchLabels: any:org: alliance egress: - toEndpoints: - matchLabels: "k8s:io.kubernetes.pod.namespace": kube-system "k8s:k8s-app": kube-dns toPorts: - ports: - port: "53" protocol: ANY rules: dns: - matchName: "cilium.io" - matchPattern: "*.cilium.io" - matchPattern: "*.api.cilium.io" - toFQDNs: - matchName: "cilium.io" - matchName: "sub.cilium.io" - matchName: "service1.api.cilium.io" - matchPattern: "special*service.api.cilium.io" toPorts: - ports: - port: "80" protocol: TCP YAML |
在此示例中,L7 DNS 策略允许查询 cilium.io
、cilium.io
的任何子域以及 api.cilium.io
的任何子域。不允许其他 DNS 查询。
单独的 L3 toFQDNs Egress 规则允许连接到 DNS 查询中返回的 cilium.io
、sub.cilium.io
、service1.api.cilium.io
和 special*service.api.cilium.io
的任何匹配 IP,如 special-region1-service.api.cilium.io
,但不包括 region1-service.api.cilium.io
。允许对 anothersub.cilium.io
进行 DNS 查询,但不允许连接到返回的 IP,因为没有 L3 toFQDNs 规则选择它们。
总结
今天我们进入 Cilium 安全相关主题, 介绍 CiliumNetworkPolicies 相比于 Kubernetes 网络策略最大的不同: 7 层网络策略能力.
L7 策略基于 L4 策略扩展而来, 增加了 toPorts
字段. 并提供了 HTTP DNS Kakfa 的 L7 策略示例.
后续我们会基于 Cilium 官方的《星球大战》 Demo 做详细演示。