随着使用容器部署微服务的流行,容器平台上的服务间有复杂的调用关系。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 集群后,我们通过容器服务控制台可以获取到 kubectl 的连接方式,具体方法可以参考 " 通过 kubectl 连接 Kubernetes 集群 "
后续我们的操作都将使用 kubectl 进行。
首先,因为集群中会有正在使用 flannel 网络的应用,所以我们首先需要把集群中使用 flannel 网络的应用停止掉,然后再卸载 flannel 网络组建,这些应用包括:
由于 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
卸载完默认的 flannel 的网络组件后,我们来安装支持 Network Policy 的 Canal 网络组件,通过 kubectl 安装 Canal 的 yaml 文件:
- [root@iZbp126bomo449eksjknkeZ ~]# kubectl apply -f http://acs-canal.oss-cn-hangzhou.aliyuncs.com/1.8-aliyun.yaml
然后查看 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 回来呀。
我们使用 Kubernetes 官方文档中的 Policy 的实例来演示下:
我们通过 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
我们通过 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)
- / #
发现默认情况下是可以访问通的。
创建一个 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
- [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
- / #
发现访问被限制而超时了
- [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 的定义。
来源: https://yq.aliyun.com/articles/332502