本文共 6329 字,大约阅读时间需要 21 分钟。
常见的应用可以分为两大类:Job和Service。Job比较简单,就是一个普通的任务,完成之后就退出,一般不需要暴露对外服务的网络监听端口。Service是指长期运行的进程,监听某个网络端口,其他服务可以通过网络连过来。生产环境里,将服务暴露在网络上存在安全风险:必须限制只有信任的用户才能访问服务。我们肯定不希望未授权的用户能调用某个删除数据的接口,把DB里的数据删光。访问控制可以在应用层做,客户端访问服务时,带上身份校验信息,服务端校验客户身份,判断客户是否有权限完成请求的操作,如果有权限,执行客户端请求,否则返回一个拒绝信息。访问控制还可以在网络层做,只允许受信的网络段访问服务。两种方式各有优劣,应用层可以做到更细粒度的权限控制,但需要开发,并且要求能客户端/服务器在通信协议上支持鉴权。网络层鉴权不依赖具体应用,还有一个额外的好处是能防DDoS。今天的主题NetworkPolicy,就是一种网络层的访问控制机制。
传统上,通常使用防火墙实现网络层的访问控制,比如iptables rule,部署应用之后,通过iptables设置运行的ip白名单。在使用Kubernetes之后,由于Pod是动态分配到机器上,而且在运行过程中随时可能迁移到其他机器,显然不适合继续使用手工配置iptables的方式。好在Kubernetes考虑到这个需求,提供了Network Policy,通过Network Policy,我们不仅能限制哪些Pod能被哪些来源访问,甚至还能控制Pod能访问哪些外部服务。Kubernetes中的Network Policy只定义了规范,并没有提供实现,而是把实现留给了网络插件。阿里云容器服务的Terway支持Network Policy,接下来我们基于Terway介绍几个使用Network Policy的场景。
首先,我们要创建一个使用Terway的集群,也就是在创建集群的时候,网络插件选Terway。
等待一会,集群创建好。这是我刚刚创建好的集群,名字就叫terway
为了操作方便,我们直接用命令行的方式,先下载kubeconfig文件,保存到本地的$HOME/.kube/config
首先部署一个nginx,两个实例,附带一个service
~ % kubectl run nginx --image=nginxdeployment.apps "nginx" created~ % kubectl get podNAME READY STATUS RESTARTS AGEnginx-65899c769f-c9s8z 1/1 Running 0 24s~ % kubectl expose deployment nginx --port=80service "nginx" exposed~ % kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes ClusterIP 172.19.0.1443/TCP 21hnginx ClusterIP 172.19.32.113 80/TCP 20s
现在,起一个新应用,访问刚刚创建nginx service
~ % kubectl run busybox --rm -ti --image=busybox /bin/shIf you don't see a command prompt, try pressing enter./ # wget nginxConnecting to nginx (172.19.32.113:80)index.html 100% |***************************************************************************************************************************************************| 612 0:00:00 ETA/ #
看上去没问题,网络是通的。接下来我们设置一个Network Policy,只允许带有label access=true的应用访问nginx,其他都不行。开一个新终端
~ % cat policy.yamlkind: NetworkPolicyapiVersion: networking.k8s.io/v1metadata: name: access-nginxspec: podSelector: matchLabels: run: nginx ingress: - from: - podSelector: matchLabels: access: "true"~ % kubectl apply -f policy.yamlnetworkpolicy.networking.k8s.io "access-nginx" created
回到运行busybox的终端,再执行一次wget nginx
/ # wget nginxConnecting to nginx (172.19.32.113:80)^C/ #
可以看到,在设置完Policy之后,之前启动的busybox已经不能访问nginx了。我们重新启动一个带有label access=true的busybox
~ % kubectl run busybox --rm -ti --labels="access=true" --image=busybox /bin/shIf you don't see a command prompt, try pressing enter./ # wget nginxConnecting to nginx (172.19.32.113:80)index.html 100% |***************************************************************************************************************************************************| 612 0:00:00 ETA/ #
成功!
给上个场景中的nginx再创建一个LoadBalance类型的service,LoadBalance类型的service会创建一个SLB
~ % cat nginx-service.yamlapiVersion: v1kind: Servicemetadata: labels: run: nginx name: nginx-slbspec: externalTrafficPolicy: Local ports: - port: 80 protocol: TCP targetPort: 80 selector: run: nginx type: LoadBalancer~ % kubectl apply -f nginx-service.yamlservice "nginx-slb" created~ % kubectl get svc nginx-slbNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEnginx-slb LoadBalancer 172.19.89.136 47.95.180.200 80:31967/TCP 17s
我们创建了LoadBalance类型的service,SLB的IP是 47.95.180.200,先从本地请求一下试试:
~ % wget 47.95.180.200--2018-09-14 08:07:23-- http://47.95.180.200/Connecting to 47.95.180.200:80... ^C~ %
网络不通,因为刚才我们设置了nginx只允许带有label access=true的应用访问,现在是我们从外部访问Kubernetes,根本不是Pod,更不要说设置label了。怎么办?
方案是修改之前创建的Network Policy,增加一个允许访问的来源IP段。把自己本地的IP地址加到白名单里去。先拿到自己的IP地址
~ % curl myip.ipip.net当前 IP:1.2.3.4 来自于:中国 浙江 #我的实际IP不是这个,根据自己的实际情况处理。
然后编辑policy.yaml,把IP地址加进去。有些网络的出口IP有多个,所以这里加上了一个/24的段。100.64.0.0/10
必须要带上,SLB健康检查地址在这个段里,不加上的话SLB健康检查会出错。
~ % cat policy.yamlkind: NetworkPolicyapiVersion: networking.k8s.io/v1metadata: name: access-nginxspec: podSelector: matchLabels: run: nginx ingress: - from: - podSelector: matchLabels: access: "true" - ipBlock: cidr: 100.64.0.0/10 - ipBlock: cidr: 1.2.3.0/24~ % kubectl apply -f policy.yamlnetworkpolicy.networking.k8s.io "access-nginx" configured
好了,再访问一次
~ % wget 47.95.180.200--2018-09-14 08:15:03-- http://47.95.180.200/Connecting to 47.95.180.200:80... connected.HTTP request sent, awaiting response... 200 OKLength: 612 [text/html]Saving to: 'index.html'index.html 100%[=========================================================================================================>] 612 --.-KB/s in 0s2018-09-14 08:15:03 (67.6 MB/s) - 'index.html' saved [612/612]
网络又通了,完美!
除了限制当前应用能被谁访问,有时候还要限制应用能访问谁,有时候我们要运行第三方应用,不希望这些应用访问到不该访问的网络。通过Network Policy,也能实现这个需求。
Network Policy只能通过IP地址配置规则,首先我们通过dig获取www.aliyun.com的地址
~ % dig +short www.aliyun.comwww-jp-de-intl-adns.aliyun.com.www-jp-de-intl-adns.aliyun.com.gds.alibabadns.com.v6wagbridge.aliyun.com.v6wagbridge.aliyun.com.gds.alibabadns.com.140.205.34.3106.11.93.21140.205.32.4140.205.230.13
这样就拿到了域名解析到的IP列表。然后编写如下的Network Policy规则:
~ % cat busybox-policy.yamlkind: NetworkPolicyapiVersion: networking.k8s.io/v1metadata: name: busybox-policyspec: podSelector: matchLabels: run: busybox egress: - to: - ipBlock: cidr: 140.205.230.13/32 - ipBlock: cidr: 140.205.34.3/32 - ipBlock: cidr: 106.11.93.21/32 - ipBlock: cidr: 140.205.32.4/32 - to: - ipBlock: cidr: 0.0.0.0/0 ports: - protocol: UDP port: 53~ % kubectl apply -f busybox-policy.yamlnetworkpolicy.networking.k8s.io "busybox-policy" configured
在这个规则里,我们配置了egress规则,也就是出网规则,限制应用对外访问。允许UDP请求,否则没法做DNS解析。
验证一下
~ % kubectl run busybox --rm -ti --image=busybox /bin/shIf you don't see a command prompt, try pressing enter./ # wget www.aliyun.comConnecting to www.aliyun.com (106.11.93.21:80)Connecting to www.aliyun.com (140.205.230.13:443)wget: note: TLS certificate validation not implementedindex.html 100% |***************************************************************************************************************************************************| 526k 0:00:00 ETA/ #
转载地址:http://unxbo.baihongyu.com/