当Spring Cloud 遇上Kubernetes

当Spring Cloud 遇上Kubernetes

许多客户在微服务顾问的评估工作做完之后,才有感而发:

以为用Spring Cloud 成功打造了微服务架构,殊不知导入了Kubernetes 之后,却和Cloud Native 的主流发展生态脱节了。


从Spring Boot 一直到了Spring Cloud,许多早已导入的大企业,很久之前就建构出了一个完整的微服务(Microservice)生态,也因为很多的解决方案早已开放原始码,可以说开发资源已经相当成熟。


这对于许多想要导入微服务架构的企业来说,无疑的是一个最佳的进入点,只要你导入Spring Cloud,并采用其生态内相关的元件,基本上构建出一套微服务架构,绝对不会有什么问题,也是正确的选择。


只是导入了Kubernetes 之后,似乎一切变了调。


导入Kubernetes 后到底发生了什么问题?我们又该如何解决?本文将浅谈这个议题,并整理一些解决的手段。


1. Kubernetes 与Spring Cloud 的冲突点?


身为Java 开发者极为幸运,有个Spring Cloud 这样完整的微服务框架可以使用,至少微服务架构下所需的基本需求,都能满足。网路上也有数不清的文献,可以快速学习怎么利用这框架开发出自己的微服务架构。


但也由于Spring Cloud 生态具备着各种完整的微服务元件,在今天Kubernetes 当道的情况下,当我们把基于Spring Cloud 开发的服务放到Kubernetes 之上后, 一些机制将变成自成一格,不受Kubernetes 生态系的工具和机制所管控。


这一切原因,都是因为从扩展部署、维运面角度出发的Kubernetes,在最原始容器、应用程式部署及网路层管理的基础之上,已经逐步实现并贴近应用层的需要,一些微服务架构下的基础需求(如:Service Discovery、API Gateway 等)开始直接或间接被纳入在Kubernetes 的生态里。


这导致两方有些元件功能重叠,而且只能择其一使用, 一旦你选了Spring Cloud 的解决方案,就代表你得放弃掉Kubernetes 那一边的机制。


2. Spring Cloud 官方提供的解决方案


为了解决这样的问题,官方在Github 上提供了一个开放原始码专案,说明如何以Spring Cloud 整合Kubernetes 生态下的元件,主要讨论从原本的元件架构过渡并移植到Kubernetes 原生环境后的处理方法:


github.com/spring-cloud
有兴趣可以自行参考,在接下来的章节,将大概整理一下这份解决方案的几个重点。

2-1. 服务发现(Service Discovery)


关于服务发现,在Spring Cloud 的经典解决方案中,最知名的不外乎是Netflix Eureka 和Hashicorp。其主要原理是在服务部署时,去注册自己的服务,让其他的服务可以查询并找到自己。


但在Kubernetes 的领域,服务的注册和查询是由Service 元件所负责,其连线名称,则是利用内部DNS 来实现。这代表我们要将服务发现的功能,接上Kubernetes 的Service 机制。
为了达成这个需求,解决方案中提供了DiscoveryClient 这个元件,让基于Spring Cloud 所开发的应用程式,可以方便查询其他服务。


使用了Kubernetes 原生的服务发现,才能被Istio 所追踪,未来才能纳入Service Mesh 的管辖。

2-2. 设定参数管理(Configuration Management)


在设定参数管理上, Spring Cloud 也有一些既有的解决方案,如:Config Server、Consult 或Netflix Archaius 等。但在Kubernetes 上,有ConfigMap 和Secret 可以使用,而且通常还会搭配Vault 来管理敏感设定。


官方的解决方案提供了ConfigMapPropertySource 和SecretsPropertySource 的参考实作,来存取Kubernetes 上的ConfigMap 和Secret。

2-3. 负载平衡和熔断器(Load Balancing & Circuit Breaker)


在Spring Cloud 上有常见的负载平衡元件Netflix Ribbon 和熔断器Hystrix,但在Kubernetes 的世界,有Service 元件可实现负载平衡,以及Istio 可实现熔断器,开发者通常不用烦恼这个问题。


由于负载平衡和熔断器的工作,会依赖着服务发现机制,因此Ribbon 和Hytrix 原先的功能在Kubernetes 的原生环境下会失效。官方解决方案内虽有提到了一些关于Ribbon 整合Kubernetes 原生环境的实作,但由于相关实作连结已经消失,因此这部分就不做多说明。

2-4. 原有的服务注册(Service Registry) 机制将失效


Spring Cloud 原本有自己的一套服务注册机制,透过下面的设定可以影响服务注册的行为:

  • spring.cloud.service-registry.auto-registration.enabled
  • @EnableDiscoveryClient(autoRegister=false)

在Kubernetes 的环境下将失效,因为服务发现不再由Spring Cloud 的框架所掌控。


另外补充

Spring Cloud 与Kubernetes 生态系之间的替代方案对照

除了Spring Cloud 官方解决方案所提及的之外,其他维运层面的部分也同样有对应的方案,在这里一并补充,可参照上面图表。


当然,我们能完全不理会Kubernetes 原生生态的元件,完全采用Spring Boot 和Spring Cloud 的解决方案和框架,然后只把Kubernetes 当作是部署应用程式的工具和平台。但显然在未来,Service Mesh 及其它通用的Cloud Native 技术发展,就会与我们脱节,无法与我们的应用程式深度整合。


后记


相较于Spring Cloud 的生态以Java 语言为主,Kubernetes 生态的发展和设计更为通用且广泛,一些Spring Cloud 内的元件功能,在Kubernetes 除了包含支援以外,甚至有更多的整合和考量及延伸的功能。


由于CNCF 的推波助澜及更多厂商投入,许多新工具、维运方法、整合能力都层出不穷。因此,在计划导入微服务架构时,关于Kubernetes 的各项原生解决方案,需要被放入评估考量之中。


原文链接:

发布于 2021-02-23 18:01