大家好,我是DD。

2022年了,你们开始用Kubernetes了吗?那么Spring Boot应用要如何部署到Kubernetes里呢?下面给大家转了一篇不错的深度好文,一起来学习一下吧!

以下内容来源:https://qingmu.io/2020/04/08/Spring-Boot-Operator-User-Guide/,作者:青木

在 Kubernetes 中部署 Spring Boot 应用整体上来说是一件比较繁琐的事情,而 Spring Boot Operator 则能带给你更清爽简单的体验。

Spring Boot Operator 基于 Kubernetes 的 Custom Resource Definitions (CRDs) 扩展 API 进行的开发。

1. 打包 Docker 镜像

在讲部署之前我们需要先将我们的 Spring Boot 应用打包成标准的 Docker Image。

Java 项目打包镜像用 Maven/Gradle 插件比较多,这里在介绍一个新的 Google 开源插件 Jib,该插件使用起来比较方便。

注意:Jib 打包的镜像会导致 Java 应用的 pid=1。在使用 Spring Boot Operator 进行发布时候,Operator 会设置 Kubernetes 的 ShareProcessNamespace 参数为 true(v1.10+版本都可使用)来解决该问题。

下面就来演示一下通过 https://start.spring.io 生成一个标准的 Spring Boot 项目 operator-demo,然后使用 Jib 插件进行镜像打包。

mvn com.google.cloud.tools:jib-maven-plugin:build
-Djib.to.auth.username=${{ secrets.MY_USERNAME }}
-Djib.to.auth.password=${{ secrets.MY_PASSWORD }}
-Djib.container.jvmFlags=--add-opens,java.base/sun.nio.ch=ALL-UNNAMED
-Djib.from.image=freemanliu/oprenjre:11.0.5
-Dimage=registry.cn-shanghai.aliyuncs.com/qingmuio/operator-demo/operator-demo:v1.0.0

执行上面的命令之后我们将得到一个标准的 Docker 镜像,该镜像会被推送到远程仓库。

2. Operator 快速体验

完成了镜像的构建之后,我们紧接着来安装我们的 Operator 到 Kubernetes 集群。

2.1 快速安装

此处快速安装只是为了快速体验 Demo。

kubectl apply -f https://raw.githubusercontent.com/goudai/spring-boot-operator/master/manifests/deployment.yaml

apply 成功之后控制台输出:

namespace/spring-boot-operator-system created
customresourcedefinition.apiextensions.k8s.io/springbootapplications.springboot.qingmu.io created
role.rbac.authorization.k8s.io/spring-boot-operator-leader-election-role created
clusterrole.rbac.authorization.k8s.io/spring-boot-operator-manager-role created
clusterrole.rbac.authorization.k8s.io/spring-boot-operator-proxy-role created
clusterrole.rbac.authorization.k8s.io/spring-boot-operator-metrics-reader created
rolebinding.rbac.authorization.k8s.io/spring-boot-operator-leader-election-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/spring-boot-operator-manager-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/spring-boot-operator-proxy-rolebinding created
service/spring-boot-operator-controller-manager-metrics-service created
deployment.apps/spring-boot-operator-controller-manager created

稍等片刻查看是否已经安装成功:

kubectl  get po -n spring-boot-operator-system

成功如下输出:

NAME                                                       READY   STATUS    RESTARTS   AGE
spring-boot-operator-controller-manager-7f498596bb-wcwtn   2/2     Running   0          2m15s

如果您正在学习Spring Boot,推荐您关注这个我连载多年,并且还在继续更新的免费教程:http://blog.didispace.com/spring-boot-learning-2x/

2.2 部署 OperatorDemo 应用

完成了 Operator 的部署之后,我们来部署我们第一个应用。这里我们就发布上面我们编写的 Spring Boot 应用 opreator-demo。

首先,我们需要先编写一个 Spring Boot Application 的 CRD 部署 yaml,如下:

# Demo.yaml
apiVersion: springboot.qingmu.io/v1alpha1
kind: SpringBootApplication
metadata:name: operator-demo
spec:springBoot:version: v1.0.0
#    image: registry.cn-shanghai.aliyuncs.com/qingmuio/operator-demo/operator-demo:v1.0.0

