本方案使用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: --pod-network-cidr
kube-proxy: --cluster-cidr
kube-controller-manager: --cluster-cidr
注意:cluster-cidr不能与service-cidr还有主机的cidr网段重叠;
vim /etc/NetworkManager/conf.d/calico.conf
[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:tunl*
stars网络隔离案例可以达到的效果:租户可以通过ns进行网络隔离,在同一个ns下的pod的能相互ping通,不同ns下的不能ping通。
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
kubectl get pods --all-namespaces -o wide | grep -E "stars|management-ui|client"
执行kubectl apply -f 05-default-deny.yaml,06-default-deny.yaml ,为stars和client两个命名空间都设置的默认拒绝所有访问的网络隔离策略。此时回到浏览器中访问http:// :30002,刷新下页面,发现management-ui已经无法获取和展示服务节点之间的网络连接信息了。
执行以下命令:kubectl create -f 07-allow-ui.yaml ,kubectl create -f 08-allow-ui-client.yaml。再刷新下UI界面,发现可以展示出所有的服务节点了。各个服务节点之间仍然是不能访问的,所以节点之间没有网络流量。
执行kubectl create -f 09-backend-policy.yaml后,等待一会。再刷新UI网页发现frontend可以访问到backend了,当然仅限于是tcp port 6379。backend仍然不能访问到frontend。client仍然不能访问到frontend和backend。
执行kubectl create -f 10-frontend-policy.yaml后,刷新下UI页面,看到client到frontend的连接也有流量了。
同一个ns下,我们也可以按租户的业务需求进行网络隔离,即同一个租户有多个业务,每个业务之间的网络隔离,相同业务之间的网络打通。
demo 这个 ns 为例,为应用创建多个 label,并打不同的标签 demo1, demo2。然后依据打的label重新修改 networkpolicy。 执行kubectl create -f demo1.yaml, demo2.yaml后的结果见图2-6。
未添加网络策略之前,demo下的4个pod能互相ping通。在执行kubectl create -f policy.yaml后, 测试结果为:a.带nginx-hello1标签的pod能互访;2.带nginx-hello2标签的pod能互访;c. 带nginx-hello1标签的pod与带nginx-hello2标签的pod, 不能互通。
Kubernetes NetworkPolicy API允许用户根据标签和端口配置Kubernetes pod的入口和出口网络流量管理策略(从Kubernetes 1.8.0开始)。本案例使用网络策略控制入口和出口流量,侧重于egress出口网关的使用。
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 -
执行kubectl create -f default-deny-ingress.yaml后, 再回到busybox的测试容器中验证上网络服务的可访问性。可以看到入口流量已经被阻止,而出口网络流量还是正常的。
运行kubectl create -f access-nginx.yaml命令以创建NetworkPolicy,允许从advanced-policy-demo命名空间中的任何pod流量到nginx pod。再回到busybox测试容器中,使用wget访问nginx服务,会发现已经可以访问了。
在执行kubectl create -f default-deny-egress.yaml后,在busybox测试容器中执行wget -q –timeout=5 com-O -,会得到一个地址解析报错信息。 执行nslookup nginx会发现,也不能访问到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服务的出口流量。