背景:
对于微服务的应用,Spring Cloud 和 Kubernetes 都声称自己是开发和运行微服务的最佳环境。如何将SpringCloud的Java微服务应用与Kubernetes相结合,一直是企业想实践却又觉得无法下手的痛点。
主要原因是两者是有很多重叠交叉部分,如下表格的对比:

关于SpringCloud
Springcloud Netfix 是最流行的SpringCloud框架,服务发现Eureka,熔断器Hystrix,网关Zuul,负载均衡Ribbon。
SpringCloud Alibaba也开源了一套微服务框架,可以替换SpringCloud Netfix,但并不能完全替换,如负载均衡仍然使用Ribbon。但是Netfix的注册中心Eureka可以被Nacos替换。
Nacos的作用:服务发现、分布式配置、动态DNS。
SpringCloud Alibaba还开源了Sentinel组件,负责流量控制、并发、熔断、过载保护。
OpenFeign rest 客户端。
Kubernetes
Kubernetes 是一个多语言的通用容器管理平台,对容器进行管理与调度。它提供的服务,如配置管理、服务发现、负载均衡、指标收集、日志聚合,都可以被各种语言使用。这允许在组织中拥有一个平台,可以被多个团队使用(包括使用 Spring 框架的 Java 开发人员),并服务于多种目的:应用程序开发、测试环境、构建环境(用于运行源代码控制系统、构建服务)。
本文将使用KubeSphere的Devops Pipeline部署一套SpringCloud微服务,然后使用脚本自动注册成KubeSphere微服务,启用流量治理功能。该微服务的架构如下:

- 使用Euraka Server当作注册中心,以StatefulSet部署
- 使用Springboot Gateway
- 使用统一的配置中心
源码地址
使用Devops Pipeline流水线部署应用
创建workspace(test)/项目Namespace(kubesphere-springcloud-sample)
创建GIthub Credential、Devops Project 、Pipeline

运行Pipeline创建流水线:

流水线运行成功后,检查负载创建成功。


当所有的pod正常后,未注入sidecar,能正常访问页面:

但是此时的流量拓扑是个黑盒,不清楚具体的服务调用关系。
转化为KubeSphere微服务
执行脚本,完成转化
curl https://raw.githubusercontent.com/zackzhangkai/spring-microservices-sample/master/app.sh | bash
app.sh脚本说明
默认为部署一个application,名为springcloud-microservice
使用inject.sh对deployment/statefulset注入sidecar,需要使用Istioctl
istioctl的安装方法:
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.10 TARGET_ARCH=x86_64 sh -
cp istio-1.6.10/bin/istioctl /usr/local/bin
如下,已经全部加入了sidecar:

再次访问页面,可以看到拓扑图:

链路追踪

看注册中心中的的所有的服务状态:

Springcloud Swagger文档


总结:
- SpringCloud
启动代码中添加 @EnableEurekaServer 注解
@EnableEurekaServer
public class DiscoveryApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(DiscoveryApplication.class).run(args);
}
}
- 如何修改应用端口
java的应用端口,需修改profile文件,如:

当环境中有PORT环境变量的时候,使用PORT;否则使用8088端口。
看kubernetes.yaml的部署文件中的定义:

- 为什么Eureka使用Statefulset?
使用statefulset后,会为每个POD分配一个DNS,如


- 路由
/department
/employee
/organization/2
/organization/2/with-employees
写在最后
对于springcloud向微服务的转换,因为有很多功能重叠,但是生产上每多一个功能,就会多一个故障点。因此需要对重叠的部分进行精简:
如:网关部分,可以移除zuul网关,改用KubeSphere的网关,本质上是使用Nginx Ingress;服务注册可以使用K8s DNS 提供的服务发现功能,直接使用服务名来访问;配置中心可以直接使用K8s的configmap;负载均衡也无需hypitrix,可以直接使用ipvs提供的功能,使用服务名来访问即可。
如下面的开源项目,作者讲述了如何从springcloud转向Kubernetes微服务,以及做的相关改造:
https://github.com/fenixsoft/microservice_arch_kubernetes