细心的同学可能发现了,为啥连 Image 都没有这怎么发布?就 name、version 就能完成发布?

是的没错!就能完成发布,后面我讲详细讲到他是如何完成的。

接着我们 apply 一下:

kubectl apply -f Demo.yaml

看到 console 输出:

springbootapplication.springboot.qingmu.io/operator-demo created

2.3 验证

表示创建成功了,接着我们来看下我们部署的第一个应用,这里我们直接用上面的 yaml 中的 name 过滤即可。

查看 pod

~# kubectl  get po | grep operator-demo
operator-demo-7574f4789c-mg58m             1/1     Running   0          76s
operator-demo-7574f4789c-ssr8v             1/1     Running   0          76s
operator-demo-7574f4789c-sznww             1/1     Running   0

查看下我们的 pid 不等于 1 的设置是否生效。

根据下面的结果可以看到通过设置 ShareProcessNamespace 该参数我们可以在 Kubernetes 层面来解决这个 pid=1 的问题。

kubectl exec -it operator-demo-7574f4789c-mg58m bash
bash-5.0# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 02:06 ?        00:00:00 /pause
root         6     0 26 02:06 ?        00:00:09 java --add-opens java.base/sun.nio.ch=ALL-UNNAMED -cp /app/resources:/app/classes:/app/libs/* io.qingmu.operator.operatordemo.Oper...
root        38     0  0 02:07 pts/0    00:00:00 bash
root        44    38  0 02:07 pts/0    00:00:00 ps -ef

查看 svc

~# kubectl  get svc | grep operator-demo
operator-demo             ClusterIP   10.101.128.6     <none>        8080/TCP            2m52s

我们来访问一下试试:

root@server1:~# curl -i http://10.101.128.6:8080
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 9
Date: Wed, 08 Apr 2020 08:45:46 GMThello !!!

我们来试着缩减副本数到 1 个。

编辑我们的 Demo.yaml,加入一个新的属性 replicas:

# Demo.yaml
apiVersion: springboot.qingmu.io/v1alpha1
kind: SpringBootApplication
metadata:name: operator-demo
spec:springBoot:version: v1.0.0replicas: 1

应用一下:

root@server1:~# kubectl apply -f Demo.yaml
springbootapplication.springboot.qingmu.io/operator-demo configured

再次查看 pod,会发现我们的 pod 已经缩放为一个副本了:

~# kubectl  get po | grep operator-demo
operator-demo-7574f4789c-sznww             1/1     Running   0          8m29s

2.4 清理 operator-demo

要删除该 pod 我们只需要执行 delete 即可:

~# kubectl delete -f Demo.yaml
springbootapplication.springboot.qingmu.io "operator-demo" deleted

再次查看 pod,已经没了:

kubectl  get po | grep operator-demo

3. 部署自己的应用

部署自己私有仓库的应用需要需要先创建 secret(如果已经创建跳过即可)。

创建 docker-registry 的 secret:

kubectl create
secret docker-registry aliyun-registry-secret
--docker-server=registry-vpc.cn-hangzhou.aliyuncs.com
--docker-username=***
--docker-password=***
--docker-email=***

自己应用的 crd Yaml:

apiVersion: springboot.qingmu.io/v1alpha1
kind: SpringBootApplication
metadata:name: 你的应用的名称
spec:springBoot:version: v1.0.0replicas: 1 image: 你的image地址imagePullSecrets: - 上面创建的secret

如果您正在学习Spring Cloud,推荐一个经典教程(含Spring Cloud Alibaba):https://blog.didispace.com/spring-cloud-learning/

3.1 一个完整的 Spring Boot Application Yam

下面是一个完整的 yaml 属性结构,大部分属性我们都可以用默认配置的即可。

不设置属性,默认使用 Operator 中设置的通用值。详见后面的自定义安装 Operator。

apiVersion: springboot.qingmu.io/v1alpha1
kind: SpringBootApplication
metadata:name: operator-demonamespace: default
spec:springBoot:# image 可以不设置,如果不设置默认使用 IMAGE_REPOSITORY+/+mate.name+:+spec.springBoot.version# registry.cn-shanghai.aliyuncs.com/qingmuio + / + operator-demo + : + v1.0.0image: registry.cn-shanghai.aliyuncs.com/qingmuio/operator-demo:v1.0.0clusterIp: "" version: v1.0.0 replicas: 1 resource:cpu:request: 50mlimit: "" memory:request: 1Gilimit: 1Gi path:liveness: /actuator/health readiness: /actuator/health hostLog: /var/applog shutdown: /spring/shutdown imagePullSecrets: - aliyun-docker-registry-secretenv: - name: EUREKA_SERVERSvalue: http://eureka1:8761/eureka/,http://eureka2:8761/eureka/,http://eureka3:8761/eureka/nodeAffinity: key: "failure-domain.beta.kubernetes.io/zone"operator: "In"values:- "cn-i"- "cn-h"- "cn-g"

3.2 优雅停机的路径

由于优雅停机默认是关闭的,并且并不支持 GET 请求,所以我们需要开启和搭个桥。

首先,在 application.yml 中启用:

management:endpoints:web:exposure:include: "*"endpoint:shutdown:enabled: true

然后,桥接一个 GET 方法:

@RestController
public class ShutdownController {@Autowiredprivate ShutdownEndpoint shutdownEndpoint;@GetMapping("/spring/shutdown")public Map<String, String> shutdown(HttpServletRequest request) {return shutdownEndpoint.shutdown();}
}

3.3 node 亲和的使用

举一个例子:我们有一个 Spring Boot 应用 user-service,希望它能分布到 3 个可用区的 6 个节点上:

首先,我们把机器划分多个可用区:

cn-i区(node-i1,node-i02)
cn-h区(node-g1,node-g02)
cn-g区(node-h1,node-h02)

现在,我们有 3 个可以区,每个区有2台 workload,一共6台。然后,我们需要给这些机器分别打上 label。

将全部的 i 区机器标注为 cn-i:

kubectl label node node-i1 failure-domain.beta.kubernetes.io/zone=cn-i
kubectl label node node-i2 failure-domain.beta.kubernetes.io/zone=cn-i

同理将 h 区的标注为 h,g 区同理。

kubectl label node node-h1 failure-domain.beta.kubernetes.io/zone=cn-i
kubectl label node node-ih2 failure-domain.beta.kubernetes.io/zone=cn-i

准备工作我们就绪了,现在我们来设置让它达到我们的调度效果,像如下编写:

spec:springBoot:nodeAffinity: #可以不设置 节点亲和 这里演示的是尽量将pod分散到 i h g 三个可用区,默认设置了pod反亲和key: "failure-domain.beta.kubernetes.io/zone"operator: "In"values:- "cn-i"- "cn-h"- "cn-g"

4. Operator 自定义安装

上面我们快速的安装了好了,接着我们来讲解下如何自定义安装,以及有哪些自定义的参数,可以个性化的参数我们用环境变量的方式注入。

下面来修改 Deployment 完成自己个性化的配置部署。从我提供的部署 yaml 中拉到最后,找到 name 是 spring-boot-operator-controller-manager 的 Deployment,我们将修改它。

apiVersion: apps/v1
kind: Deployment
metadata:labels:control-plane: controller-managername: spring-boot-operator-controller-managernamespace: spring-boot-operator-system
.....#注意:一下配置针对通用全局的spring boot默认配置,对crd的spring boot生效,这里不配置也可以在部署的yaml中指定# 私有仓库的地址,比如我的最终打包的镜像地址是 registry.cn-shanghai.aliyuncs.com/qingmuio/operator-demo/operator-demo:v1.0.0# 那么配置的值是 registry.cn-shanghai.aliyuncs.com/qingmuio/operator-demo# 配置这个值之后,我们我们如果在发布的yaml中不写image,那么使用的image就是 IMAGE_REPOSITORY+"/"+mate.name+spec.springBoot.version- name: IMAGE_REPOSITORYvalue: registry.cn-shanghai.aliyuncs.com/qingmuio# 请求CPU限制- name: REQUEST_CPUvalue: 50m# 限制最大能用最大CPU java应用可以不用限制,限制不合理会导致启动异常缓慢- name: LIMIT_CPUvalue: ""# 请求内存大小- name: REQUEST_MEMORYvalue: 500Mi# 限制最大内存大小 一般和request一样大即可- name: LIMIT_MEMORYvalue: 500Mi# 就绪检查Path,spring boot actuator 默认Path- name: READINESS_PATHvalue: /actuator/health# 就绪存活Path,spring boot actuator 默认Path- name: LIVENESS_PATHvalue: /actuator/health# 就绪存活Path,优雅停机Path- name: SHUTDOWN_PATHvalue: /spring/shutdown# 复制级 即副本数- name: REPLICASvalue: "3"# 将日志外挂到主机磁盘Path,默认两者相同- name: HOST_LOG_PATHvalue: /var/applog# 用于pull 镜像的secrets- name: IMAGE_PULL_SECRETSvalue: ""# 用于pull 镜像的secrets- name: SPRING_BOOT_DEFAULT_PORTvalue: "8080"# node亲和,比如我可以设置pod尽量分散在不同可用区cn-i,cn-g,cn-h区- name: NODE_AFFINITY_KEYvalue: ""- name: NODE_AFFINITY_OPERATORvalue: ""- name: NODE_AFFINITY_VALUESvalue: ""# 全局的环境变量,会追加到每个spring boot的每个pod中,格式 k=v;k1=v2,# 如 EUREKA_SERVERS=http://eureka1:8761/eureka/,http://eureka2:8761/eureka/,http://eureka3:8761/eureka/;k=v- name: SPRING_BOOT_ENVvalue: ""image: registry.cn-shanghai.aliyuncs.com/qingmuio/spring-boot-operator-controller:latest.....

4.1 自定义安装之后部署

yaml 可以简化为如下。

apiVersion: springboot.qingmu.io/v1alpha1
kind: SpringBootApplication
metadata:name: 你的应用的名称
spec:springBoot:version: v1.0.0

附录

环境变量表格:

GitHub仓库:https://github.com/goudai/spring-boot-operator

作者:青木,来源:https://qingmu.io/2020/04/08/Spring-Boot-Operator-User-Guide/

------

我们创建了一个高质量的技术交流群,与优秀的人在一起,自己也会优秀起来,赶紧点击加群,享受一起成长的快乐。另外,如果你最近想跳槽的话,年前我花了2周时间收集了一波大厂面经,节后准备跳槽的可以点击这里领取!

推荐阅读

  • 在公司wiki发布“女优一览表”遭开除

  • GitHub上发现个菜谱仓库

  • 领了红包不点赞,就是傻逼?

··································

你好,我是程序猿DD,10年开发老司机、阿里云MVP、腾讯云TVP、出过书、创过业、国企4年互联网6年。10年前毕业加入宇宙行,工资不高、也不算太忙,业余坚持研究技术和做自己想做的东西。4年后离开国企,加入永辉互联网板块的创业团队,从开发、到架构、到合伙人。一路过来,给我最深的感受就是一定要不断学习并关注前沿。只要你能坚持下来,多思考、少抱怨、勤动手,就很容易实现弯道超车!所以,不要问我现在干什么是否来得及。如果你看好一个事情,一定是坚持了才能看到希望,而不是看到希望才去坚持。相信我,只要坚持下来,你一定比现在更好!如果你还没什么方向,可以先关注我,这里会经常分享一些前沿资讯,帮你积累弯道超车的资本。

点击阅读原文,领取2022最新10000T学习资料

使用 Spring Boot Operator 部署 Spring Boot 到 Kubernetes相关推荐

  1. 使用Spring Boot Operator部署SpringBoot到K8S

    点击关注公众号,实用技术文章及时了解 来源:qingmu.io/2020/04/08/ Spring-Boot-Operator-User-Guide 前言 在Kubernetes中部署spring ...

  2. k8s部署tomcat及web应用_部署 Spring Boot 应用到 K8S 教程

    点击上方 Java后端,选择 设为星标 优质文章,及时送达 作者:qingmu qingmu.io/2020/04/08/Spring-Boot-Operator-User-Guide/ 前言 在Ku ...

  3. springboot(十六):使用Jenkins部署Spring Boot

    jenkins是devops神器,本篇文章介绍如何安装和使用jenkins部署Spring Boot项目 jenkins搭建 部署分为三个步骤: 第一步,jenkins安装 第二步,插件安装和配置 第 ...

  4. Spring Boot 2 (四):使用 Docker 部署 Spring Boot

    Docker 技术发展为微服务落地提供了更加便利的环境,使用 Docker 部署 Spring Boot 其实非常简单,这篇文章我们就来简单学习下. 首先构建一个简单的 Spring Boot 项目, ...

  5. docker添加新的环境变量_Docker的安装及部署Spring Boot项目操作详解!

    本文使用Docker部署Spring Boot项目.部署之前需要环境中已经安装Docker和Maven(用于打包),所以本文先进行安装Docker和Maven:接着搭建一个Spring Boot项目, ...

  6. Spring Boot 2.0(四):使用 Docker 部署 Spring Boot

    Docker 技术发展为微服务落地提供了更加便利的环境,使用 Docker 部署 Spring Boot 其实非常简单,这篇文章我们就来简单学习下. 首先构建一个简单的 Spring Boot 项目, ...

  7. 多个Spring Boot项目部署在一个Tomcat容器无法启动

    Tomxin7 Simple, Interesting | 简单,有趣 本文将花费您五分钟时间 业务介绍 最近用Spring Boot开发了一个翻译的小项目,但是服务器上还跑着其他项目,包括一个同样用 ...

  8. 【java】四步法:spring boot项目部署在CentOS 8(后端篇)

    四步法:spring boot项目部署在CentOS 8(后端篇) 一.使用IDEA打包项目为jar包(构建) 1. IDEA版本 2. maven版本 3. pom.xml 设置 4. 构建jar包 ...

  9. Spring Boot 热部署入门

    转载自  Spring Boot 热部署入门 1. 概述 在日常开发中,我们需要经常修改 Java 代码,手动重启项目,查看修改后的效果.如果在项目小时,重启速度比较快,等待的时间是较短的.但是随着项 ...

最新文章

  1. vc 只有顶级窗口可以弹出窗口_如果你刚换了新电脑,这几个地方记得设置一下,电脑可以多用几年...
  2. C语言 · 征税程序
  3. 什么是内卷?华为内部这篇文章读懂
  4. Struts07---访问servlet的API
  5. 用javascript自制ctf词频分析工具
  6. Java死锁、活锁,悲观锁、乐观锁
  7. 学习nginx 下面只是简单的配置文件
  8. java 析构函数_C++与Java的区别(一)
  9. 【操作系统】内存的分页管理与分段管理の异同
  10. wordpress常用插件打包 百度搜索推送插件+sitemap生成等
  11. OPPO全球营销总裁沈义人宣布卸任,网友:第二天宣布入职小米?
  12. POJ-3422-Kaka's Matrix Travels(最小费用最大流)
  13. 2010年 我的齐鲁软件大赛作品
  14. TensorFlow by Google CNN分类真实图片 Machine Learning Foundations: Ep #5 - Classifying real-world images
  15. java 中文乱码转换_java中文乱码怎么转换
  16. 冲量在线荣获STIF2021国际科创节2021年度技术先锋奖
  17. C++复数运算符重载,复数开平方
  18. 【技巧】SourceInsight如何设置为相对路径
  19. 一款专为APP设计的后台管理系统平台
  20. 1022 - 快手短视频广告主接入实践笔记

热门文章

  1. 基础知识《二》java的基本类型
  2. cisco-ccna-第九章测试-work1-汉语
  3. 关于web.config中customErrors
  4. 正确使用硬盘的方法与维护
  5. 0X000000该内存不能read的解决方法
  6. 一个程序员的小笑话.(纯属虚构)
  7. golang gopsutil 进程 系统硬件 docker 信息获取
  8. golang 调用c代码
  9. linux ulimit命令 控制shell执行程序的资源
  10. linux centos7 升级 make 4.0