Calico Tiers:实现Kubernetes网络策略细粒度优先级管理的利器
在复杂的Kubernetes环境中,网络策略的管理往往是一项挑战。随着应用数量的增长和安全要求的提高,我们可能需要定义大量的网络策略来控制Pod间的流量。Calico作为流行的Kubernetes CNI插件,提供了强大的网络策略能力。然而,仅靠order字段来管理所有策略的优先级,在某些场景下可能会显得力不从心,尤其是在需要确保某些关键策略(如安全策略)拥有绝对优先权时。
这时,Calico的Tiers(层级)功能就显得尤为重要。Tiers允许你将网络策略组织到不同的逻辑层级中,每个层级拥有独立的优先级,从而实现更细粒度的策略管理和更清晰的职责划分。
为什么需要Calico Tiers?
在没有Tiers的情况下,所有Calico的NetworkPolicy和GlobalNetworkPolicy都通过其spec.order字段来决定优先级。order值越小,优先级越高。这种扁平化的优先级管理方式在策略数量不多时尚可接受,但当策略数量庞大且由不同团队(如安全团队、平台团队、应用团队)维护时,就容易出现以下问题:
- 优先级冲突难以管理: 很难确保关键的安全策略或基础设施策略始终高于应用团队定义的通用策略。
- 策略变更风险高: 对现有
order值的调整可能影响到所有其他策略的相对优先级,容易引入意外行为。 - 职责分离困难: 不同团队的策略混杂在一起,难以清晰地划分管理边界。
Tiers机制通过引入一个额外的优先级维度来解决这些问题。每个Tier都有自己的order值,Tier的优先级高于其中包含的任何策略的order值。这意味着,首先比较Tier的优先级,然后在同一个Tier内部,再根据策略自身的order字段进行比较。
Tiers的工作原理
Calico策略评估的顺序遵循以下规则:
- Tier优先级: 首先根据Tier的
order值进行评估。order值最小的Tier拥有最高的优先级。 - Tier内策略优先级: 在同一个Tier内部,再根据策略(
NetworkPolicy或GlobalNetworkPolicy)自身的order字段进行评估。同样,order值最小的策略拥有最高的优先级。 - 默认行为: 如果流量通过所有Tiers和策略后都没有被
Allow或Deny,则会根据Calico的默认行为进行处理(通常是允许出站,拒绝入站,除非有特定的deny-all策略)。
如何使用Tiers实现细粒度策略管理
让我们以用户提出的“高优先级安全Tier”为例,演示如何操作。
1. 定义Tiers
首先,我们需要定义所需的Tiers。通常,我们会设置几个不同的层级,例如:
securityTier (最高优先级): 用于关键的安全策略,如禁止未经授权的外部访问、隔离敏感服务等。infrastructureTier (次高优先级): 用于平台基础设施相关的网络策略,如允许监控系统访问、Kube-API Server通信等。applicationTier (较低优先级): 用于应用团队定义的应用间通信策略。defaultTier (最低优先级): Calico默认的Tier,如果策略未指定Tier,则归入此Tier。
定义 security Tier 和 application Tier 的YAML示例:
# security-tier.yaml
apiVersion: projectcalico.org/v3
kind: Tier
metadata:
name: security # Tier 的名称
spec:
order: 100 # security Tier 的优先级,值越小优先级越高。
# 建议保留更小的数字给Calico内部使用或未来扩展。
# application-tier.yaml
apiVersion: projectcalico.org/v3
kind: Tier
metadata:
name: application # Tier 的名称
spec:
order: 200 # application Tier 的优先级,低于 security Tier
部署这些Tier:
kubectl apply -f security-tier.yaml
kubectl apply -f application-tier.yaml
2. 将策略分配到Tiers
定义了Tier之后,我们就可以创建网络策略,并通过spec.tier字段将其分配到对应的Tier。
示例1:security Tier 中的高优先级安全策略
假设我们有一个全局安全策略,要求所有非授权的入站流量默认被拒绝,除了明确允许的白名单。我们将这个策略放入security Tier。
# security-deny-all-ingress.yaml
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: security-deny-all-ingress
spec:
tier: security # 指定策略所在的Tier
order: 10 # 在 security Tier 内部的优先级
selector: all() # 匹配所有Pod
ingress:
- action: Deny # 默认拒绝所有入站流量
source: {} # 针对所有来源
egress:
- action: Allow # 允许所有出站流量 (如果需要,可进一步细化)
destination: {}
types:
- Ingress
- Egress
部署此安全策略:
kubectl apply -f security-deny-all-ingress.yaml
解释: 这个security-deny-all-ingress策略由于处于security Tier (order: 100),其优先级高于application Tier (order: 200)中的任何策略。这意味着,即使application Tier中有一个order:10的策略试图允许流量,security Tier中的order:10的拒绝策略也会优先被评估和执行。
示例2:application Tier 中的应用策略
现在,假设我们有一个Web应用,需要允许来自特定Ingress Controller的入站流量。我们将这个策略放入application Tier。
# web-app-allow-ingress.yaml
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
name: web-app-allow-ingress
namespace: my-app-namespace
spec:
tier: application # 指定策略所在的Tier
order: 10 # 在 application Tier 内部的优先级
selector: app == 'web-app' # 匹配名为 'web-app' 的Pod
types:
- Ingress
ingress:
- action: Allow
protocol: TCP
destination:
ports:
- 80
- 443
source:
selector: app == 'ingress-controller' # 允许来自 Ingress Controller 的流量
部署此应用策略:
kubectl apply -f web-app-allow-ingress.yaml
优先级分析:
当有流量尝试访问 my-app-namespace 下的 web-app Pod 时:
- Calico首先评估
securityTier (order: 100)。 - 在
securityTier 中,security-deny-all-ingress策略 (order: 10) 匹配到所有入站流量并将其Deny。
结果: 即使web-app-allow-ingress策略 (位于 application Tier, order: 200) 试图允许流量,但由于 security Tier 的优先级更高,并且其中的 security-deny-all-ingress 策略已经明确拒绝了所有入站流量,因此web-app将无法接收到来自Ingress Controller的流量。
注意: 如果我们希望Ingress Controller的流量能够到达web-app,那么就需要将允许Ingress Controller流量的策略也放在security Tier中,并且其order值要小于(优先级更高)security-deny-all-ingress策略,或者将security-deny-all-ingress策略的匹配范围限制得更窄。
修正示例:在 security Tier 中允许特定白名单
如果想让web-app能够接收来自Ingress Controller的流量,需要将允许规则放在优先级更高的Tier中,并且其内部order要高于Deny规则。
或者更常见的方式是,在security-deny-all-ingress之前,先定义一个允许白名单的GlobalNetworkPolicy。
# security-allow-ingress-controller.yaml
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: security-allow-ingress-controller
spec:
tier: security
order: 5 # 优先级高于 security-deny-all-ingress (order: 10)
selector: k8s-app == 'ingress-nginx' # 匹配Ingress Controller Pods
egress:
- action: Allow
destination: {}
types:
- Egress
这个策略是允许Ingress Controller自身出站,这与我们希望Ingress Controller访问应用是两回事。我们需要的是一个允许web-app接收来自Ingress Controller流量的策略,且这个策略要在security-deny-all-ingress之前被评估。
正确的做法是,修改security-deny-all-ingress策略,让它先允许特定白名单,然后再拒绝其余的:
# security-global-policy.yaml
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
name: security-global-policy
spec:
tier: security
order: 10 # 在 security Tier 内部的优先级
selector: all()
ingress:
- action: Allow # 首先允许来自特定源的入站流量
source:
selector: k8s-app == 'ingress-nginx' # 允许Ingress Controller访问
- action: Deny # 然后拒绝所有其他入站流量
source: {}
egress:
- action: Allow # 允许所有出站流量 (如果需要,可进一步细化)
destination: {}
types:
- Ingress
- Egress
通过这样配置,位于security Tier的security-global-policy将首先被评估。其中第一条Allow规则会允许Ingress Controller的流量,随后的Deny规则会拒绝其他未被明确允许的入站流量。这样,web-app-allow-ingress策略(在application Tier中)就能够生效了,因为它所期望的流量已经被高优先级Tier中的策略放行了。
Tiers的最佳实践
- 分层清晰: 根据功能和管理职责将策略分成明确的Tiers,例如:
security(安全),infrastructure(基础设施),platform(平台),application(应用),quarantine(隔离)。 - 优先级规划: 仔细规划每个Tier的
order值。一般来说,最重要的全局性策略(如安全、基础设施)应该放在order值较小的Tier中。 - 避免交叉引用: 尽量保持Tier间的独立性,减少在一个Tier的策略中引用另一个Tier的资源,以简化管理和故障排查。
- 从小范围开始: 在生产环境部署前,在测试环境中充分验证Tiers和策略的交互行为。
- 文档化: 清晰地文档化Tiers的定义、优先级以及每个Tier中主要策略的功能。
总结
Calico的Tiers功能为Kubernetes中的网络策略管理带来了急需的组织性和灵活性。通过将策略划分为不同的优先级层级,我们可以确保关键的安全和基础设施策略始终具有最高优先级,从而大大降低策略冲突的风险,提高整体网络安全态势,并简化复杂环境下的策略管理。掌握并合理运用Tiers,是构建健壮、可维护的Kubernetes网络安全策略体系的关键一步。