网络策略介绍


默认情况下,Kubernetes 集群网络没任何网络限制,Pod 可以与任何其他 Pod 通信,在某些场景下就需要进行网络控制,减少网络攻击面,提高安全性,这就会用到网络策略。



网络策略(Network Policy):是一个K8s资源,用于限制Pod出入流量,提供Pod级别和Namespace级别网络访问控制。



网络策略的应用场景:


• 应用程序间的访问控制,例如项目A不能访问项目B的Pod


• 开发环境命名空间不能访问测试环境命名空间Pod


• 当Pod暴露到外部时,需要做Pod白名单


• 多租户网络环境隔离(多租户指的是,可能有很多公司不同的人,或者不同的团队,或者不同的业务线,或者不同的公司用我们这一个k8s平台,这称之为多租户,比如公有云就是纯多租户环境了)


前置条件 


网络策略通过​​网络插件​​ 来实现。要使用网络策略,你必须使用支持 NetworkPolicy 的网络解决方案。 创建一个 NetworkPolicy 资源对象而没有控制器来使它生效的话,是没有任何作用的。

使用K8S网络策略有个前提:你的网络组件(CNI)必须支持网络策略,比如flannel是不支持网络策略,calico是支持网络策略的。

K8S NetworkPolicy网络策略介绍与实战_nginx

上面是在default命名空间下创建网络策略,网络策略分为这几块:

 podSelector是目标pod,也就是基于default命名空间哪组pod去应用网络策略,policyType是进出流量,之后ingress是对进流量的限制,egress是出流量的限制。其实也就是针对标签为role=db这组pod对其进出流量都做限制,进流量172.17.0.0/16这个网端是可以访问的,但是除了172.17.1.0/24不能访问。同时还定义了网络命名空间和哪些标签的pod可以访问我,访问的端口为6379。

同时定义了出流量,针对role=db的pod只能访问10.0.0.0/24的5978这个端口。

所有策略都是交集的,没有优先级之分。

案例1:拒绝命名空间下所有Pod出入站流量



apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: test
spec:
podSelector: {} # 匹配本命名空间所有pod
policyTypes:
- Ingress
- Egress
# ingress和egress没有指定规则,则不允许任何
流量进出pod

网络命名空间在哪个namespace下面创建就限制哪个命名空间下的pod 



测试访问外部(拒绝访问):



kubectl run busybox --image=busybox -n test -- sleep 12h
kubectl exec busybox -n test -- ping baidu.com


测试外部pod访问(拒绝访问):


kubectl run web --image=nginx -n test
kubectl run busybox --image=busybox -- sleep 12h
kubectl exec busybox -- ping 10.244.169.135



测试内部pod之间访问(拒绝访问):



kubectl exec busybox -n test -- ping 10.244.169.135

案例2:拒绝其他命名空间Pod访问



需求:test命名空间下所有pod可以互相访问,也可以访问其他命名空间Pod,但其他命名



空间不能访问default命名空间Pod。


apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-namespaces
namespace: test
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {} # 匹配本命名空间所有pod


[root@master networkpolicy]# kubectl get networkpolicy -n ms
NAME POD-SELECTOR AGE
deny-all-namespaces <none> 14s

K8S NetworkPolicy网络策略介绍与实战_命名空间_02

This rule allows pods in the namespace 'ms' to receive traffic from all pods in the same namespace on all ports

案例3:允许其他命名空间Pod访问指定应用



apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-all-namespaces
namespace: default
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector: {} # 匹配所有命名空间的pod

案例4:同一个命名空间下应用之间限制访问




需求:将标签为run=web的pod隔离,只允许标签为run=client1的pod访问80端口



同一个命名空间下不同项目pod之间访问

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: app-to-app
namespace: test
spec:
podSelector:
matchLabels:
run: web
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: client1
ports:
- protocol: TCP
port: 80



案例5:只允许指定命名空间中的应用访问




需求:只允许指定命名空间中的应用访问和其他所有命名空间指定标签pod访问(注意这里有两个目标)



• 应用策略命名空间在dev,web的pod标签为env=dev



• 允许prod命名空间中的pod访问,及其他命名空间中的pod标签为app=client1的pod访问



命名空间的匹配也是基于标签的 ,所有的匹配都是基于标签的包括命名空间。

[root@master ~]# kubectl get ns --show-labels
NAME STATUS AGE LABELS
default Active 35d kubesphere.io/namespace=default,kubesphere.io/workspace=system-workspace
ingress-nginx Active 22d app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/part-of=ingress-nginx,kubesphere.io/namespace=ingress-nginx
kube-node-lease Active 35d kubesphere.io/namespace=kube-node-lease,kubesphere.io/workspace=system-workspace
kube-public Active 35d kubesphere.io/namespace=kube-public,kubesphere.io/workspace=system-workspace
kube-system Active 35d kubesphere.io/namespace=kube-system,kubesphere.io/workspace=system-workspace
kubesphere-alerting-system Active 35d kubesphere.io/namespace=kubesphere-alerting-system,kubesphere.io/workspace=system-workspace
kubesphere-controls-system Active 35d kubesphere.io/namespace=kubesphere-controls-system,kubesphere.io/workspace=system-workspace
kubesphere-monitoring-system Active 35d kubesphere.io/namespace=kubesphere-monitoring-system,kubesphere.io/workspace=system-workspace
kubesphere-system Active 35d kubesphere.io/namespace=kubesphere-system,kubesphere.io/workspace=system-workspace
ms Active 16d kubesphere.io/namespace=ms
openpitrix-system Active 35d kubesphere.io/namespace=openpitrix-system,kubesphere.io/workspace=system-workspace

具体实现如下


apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: dev-web
namespace: dev
spec:
podSelector:
matchLabels:
env: dev
policyTypes:
- Ingress
ingress:
# 满足允许prod命名空间中的pod访问
- from:
- namespaceSelector:
matchLabels:
env: prod
# 允许pod标签为app=client1的pod访问,所有命名空间
- from:
- namespaceSelector: {}
podSelector:
matchLabels:
app: client1

 限制某个命名空间下的某个pod访问

  ingress:
- from:
- namespaceSelector:
matchLabels:
project: myproject
podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379