21.实践篇:Kubernetes中的网络安全组:Network-Policy
21.实践篇:Kubernetes中的网络安全组:Network-Policy
网络策略是关于如何定义Pod组与彼此间,以及其他网络端点进行通信的规范。NetworkPolicy资源使用标签选择pod并且定义网络流量策略。
1.Network-Policy概述
默认情况下,pod资源是非隔离性的,它可以接收任何来源的流量。这其实不是我们生产环境所期望的,因为它不够安全!
此时就诞生了Network-Policy,如果做个比喻,我觉得它更像是阿里云上安全组的概念。
用于实现:
1.多租户的隔离(名称空间级别、Pod级别)
2.K8S集群概念的安全组
Network-Policy的策略不仅仅于此,还有更高级功能:如流量镜像、流量分割等,这里先不展开
我们使用kubeadm初始化学习环境的时候,使用的是flannel网络插件。在上一节的学习中,我是这样描述的:flannel是一个非常简单的覆盖网络,可以满足Kubernetes的基本要求。所以,flannel本身并不支持Network Policy,需要使用calico、envoy、istio等service mesh服务网格插件进行赋能。最后,我来聊一聊Network Policy的作用:
Network Policy的作用对象是Pod,也可以应用到Namespace和集群的入和出的流量;
Network Policy是作用在L3/4层的,即限制的是对IP地址和端口的访问;
如果需要对应用层做访问限制需要使用如Istio这类Service Mesh服务网格。
2.Network-Policy策略
如图所示,Network-Policy细分为Ingress和egress两种,其中:
Ingress(类似安全组的内外网入):定义能接收哪些客户端的访问(-from,ports:需要指明自己端口)
egress(类似安全组的内外网出):定义能访问哪些目标(-to,ports:目标端口)
备注:当对应区域有多条规则时,满足其一即可
3.基于Flannel网络叠加Calico策略
我们初始化集群时候使用的是flannel,他本身并不具有网络策略的功能,所以我这里将演示:如何基于已有的flannel网络,将calico的网络策略的能力进行赋能。
1) 因为我们初始化集群配置flannel的时候用的是10.244.0.0/16,所以不需要额外调整calico的配置文件,直接下载下来,apply即可
curl https://docs.projectcalico.org/v3.10/manifests/canal.yaml -O kubectl apply -f canal.yaml
更多calico介绍,可参阅Calico官方文档。
2) 等相关pod运行成功之后,我们就可以编辑网络策略进行测试
[root@centos-1 dingqishi]# kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE canal-5jp8z 2/2 Running 0 22m canal-85l9r 2/2 Running 0 22m canal-mgfzd 2/2 Running 0 22m
4.实战:Calico网络策略
1) 实战开始之前,你可以通过kubectl explain netpol帮助命令,了解并获得相关配置
[root@centos-1 dingqishi]# kubectl explain netpol KIND: NetworkPolicy VERSION: networking.k8s.io/v1
2) 首先,我们先创建两个namespace,用于运行pod,其中dev的名称空间运行服务端,prod的名称空间中运行客户端进行模拟测试
#创建namespace [root@centos-1 dingqishi]# kubectl create ns dev namespace/dev created [root@centos-1 dingqishi]# kubectl create ns prod namespace/prod created #部署服务端pod [root@centos-1 dingqishi]# kubectl create deployment myapp --image=registry.cn-hangzhou.aliyuncs.com/aaron89/myapp:v1 -n dev deployment.apps/myapp created #部署客户端pod.yaml,其运行在prod的名称空间 kubectl apply -f pod.yaml -n prod
3) 观察pod情况,并进客户端的交互式接口进行测试,发现pod通信是成功的。
我上面说过:默认情况下,pod资源是非隔离性的,它可以接收任何来源的流量。
[root@centos-1 dingqishi]# kubectl get pod -n dev -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-5c6976696c-fhn9q 1/1 Running 0 4m31s 10.244.2.2 centos-3.shared <none> <none> [root@centos-1 dingqishi]# kubectl get pod -n prod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES client-pod 1/1 Running 0 31s 10.244.2.3 centos-3.shared <none> <none> #测试 [root@centos-1 dingqishi]# kubectl exec -it client-pod -n prod -- /bin/sh / # ping 10.244.2.2 PING 10.244.2.2 (10.244.2.2): 56 data bytes 64 bytes from 10.244.2.2: seq=0 ttl=63 time=0.265 ms 64 bytes from 10.244.2.2: seq=1 ttl=63 time=0.137 ms
4) 这时候,我们编辑deny-all-ingress.yaml(拒绝所有入站流量,且dev内pod不能相互通信),并apply
apiVersion: networking.k8s.io/v1 #dev名称空间下的所有pod,不允许相互访问也不允许被外部访问 kind: NetworkPolicy metadata: name: deny-all-ingress namespace: dev spec: podSelector: {} #没指定 就是该名称空间下所有的Pod # ingress: #补充:注释的这两行表示放行所有入站流量 # - {} policyTypes: - Ingress #只控制入站流量,没具体定义,就表示一个都不放行
5) 查看对应的netpol生成情况
[root@centos-1 dingqishi]# kubectl get netpol -n dev NAME POD-SELECTOR AGE deny-all-ingress <none> 6s [root@centos-1 dingqishi]# kubectl describe netpol -n dev Name: deny-all-ingress Namespace: dev Created on: 2019-12-11 14:04:23 +0800 CST Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"networking.k8s.io/v1","kind":"NetworkPolicy","metadata":{"annotations":{},"name":"deny-all-ingress","namespace":"dev"},"spe... Spec: PodSelector: <none> (Allowing the specific traffic to all pods in this namespace) Allowing ingress traffic: <none> (Selected pods are isolated for ingress connectivity) Allowing egress traffic: <none> (Selected pods are isolated for egress connectivity) Policy Types: Ingress
6) 返回我们之前的交互式接口,测试发现,现在已经访问不到dev名称空间下面的资源了,和预期隔离配置一致
(同理:dev内的pod也不能相互访问)
/ # wget -o - -q 10.244.2.2 ^C / # ping 10.244.2.2 PING 10.244.2.2 (10.244.2.2): 56 data bytes
7) 接下来我们需要开放ingress规则,使得他们能够访问,首先给prod的名称空间打标签,以便network policy能够用选择器选中
[root@centos-1 dingqishi]# kubectl label ns prod name=prod namespace/prod labeled [root@centos-1 dingqishi]# kubectl get ns --show-labels NAME STATUS AGE LABELS default Active 15d <none> dev Active 23m <none> ingress-nginx Active 5d23h app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/part-of=ingress-nginx kube-node-lease Active 15d <none> kube-public Active 15d <none> kube-system Active 15d <none> kubernetes-dashboard Active 25h <none> prod Active 19m name=prod
8) 新增dev-allow-prod-ingress配置文件,并apply
apiVersion: networking.k8s.io/v1 #dev名称空间下的所有pod,不允许相互访问也不允许被外部访问 kind: NetworkPolicy metadata: name: dev-allow-prod-ingress namespace: dev spec: podSelector: {} #没指定 就是该名称空间下所有的Pod ingress: - from: - namespaceSelector: matchLabels: name: prod #指定prod名称空间下的pod可以进行访问 policyTypes: - Ingress #只控制入站流量,没具体定义,就表示一个都不放行
9) 观察配置是否生效
[root@centos-1 dingqishi]# kubectl describe netpol dev-allow-prod-ingress -n devName: dev-allow-prod-ingress Namespace: dev Created on: 2019-12-11 14:58:06 +0800 CST Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"networking.k8s.io/v1","kind":"NetworkPolicy","metadata":{"annotations":{},"name":"dev-allow-prod-ingress","namespace":"dev"... Spec: PodSelector: <none> (Allowing the specific traffic to all pods in this namespace) Allowing ingress traffic: To Port: <any> (traffic allowed to all ports) From: NamespaceSelector: name=prod Allowing egress traffic: <none> (Selected pods are isolated for egress connectivity) Policy Types: Ingress
10) 继续进行测试,发现此时已可以访问dev下的pod资源。
[root@centos-1 dingqishi]# kubectl exec -it client-pod -n prod -- /bin/sh / # ping 10.244.2.2 PING 10.244.2.2 (10.244.2.2): 56 data bytes 64 bytes from 10.244.2.2: seq=0 ttl=63 time=0.166 ms 64 bytes from 10.244.2.2: seq=1 ttl=63 time=0.091 ms
通过上面的实战,你应该已经充分了解了:
1.基于flannel底层网络的calico网络策略的赋能作用
2.Network-Policy中ingress和egress的实际配置效果
@版权声明:51CTO独家出品,未经允许不能转载,否则追究法律责任