SpringCloud微服务迁移至Kubernetes实践
前言
原SpringCloud基础上的微服务已稳定运行近1年,遗留了一些问题不太好处理。原SpringCloud的整理文章见基于SpringCloud微服务的服务平台搭建的一些总结
问题如下:
- 客户端侧负载均衡在服务实例故障下线时候,不能及时发现,导致请求到故障实例地址造成请求错误,若增加请求重试配置,对于非幂等接口处理困难。
- 基于SpringCloud Config的配置中心有时候会有不及时刷新svn上的配置信息的情况(需要重新config),没找到这个问题的原因。另外多环境(生产、测试环境独立的配置)、多级配置(本地、配置中心)的组合设置对于组内其他开发者而言,学习成本较大,经常出现用错配置的情况。
- 若要使用微服务,则必须使用SpringCloud技术栈开发,对开发人员的技术选型是一种不必要的约束,另外大量的SpringCloud应用对与机器内存资源的占用比较严重(一个应用动辄上百兆内存),拆分成大量微服务后对于机器内存的浪费尤为严重。
- 虽然SpringCloud有Eureka,但是由于各个服务不是在所有物理机器上都起着副本,当服务器故障需要恢复时,仍然需要留意当时机器上运行程序的情况,常常出现机器上残留的旧版本应用被其他人启动起来的情况。无法做到不关心实例的具体部署。
- 服务的升级较为麻烦,在缺乏有效的自动化部署程序,缺乏有效滚动升级方案,以达到不中断服务的同时逐个替换现有服务实例。
改造方式
部署Kubernetes集群
网上教程挺多的,这里就不详细写了,用的1.11。但是遇到过问题。我们集群用的3.10的kernel,在1.11的kubernetes中网络默认用的ipvs,经常导致kernel panic,后来重新部署时候把ipvs去掉,换回原来的iptables就好了。
SpringCloud应用改造
首先要去除对于eureka的maven依赖和config的依赖,并去除@EnableEurekaClient的注解即可。
其次服务调用方面由于没有Eureka了,FeignClient也需要进行一些变动,但是又要尽量简化开发和修改步骤,如果还得由开发人员记住每个服务的IP和端口那就有点退化的厉害了。我们做如下设置。
1) 应用在Kubernetes内的封装
– 关于端口:每一个微服务在kubernetes内都有一个Deployment负责Pod的部署、端口暴露(Expose出Spring应用的server.port即可)
– 对服务的封装:每个应用还需要一个Service来做服务实例的负载均衡,这样服务之间调用就只要找服务对应的Service就好。Service的ip地址由Kubernetes内部DNS负责解析。服务对外统一用80端口,这样集群内部访问时候就只要写服务名称即可。同时Service的名称和微服务的应用名称一致。
2)FeignClient的改造
原SpringCloud内只要指定serviceName就能通过Ribbon自行负载到对应的实例上,现在则需要通过Kubernetes的service实现调用,由于1)已经约定了Service名称与原服务名称一致,同时端口是80。因此只要加上url就行。
如:
// 这里的url是新增参数
@FeignClient(name="remote-service", url="remote-service")
public