Kubernetes原生防火墙kubewall:基于Zone与Policy实现东西向流量安全隔离
1. 项目概述:一个Kubernetes原生防火墙的诞生
在云原生世界里,Kubernetes已经成为了事实上的编排标准。我们习惯了用Deployment部署应用,用Service暴露服务,用Ingress管理入口流量。但当我们把越来越多的业务,尤其是那些包含敏感数据或核心逻辑的服务搬上K8s集群后,一个老问题以新的形式浮现出来: 东西向流量的安全隔离 。传统防火墙守护在数据中心的边界,而K8s集群内部,Pod之间默认是“全通”的。任何一个被攻破的Pod,都可能成为攻击者在你的集群内部横向移动的跳板。kubewall/kubewall这个项目,正是为了解决这个痛点而生。它不是一个简单的网络策略生成器,而是一个旨在成为Kubernetes原生防火墙的控制器,其核心思想是 将防火墙的安全策略模型与Kubernetes的声明式API和资源模型深度结合 。
简单来说,kubewall试图回答这样一个问题:如果我们能把防火墙管理员熟悉的“源区域”、“目的区域”、“服务(端口/协议)”和“动作(允许/拒绝)”这套逻辑,直接映射为Kubernetes里的几种自定义资源(CRD),然后由一个控制器自动将其转换为底层的NetworkPolicy或类似实现,那会怎样?这对于那些安全团队和运维团队分离,或者运维人员对复杂网络策略语法望而生畏的场景,无疑是一个福音。它抽象了底层实现细节,提供了一套更直观、更贴近传统安全思维的管理界面。
2. 核心设计理念与架构拆解
2.1 从防火墙概念到K8s资源映射
kubewall的设计精髓在于其建立的概念映射关系。理解这个映射,是理解整个项目的基础。
-
区域(Zone) : 这是防火墙中最核心的概念之一,代表一组具有相同安全等级或功能的网络对象。在kubewall中,一个Zone资源对应Kubernetes中的一个或多个命名空间(Namespace),或者通过标签选择器(Label Selector)选定的一组Pod。例如,你可以定义一个名为
zone-web的Zone,包含所有打有tier: frontend标签的Pod所在的命名空间。这相当于在防火墙上划分了“Web服务器区”。 -
服务(Service) : 这里的Service并非K8s的Service资源,而是防火墙术语中的“服务”,指代具体的协议和端口组合。kubewall的Service CRD允许你定义像
tcp-80、tcp-443-https或自定义的端口范围。这比直接写NetworkPolicy中的ports块更易于管理和复用。 -
策略(Policy) : 这是将上述元素组合起来的规则。一条Policy规则会声明:来自某个源Zone(或具体的源Pod选择器),去往某个目的Zone,针对某个Service,是允许(Allow)还是拒绝(Deny)。这完全复刻了防火墙策略表(
<source, destination, service, action>)的格式。 -
规则集(RuleSet) : 一组Policy的集合,可以绑定到特定的Zone上。这提供了策略的分组和批量应用能力,类似于防火墙上的策略配置文件。
这套模型的美妙之处在于,它让安全工程师可以用自己熟悉的语言(区域、服务、策略)来定义需求,而无需深入理解Kubernetes NetworkPolicy的特定语法和实现限制(比如,大多数CNI插件不支持基于DNS名的策略,或者出口策略的限制)。kubewall的控制器(Controller)负责监听这些CRD的变化,并将其“编译”和“翻译”成集群中实际生效的NetworkPolicy资源。
2.2 控制器工作原理与数据流
kubewall控制器的核心是一个标准的Kubernetes Operator。它通过监听(Watch)自定义资源(Zone, Service, Policy, RuleSet)的创建、更新和删除事件来驱动工作流。
其内部数据处理流程可以概括为以下几个阶段:
- 监听与获取 : Controller启动后,会向Kubernetes API Server注册监听(Informer)上述所有CRD类型的事件。
-
关联解析
: 当一条Policy被创建或修改时,控制器会解析其规约(Spec)。例如,一条策略指定了源Zone
zone-a和目的Zonezone-b。 - 资源查询 : 控制器会根据Zone CRD中的定义(如命名空间选择器或标签选择器),去实时查询Kubernetes API,获取当前所有匹配的命名空间或Pod的列表。
-
策略生成
: 这是最关键的一步。控制器将抽象的Policy规则,结合查询到的具体目标(Pod IP或命名空间),生成一个或多个具体的、可执行的Kubernetes NetworkPolicy资源。例如,如果
zone-a匹配了命名空间ns1和ns2,zone-b匹配了命名空间ns3,那么这条Policy可能会生成多条NetworkPolicy,分别应用于ns1->ns3和ns2->ns3的流量路径上。 - 应用与调和 : 生成的NetworkPolicy会被创建或更新到对应的命名空间中。控制器会持续进行调和(Reconcile)循环,确保实际集群状态(NetworkPolicy)与用户声明的期望状态(kubewall CRDs)保持一致。如果底层Pod发生扩缩容或标签变更,控制器会通过Zone的查询重新计算并更新NetworkPolicy。
注意 : 这里存在一个关键设计选择:生成的NetworkPolicy是“白名单”模式。这意味着,一旦在某个命名空间激活了kubewall管理的策略,该命名空间内默认的“全通”规则就会失效,只有显式允许的流量才能通行。这符合最小权限原则,但要求管理员必须仔细规划所有必要的通信路径。
3. 实战部署与策略配置详解
3.1 环境准备与kubewall安装
假设我们已经在一个标准的、支持NetworkPolicy的Kubernetes集群上(例如使用Calico、Cilium、Weave Net等CNI插件),准备部署kubewall。项目通常以Helm Chart或直接应用YAML清单的方式提供。
步骤一:安装CRD和控制器 这是最标准的Operator安装方式。你需要先应用CustomResourceDefinitions,然后部署控制器本身的Deployment、ServiceAccount、Role、RoleBinding等资源。
# 克隆仓库(假设示例)
git clone https://github.com/kubewall/kubewall.git
cd kubewall/deploy
# 安装CRD
kubectl apply -f crds/
# 安装控制器RBAC和部署
kubectl apply -f rbac.yaml
kubectl apply -f deployment.yaml
安装完成后,使用
kubectl get pods -n <kubewall-namespace>
查看控制器Pod是否运行正常。同时,用
kubectl api-resources | grep kubewall
应该能看到新增的几种CRD资源。
步骤二:规划你的安全区域 在开始写策略之前,必须进行规划。以一个典型的三层Web应用为例:
-
frontend zone
: 包含运行Nginx/React等前端应用的Pod,标签可为
app: frontend。 -
backend zone
: 包含运行API服务(如Golang, Java Spring)的Pod,标签可为
app: backend。 -
data zone
: 包含数据库(如PostgreSQL, Redis)的Pod,标签可为
app: database。 -
monitoring zone
: 包含Prometheus、Grafana等监控组件,标签可为
app: monitoring。
3.2 定义核心资源:从Zone到Policy
接下来,我们将上述规划转化为kubewall资源。
1. 创建Zone Zone资源是策略的基石。你可以选择基于命名空间或基于Pod标签来定义。
# zone-frontend.yaml
apiVersion: networking.kubewall.io/v1alpha1
kind: Zone
metadata:
name: frontend
spec:
# 方式一:选择命名空间(适合按功能划分的命名空间)
namespaceSelector:
matchLabels:
purpose: frontend
# 方式二:选择Pod(更灵活,适合跨命名空间的同类Pod)
podSelector:
matchLabels:
tier: frontend
# 可以同时使用,取并集
对于backend和data zone,只需修改
name
和选择器即可。我个人的经验是,
在项目初期,更推荐使用
namespaceSelector
。因为命名空间本身就是K8s提供的一个天然隔离边界,将安全区域与命名空间对齐,管理起来更清晰,也避免了跨命名空间的标签管理混乱。后期如果需要在同一命名空间内做更细粒度的隔离,再引入
podSelector
作为补充。
2. 创建Service(防火墙服务) 定义常用的端口协议组合,便于策略引用。
# service-http.yaml
apiVersion: networking.kubewall.io/v1alpha1
kind: Service
metadata:
name: http
spec:
ports:
- port: 80
protocol: TCP
# service-https.yaml
apiVersion: networking.kubewall.io/v1alpha1
kind: Service
metadata:
name: https
spec:
ports:
- port: 443
protocol: TCP
# service-postgres.yaml
apiVersion: networking.kubewall.io/v1alpha1
kind: Service
metadata:
name: postgres
spec:
ports:
- port: 5432
protocol: TCP
3. 创建Policy(核心策略规则) 现在,我们可以编写符合业务需求的策略规则了。规则遵循“谁,能到哪里,做什么”的结构。
# policy-frontend-to-backend.yaml
apiVersion: networking.kubewall.io/v1alpha1
kind: Policy
metadata:
name: allow-frontend-to-backend-api
spec:
sourceRef:
name: frontend
kind: Zone
destinationRef:
name: backend
kind: Zone
serviceRefs:
- name: http
- name: https
action: Allow
# priority: 100 # 可选,定义规则优先级
这条策略允许来自
frontend
zone的Pod,访问
backend
zone的Pod的80和443端口。
# policy-backend-to-data.yaml
apiVersion: networking.kubewall.io/v1alpha1
kind: Policy
metadata:
name: allow-backend-to-database
spec:
sourceRef:
name: backend
kind: Zone
destinationRef:
name: data
kind: Zone
serviceRefs:
- name: postgres
action: Allow
这条策略允许backend服务访问数据库。
4. 创建默认拒绝规则 根据安全最佳实践,我们应该显式拒绝所有未明确允许的流量。这可以通过一条针对所有Zone的拒绝规则来实现,或者更精细地控制。kubewall通常通过一个特殊的“默认规则集”或高优先级的拒绝所有策略来实现。
# policy-deny-all-ingress.yaml
apiVersion: networking.kubewall.io/v1alpha1
kind: Policy
metadata:
name: deny-all-ingress
spec:
sourceRef: {} # 空,表示匹配所有源
destinationRef:
name: data # 例如,对数据区实施最严格的默认拒绝
kind: Zone
action: Deny
priority: 1 # 设置一个非常低的优先级,确保它在具体允许规则之后被处理?(这里需要根据kubewall的具体优先级逻辑调整,有些系统是数字越大优先级越高)
实操心得 : 策略的优先级(如果支持)是配置中的关键点。务必理清你的策略优先级逻辑。一个常见的模式是:高优先级的“具体允许规则”先行,最后一条低优先级的“拒绝所有”规则兜底。在应用默认拒绝规则前,一定要确保所有必要的通信路径都已通过允许规则开放,否则会导致业务中断。
3.3 策略验证与效果观察
应用所有YAML文件后,如何验证策略是否生效?
-
检查生成的NetworkPolicy : 这是最直接的证据。到你的前端、后端、数据库所在的命名空间下,执行
kubectl get networkpolicy。你应该能看到由kubewall控制器生成的、名称可能包含哈希值的NetworkPolicy资源。查看其具体内容,确认其podSelector和ingress规则符合你的预期。 -
进行连通性测试 : 在集群内部启动一个临时测试Pod,进行网络测试。
# 测试从前端区域到后端区域的HTTP访问 kubectl run -it --rm test-curl --image=curlimages/curl --restart=Never -n <frontend-namespace> -- curl -v http://<backend-service>.<backend-namespace>.svc.cluster.local # 测试从前端区域直接访问数据库端口(应该被拒绝) kubectl run -it --rm test-nc --image=busybox --restart=Never -n <frontend-namespace> -- nc -zv <database-service>.<data-namespace>.svc.cluster.local 5432第二个测试应该失败或超时,证明默认拒绝或缺乏允许规则在起作用。
-
查看控制器日志 : 如果策略未按预期生效,查看kubewall控制器的日志是首要的排查手段。
kubectl logs -f deployment/kubewall-controller-manager -n kubewall-system日志中可能会显示资源同步状态、策略转换过程或遇到的错误。
4. 高级场景与最佳实践
4.1 处理出口策略与外部流量
东西向流量是kubewall的重点,但一个完整的防火墙也需要考虑南北向流量(出口到互联网)和来自外部的入口流量。
-
出口策略(Egress) : 默认情况下,K8s Pod可以自由访问外部网络。出于安全合规,我们可能需要限制只有特定的Pod(如数据同步服务)才能访问特定的外部API或地址。kubewall的模型可以扩展支持Egress Policy,其原理与Ingress类似,只是
sourceRef和destinationRef的含义对调,并且destinationRef可能是一个代表外部CIDR的“ExternalZone”概念。在实现上,这依赖于底层CNI插件对Egress NetworkPolicy的支持程度(如Calico的GlobalNetworkPolicy, Cilium的CiliumNetworkPolicy)。 -
入口策略(Ingress from External) : 对于从集群外(如互联网)通过LoadBalancer或NodePort访问的流量,策略的源(source)不再是内部的Zone。一种常见的做法是定义一个特殊的Zone,例如
external,它不选择任何具体的Pod或命名空间,而是在策略生成时,被控制器翻译为NetworkPolicy中ipBlock或空的podSelector(表示任何源)。然后,你可以创建从externalZone到你的frontendZone,仅允许HTTP/HTTPS服务的策略。
最佳实践建议 : 对于出口策略,先从“允许访问外部K8s API Server”和“允许访问核心公共服务(如镜像仓库、包管理器)”开始配置,再逐步添加业务需要的特定外部地址。避免一开始就全局拒绝出口导致集群基础功能受损。
4.2 策略的版本管理与CI/CD集成
将网络安全策略像应用代码一样进行版本控制和管理,是DevSecOps的关键一环。kubewall的CRD资源是纯YAML,天然适合用Git管理。
-
专用Git仓库
: 为kubewall的策略创建一个独立的Git仓库,或者在你的应用Helm Chart中增加一个
kubewall-policies/目录。 -
目录结构
: 建议按环境或项目组织。
kubewall-policies/ ├── base/ # 基础Zone和Service定义 │ ├── zones.yaml │ └── services.yaml ├── overlays/ │ ├── dev/ # 开发环境策略 │ │ └── policies.yaml │ ├── staging/ # 预发环境策略 │ │ └── policies.yaml │ └── prod/ # 生产环境策略(最严格) │ └── policies.yaml └── kustomization.yaml -
CI/CD流水线
: 在部署应用的流水线中,增加一个“部署网络策略”的阶段。可以使用
kubectl apply -k(kustomize) 或helm upgrade来应用对应环境的策略。 务必在部署策略后,运行一套自动化测试 ,验证核心业务链路依然通畅。这可以是一些简单的容器内curl命令,也可以是更复杂的服务网格集成测试。
4.3 与服务网格的协同与取舍
当集群中同时存在kubewall(或原生NetworkPolicy)和服务网格(如Istio)时,就形成了两层网络控制: L3/L4层(网络策略) 和 L7层(服务网格策略) 。
-
分工与协同 : 一个清晰的边界是,让kubewall负责基础的、粗粒度的“能否通信”问题(基于IP/端口),即网络可达性控制。让服务网格负责更精细的、应用层的“如何通信”问题,如基于JWT的身份认证、基于HTTP路径或Header的路由、熔断、限流等。例如,kubewall可以只允许来自frontend zone的流量访问backend zone的80端口,而Istio可以进一步规定,这些流量必须携带有效的Bearer Token才能访问
/api/v1/路径。 -
配置冲突避免 : 务必注意避免规则冲突。例如,kubewall拒绝了一条流量,那么无论Istio的规则如何允许,该流量在TCP层就被丢弃了,根本到不了Envoy sidecar。因此, 配置顺序应该是先配通L3/L4层策略,再叠加L7层策略 。在排查网络问题时,也应遵循从底层到高层的顺序。
踩坑记录 : 我曾在一个项目中,先详细配置了Istio的AuthorizationPolicy,但忽略了NetworkPolicy。结果发现某些Pod间通信失败,排查了很久才发现是默认的NetworkPolicy阻止了流量。教训是: 在启用服务网格的同时,绝不能忽视基础的网络策略 。两者不是替代关系,而是互补的纵深防御层次。
5. 常见问题排查与运维技巧
5.1 策略不生效的排查路径
当配置了策略但流量似乎未被影响时,可以按照以下路径排查:
| 排查步骤 | 命令/操作 | 预期结果与说明 |
|---|---|---|
| 1. 控制器状态 |
kubectl get pods -n kubewall-system
|
确认控制器Pod处于
Running
状态。
|
| 2. CRD资源状态 |
kubectl get zone,service,policy -A
|
确认你创建的CRD资源是否存在且无报错。检查
kubectl describe policy <name>
的事件和状态字段。
|
| 3. 生成物检查 |
kubectl get networkpolicy -n <target-namespace>
| 在策略的目标命名空间查看生成的NetworkPolicy。如果没有,说明控制器未成功转换或同步。 |
| 4. NetworkPolicy语法 |
kubectl get networkpolicy <name> -n <ns> -o yaml
|
手动检查生成的NetworkPolicy YAML。确认
podSelector
是否正确匹配了目标Pod的标签?
ingress.from
是否匹配了源Pod?
|
| 5. Pod标签匹配 |
kubectl get pods -n <ns> --show-labels
| 确认你的Pod是否打上了Zone定义中所期望的标签。这是最常见的配置错误。 |
| 6. CNI插件支持 | 查阅集群CNI插件文档 | 确认你的CNI插件(如Calico, Cilium)是否启用并正确配置了NetworkPolicy功能。有些环境需要额外开启。 |
| 7. 命名空间隔离 | 检查命名空间默认策略 |
如果命名空间存在一条
Deny All
的默认NetworkPolicy,需要确保你的允许规则优先级更高或能正确匹配。
|
| 8. 实时流量测试 |
使用
kubectl run
创建临时测试Pod
|
从源命名空间发起对目标服务的访问测试,这是最直接的验证方式。结合
kubectl logs
和
kubectl describe
分析失败原因。
|
5.2 性能考量与大规模部署建议
随着Zone和Policy数量的增长,需要关注控制器的性能和生成策略的规模。
-
控制器资源限制 : 确保为kubewall控制器Pod设置合适的资源请求(requests)和限制(limits)。它需要内存来缓存CRD和K8s资源信息,需要CPU来处理事件和生成策略。在超过1000个Pod或数百条Policy的集群中,建议监控其资源使用情况。
-
NetworkPolicy数量爆炸 : 这是最需要警惕的一点。如果一条kubewall Policy的源Zone和目的Zone各自匹配了大量Pod或命名空间,控制器可能会生成数量巨大的NetworkPolicy资源(N x M条)。这会给API Server和CNI插件带来压力。 优化建议 :
- 尽量使用命名空间级别的Zone : 基于命名空间的Zone产生的策略数量远少于基于Pod标签的Zone。
- 合并策略 : 审视Policy规则,将多条访问同一目标、同一服务的规则合并,使用更宽泛但安全的源选择器。
- 评估CNI插件能力 : 像Cilium这样的CNI,其CiliumNetworkPolicy功能更强大,单条策略可以表达更复杂的规则,可能减少策略条目数量。评估kubewall是否支持或未来计划支持生成插件特定的策略CRD。
-
策略变更的影响 : 修改一条影响范围很广的Policy,会导致控制器批量更新大量NetworkPolicy。在此期间,网络连接可能会有短暂中断。 建议在业务低峰期进行批量策略变更 ,并考虑采用蓝绿部署的方式,先在新命名空间测试策略,再逐步切流。
5.3 监控与告警
不能仅仅部署了策略就高枕无忧,需要建立监控来确保策略按预期工作,并及时发现异常。
-
控制器健康监控 : 为kubewall控制器部署Pod健康检查(Readiness/Liveness Probe),并设置Prometheus监控,关注其Pod重启次数、事件处理队列深度、调和循环错误等指标。
-
网络策略审计 : 定期使用
kubectl get networkpolicy --all-namespaces审计集群中的策略,确保没有冗余或陈旧的策略。可以编写脚本,对比Git仓库中声明的策略与集群中实际生成的策略是否一致。 -
网络流日志分析 : 如果CNI插件支持(如Calico的Flow Logs, Cilium的Hubble),可以收集网络流日志。通过分析被拒绝的流量(Deny Logs),可以发现潜在的误配置策略,或者异常的攻击行为。例如,突然出现大量从某个Pod发往数据库端口的被拒绝请求,可能意味着该Pod被入侵并尝试横向移动。
kubewall项目代表了一种趋势:将传统基础设施的安全模型,通过Operator模式,无缝地融入云原生环境。它降低了Kubernetes网络策略的使用门槛,让安全策略的声明和管理变得更直观、更易于集成到GitOps工作流中。然而,它并非银弹,其效能和规模受制于底层CNI插件的能力,且在大规模场景下需要精心设计Zone和Policy结构以避免性能问题。在实际引入时,我的建议是从一个非核心的业务、一个小规模的命名空间开始试点,逐步建立策略模板和部署流程,待模式成熟后再向全集群推广。安全是一个持续的过程,而kubewall这样的工具,为我们提供了在这个过程早期就嵌入安全控制的强大能力。
更多推荐
所有评论(0)