kubernetes之NetworkPolicy
官网链接:https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/#networkpolicy-resource
1 什么是NetworkPolicy
首先NetworkPolicy是k8s的一种resource,可以通过以下三种维度对整个namespace或单一POD进行隔离:pod(允许某些pod访问)、namespace(允许某些namespace访问)、ip段(CIDR,但是pod所运行node节点始终可以访问该pod)
当定义基于pod和namespace的NetworkPolicy时,需要根据标签来选择对应的pod或者namespace。
另外当需要使用NetworkPolicy资源时,k8s集群采用的网络插件必须支持,比如calico。
2 隔离和非隔离pod
默认情况所有的pod都是非隔离的,当pod被NetworkPolicy选择后,那么pod就是一个隔离的pod,出栈和入栈都要遵循NetworkPolicy的策略,并且如果有多个NetworkPolicy时,他们是叠加的而不是冲突的。
限制一个pod的NetworkPolicy需要从两个方向去考虑:ingress和egress。ingress表示入方向,egress表示出方向。
3 基于namespace的NetworkPolicy
以下yaml文件代表在olda下创建一个NetworkPolicy资源,该策略作用在所有被打了app=nginx-test标签的pod,策略内容为只接受来自namespace为oldb的访问。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ns-network-policy
namespace: olda
spec:
#定义策略的类型:值是一个列表,支持Ingress和Egress两种,默认Egress不做任何限制
policyTypes: ["Ingress"]
#表示该策略作用的pod,以标签匹配,当该值是一个{}空字典时,代表所有POD
podSelector:
matchLabels:
app: nginx-test
#以下表示ingress策略
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: oldb
验证如下:

4 基于POD的NetworkPolicy
以下yaml文件策略表示:允许带有app=nginx-test的所有pod访问app=nginx-test的pod
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ns-network-policy
namespace: olda
spec:
policyTypes: ["Ingress"]
podSelector:
matchLabels:
app: nginx-test
ingress:
- from:
- podSelector:
matchLabels:
app: nginx-test2
验证:

5 基于IP段的NetworkPolicy
以下yaml文件表示策略为:允许10.244.206.0/16段但是不包括10.244.206.7/32来访问带有app=nginx-test的pod
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ns-network-policy
namespace: olda
spec:
policyTypes: ["Ingress"]
podSelector:
matchLabels:
app: nginx-test
ingress:
- from:
- ipBlock:
cidr: 10.244.206.0/16
except:
- 10.244.206.7/32
验证如下图所示:

6 关于端口号的限制
创建一个双容器的pod,两个容器分别为nginx和mysql,端口号为80和3306,yaml文件如下:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: test
name: test
namespace: olda
spec:
replicas: 1
selector:
matchLabels:
app: test
template:
metadata:
labels:
app: test
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
ports:
- containerPort: 80
- image: mysql:5.7
imagePullPolicy: Always
name: mysql
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: root
单个端口号,只允许oldb名称空间下的pod连接80端口,具体策略如下
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: olda
spec:
policyTypes: ["Ingress"]
podSelector:
matchLabels:
app: test
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: oldb
ports:
- protocol: TCP
port: 80
将上述创建双容器的yaml文件内的namespace字段修改为oldb再创建一次,这是因为要测试mysql连通性必须有mysql的客户端,这样方便测试。

多个端口号,在网络策略里增加3306端口,在进行测试
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: olda
spec:
policyTypes: ["Ingress"]
podSelector:
matchLabels:
app: test
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: oldb
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 3306

另外有些网络插件支持endPort的写法,如果没有生效就是代表不支持,本次测试集群使用的calico网络CNI,经过测试发现不支持。
这么写就代表支持的端口范围是:80-3306
ports: - protocol: TCP port: 80 endPort:3306
7 总结
1)NetworkPolicy可以有效的隔离不同应用,但是比较依赖CNI插件;
2)如果通过IP CIDR来定义时,对于集群外IP的限制可能需要集群出口具备源地址透传的功能。

浙公网安备 33010602011771号