TT Lab
开始
学习 学习路径 课程

CCA — Cilium 认证助理

亲眼看 Cilium 真的挡住了什么

在 TT Lab 中继续学习

本实验在真正的 Cilium 中运行

VM 中真实运行着 k3s + Cilium。kube-proxy 被关闭,由 Cilium 代替它的工作(kubeProxyReplacement),L7 策略由 Envoy 真正强制执行,Hubble 负责收集 flow。

CCA 课程中的其他实验运行在只加载了 CRD 的假集群上。在那里,kubectl apply 只是能通过而已,什么也不会阻断。在这里会阻断。

首次启动需要 4–5 分钟,因为要安装 Cilium。

目标

亲眼确认身份是什么,依次叠加 L3 策略和 L7 策略,然后用 Hubble 读出“什么被阻断、为什么被阻断”。

为什么重要

Kubernetes 默认的 NetworkPolicy 也通过 Pod 和命名空间的标签选择器以及 ipBlock 来选择通信对端。podSelector 和 namespaceSelector 既可用于 ingress 的 from,也可用于 egress 的 to。它并不是只能逐个列出 IP 的 API。真正的强制执行由支持它的网络插件完成。

Cilium 在实现这种策略意图时,会把与安全相关的标签集合对应到身份编号。只有 app=tgt 相同,并不代表身份相同。还必须比较命名空间等其他与安全相关的标签。同一集合中的 endpoint 共享身份,所以不必在策略中逐个写死 Pod IP。与其把编号本身当作永久标识符,不如确认哪个标签集合对应这个编号。

此外,Cilium 还能看到 HTTP 路径和方法。可以在网络层强制“这个服务只能调用 /api/read”,而且被阻断时不是连接断开,而是返回 403——对应用来说处理起来容易得多。

步骤

  1. 把 cilium status 的输出保存到 /root/cca/status.txt。应能看到 KubeProxyReplacement: True,并且不应存在 kube-proxy DaemonSet。
  2. 在 mesh 命名空间中创建 tgt(app=tgt,nginx)和 client(app=client,curl),并把 tgt 的身份编号以及该编号来自哪些标签,保存到 /root/cca/identity.txt。
  3. 用 l3-allow CiliumNetworkPolicy 只让 app=client 能访问 tgt,并对被允许的一方和不被允许的一方都进行测试,把结果保存到 /root/cca/l3.txt。
  4. 用 l7-allow 策略只允许 /allowed 路径。把 /secret 收到 403 的情况记录到 /root/cca/l7.txt。
  5. 发送一次会被阻断的请求后,用 hubble observe 观察 flow,保存到 /root/cca/hubble.txt。FORWARDED 和 DROPPED 必须同时出现。
  6. 用 egress-fqdn 策略让 tgt 只能通过特定名称出站。把结果保存到 /root/cca/dnspolicy.txt。
  7. 用 hubble observe --type policy-verdict 提取为什么被阻断的判定日志,保存到 /root/cca/verdict.txt。
  8. 在 /root/cca/report.md 中写入 tgt_identity=、l7_denied_code=、policies= 三行及说明。

参考

没有 kube-proxy 的集群

把 cilium status 的输出保存到 /root/cca/status.txt。应能看到 KubeProxyReplacement: True,并且不应存在 kube-proxy DaemonSet。

查看 cilium status 中的 KubeProxyReplacement 一行。如果是 True,说明 Service 的负载均衡是由 eBPF 而不是 iptables 完成的。

策略依据编号而不是 IP 来判断

在 mesh 命名空间中创建 tgt(app=tgt,nginx)和 client(app=client,curl),并把 tgt 的身份编号以及该编号来自哪些标签,保存到 /root/cca/identity.txt。

查看 kubectl get ciliumendpoint -n mesh tgt -o yaml 中的 status.identity。也请把该编号来自哪种标签组合一并写进去。

L3——谁能够访问

用 l3-allow CiliumNetworkPolicy 只让 app=client 能访问 tgt,并对被允许的一方和不被允许的一方都进行测试,把结果保存到 /root/cca/l3.txt。

endpointSelector 选择受保护的 Pod,ingress.fromEndpoints 选择允许的来源。方向规则与 Kubernetes NetworkPolicy 相同。

L7——允许到哪条路径

用 l7-allow 策略只允许 /allowed 路径。把 /secret 收到 403 的情况记录到 /root/cca/l7.txt。

HTTP 规则写在 toPorts[].rules.http 里面。被阻断时不是连接断开,而是返回 403。

亲眼看到 flow

发送一次会被阻断的请求后,用 hubble observe 观察 flow,保存到 /root/cca/hubble.txt。FORWARDED 和 DROPPED 必须同时出现。

先启动 cilium hubble port-forward &,再使用 hubble observe -n mesh --last 30。必须在发送被阻断的请求之后再观察,才能看到 DROPPED。

按名称选择可出站的目的地

用 egress-fqdn 策略让 tgt 只能通过特定名称出站。把结果保存到 /root/cca/dnspolicy.txt。

toFQDNs 要求 Cilium 能够查看 DNS 响应才会生效。所以必须先用 toEndpoints + rules.dns.matchPattern 放行 DNS 本身。

追问为什么被阻断

用 hubble observe --type policy-verdict 提取为什么被阻断的判定日志,保存到 /root/cca/verdict.txt。

hubble observe --type policy-verdict 会显示每个 flow 命中了哪条策略、被怎样判定。

学到了什么

在 /root/cca/report.md 中写入 tgt_identity=、l7_denied_code=、policies= 三行及说明。

除了 tgt_identity=、l7_denied_code=、policies= 三行之外,还要说明身份为什么比 IP 更好,以及 L7 拒绝为什么是 403。