--昨夜西风凋碧树,独上高楼,望尽天涯路

  • 问题

当通过Kubernetes部署微服务的时候,发现Spring Cloud配置文件中配置的外部数据库链接无法访问(数据库在其他不受k8s控制的服务器,以及配置的ip是内网ip)。通过docker exec进入容器内部访问数据库ip,发现无法访问:

  • 原因分析

这是由于部署Kubernetes的时候大多使用flannel或者calico插件带来的解决方案,这种扁平化的解决方案使得所有的pod之间可以相互通信(可以跨主机哦)。每个容器相当于一个endpoint(可以理解为虚拟网卡),这些endpoint向flannel传送包,flannel在做分发和处理。但是当通过容器内部连接其他服务器的内网的时候是不可达的。

我们继续在容器内部ping 数据库的内网,之后新开一个窗口通过tcpdump命令追踪cni0发包(cni0可以理解为类似eth0):

发现根本没有响应。

  • 解决方案

基于上述情况,Kubernetes提供了Endpoint方式方式来访问外部服务。大致做法就是定义一对匹配的endpoint和service,Service负责Pod和外部网络的交互,Endpoint连接Service和外部服务,配置如下:

Endpoint:

apiVersion: v1
kind: Endpoints
metadata:
  name: mysql-service         #必须和对应的Service一样   
subsets:
  - addresses:
    - ip: 10.10.14.21         #数据库内网地址
    ports:
    - port: 3306              #数据库端口
      protocol: TCP

Service:

apiVersion: v1
kind: Service
metadata:
  name: mysql-service            #service name 必须和endpoint name 一致
spec:
  clusterIP: 10.106.106.106      #自定义暴露的Ip 在spring cloud配置文件中填写该ip
  ports:
  - port: 3306                   #service ip
    targetPort: 3306             #与endpoint对应的ip
    protocol: TCP

Spring Cloud配置如下:

所以大致流程为:加载Spring Cloud配置文件的时候会通过配置的Kubernetes ServiceIP来打通一条网络,之后Kubernetes Service通过与之匹配的Endpoint来访问远程服务

Logo

开源、云原生的融合云平台

更多推荐