calico多租户网络隔离和部分租户业务隔离方案
calico多租户隔离和部分租户业务隔离方案
- 摘要
- 一.前提条件
- 二.Ingress入口网关
- 2.1 不同namespace间的多租户网络隔离
- 2.1.1 创建frontend, backend, client, and management-ui 等应用
- 2.1.2 启用隔离策略
- 2.1.3 增加一个授权策略以允许UI应用访问stars和client命名空间中的服务
- 2.1.5 增加一个授权client命名空间访问stars命名空间中frontend服务的网络策略
- 2.2 同一namespace下部分租户业务隔离
- 三.Egress出口网关
- 3.1创建一个新的命名空间并运行一个测试用途的nginx容器
- 3.2 创建一个网络策略,阻止所有的入口网络流量
- 3.3创建一个nginx服务的入口网络策略
- 3.4阻止所有的出口网络流量
- 3.5放行访问DNS的出口网络流量
- 参考资料
摘要
本方案使用calico cni网络组件,基于k8s 提供的networkpolicy 定义网络策略,以实现ingress入口流量和egress出口流量的控制。该方案重点介绍了不同namespace的多租户的网络隔离,分为2大步骤:a. 为 namespace 创建默认拒绝所有访问策略,使所有的容器都不能访问互相访问;b. 为在同一 namespace 中的 deployment, pod, svc 打上标签,如"environment: demo",设定 network ingress 准入 pods。同时,该方案也给出了同一namespace下部分租户的业务隔离以及容器的出口流量限制的案例。
一.前提条件
Network Policy 提供了基于策略的网络控制,用于隔离应用并减少攻击面。它使用标签选择器模拟传统的分段网络,并通过策略控制它们之间的流量以及来自外部的流量。但这个 networkpolicy 需要有第三方外接网络插件的支持,如Calico、Romana、Weave Net和trireme等。本方案采用了calico网络组件,其正常运行的前提条件如下:
- kube-apiserver必须开启运行时extensions/v1beta1/networkpolicies,即设置启动参数:–runtime-config=extensions/v1beta1/networkpolicies=true;
- kubelet必须启用cni网络插件,即设置启动参数:–network-plugin=cni;
- kube-proxy必须启用iptables代理模式,这是默认模式,可以不用设置;
- kube-proxy不得启用–masquerade-all,因为它会跟calico冲突;
- 确保以下三个参数必须等于或包含Calico IP池CIDR:
kube-apiserver: --pod-network-cidr
kube-proxy: --cluster-cidr
kube-controller-manager: --cluster-cidr
注意:cluster-cidr不能与service-cidr还有主机的cidr网段重叠;
- 配置NetworkManager:
vim /etc/NetworkManager/conf.d/calico.conf
[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:tunl*
二.Ingress入口网关
2.1 不同namespace间的多租户网络隔离
stars网络隔离案例可以达到的效果:租户可以通过ns进行网络隔离,在同一个ns下的pod的能相互ping通,不同ns下的不能ping通。
2.1.1 创建frontend, backend, client, and management-ui 等应用
kubectl apply -f 00-namespace.yaml,01-management-ui.yaml,02-backend.yaml, 03-frontend.yaml, 04-client.yaml
- 观察资源创建过程,因为涉及到镜像下载,所以需要几分钟:
kubectl get pods --all-namespaces --watch
- 检查下是否成功创建出以下资源, 见图2-1:
kubectl get pods --all-namespaces -o wide | grep -E "stars|management-ui|client"
- management-ui在Kubernetes上作为NodePort服务运行,并显示在此示例中服务的网络连接。可以通过在浏览器中访问http:// :30002来查看UI。
2.1.2 启用隔离策略
执行kubectl apply -f 05-default-deny.yaml,06-default-deny.yaml ,为stars和client两个命名空间都设置的默认拒绝所有访问的网络隔离策略。此时回到浏览器中访问http:// :30002,刷新下页面,发现management-ui已经无法获取和展示服务节点之间的网络连接信息了。
2.1.3 增加一个授权策略以允许UI应用访问stars和client命名空间中的服务
执行以下命令:kubectl create -f 07-allow-ui.yaml ,kubectl create -f 08-allow-ui-client.yaml。再刷新下UI界面,发现可以展示出所有的服务节点了。各个服务节点之间仍然是不能访问的,所以节点之间没有网络流量。
2.1.4 创建一个backend-policy.yaml的授权策略,允许frontend访问backend
执行kubectl create -f 09-backend-policy.yaml后,等待一会。再刷新UI网页发现frontend可以访问到backend了,当然仅限于是tcp port 6379。backend仍然不能访问到frontend。client仍然不能访问到frontend和backend。
2.1.5 增加一个授权client命名空间访问stars命名空间中frontend服务的网络策略
执行kubectl create -f 10-frontend-policy.yaml后,刷新下UI页面,看到client到frontend的连接也有流量了。
2.2 同一namespace下部分租户业务隔离
同一个ns下,我们也可以按租户的业务需求进行网络隔离,即同一个租户有多个业务,每个业务之间的网络隔离,相同业务之间的网络打通。
2.2.1 创建pod
demo 这个 ns 为例,为应用创建多个 label,并打不同的标签 demo1, demo2。然后依据打的label重新修改 networkpolicy。 执行kubectl create -f demo1.yaml, demo2.yaml后的结果见图2-6。
2.2.1 同一 namespace 下的部分租户网络隔离测试结果
未添加网络策略之前,demo下的4个pod能互相ping通。在执行kubectl create -f policy.yaml后, 测试结果为:a.带nginx-hello1标签的pod能互访;2.带nginx-hello2标签的pod能互访;c. 带nginx-hello1标签的pod与带nginx-hello2标签的pod, 不能互通。
三.Egress出口网关
Kubernetes NetworkPolicy API允许用户根据标签和端口配置Kubernetes pod的入口和出口网络流量管理策略(从Kubernetes 1.8.0开始)。本案例使用网络策略控制入口和出口流量,侧重于egress出口网关的使用。
3.1创建一个新的命名空间并运行一个测试用途的nginx容器
kubectl create ns advanced-policy-demo
kubectl run --namespace=advanced-policy-demo nginx --replicas=2 --image=nginx
kubectl expose --namespace=advanced-policy-demo deployment nginx --port=80
另外打开一个登录容器,创建一个基于busybox的测试容器:
kubectl run --namespace=advanced-policy-demo access --rm -ti --image busybox /bin/sh
访问同命名空间里的另一个nginx服务,访问公网上的网站服务:
wget -q --timeout=5 nginx -O -
wget -q --timeout=5 baidu.com -O -
3.2 创建一个网络策略,阻止所有的入口网络流量
执行kubectl create -f default-deny-ingress.yaml后, 再回到busybox的测试容器中验证上网络服务的可访问性。可以看到入口流量已经被阻止,而出口网络流量还是正常的。
3.3创建一个nginx服务的入口网络策略
运行kubectl create -f access-nginx.yaml命令以创建NetworkPolicy,允许从advanced-policy-demo命名空间中的任何pod流量到nginx pod。再回到busybox测试容器中,使用wget访问nginx服务,会发现已经可以访问了。
3.4阻止所有的出口网络流量
在执行kubectl create -f default-deny-egress.yaml后,在busybox测试容器中执行wget -q –timeout=5 com-O -,会得到一个地址解析报错信息。 执行nslookup nginx会发现,也不能访问到DNS服务。
3.5放行访问DNS的出口网络流量
运行kubectl label namespace kube-system name=kube-system命令,以在kube-system命名空间上创建名称为kube-system的标签。运行kubectl create -f allow-dns-access.yaml命令,以创建一个NetworkPolicy策略,允许从advanced-policy-demo命名空间中的任何pod到kube-system命名空间的DNS服务的出口流量。