当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 原生环境后的处理方法:
https://github.com/spring-cloud/spring-cloud-kubernetes
有兴趣可以自行参考,在接下来的章节,将大概整理一下这份解决方案的几个重点。
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 Boot 和Spring Cloud 的解决方案和框架,然后只把Kubernetes 当作是部署应用程式的工具和平台。但显然在未来,Service Mesh 及其它通用的Cloud Native 技术发展,就会与我们脱节,无法与我们的应用程式深度整合。
后记
相较于Spring Cloud 的生态以Java 语言为主,Kubernetes 生态的发展和设计更为通用且广泛,一些Spring Cloud 内的元件功能,在Kubernetes 除了包含支援以外,甚至有更多的整合和考量及延伸的功能。
由于CNCF 的推波助澜及更多厂商投入,许多新工具、维运方法、整合能力都层出不穷。因此,在计划导入微服务架构时,关于Kubernetes 的各项原生解决方案,需要被放入评估考量之中。
原文链接: