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.4 创建一个backend-policy.yaml的授权策略,允许frontend访问backend
      • 2.1.5 增加一个授权client命名空间访问stars命名空间中frontend服务的网络策略
    • 2.2 同一namespace下部分租户业务隔离
      • 2.2.1 创建pod
      • 2.2.1 同一 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网络组件,其正常运行的前提条件如下:

  1. kube-apiserver必须开启运行时extensions/v1beta1/networkpolicies,即设置启动参数:–runtime-config=extensions/v1beta1/networkpolicies=true;
  2. kubelet必须启用cni网络插件,即设置启动参数:–network-plugin=cni;
  3. kube-proxy必须启用iptables代理模式,这是默认模式,可以不用设置;
  4. kube-proxy不得启用–masquerade-all,因为它会跟calico冲突;
  5. 确保以下三个参数必须等于或包含Calico IP池CIDR:
kube-apiserver: --pod-network-cidr 
kube-proxy: --cluster-cidr 
kube-controller-manager: --cluster-cidr

注意:cluster-cidr不能与service-cidr还有主机的cidr网段重叠;

  1. 配置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" 

calico多租户网络隔离和部分租户业务隔离方案_第1张图片

图2-1 stars案例中的pod列表

  • management-ui在Kubernetes上作为NodePort服务运行,并显示在此示例中服务的网络连接。可以通过在浏览器中访问http:// :30002来查看UI。
    calico多租户网络隔离和部分租户业务隔离方案_第2张图片
图2-2 stars案例的网络拓扑示意图。页面中的图标的:backend -> Node “B” frontend -> Node “F”;client -> Node “C”。

2.1.2 启用隔离策略

执行kubectl apply -f 05-default-deny.yaml,06-default-deny.yaml ,为stars和client两个命名空间都设置的默认拒绝所有访问的网络隔离策略。此时回到浏览器中访问http:// :30002,刷新下页面,发现management-ui已经无法获取和展示服务节点之间的网络连接信息了。
calico多租户网络隔离和部分租户业务隔离方案_第3张图片

启用stars和client两个命名空间的网络隔离后,management-ui结果示意图。

2.1.3 增加一个授权策略以允许UI应用访问stars和client命名空间中的服务

执行以下命令:kubectl create -f 07-allow-ui.yaml ,kubectl create -f 08-allow-ui-client.yaml。再刷新下UI界面,发现可以展示出所有的服务节点了。各个服务节点之间仍然是不能访问的,所以节点之间没有网络流量。
calico多租户网络隔离和部分租户业务隔离方案_第4张图片

图2-3. 左图为增加UI应用访问stars命名空间中的服务的网络拓扑图,右图为增加UI应用访问client命名空间中的服务的网络拓扑图。

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。
calico多租户网络隔离和部分租户业务隔离方案_第5张图片

2.4 增加backend-policy.yaml的授权策略后的网络拓扑图

2.1.5 增加一个授权client命名空间访问stars命名空间中frontend服务的网络策略

执行kubectl create -f 10-frontend-policy.yaml后,刷新下UI页面,看到client到frontend的连接也有流量了。
calico多租户网络隔离和部分租户业务隔离方案_第6张图片

图2-5 增加frontend-policy.yaml的授权策略后的网络拓扑图。

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-6 创建具有demo命名空间下的具有不同label的pod列表

图2-6 创建具有demo命名空间下的具有不同label的pod列表

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, 不能互通。
calico多租户网络隔离和部分租户业务隔离方案_第7张图片

图2-7 nginx-hello1-deployment-548dcf6bd7-chcrw ping同一namespace下的pod ip结果。

calico多租户网络隔离和部分租户业务隔离方案_第8张图片

图2-8 nginx-hello1-deployment-548dcf6bd7-chcrw ping同一namespace下的pod ip结果。

三.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的测试容器中验证上网络服务的可访问性。可以看到入口流量已经被阻止,而出口网络流量还是正常的。
calico多租户网络隔离和部分租户业务隔离方案_第9张图片

图3-1 添加default-deny-ingress后的测试结果

3.3创建一个nginx服务的入口网络策略

运行kubectl create -f access-nginx.yaml命令以创建NetworkPolicy,允许从advanced-policy-demo命名空间中的任何pod流量到nginx pod。再回到busybox测试容器中,使用wget访问nginx服务,会发现已经可以访问了。
calico多租户网络隔离和部分租户业务隔离方案_第10张图片

图3-2 添加access-nginx后的测试结果

3.4阻止所有的出口网络流量

在执行kubectl create -f default-deny-egress.yaml后,在busybox测试容器中执行wget -q –timeout=5 com-O -,会得到一个地址解析报错信息。 执行nslookup nginx会发现,也不能访问到DNS服务。
calico多租户网络隔离和部分租户业务隔离方案_第11张图片

图3-3 添加default-deny-egress后的测试结果

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服务的出口流量。
calico多租户网络隔离和部分租户业务隔离方案_第12张图片

图3-4 添加default-deny-egress后的测试结果
## 3.6 继续放行访问nginx服务的网络出口流量 运行kubectl apply -f allow-egress-to-advance-policy-ns.yaml命令以创建NetworkPolicy,该策略允许从advanced-policy-demo命名空间中的任何pod的出口流量到具有与相同命名空间中的run:nginx匹配的标签的pod。此时,从busybox测试容器中测试下访问同命名空间中的nginx服务,访问外部网站服务。 ![图3-5 添加allow-egress-to-advance-policy-ns后的测试结果](https://img-blog.csdnimg.cn/20200119181650351.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjY4ODI1NQ==,size_16,color_FFFFFF,t_70) # 结论 本方案既能满足mec多租户按namespace隔离的基本需求,又能实现同一租户下按pod-label的业务隔离, 以及控制出口流量。我们上述案例采用yaml文件的形式实现了网络隔离。若结合mec实际,则需开发networkpolicy相应的模块,以实现在web端实现k8s网络策略的查询、新增与变更。因mec部分k8s节点采用flanneld网络组件,不支持网络策略,故需要将flanneld替换为calico网络组件。特别说明,calico的配置和维护比flanneld复杂很多,但calico的性能更好,支持复杂的网络策略。

参考资料

  1. calico 网络结合 k8s networkpolicy 实现租户隔离及部分租户下业务隔离
  2. Calico on Kubernetes 从入门到精通
  3. About Calico
  4. Kubernetes policy, advanced tutorial
  5. K8S容器编排之NetWorkPolicy官方实例
  6. 二进制部署Kubernetes-v1.14.1集群 - weavepub - 博客园

你可能感兴趣的:(解决方案)