k8s 内网和办公网络的打通实践
1、背景
第一想法:关掉这个redis
服务,让研发“被迫”主动告知;规范要求,在k8s
集群内部部署该项目的redis
服务集群,保证环境一致性,减少不必要麻烦。
项目多数属于微服务应用模块,研发本地无法完整运行全部依赖,希望在本地运行某个服务后,能够注册到qa
容器环境的依赖服务中进行调试。例如在k8s
中运行的redis
、rabbitmq
等服务,研发在当前环境下无法直接通过客户端工具连接进行访问,给研发测试进行联调带来了很大麻烦,且k8s
内部通过cni
插件创建pod
和service
的内部网络,这类服务无法通过ingress
进行7层暴露,如果通过NodePort
模式暴露给研发,不仅使用有限而且会导致端口管理困难从而工作量加大。因此打通开发和测试环境k8s
集群内网和办公局域网络是有很大必要性的。
2、环境说明
相关网络拓扑如下
-
办公子网:172.16.0.0/24 -
DMZ
区域服务器子网:172.16.1.0/24、172.16.2.0/24 -
k8s pod
子网:172.20.0.0/16 -
k8s service
子网:10.68.0.0/16
其他涉及到的相关服务及ip
说明
-
k8s
网络插件:flannel
,对应网络模式为host-gw
-
k8s kube-dns service ip
:10.68.0.2 -
内网
dns
服务:ms(windows) server dns -
内网
dns ip
:172.16.2.3 -
FortiGate ip
:172.16.2.254
3、总体思路
k8s
集群部署在测试机房,整个局域网链路、外网、防火墙由飞塔防火墙FortiGate
设备统一控制,除k8s
集群内部网络外,其他网络均已通过FortiGate
打通,所以目前面临的问题就是网络打通和dns
解析打通。
-
网络打通
-
dns
解析打通网络打通后,就可以在办公网络通过
pod
或service
的ip
进行连通了。但是每次更新服务,ip
通常都会发生变化,我们想通过服务名称(域名)而不是ip
进行通信,解决dns
问题主要有以下两个方向 -
网络已经打通了,那么就可以把 k8s
的coredns
作为本地的dns
服务器 -
把所有通过办公网络请求 k8s
中的服务(域名)的记录从内网dns
服务器转发到k8s
的coredns
4、网络打通的具体实现
4.1 检查现有网络连通情况
4.1.1 办公网络和k8s node
在本地pc
电脑上操作
➜ ~ ping 172.16.1.106 -c 4
PING 172.16.1.106 (172.16.1.106): 56 data bytes
64 bytes from 172.16.1.106: icmp_seq=0 ttl=63 time=1.621 ms
64 bytes from 172.16.1.106: icmp_seq=1 ttl=63 time=1.568 ms
64 bytes from 172.16.1.106: icmp_seq=2 ttl=63 time=1.221 ms
64 bytes from 172.16.1.106: icmp_seq=3 ttl=63 time=1.338 ms
--- 172.16.1.106 ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.221/1.437/1.621/0.164 ms
4.1.2 k8s node和pod及svc
在k8s
任意一台node
上操作,通过nslookup
同时检查网络和dns
功能是否正常,这里以172.16.1.106
这台node
为例
[root@k8s-qa-node-02 ~]# nslookup -q=A kubernetes.default.svc.cluster.local 10.68.0.2
Server: 10.68.0.2
Address: 10.68.0.2#53
Name: kubernetes.default.svc.cluster.local
Address: 10.68.0.1
查看node
的路由
[root@k8s-qa-node-02 ~]# ip route
default via 172.16.1.254 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
172.16.1.0/24 dev eth0 proto kernel scope link src 172.16.1.106
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
172.20.0.0/24 via 172.16.1.100 dev eth0
172.20.1.0/24 via 172.16.1.101 dev eth0
172.20.2.0/24 via 172.16.1.110 dev eth0
172.20.3.0/24 dev cni0 proto kernel scope link src 172.20.3.1
172.20.4.0/24 via 172.16.1.107 dev eth0
172.20.5.0/24 via 172.16.1.108 dev eth0
172.20.6.0/24 via 172.16.1.109 dev eth0
# ...省略部分条目
4.2 添加地址
网络打通主要在网关和路由器设备上进行操作,这里仅以FortiGate
为例进行记录。为了配置流程清晰,通过终端命令行进行配置而不是web
界面操作,首先通过console
或者ssh
连接上FortiGate
的终端
FortiGate # config firewall address
FortiGate (address) # edit k8s_SERVICE_CIDR
new entry 'k8s_SERVICE_CIDR' added
FortiGate (clientnet) # set subnet 10.68.0.0 255.255.0.0
FortiGate (clientnet) # next
FortiGate (address) # edit k8s_POD_CIDR
new entry 'k8s_POD_CIDR' added
FortiGate (clientnet) # set subnet 172.20.0.0 255.255.0.0
FortiGate (clientnet) # next
FortiGate (address) # end
FortiGate #
4.3 配置静态路由
配置到达k8s svc
子网的路由
FortiGate # config router static
# 新增一条静态路由,id尽量大,不与已有的冲突
FortiGate (static) # edit 10
new entry '10' added
# 配置目标地址和掩码
FortiGate (2) # set dst 10.68.0.0 255.255.0.0
# 配置网关(下一跳)
FortiGate (2) # set gateway 172.16.1.106
# 配置接口名
FortiGate (2) # set device Test
FortiGate (2) # next
FortiGate (static) # end
FortiGate #
同理,配置到达k8s pod
子网的路由
FortiGate # config router static
FortiGate (static) # edit 11
FortiGate (2) # set dst 172.20.0.0/16 255.255.0.0
FortiGate (2) # set gateway 172.16.1.106
FortiGate (2) # set device Test
FortiGate (2) # next
FortiGate (static) # end
FortiGate #
检查配置的静态路由
FortiGate # get router info routing-table static
# ...省略部分条目
S 10.68.0.0/16 [10/0] via 172.16.1.106, Test
S 172.20.0.0/16 [10/0] via 172.16.1.106, Test
4.4 配置策略
配置到达k8s service
网络放行策略
FortiGate # config firewall policy
# 新增一条网络策略,id尽量大,不与已有的冲突
FortiGate (policy) # edit 100
# 配置源接口
FortiGate (100) # set srcintf internal
# 配置目的接口
FortiGate (100) # set dstintf Test
# 配置源地址
FortiGate (100) # set srcaddr 172.16.0.0/24
# 配置目的地址
FortiGate (100) # set dstaddr k8s_SERVICE_CIDR
# 配置动作类型
FortiGate (100) # set action accept
# 配置动作时间
FortiGate (100) # set schedule always
# 配置服务(协议类型)
FortiGate (100) # set service ALL_TCP
# 配置是否开启日志
FortiGate (100) # set logtraffic disable
# 配置是否开启nat
FortiGate (100) # set nat disable
end
同理,配置到达k8s pod
网络放行策略
FortiGate # config firewall policy
FortiGate (policy) # edit 101
FortiGate (100) # set srcintf internal
FortiGate (100) # set dstintf Test
FortiGate (100) # set srcaddr 172.16.0.0/24
FortiGate (100) # set dstaddr k8s_POD_CIDR
FortiGate (100) # set action accept
FortiGate (100) # set schedule always
FortiGate (100) # set service ALL_TCP
FortiGate (100) # set logtraffic disable
FortiGate (100) # set nat disable
end
4.5 验证配置
4.5.1 web界面检查
登录到FortiGate
界面,查看配置的静态路由
网络策略
4.5.2 pc网络检查
在pc
端检查pod
网络是否可达并在上文中选取的网关node
上抓包
5、dns解析打通的具体实现
5.1 配置dns条件转发
上面已经将网络进行了打通,dns
解析的打通在内网dns服务器上设置dns
转发即可。
打开ms(windows) server
类型的dns
管理器配置界面,新增条件转发器,如下所示,dns
域填写k8s
集群中兼容所有命名空间的搜索域。当然,为了安全,建议单独设置允许可达的命名空间下的服务,例如default
,则填为default.svc.cluster.local
。
5.2 验证配置
在本地终端上测试解析k8s service
域名,成功解析
➜ ~ nslookup redis-abc-gns.default.svc.cluster.local
Server: 172.16.2.3
Address: 172.16.2.3#53
Non-authoritative answer:
Name: redis-dkj-gns.default.svc.cluster.local
Address: 172.20.4.222
6、小结
至此,就成功的将办公网络和k8s
内网进行打通,研发以后就可以在开发机器上利用和qa
环境一样配置的svc name
连接对应依赖的redis
等组件了。
此方案主要利用局域网静态路由,在网关进行配置。透明且高效,且开发测试环境无须再部署其他组件。