Spring Cloud 微服务与 K8S 的协作之道
近年微服务思想逐渐流行起来。各个企业纷纷搭建自己的微服务平台。Spring Cloud框架作为微服务架构领域中不可忽视的一员,也被很多企业选中作为搭建自身微服务平台的基石。Spring Cloud框架的组件很多,看起来有点让人眼花缭乱。
框架的核心是服务治理,只要将服务治理工具箱中的注册中心(Eureka)、服务路由(Gateway)、服务调用(Feign)组件拿出来,再加上一个配置中心,就能搭建一个小而美的微服务系统了。但是Spring Cloud框架的配置中心Spring Cloud Config因为无界面、无权限管理,并且需要Bus总线支持才能实现配置实时生效一直为人诟病。所以很多企业选择了其他开源的配置中心框架,如携程开源的Apollo。最终这个最小微服务系统变成如下的样子:
微服务启动时,统一从配置中心拉取配置,然后向注册中心注册自己的服务名称和地址等信息并保持心跳。当请求到来时,从注册中心拉取的注册信息列表中找到目标服务地址和端口,再通过Feign组件远程调用目标服务的接口。
相比SOA架构,微服务体系对服务划分粒度更细,子服务类型更多。随着业务的扩展微服务系统会迅速膨胀。这就对微服务系统的容器化部署、自动扩容、业务监控、异常告警等能力提出了更高的要求。
值得一提的是,K8s架构也提供了服务发现能力。相比Eureka的注册和发现机制。K8s使用DNS做服务发现,对异构系统的兼容性上比Eureka更好。此外,K8s的Ingress能借助Nginx、Traefik等组件引入外部流量,同时提供流量监控、熔断、限流、监控Ui等功能。能够代替Spring Cloud架构中的Gateway网关角色。
如果既要保留整个SpringCloud架构,又要借助K8s框架为微服务系统提供容器化部署和扩容能力。那么如何在K8s中部署Apollo和Eureka服务,才能在这类服务崩溃并被调度到其他节点重启后仍然能被其它子服务发现?如何在K8s中部署Gateway网关,才能引入外部流量,又能提供高可用和负载均衡能力?
上图是一个Apollo和Eureka服务部署方案。借助K8s提供的DNS服务发现和Service虚拟Pod组功能,为ApolloConfig Pod和Eureka Pod创建对应的Service。需要注意的一点是Apollo Config Pod可以共用一个Service,但是Eureka Pod需要创建各自的Service。其他普通服务使用Apollo Config Service和Eureka Service的服务名称作为配置中心和注册中心的地址。普通服务拉取配置或注册的时候,先到Coredns服务查询服务名称对应的Service访问地址。访问请求发到对应的Service上后会被负载均衡到后端的Pod上,最终到达真正的服务实例上。
下面讲一下SpringCloud网关Gateway的部署方式:
K8s的Service有4种类型。其中的“LoadBalancer”类型能够实现引入外部流量的功能,但是需要云平台负载均衡器的支持,所以使用范围受限。“NodePort”类型,则是在所有Node上开通一个Node Port端口接收外部流量。为Gateway Pod创建一个“NodePort”类型的Gateway Service,然后选择几个Node的访问地址,将这些地址和Nodeport端口配置到外部的负载均衡器中。这种配置对负载均衡器没有特殊要求。
