SpringBoot工程开发Docker化微服务
目录
5.1.4 采用LoadBalancer模式部署微服务到K8S
1. 微服务容器化治理的优缺点
1.1 微服务容器化的优点
最近一直在研究在项目中推进Docker化的可行性,原来项目组采用的技术栈是SpringCloud,而Docker化带来的价值主要包括以下几个SpringCloud体系所不具备的优势:
- 产品的安装部署和版本发布效率会提升。这里的背景是我们的产品主要是需要能够为不同的客户进行本地化部署,而不是目前主要的互联网公司的一个网站的模式。用SpringCloud,则产品的安装部署主要是用自己写安装部署脚本,或开发安装部署工具,较为复杂。
- 产品的动态伸缩能力会更强。基于K8S可以实现Docker容器的动态伸缩,而SpringCloud体系实现该能力要难度高一些。
- 灰度发布能力会更强。这点SpringCloud也能实现,但是需要借助第三方工具,且相对于K8S,实现起来会比较复杂。
- 写代码时可以更聚焦业务,不需要把微服务的治理和业务代码耦合。而SpringCloud体系本身需要业务代码和微服务治理体系耦合,如微服务需要知道Nacos,SpringCloud的SDK中也要求微服务对微服务治理相关的组件要了解,并做好配置。
1.2 微服务容器化的缺点
当然,采用全面的Docker化也存在一些缺点:
- 第一就是运维成本的升高。采用K8S对微服务进行治理,虽然将业务代码和微服务管理进行了剥离,但是K8S本质上是将微服务管理IaaS化了,所以对K8S运维的要求比较高,对人员技能要求也比较高。
- 第二就是这种模式并不太成熟。K8S对微服务的管理,本质上是ServiceMesh模式,而非SpringCloud的Microservice SDK模式。而ServiceMesh模式目前主流的技术方案是Istio K8S,技术成熟度还不太高。
2. 微服务的两种模式
刚刚学习Docker和K8S的时候,习惯性的想把SpringCloud的微服务治理体系装到K8S里面。但直觉上一直认为这种模式很别扭,因为K8S也有类似SpringCloud的完整微服务治理体系,如etcd、API Server等。只到后来看到一个华为大神写的文章《最佳实践:从Spring Cloud 到 Istio》(https://zhuanlan.zhihu.com/p/358891699),才恍然大悟:SpringCloud是Microservice SDK模式,K8S时ServiceMesh模式;两者完全是不同的两种设计思想,强行把他们揉到一起,有点儿要把马车和汽车焊在一起的赶脚。
2.1 Microservice SDK
微服务SDK曾经是一个常用的解决方案。将微服务化后通用的能力封装在一个开发框架中,开发者使用这个框架开发写自己的业务代码,生成的微服务自然就内置了这些能力。这种模式中,业务代码和微服务框架代码是耦合在一起的的。SpringCloud就是这种模式的典型代表,采用SpringCloud框架,业务代码和SpringCloud框架的Nacos、Sentinel、SpringCloud Gateway等是强耦合的,业务代码的Maven工程和SpringCloud的这些工具集是强绑定的。如果后续不采用SpringCloud框架了,那业务代码基本上也要进行大面积的重构。
这里适当展开一下,SpringCloud本身包含最核心的Spring Framework,和简化配置开发能力的SpringBoot框架,以及SpringCloud框架。
早期SpringCloud大部分基于Netflix的版本,采用Eureka、Ribbon、Hystrix、Zuul/Zuul2、SpringCloud Config等工具库来实现微服务治理的基本框架。但随着框架的演进,Netflix版本目前已经不再维护了。
当前业界采用的主要是SpringCloudAlibaba版本,是阿里基于SpringCloud开发的版本,采用Nacos、Sentinel、SpringCloud Gateway等工具实现了微服务治理的基本框架。
目前SpringCloudAlibaba版本的主要工具库如下图所示。
2.2 ServiceMesh
ServiceMesh,也就是常说的服务网格,是通过另一种形态提供治理能力。不同于SDK方式,服务治理的能力在一个独立的代理进程中提供,完全和业务代码开发解耦。从本质上讲,微服务SDK是一种开发框架,而ServiceMesh是一个基础设施。
当前最流行的ServiceMesh模式是K8S Istio,采用SideCar模式实现业务代码和服务治理的解耦。
3. 微服务容器化治理的推荐模式
根据上一章的说明,大家应该可以看到,如果要将微服务容器化,建议大家采用ServiceMesh模式。在该模式下,可以灵活的采用不同的开发语言,如Golang、Node.js、Python、Java等;同时也不需要再绑定SpringCloud等微服务框架,只需要聚焦最核心的业务代码开发既可。
仍然以Java语言为例,采用ServiceMesh模式,只需要采用Maven SpringBoot框架开发既可。
4.Windows下开发容器化微服务(非K8S)
按照前面的总结,我们将采用SpringBoot为开发框架,搭建容器化的微服务环境。
4.1 开发环境
开发语言:Java
代码框架:Maven SpringBoot
开发工具:VSCode
开发插件:Extension Pack for Java, Spring Boot Extension Pack, Docker
Docker环境:Docker Desktop
K8S环境:利用Docker Desktop中自带的对Kubernetes的支持
具体的安装部署这里不再赘述,大家可以上网搜索。配置国内的Maven库和Docker Registry也不再赘述,大家网上搜索既可。
这里重点要说一下VSCode真的是很不错的开发环境,微软官方的开发插件对开发效率有极大的提升,上述几个开发插件大家一定要用好。
4.2 代码框架
4.2.1 SpringBoot开发框架
VSCode的Extension Pack for Java和Spring Boot Extension Pack对SpringBoot的Maven工程创建支持非常好,可以在VSCode中按照引导一步步创建工程即可。
这里建议创建Spring Boot类型的工程,然后再选择Maven类型工程,再按提示选择。
不建议创建Maven类型的工程,然后再选择SpringBoot类型的archetype。因为这种模式,可选的archetype比较杂,对SpringBoot的版本配置也比较乱,需要手动做不少调整。
4.2.2 增加docker支持
4.2.2.1 pom中增加dockerfile-maven-plugin
这里用到了dockerfile-maven-plugin插件,来为maven工程增加docker能力的支持。该插件是spotify公司开发的插件,将docker和maven进行了集成,可以在maven工程中,基于Dockerfile的配置,将工程打包成docker镜像,并支持push和tag等功能。具体的pom配置请见下图。
需要注意的是,该插件的前身是docker-maven-plugin,官方已经声明docker-maven-plugin不再继续演进,建议开发者切换到dockerfile-maven-plugin。目前往上有大量的docker-maven-plugin的教程,需要大家注意不要被误导采用老旧的插件。
4.2.2.2 工程中增加Dockerfile
在VScode中按F1键,输入Docker: Add Docker File to Workspace,可以在工程中增加Dockerfile。默认增加Dockerfile到根目录,如果手动添加到其他目录,会出现编译错误。
Dockerfile创建后,VSCode的Docker插件会根据Maven工程自动初始化Dockerfile的内容,如下图所示。
这里需要注意的是,Docker镜像打包时,需要有底层OS和JDK的支持,开发人员可以根据自己工程采用的java版本,在hub.docker.com上搜索对应的底层docker依赖,并写到Dockerfile的FROM部分。如上图所示,这里用到的是JDK 19,在hub.docker.com中可以搜到很多版本,这里选择的事openjdk: 19-jdk-alpine。选择openjdk是为了避免被Oracle收费,19-jdk表示jdk 19版本,alpine表示基于alpine的linux,这个版本的linux比较小,占用的资源较少,连同jdk合计185.34MB。
另外,根据工程的需要,刻在Dockerfile中通过EXPOSE port,开放指定端口,以便外部访问。示例工程中开放到是8080端口。
Dockerfile配置完成后,启动本地的Docker Desktop,再执行Maven编译,可以生成docker image,并自动推送到Docker Desktop。如下图所示:
至此,该工程的docker文件已编译打包完成,并成功push到本地的docker库上。
4.3 运行Docker化的微服务
基于Docker Desktop可以启动上面创建的微服务的Docker容器,启动时需要配置一下端口映射,将容器暴露的端口映射到本地端口,以便可以通过本地浏览器访问发布的docker服务。具体操作可以用Docker Desktop提供的功能设置。
如下图所示,选择要运行的image,点击Run按钮。
在弹出的窗口中可以配置Container name和端口映射,完成后点击Run:
执行Run后,可以在Docker Desktop上看到启动日志,如下图所示,启动正常。
Terminal标签是该Container的shell,可以在里面执行shell命令,如下图所示。
5. 部署基于SpringBoot的微服务容器到K8S
根据前面章节的步骤,我们创建出了基于SpringBoot框架的微服务的Docker image,并上传到了本地Repository上。本章我们将前面创建的微服务部署到K8S上,并能通过外部访问。
5.1 微服务容器在K8S上的部署架构
由于K8S内部有自己的网络结构,K8S集群外部访问K8S上部署的服务时有多种方法。这里先简单介绍一下K8S内部署的服务的内外部访问方式,以便于大家理解本文示例的部署架构。
在往下看之前,请大家先自行学习K8S的网络结构,理解Pod、Service、Node几个概念,以及各自的IP和Port分别是在哪个子网中,是否和外网相通等概念。
5.1.1 K8S集群内服务访问方式
K8S集群内的Pod之间,可以通过两种方式互相访问:
5.1.1.1 通过ServiceIP访问
ServiceIP可以通过kubectl get svc命令获取。
5.1.1.2 通过服务名访问
通过服务名访问,会通过K8S的DNS进行解析。访问方式有2种:
1.在同一个Namespace下的服务,通过http://servicename:port来互相访问。
2.在不同Namespace下的服务,通过http://servicename.namespace:port来互相访问。
5.1.2 K8S集群外访问K8S集群内服务的方式
5.1.2.1 通过hostNetwork访问
在Pod中设置hostNetwork: true,即可通过http://NodeIP:PodPort来访问。
该方式由于Pod动态启停,部署到的Node会变化,NodeIP会变化,所以只适合临时访问,或者每一个Node只能启动一个同deployment的Pod的情况下。
5.1.2.2 通过hostPort访问
通过将Pod的端口直接映射为Node上的端口,即可通过http://NodeIP:NodePort来访问。
该方式需要维护端口映射关系,不然Pod重新调度后端口的变化会导致地址失效。所以也只适合临时访问。
5.1.2.3 通过NodePort访问
为Pod创建NodePort类型的Service后,即可通过http://NodeIP:PodPort来访问。
该方式下,NodeIP和PodPort是固定的,不会随着K8S的动态调度而发生变化。
5.1.2.4 通过LoadBalancer访问
这种方式一般是部署到华为云、阿里云等公有云上,利用他们提供的LoadBalancer,来通过外网IP和Port来访问。
当然,也可以通过MetalLB等第三方中间件实现本地化部署的LoadBalancer。
5.1.2.5 通过Ingress访问
通过部署K8S官网的Ingress-Nginx-Controller,可以配置以域名的方式访问K8S上部署的服务。
5.1.3 采用NodePort模式部署微服务到K8S
这里先采用NodePort的方式将微服务部署K8S上,部署架构大体如下图所示:
上图为网上找到的一张图,对NodePort的描述比较形象。如图所示,NodePort模式下,只能通过一个固定的Node的IP Port来访问本Node中部署的Pod上的服务,并未经过API Server,也不支持负载均衡。如果Pod被部署到多个Node上,实际上只会访问NodeIP对应的一个Node上,无法实现多个Node之间的负载均衡。
由于在Service定义时,会通过nodePort配置,把K8S内部的服务映射到Node本地的端口上,所有可以使用Node的本地IP加上映射出的外部端口(nodePort)实现外网访问。
整个部署过程,主要通过deployment文件进行相应的配置,并通过kubectl apply命令来完成部署。
5.1.3.1 创建Namespace
为了将微服务统一部署到一个Namespace下,首先需要通过yaml文件创建Namespace,如下图所示。
然后执行kubectl apply -f namespace.yaml命令,可以创建名称为accchn的Namespace。如下图所示。
5.1.3.2 通过deployment文件部署pod
编写微服部署到K8S的deployment.yaml文件,内容如下图所示。其中,spec.containers.image,按照第4章生成的Docker Image的实际路径获取。spec.containers.ports.containerPort配置程8080,因为该Docker容器下的微服务暴露了8080端口。
然后执行kubectl apply -f deployment.yaml,来部署微服务,如下图所示。
5.1.3.3 创建访问该微服务的Service
编写相应的Service部署的yaml文件,如下图所示。通过配置spec.ports.nodePort,将服务端口映射到Node服务器本地的30777端口,可以直接通过Node的外网IP:30777来访问。
执行kubectl apply -f service.yaml来创建该服务。
5.1.3.4 通过NodePort方式访问部署好的微服务
通过前面的3个步骤,将服务映射到了Node上。因为我们是在单机的Docker Desktop上部署了K8S,所以Node的外网IP就是localhost。通过http://localhost:30777即可访问部署好的微服务。
5.1.3.5 该模式存在的问题
由于采用了NodePort的模式,并未实现LoadBalancer。后续继续学习LoadBalancer的部署模式,从而实现基于外网IP的、不需要域名的全面负载均衡。
有同学可能会问,为什么不直接用Ingress?主要是因为Ingress必须要映射域名,而我自己的测试环境,没有公网IP,同时配置host文件又会增加跨用户/开发设备调测的复杂度,不利于刚刚接触项目的开发人员更快的熟悉环境。所以才会研究LoadBalancer的模式。
5.1.4 采用LoadBalancer模式部署微服务到K8S
(未完待续。。。)
6 创建基于K8S的ServiceMesh
(未完待续。。。)
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhiaccbc
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
微信运动停用后别人还能看到步数吗
PHP中文网 07-22