- 1 前置条件
- 2 控制范围
- 3 隔离类型
- 4 如何识别
- 5 主要字段
- 6 案例演示
前置条件
网络策略通过网络插件来实现。 要使用网络策略,你必须使用支持 NetworkPolicy 的网络解决方案。 创建一个 NetworkPolicy 资源对象而没有控制器来使它生效的话,是没有任何作用的。那么如何查看我们的集群中是否有这个资源呢?如果你使用的CNI网络查件是Flannel, 是不支持的, Calico是支持的.
检查API版本兼容性
]# kubectl api-versions | grep networking.k8s.io
networking.k8s.io/v1
]# kubectl api-resources | grep -i networkpolicy
globalnetworkpolicies crd.projectcalico.org/v1 false GlobalNetworkPolicy
networkpolicies crd.projectcalico.org/v1 true NetworkPolicy
networkpolicies netpol networking.k8s.io/v1 true NetworkPolicy
下面我们简单创建一个networkpolicy资源来检查下是否能正常使用.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:name: test-policy
spec:podSelector: {}policyTypes:- Ingress]# kubectl apply -f networkpolicy_functest.yaml
]# kubectl get networkpolicy #可以看到创建成功了
控制范围
OSI 第 3 层或第 4 层. 如果你想在7层控制流量,可以考虑使用istio,后面我会专门演示istio的使用案例
隔离类型
- 出口的隔离 policyTypes: “Egress”
- 入口的隔离 policyTypes: “Ingress”
如何识别
Pod 可以与之通信的实体是通过如下三个标识符的组合来辩识的:
- 其他被允许的 Pod(例外:Pod 无法阻塞对自身的访问)
- 被允许的名字空间
- IP 组块(例外:与 Pod 运行所在的节点的通信总是被允许的, 无论 Pod 或节点的 IP 地址)
主要字段
apiVersion : 必须字段,不同版本可能group和version有所差别,通过explain命令可以查看当前k8s版本支持的apiVersion,如下图所示,我的k8s版本是1.28,所以他的networkpolicy 接口的apiVersion应该是 networking.k8s.io/v1
kind : 必须字段, 填NetworkPolicy
metadata : 必须字段,需要指定一些元数据,例如name
spec : 包含了在一个名字空间中定义特定网络策略所需的所有信息
podSelector : 对该策略所适用的一组 Pod 进行选择。示例中的策略选择带有 “role=db” 标签的 Pod。 空的 podSelector 选择名字空间下的所有 Pod。
policyTypes : 包含 Ingress 或 Egress 或两者兼具。policyTypes 字段表示给定的策略是应用于进入所选 Pod 的入站流量还是来自所选 Pod 的出站流量,或两者兼有。 如果 NetworkPolicy 未指定 policyTypes 则默认情况下始终设置 Ingress; 如果 NetworkPolicy 有任何出口规则的话则设置 Egress。
ingress : 每个 NetworkPolicy 可包含一个 ingress 规则的白名单列表。 每个规则都允许同时匹配 from 和 ports 部分的流量。
egress : 每个 NetworkPolicy 可包含一个 egress 规则的白名单列表。 每个规则都允许匹配 to 和 ports 部分的流量。
下面我们来分析一个示例:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:name: test-network-policynamespace: default
spec:podSelector:matchLabels:role: dbpolicyTypes:- Ingress- Egressingress:- from:- ipBlock:cidr: 172.17.0.0/16except:- 172.17.1.0/24- namespaceSelector:matchLabels:project: myproject- podSelector:matchLabels:role: frontendports:- protocol: TCPport: 6379egress:- to:- ipBlock:cidr: 10.0.0.0/24ports:- protocol: TCPport: 5978该示例表达的是:1. 隔离 default 名字空间下 role=db 的 Pod 2. Ingress 规则)允许以下 Pod 连接到 default 名字空间下的带有 role=db 标签的所有 Pod 的 6379 TCP 端口:- default 名字空间下带有 role=frontend 标签的所有 Pod- 带有 project=myproject 标签的所有名字空间中的 Pod- IP 地址范围为 172.17.0.0–172.17.0.255 和 172.17.2.0–172.17.255.255 (即,除了 172.17.1.0/24 之外的所有 172.17.0.0/16)3. (Egress 规则)允许 default 名字空间中任何带有标签 role=db 的 Pod 到 CIDR 10.0.0.0/24 下 5978 TCP 端口的连接。
## 案例演示
下面我来演示一个案例. 我已经安装好了一个k8s集群 版本是1.28的, 而且部署好了monitoring. 我们就简单的拿grafana来举个例子, grafana我开放了两种访问方式,
一种是4层,通过NodePort方式,
一种是创建了Ingress七层访问,不过他们的最终链路都是一样的
可以看到不管是浏览器还是curl,都正常跳转和返回数据
可以看到目前我访问grafana页面正常,下面是我的ing和svc资源
下面我创建networkpolicy资源,yaml如下
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:name: grafana-network-policynamespace: monitoring
spec:podSelector:matchLabels:app.kubernetes.io/name: grafana policyTypes:- Ingressingress:- from:- ipBlock:cidr: 10.233.58.225/32ports:- protocol: TCPport: 80
我来apply 一下
ok. 已经生效. 我们再次访问grafana测试下
为了验证下这个networkpolicy确实只作用于monitoring命名空间下的grafana这个pod上,我们进入Alert
Pod去nc 探测grafana svc的端口是否被阻断。
那我们进入Grafana的pod上去反向探测下alert端口。
可以看到,符合预期. 下面我们删除networkpolicy.在测试下
再次从alert pod内部去nc grafana的Svc:80端口。
网页也恢复正常. 后面我会测试7层 service mesh相关的Istio案例.