容器化时代,注册中心是一个比较尴尬的存在,容器编排系统提供了比较完善的服务发现和负载均衡机制。但是这就够了吗?很明显不是,其实注册中心除了服务发现和负载均衡之外,还有很多“增值服务”,这些增值服务是容器编排做不到的。

如果微服务有些实例部署在容器外部,如服务B,有些部署在容器里面如服务A,而且都使用注册中心来互相发现,这样就有点棘手了,如果是容器内的服务,默认在注册中心上注册的是容器的IP,那么当容器外部的服务从注册中心获取到的目标服务IP肯定是无法调用的。怎么解决这个问题?本文提供了两种解决方案。
我们拿经典的spring cloud和eureka来举例:
方法1:
在容器中的应用注册的时候,以所在的hostip去注册到注册中心,同时将容器的Service的暴露方式设为NodePort,容器的containerPort设置为相同的NodePort。
eureka:client:serviceUrl:defaultZone: http://eureka.xx.com/eureka/ #注册中心地址instance:prefer-ip-address: trueinstance-id: ${spring.cloud.client.ip-address}:${eureka.instance.non-secure-port}appname: gateway2ip-address: ${EUREKA_HOST_IP}non-secure-port: ${EUREKA_NODE_PORT}server:port: ${EUREKA_NODE_PORT}
其中EUREKA_NODE_PORT和EUREKA_HOST_IP都是容器的环境变量,在创建的时候注入进去,使用Downward API,同时设置启动的端口号,该端口号和NodePort保持一致:

这样,就可以使用pod所在的host的ip注册到注册中心,且以nodeport的方式对外提供服务,达到集群内部混合部署可以同时访问的目的。
方案2:
由于POD的IP在集群内部,集群外部肯定是访问不到的,那么如何让其访问到呢?很简单,就是使用BGP或者静态路由,如服务B在集群外部,服务A在集群内部,那么在服务A所在的机器上配置静态路由,到服务B的IP的访问静态路由到k8s Node,到达任意一台k8s node都能保证被路由到正确的节点,k8s node起到一台路由器的作用,可以保证目标pod的ip被寻址到。
除此之外,其实还有很多其他的方案,不过需要做一些额外的措施,在此不再叙述了。





