欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

calico多租户网络隔离和部分租户业务隔离方案

程序员文章站 2022-03-17 14:13:26
...

摘要

本方案使用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多租户网络隔离和部分租户业务隔离方案

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

  • management-ui在Kubernetes上作为NodePort服务运行,并显示在此示例中服务的网络连接。可以通过在浏览器中访问http:// :30002来查看UI。
    calico多租户网络隔离和部分租户业务隔离方案
图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多租户网络隔离和部分租户业务隔离方案

启用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多租户网络隔离和部分租户业务隔离方案

图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多租户网络隔离和部分租户业务隔离方案

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

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

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

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

图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多租户网络隔离和部分租户业务隔离方案

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

calico多租户网络隔离和部分租户业务隔离方案

图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多租户网络隔离和部分租户业务隔离方案

图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多租户网络隔离和部分租户业务隔离方案

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

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

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

图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多租户网络隔离和部分租户业务隔离方案

图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 - 博客园
相关标签: 解决方案