随着使用容器部署微服务的流行,容器平台上的服务间有复杂的调用关系。kubernetes为了满足服务间调用的访问控制,在1.3的版本中便引入了Network Policy,通过它可以实现通过标签方便的去定义访问的策略 。
阿里云容器服务在Kubernetes的Flannel网络插件的基础上,配置自研的阿里云VPC驱动为容器提供了高性能的网络方案。
但目前版本的Flannel并未实现Kubernetes的Network Policy,为了让Flannel插件能够满足Network Policy的要求,Calico团队结合Calico中的Felix组件和Flannel驱动构建了Canal驱动,我们本文中就基于Canal在阿里云上部署Network Policy支持,同时也不会造成不必要的性能损失。
在阿里云上创建kubernetes集群
通过阿里云容器服务的控制台可以一键创建出一个云上的Kubernetes集群,如图:
创建好了Kubernetes集群后,我们通过容器服务控制台可以获取到kubectl
的连接方式,具体方法可以参考“通过 kubectl 连接 Kubernetes 集群”
后续我们的操作都将使用kubectl
进行。
卸载默认的flannel网络组件
首先,因为集群中会有正在使用flannel网络的应用,所以我们首先需要把集群中使用flannel网络的应用停止掉,然后再卸载flannel网络组建,这些应用包括:
- 用户自己部署的应用
- kubernetes中再flannel网络中的系统应用,包括kubedns, default-http-backend, nginx-ingress-controller, kubernetes-dashboard, heapster, monitoring-influxdb, tiller-deploy
由于kubernetes没有停止应用的选项,只有删除和创建,我们为了保留应用的配置,可以采用把应用的replicas调整成0的方式使应用的实例都“停止”,我们以kubedns为例:
[root@iZbp126bomo449eksjknkeZ ~]# kubectl scale deploy kube-dns --replicas=0 -n kube-system
deployment "kube-dns" scaled
[root@iZbp126bomo449eksjknkeZ ~]# kubectl get deploy kube-dns -n kube-system
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
kube-dns 0 0 0 0 4h
这样就将kube-dns “停止”了,同样的方法可以用于别的系统服务和自己的应用,在部署完成后我们还可以再通过scale的方式将这些应用“启动”回来。
应用都停止完成后,我们将卸载flannel的网络组件,卸载命令如下:
kubectl delete DaemonSet kube-flannel-ds -n kube-system
kubectl delete ConfigMap kube-flannel-cfg -n kube-system
kubectl delete ServiceAccount flannel -n kube-system
kubectl delete ClusterRoleBinding flannel
kubectl delete ClusterRole flannel
安装支持network policy的Canal网络组件
卸载完默认的flannel的网络组件后,我们来安装支持Network Policy的Canal网络组件,通过kubectl安装Canal的yaml文件:
[root@iZbp126bomo449eksjknkeZ ~]# curl -O http://acs-canal.oss-cn-hangzhou.aliyuncs.com/1.8-aliyun.yaml
[root@iZbp126bomo449eksjknkeZ ~]# vim 1.8-aliyun.yaml #修改其中的CALICO_IPV4POOL_CIDR的环境变量的网段为集群的网段,修改完保存
[root@iZbp126bomo449eksjknkeZ ~]# kubectl apply -f 1.8-aliyun.yaml #安装canal的网络组件
然后查看Canal的状态全都是READY后,说明Canal网络组件部署完成:
[root@iZbp126bomo449eksjknkeZ ~]# kubectl get pod -n kube-system -l k8s-app=canal
NAME READY STATUS RESTARTS AGE
canal-5tdht 3/3 Running 0 2h
canal-6kxkx 3/3 Running 0 2h
canal-h7gnp 3/3 Running 0 2h
canal-j9lgc 3/3 Running 0 2h
canal-xnwpb 3/3 Running 0 2h
在部署完成后别忘了将之前“停止”的应用再kubectl scale
回来呀。
验证network policy的支持
我们使用Kubernetes官方文档中的Policy的实例来演示下:
首先部署并暴露一个nginx服务
我们通过kubectl run
创建出一个nginx的deploy,然后用kubectl expose
通过service暴露nginx服务。
[root@iZbp126bomo449eksjknkeZ ~]# kubectl run nginx --image=nginx --replicas=2
deployment "nginx" created
[root@iZbp126bomo449eksjknkeZ ~]# kubectl expose deployment nginx --port=80
service "nginx" exposed
等待他们部署完成:
[root@iZbp126bomo449eksjknkeZ ~]# kubectl get svc,pod -l run=nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/nginx ClusterIP 172.21.0.225 <none> 80/TCP 59s
NAME READY STATUS RESTARTS AGE
po/nginx-7c87f569d-dhvmw 1/1 Running 0 1m
po/nginx-7c87f569d-xtdxb 1/1 Running 0 1m
在别的容器中测试到nginx服务的访问:
我们通过kubectl run
创建出另外一个pod来访问nginx的服务:
[root@iZbp126bomo449eksjknkeZ ~]# kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget --spider --timeout=1 nginx
Connecting to nginx (172.21.0.225:80)
/ #
发现默认情况下是可以访问通的。
通过Network Policy限制对nginx服务的访问
创建一个NetworkPolicy的配置规则,规则中我们通过podSelector描述只有服务access: "true"
的label的Pod才能访问的到run:nginx
的Pod。
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: access-nginx
spec:
podSelector:
matchLabels:
run: nginx
ingress:
- from:
- podSelector:
matchLabels:
access: "true"
```
通过`kubectl create`使NetworkPolicy配置生效:
[root@iZbp126bomo449eksjknkeZ ~]# kubectl create -f policy.yaml networkpolicy
"access-nginx" created
测试当没定义access的label的Pod去访问nginx服务
[root@iZbp126bomo449eksjknkeZ ~]# kubectl run busybox --rm -ti --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget --spider --timeout=1 nginx
Connecting to nginx (172.21.0.225:80)
wget: download timed out
/ #
发现访问超时了
测试定义了access的label的Pod去访问nginx服务
[root@iZbp126bomo449eksjknkeZ ~]# kubectl run busybox --rm -ti --labels="access=true" --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget --spider --timeout=1 nginx
Connecting to nginx (172.21.0.225:80)
/ #
是可以访问的,满足了Kubernetes的NetworkPolicy的定义。