STEP BY STEP的指导客户将微服务从Eureka快速迁移到NACOS注册中心上并使用EDAS联动K8s快速上线应用。
背景信息
企业级分布式应用服务EDAS(Enterprise Distributed ApplicationService)是阿里巴巴中间件团队研发的PaaS平台,为企业提供高可用和分布式的互联网架构解决方案。
EDAS支持三大主流微服务框架HSF、Apache Dubbo 和 Spring Cloud,此次介绍的是Spring Cloud应用上云,包括:将客户注册中心Eureka微服务迁移至EDAS,云服务器及容器服务的应用部署。
组件介绍
Eureka注册中心
Eureka是Netflix开发的服务发现框架,基于REST的服务,主要用于负载均衡和中间层服务故障转移。Spring Cloud将它集成在其子项目spring-cloud-netflix中,以实现Spring Cloud的服务发现功能。
Eureka包含两个组件:Eureka Server和Eureka Client。
- Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在页面中直观的看到。
- Eureka Client是一个Java客户端,用于简化与Eureka Server的交互,客户端同时也就是一个内置的、使用轮询(round-robin)负载算法的负载均衡器。
EDAS注册中心
EDAS产品包含新老两种组件,一种是老版本的ANS组件,一种是功能更为多样的新组件Nacos。
ANS(Application Naming Service) 是隶属于阿里云 EDAS 产品的组件, Spring Cloud AliCloud ANS 提供了 Spring Cloud 规范下商业版的服务注册与发现,可以让用户方便的在本地开发,同时也可以运行在云环境里。
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
组件关系
应用环境
- EDAS基于专有云企业版V3.9.0版本。
- Spring Cloud框架基于Finchley.SR1版本。
注册中心原理图
Eureka迁移到EDAS Nacos
Eureka是Spring Cloud套件中常用的服务注册中心。
- 替换pom.xml文件的导入依赖包。Eureka-Server的pom.xml文件配置:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency>
Eureka-Client的pom.xml文件配置:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency>
Nacos服务注册pom.xml的文件配置:
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.1.0.RELEASE</version> </dependency>
- 替换注册中心配置文件。Eureka-Server的application.yml:
eureka: server: enable-self-preservation: false instance: hostname: eureka7001.com #eureka服务端的实例名称,单机配置是localhost client: register-with-eureka: false fetch-registry: false service-url: #单机配置 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ defaultZone: http://eureka7002.com:7002/eureka
Eureka-Client的application.yml:
eureka: client: #客户端注册进eureka服务列表内 service-url: #单机配置defaultZone: http://localhost:7001/eureka defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ register-with-eureka: true fetch-registry: true instance: instance-id: mircoservicecloud-dept8001 prefer-ip-address: true #访问路径可以显示IP地址 info: app.name: poc-mircoservicecloud company.name: www.***.com build.artifactId: $project.artifactId$ build.version: $project.version$
Nacos服务注册的application.properties:
spring.application.name=nacos-service-consumer server.port=8082 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
- 替换应用主程序类注解。Eureka启动类注解:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class}) @MapperScan(basePackages="com.poc.springcloud.dao") @EnableEurekaClient //@EnableDiscoveryClient //服务发现 //@EnableCircuitBreaker //对Hystrix熔断机制支持 public class DeptProvider_App { public static void main(String[] args) { SpringApplication.run(DeptProvider_App.class, args); } }
Nacos启动类注解:
@SpringBootApplication @EnableDiscoveryClient public class ProviderApplication { public static void main(String[] args) {SpringApplication.run(ProviderApplication.class, args);} }
EDAS ANS迁移到Nacos
当专有云为企业版V3.8.0或V3.8.1时Spring Cloud应用需要从EDAS ANS向EDAS Nacos注册中心进行迁移。
- 替换pom.xml文件的导入依赖包。ANS的pom.xml文件的配置:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alicloud-ans</artifactId> <version>0.2.2.RELEASE</version> </dependency>
Nacos的pom.xml文件的配置:
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>2.1.0.RELEASE</version> </dependency>
- 替换注册中心配置文件。说明 注解无需替换。
ANS的application.properties:
spring.application.name=ans-service-consumer server.port=8081 # ans directory and amc config spring.cloud.alicloud.ans.server-list=127.0.0.1 spring.cloud.alicloud.ans.server-port=8080 #alibaba.acm.endpoint=127.0.0.1 logging.path=/home/admin/logs #logging.path=c:\ logging.file=biz.log logging.level.root=info
Nacos的application.properties:
spring.application.name=nacos-service-consumer server.port=8082 # nacos directory and amc config spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 #alibaba.acm.endpoint=127.0.0.1 logging.path=/home/admin/logs #logging.path=c:\ logging.file=biz.log logging.level.root=info
在 ECS 集群中部署 Web 应用
- 创建ECS实例。
- 登录 Apsara Stack控制台。
- 在左侧导航栏中单击云基础产品 > 云服务器。
- 在云服务器页面中,单击创建实例。
- 在创建云服务器ECS页面中,根据提示完成参数配置:
表 1. 实例参数配置 类别 配置 说明 区域 区域 ECS实例所在的地理位置。 可用区 指在同一区域下,电力、网络隔离的物理区域,可用区之间内网互通,不同可用区之间故障隔离。如果您需要提高应用程序的高可用性,建议您将实例创建在不同的可用区内。 基本配置 部门 待创建的ECS实例所属的部门。 项目 待创建的ECS实例所属的项目。 网络 网络类型 默认为专有网络,必选项。请选择具体的专有网络名称以及交换机名称。 配置私网IP 可选项,IP地址网段取决于交换机网段。 说明- 如果私网IP为空,系统会自动分配私网IP。
- 如果此处配置了私网IP,则无法批量创建实例。
安全组 安全组 必选项,选择实例所属的安全组。 说明 创建ECS实例前,您需要提前创建好安全组。实例 I/O优化 可选项,默认为I/O优化实例。 实例系列 必选项,支持创建的实例系列:系列二、系列三和系列四。 实例规格 可选项,根据实际应用需要选择CPU和内存,有些CPU和内存的组合不能选择Windows的镜像。 镜像 镜像类型 必选项,根据需要选择镜像类型为公共镜像或自定义镜像,并选择具体的镜像信息。 存储 系统盘 必选项,选择SSD磁盘或高效磁盘,用于安装操作系统。 数据盘 可选项,选择SSD磁盘或高效磁盘。最多可以添加16块数据盘。每个数据盘的最大容量为32 TB,可以勾选随实例释放和加密。 说明- 勾选随实例释放,则该磁盘随实例一起释放,数据不可恢复;如果不勾选,则该实例释放时,系统会为用户从实例上卸载该云盘,不会被释放。
- 勾选加密,则所创建的磁盘为加密磁盘;如果不勾选,所创建的磁盘为非加密磁盘。
- 您也可以在创建实例后再添加数据盘。
配置密码 设置密码 可选项。默认为立即设置,您也可以选择创建后设置,即在控制台通过重置密码来设置密码。 登录密码 若选择立即设置,需输入登录密码。密码要求为8-30个字符,且同时包含三项(大写字母、小写字母、数字、特殊字符)。 确认密码 重新输入已设置的登录密码。 说明 这里设置的密码为远程连接实例的登录密码,非VNC密码。部署集 部署集 选择实例要加入的部署集名称。 实例名称 实例名称 可选项。建议您为自己的实例设置一个易识别的名称。 说明 2-114个字符,以大小写字母或中文开头,可包含字母数字、下划线和横杠。自定义数据 自定义数据 您可以输入相应的自定义数据编码。如果您要输入的数据已经采用Base64编码,应勾选输入已采用 Base64 编码。 说明 Windows支持bat和powershell两种格式,在Base64编码前,第一行为[bat] 或者[powershell]。Linux支持Shell脚本。申请数量 申请台数 默认为1台。如果这里申请的数量多于1台,则会按照您当前选择的配置批量创建实例。 说明 最多可批量创建50台ECS,如果配置了私网IP,则不支持批量创建。 - 单击创建。
- 创建EDAS集群。
- 登录 Apsara Stack控制台。
- 在左侧导航栏中,单击中间件产品 > 分布式应用服务 。
- 在分布式应用服务页面选择区域和部门后单击EDAS。
- 在左侧导航栏中,选择资源管理 > 集群 。
- 在集群页面上方选择命名空间,然后在右侧单击创建集群。
- 在创建集群对话框中设置集群参数,然后单击创建。
- 集群名称:输入集群名称。名字仅支持字母、数字、下划线(_)、中划线(-)和英文句号(.),且长度不能超过64个字符。
- 集群类型:选择 ECS。
- 集群网络类型:包括经典网络和 VPC 网络。根据实际需求在下拉菜单中选择网络类型。
-
VPC 网络:在下拉菜单中选择 VPC。
说明 如果没有可选 VPC 网络,请单击创建 VPC 跳转到 VPC 控制台创建。 - 命名空间:显示在集群列表页面选择的命名空间,不可配置。如果未选择,则默认显示地域。
集群创建成功后当前页面右上角会出现创建成功的提示,同时新创建的集群会在集群列表中显示。
- 在左侧导航栏中,选择资源管理 > 集群 。
- 单击集群名称,进入集群详情页面。
- 在集群详情页面,单击添加已有ECS。
- 在添加ECS实例页面,单击同步ECS,选择需要添加的ECS实例,单击完成。
- 部署应用。
- 在EDAS控制台页面,单击左侧导航栏应用管理 > 命名空间,单击创建命名空间创建新的命名空间。说明 命名空间为应用提供互相隔离的运行环境,如开发、测试和生产环境等
- 在左侧导航栏选择应用管理 > 应用列表。
- 在应用列表页面右上角单击创建应用。
- 在应用基本信息页面设置应用参数,然后单击下一步。
表 2. 应用基本信息参数说明 名称 描述 命名空间 在下拉菜单中选择命名空间。 集群类型 在第一个下拉菜单中选择 ECS集群,在第二个下拉菜单中选择一个具体集群。 应用名称 输入应用名称,长度为 1~36 个字符。 应用部署方式 根据实际应用,选择 WAR包部署或 JAR包部署。 应用运行环境 选择 标准Java应用运行环境。 Java环境 选择Open JDK 8。 应用描述 输入该应用的备注信息。 - 单击下一步,在实例例表页面中按下图所示顺序来选择实例。
- 选择立即部署,上传JAR包,输入版本号,然后单击确认创建。
- 部署完成之后,在应用列表找到部署应用名称,单击进入可以查看部署好应用的实例部署信息,同时该页面可以对部署的应用执行停止、回滚、扩容、删除、重新部署操作。
- 单击左侧导航栏日志管理 > 日志目录,日志文件catalina.out可以查看启动日志。
- 在EDAS控制台页面,单击左侧导航栏应用管理 > 命名空间,单击创建命名空间创建新的命名空间。
在容器服务K8s集群中部署应用
- 创建K8s集群。
- 登录EDAS控制台。
- 单击左侧导航中的集群 > 集群,单击右上角的创建Kubernetes集群。
- 设置集群的基本信息。
表 3. 集群参数配置表 名称 描述 集群名称 要创建的集群的名称。可以包含1~63个字符,包括数字、中文字符、英文字符和短划线(-)。 说明 集群名称在同一个用户下必须唯一。地域 所创建集群将要部署到的地域。 可用区 集群的可用区。 专有网络 您可以在已有VPC列表中选择所需的VPC。 - 如果您使用的VPC中当前已有NAT网关,容器服务会使用已有的NAT网关。
- 如果VPC中没有NAT网关,系统会默认自动为您创建一个NAT网关。如果您不希望系统自动创建NAT网关,可以取消勾选页面下方的为专有网络配置SNAT。
说明 若选择不自动创建NAT网关,您需要自行配置NAT网关实现 VPC安全访问公网环境,或者手动配置SNAT,否则VPC内实例将不能正常访问公网,会导致集群创建失败。节点类型 计划支持两种节点类型:按量付费和包年包月,包年包月暂未开放。 Master配置 选择实例规格和系统盘: - 实例规格:参见ECS云服务器 《用户指南》中关于实例规格族的文档。
- 系统盘:支持SSD云盘和高效云盘。
- Master实例数量:支持添加3个实例。
Worker实例 您可选择新增实例或添加已有实例。 Worker配置 若Worker实例选择新增实例,可进行如下配置。 - 实例规格:参见ECS云服务器 《用户指南》中关于实例规格族的文档。
- 数量:选择Worker的数量。
- 系统盘:支持SSD云盘和高效云盘。
- 挂载数据盘:支持SSD云盘、高效云盘和普通云盘。
Docker 版本和Kubernetes 版本 显示当前支持的Docker版本和Kubernetes版本,您可查看对应版本,并根据需要进行选择。 登录密码 设置节点的登录密码。 确认密码 确认设置的节点登录密码。 网络插件 支持Flannel和Terway,默认启用Flannel。 Pod网络CIDR和Service CIDR(可选项) 选择使用已有专有网络时可配置。 配置 SNAT 可选,若不选择,需要自行配置NAT网关,或手动配置SNAT。 公网SLB 会创建一个公网SLB,同时把Master节点的6443端口(对应API Server)暴露出来,用户可以在外网通过kubeconfig连接/操作集群。 SSH登录 - 选择开放公网SSH登录,您可以SSH访问集群。
- 选择不开放公网SSH登录,将无法通过SSH访问集群,也无法通过kubectl连接集群。您可手动进行配置 。
日志服务 您可使用已有Project或新建一个Project。勾选使用日志服务,会在集群中自动配置日志服务插件。 集群删除保护 防止通过控制台或API误删除集群。 高级选项 - 节点Pod数量:单节点可运行Pod数量的上限。
- 集群CA:设置是否开启集群CA。
- 在集群设置页面的右上角,最后单击创建集群。
- 在当前配置确认页面,所有项目检查通过后,单击确认,启动部署。
- 在容器服务K8s集群中部署应用(镜像)。EDAS 支持通过镜像部署容器服务Kubernetes版集群应用,您需准备好镜像,在容器服务 Kubernetes 版控制台中创建容器服务Kubernetes版集群,并将该集群导入到EDAS控制台,然后创建应用并完成部署。
容器服务Kubernetes版提供高性能可伸缩的容器应用管理能力,支持企业级Kubernetes容器化应用的全生命周期管理。容器服务Kubernetes版简化集群的搭建和扩容等工作,整合阿里云虚拟化、存储、网络和安全能力,打造云端极佳的Kubernetes容器化应用运行环境。
- 登录EDAS控制台。
- 在左侧导航栏中选择资源管理 > 集群。
- 在集群列表页面单击容器服务 K8S 集群。在集群列表中选择已创建的容器服务 Kubernetes 集群,在操作列单击导入,并在导入 Kubernetes 集群的对话框中单击导入。
当创建的容器服务 Kubernetes 集群的操作列的按钮变为删除,且集群状态为运行中,则表示容器服务的 Kubernetes 版集群已成功导入到 EDAS。
- 在 EDAS 控制台左侧导航栏选择应用管理 > 应用列表。
- 在应用列表页面选择地域和命名空间,然后在页面右上角单击创建应用。
- 在应用基本信息页面中设置应用的基本信息和参数,然后单击下一步。
- 命名空间:在左侧下拉列表选择地域;在右侧下拉列表选择命名空间,如果不做选择命名空间则设置为默认。
- 集群类型:在左侧下拉列表中选择集群类型为 容器服务 K8s 集群,右侧下拉列表内选择具体的集群。
- K8s Namespace:K8s Namespace 通过将系统内部的对象分配到不同的 Namespace 中,形成逻辑上分组的不同项目、小组或用户组,便于不同的分组在共享使用整个集群的资源的同时还能被分别管理。
- default:没有其他命名空间的对象的默认命名空间。
- kube-system:系统创建的对象的命名空间。
- kube-public:此命名空间是自动创建的,并且可供所有用户(包括未经过身份验证的用户)读取。
- 应用名称:输入应用名称。
- 应用描述:填写应用的基本情况。
- 在应用配置页面配置镜像。应用部署方式默认选择为镜像。在我的镜像区域选择您创建的镜像。
- 设置 Pod。
- 设置单 Pod 资源配额。
Pod 在运行失败或出现故障时,可以自动重启或者快速迁移,保证应用的高可用。有状态应用如果使用了持久化存储,能保存实例数据;无状态应用重新部署时不保存实例数据。您最多可以设置 Pod 总数为 50 。
- 设置单 Pod 资源配额。
系统默认不做配额限制,即单 Pod 的 CPU 和 Memory 显示为 0。如果需要限制配额,请填设置数字。
- 设置单 Pod 资源配额。
- 设置启动命令和启动参数。
- 启动命令:输入启动命令,如命令
CMD ["/usr/sbin/sshd","-D"]
,则在输入框内填写/usr/sbin/sshd –D
。 - 启动参数:一个参数写一行。如
args:["-c"; "while sleep 2"; "do echo date"; "done"]
中包含 4 个参数,需要分为 4 行来填写。
- 启动命令:输入启动命令,如命令
- 设置环境变量。
在创建应用过程中,将所填环境变量注入到即将生成的容器中,这样可以避免常用环境变量的重复添加。
假如您使用 MySQL 镜像时,可以参考如下环境变量:
- MYSQL_ROOT_PASSWORD(必选项):用于设置 MySQL 的 root 密码,必选项。
- MYSQL_USER 和 MYSQL_PASSWORD(可选项):用于添加除 root 之外的账号并设置密码。
- MYSQL_DATABASE(可选项):用于设置生成容器时需要新建的数据库。
如使用其它类型的镜像,请根据实际需求进行配置。
- 设置应用生命周期管理。
容器服务 Kubernetes 集群中的应用有两种状态:
-
无状态应用:支持多副本部署。重新部署时不保存实例数据。适用于以下使用场景:
- Web 应用,应用升级或迁移时,实例内数据不保留。
- 需要灵活水平扩展,以应对业务量骤然变化的应用。
-
有状态应用:区别于无状态应用,有状态应用会存储需要持久化的数据,在应用升级或迁移时,实例内数据不会丢失。适用于以下使用场景:
- 需要频繁通过 SSH 到容器进行操作。
- 数据需要持久化存储(如数据库应用 MySQL 等),或者集群之间有选举特性,服务发现的应用,如 ZooKeeper,etcd等。
有状态应用可以选择设置应用生命周期管理。
生命周期管理脚本说明:
-
Poststart 脚本:一种容器钩子。该钩子在容器被创建后立刻触发,通知容器它已经被创建。该钩子不需要向其所对应的 hook handler 传入任何参数。如果该钩子对应的 hook handler 执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器。
-
PreStop 脚本:一种容器钩子。该钩子在容器被删除前触发,其所对应的 hook handler 必须在删除该容器的请求发送给 Docker daemon 之前完成。在该钩子对应的 hook handler 完成后不论执行的结果如何,Docker daemon 会发送一个 SGTERN 信号量给 Docker daemon 来删除该容器。
-
Liveness 脚本:一种探测容器状态的探针,探测应用是否处于健康状态。如果不健康,则删除重建容器。
-
Readiness 脚本:一种探测容器状态的探针,探测应用是否启动完成并且处于正常服务状态。如果不正常,则更新容器的状态。
-
- 设置完成后,单击确认创建。
- 优化镜像部署。
使用通用的镜像打包出来的容器镜像体积很大,经常会达到700MB~800MB,不利于应用快速部署。
- 原因分析:
选择基础镜像CentOS7的镜像:CentOS7的镜像大小在200MB以上,在CentOS7上安装openjdk8就已经接近600MB,加上应用jar包镜像基本会达到700MB~800MB。
- 优化方法:
选择较小的基础镜像:以openjdk:8-jre-alpine作为基础镜像,openjdk:8-jre-alpine的大小不到100MB,加上jar包镜像基本为100MB~200MB。
下图为demo应用(jar包39M)和openjdk:8-jre-alpine的镜像大小:
将应用包打成镜像,需要执行以下Dockerfile代码:FROM openjdk:8-jre-alpine ENV ADMIN_HOME /home/admin ENV LANG="en_US.UTF-8" ENV TERM=xterm ENV JAVA_OPTS="" RUN mkdir -p /home/admin/app/ ADD nacos-service-consumer-0.0.1-SNAPSHOT.jar /home/admin/app/app.jar RUN echo 'java -jar $CATALINA_OPTS /home/admin/app/app.jar --server.port=8080' >> /home/admin/start.sh RUN chmod +x /home/admin/start.sh WORKDIR $ADMIN_HOME CMD ["/bin/bash", "/home/admin/start.sh"]
- 原因分析: