前言
本文中的Kubernetes集群统称为集群。
现实的工作环境中,我们可能会在开发环境使用Kubernetes,也会在测试和开发环境使用Kubernetes。而一般来说,大部分人不会直接去连接或访问生产环境的集群,但是对于开发环境就不一样了。很多开发人员需要经常访问开发环境,而不是在本地起一堆依赖的服务。而且真的只有这么一个问题吗?
常见问题
整理了若干常见的问题:
- 开发人员本地服务访问开发环境
- 新集群和旧集群的网络互通,或者迁移
- 域名访问
因此,我们需要解决以上问题,才能更安心的使用Kubernetes。
网络互通
首先来解决最主要的问题,如何实现不同网络环境下的互通问题?
众所周知,集群暴露服务的方式有以下几种:
- NodePort 每个服务维护一个端口,服务越多端口越多
- LoadBalancer 在nodePort的基础上使用公有云的负载均衡器
- ClusterIP 每个service有一个虚拟IP
- Ingress 一个服务暴露多个service的服务,本质是一种路由转发机制
场景一、注册中心eureka的应用
首先eureka可以使用StatefulSet的方式,实现一个集群的部署。以下文件可以直接使用:
- 服务配置文件 https://img.mknight.cn/k8s/eureka/eureka-svc-np.yaml
- StatefulSet 文件 https://img.mknight.cn/k8s/eureka/eureka-sts.yaml
- Service 文件 https://img.mknight.cn/k8s/eureka/eureka-svc-np.yaml
1. 办公网访问应用
开发人员本地访问的时候可以使用NodePort的方式访问,也可以使用Ingress的方式访问。
如图所示,创建了两个Python的应用,并注册到eureka。代码如下:
1 | #!/usr/bin/python |
另外一个测试脚本:
1 | #!/usr/bin/python |
调用测试结果:
1 | python test_eureka-service.py |
这个时候说明注册中心是可以正常使用的,但是如果调用集群的服务就无法访问了,毕竟不在一个网段,也没有合适的路由。接下来就去解决这个问题。
2.办公网访问集群Pod/Service
在网关和路由器上添加路由,把属于集群的Pod和Service的子网IP全部转发给其中某个node,这样访问Pod IP和Service IP,网络包会到达某个node,而集群内的node中,CNI会与这些目的地址互通。
网段:
网段名称 | 网段范围 |
---|---|
办公网段 | 10.1.3.0/24 |
Pod地址池 | 10.200.0.0/16 |
Svc地址池 | 10.96.0.0/12 |
如果不记得当时设置的网段是多少,可以用以下方式查询:
1 | ~ kubectl get cm kubeadm-config -n kube-system -o yaml | grep -i podsub |
steps 1
选择集群中的一个节点进行路由转发,可以使用一台配置不高的节点,打上污点不允许调度占用资源。本文中使用的是master节点。
- 设置污点
kubectl taint nodes k8s-master forward=k8s-node5:NoSchedule
- 开启路由转发
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
- 查看是否生效
sysctl -p
1 | # 开启转发 |
setps 2
在办公网的出口路由上设置静态路由,将集群的Pod和Service网段,路由到master节点。
1 | # 在路由器上需要做的配置: |
setps 3
这个时候在办公网主机上ping
集群中的Pod或者service的IP,理论上就是通的。
1 | # Pod |
问题总结
如果以上操作都执行了,但是还是不通,请检查以下项目:
- 转发是否开启
- iptables的规则是否正确
- iptables规则是否有
MASQUERADE all -- 192.168.1.0/24 0.0.0.0/0
这么一条
至此,解决了开发人员无法在办公网访问集群环境的IP问题。
跨集群访问
如果我们有多个集群,这个时候如果实现网络打通呢,比如新旧集群迁移的时候?
以IP形式访问
其实我们依然可以采用之前的方案,添加静态路由。
网段:
网段名称 | 网段范围 |
---|---|
办公网段 | 10.1.3.0/24 |
集群A Pod地址池 | 10.200.0.0/16 |
集群A Svc地址池 | 10.96.0.0/12 |
集群B Pod地址池 | 10.100.0.0/16 |
集群B Svc地址池 | 10.254.0.0/16 |
主要实现逻辑是每个集群选择一个节点,开启路由转发,实现办公网段可以访问集群中的IP。
1 | ~ iptables -t nat -A POSTROUTING -s 10.1.3.0/24 -d 10.254.0.0/16 -j MASQUERADE -w |
验证:
1 | # 办公网 |
办公网通过注册中心调用
以域名形式访问Service
实现了办公网和集群的网络互通后,就可以实现自由访问Pod和Service了。但是由于Pod IP会经常变化,Service IP也不是很容易记住,所以希望通过内网DNS的形式访问*.cluser.local
时自动解析相应的IP。
steps 1. 获取coredns的IP
1 | ~ kubectl get svc -n kube-system -l k8s-app=kube-dns |
steps 2. 部署DNS服务dnsmasq
1 | yum install dnsmasq |
修改/etc/dnsmasq.conf:
1 | resolv-file=/etc/resolv.dnsmasq.conf #指定上游dns服务器 |
修改resolv.dnsmasq.conf
1 | nameserver 61.139.2.69 |
开机并启动:
1 | systemctl enable dnsmasq && systemctl start dnsmasq |
steps 3. 验证
在其他机器上测试
1 | ~ traceroute eureka.default.svc.cluster.local |
后来在其他的服务器上测试可以正常访问,在Mac下能使用nslookup解析,但是无法访问,也无法路由跟踪,以后再解决。
后来发现如果是Mac的话,直接在网络设置-高级-DNS,添加dns地址并拖到上面即可实现访问。只是奇怪的是手动修改/etc/resolv.conf
并没有实现访问,这种界面的形式反而可以,总之,解决了问题。