上一篇:杭州程序员从互联网跳央企,晒一天工作和收入,网友:待一年就废

作者:qingmu

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进行的开发。

打包Docker镜像

在讲部署之前我们需要先将我们的SpringBoot应用打包成标准的DockerImage。

java项目打包镜像用maven/gradle插件比较多,我的另一篇文章构建SpringBoot的Docker镜像,这里在介绍一个新的google开源的插件Jib,该插件使用起来比较方便。

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

下面就来演示一下我们通过https://start.spring.io生成一个标准的SpringBoot项目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镜像,该镜像会被推送到远程仓库。

Operator快速体验

完成了镜像的构建之后,我们紧接着来安装我们的Operator到kubernetes集群,当然了首先你需要一套集群,可以参考我之前一篇文章部署高可用kubernetes,虽然版本比较老,但是新版本其实也差不多的一个思路。

https://qingmu.io/2019/05/17/Deploy-a-highly-available-cluster-with-kubeadm/

快速安装

此处快速安装只是为了快速体验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

部署OperatorDemo应用

完成了Operator的部署之后,我们来部署我们第一个应用,这里我们就发布上面我们编写的springboot应用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

验证

表示创建成功了,接着我们来看下我们部署的第一个应用,这里我们直接用上面的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          76s

查看下我们的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

清理operator-demo

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

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

再次查看pod,已经没了

kubectl  get po | grep operator-demo

部署自己的应用

部署自己私有仓库的应用需要需要先创建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 Boot Application Yaml

下面是一个完整的yaml属性结构,大部分属性我们都可以用默认配置的即可。推荐:一百期Java面试题汇总

不设置属性,默认使用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"

优雅停机的路径

由于优雅停机默认是关闭的并且并不支持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();}
}

node亲和的使用

举一个列子 我们有一个springboot应用 user-service 希望他能分布到3个可用区的6个节点上:

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

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

现在我们有三个可以区 每个区有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"

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.....

自定义安装之后部署

yaml可以简化为如下。

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

附录

环境变量表格

Github仓库

SpringBootOperator: https://github.com/goudai/spring-boot-operator

感谢您的阅读,也欢迎您发表关于这篇文章的任何建议,关注我,技术不迷茫!

小编到你上高速。

· END ·

最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全。

正文结束

推荐阅读 ↓↓↓

1.不认命,从10年流水线工人,到谷歌上班的程序媛,一位湖南妹子的励志故事

2.如何才能成为优秀的架构师?

3.从零开始搭建创业公司后台技术栈

4.程序员一般可以从什么平台接私活?

5.37岁程序员被裁,120天没找到工作,无奈去小公司,结果懵了...

6.IntelliJ IDEA 2019.3 首个最新访问版本发布,新特性抢先看

7.这封“领导痛批95后下属”的邮件,句句扎心!

8.15张图看懂瞎忙和高效的区别!

简单几步把Spring Boot 项目部署到 K8S,步骤来了!相关推荐

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

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

  2. Spring Boot项目部署到Docker的流程及一些容易踩的坑

    Spring Boot项目部署到Docker的流程及一些容易踩的坑 前期准备 准备Spring Boot项目 编写简单的控制类,方便测试 编写日志打印相关 测试项目是否能正常工作 准备部署到docke ...

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

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

  4. java servlet 部署到tomcat_如何把spring boot项目部署到tomcat容器中

    把spring-boot项目按照平常的web项目一样发布到tomcat容器下 一.修改打包形式 在pom.xml里设置 war 二.移除嵌入式tomcat插件 在pom.xml里找到spring-bo ...

  5. Spring Boot项目部署服务器 本地正常 远程无法访问问题排错

    Spring boot项目部署linux 服务器本地正常 远程无法访问 问题描述 排错 原因 最后 最近买个云主机学大佬部署项目..然后直接炸裂了... 问题描述 本地保证代码没问题的情况下( jav ...

  6. 腾讯云服务器 - 将 Spring Boot 项目部署到云服务器上(保姆级教程)

    目录 前言 1.在云服务器上安装 jdk 2.在云服务器上安装 mysql 2.1.安装 mysql 2.2.启动 mysql 服务 2.3.验证 3.将 Spring Boot 项目打包成 jar ...

  7. spring boot项目 部署 使用Procrun 注册为windows服务。

    1.下载Procrun 下载链接:https://downloads.apache.org/commons/daemon/binaries/windows/ 2.新建部署目录workSpace 3.添 ...

  8. 【Linux部署】Spring Boot 项目部署在Linux环境下的Docker容器内举例【任务调度系统 xxl-job 任务调度中心】(手动版)

    1.将SpringBoot项目打jar包 这里打包的是xxl-job任务调度系统的调度器. 2.编写Dockerfile FROM java:8 VOLUME /tmp ADD xxl-job-adm ...

  9. Spring Boot 项目部署方案 /打包 + Shell 脚本部署详解,稳的一批

    本篇和大家分享的是 Spring Boot 打包并结合 Shell 脚本命令部署,重点在分享一个shell 程序启动工具,希望能便利工作: profiles指定不同环境的配置 maven-assemb ...

  10. Spring Boot项目部署到Heroku

    1. 注册 Heroku 免费账户 浏览器打开Heroku官网,注册一个免费的用户,在注册时选择 java 语言 2.安装 Heroku CLI 可以从Heroku官网的Getting Started ...

最新文章

  1. 关于过滤空格问题(未经测试)
  2. WebService大讲堂之Axis2(6):跨服务会话(Session)管理
  3. ElasticSearch简介与安装
  4. vue接收json数据_Vue之使用ajax获取json数据,并用v-for循环显示在表格中
  5. Java Web之基于注解的Spring MVC环境配置
  6. spyder python下载_Spyder Python软件-Spyder Python下载-最火软件站
  7. 如何制作图片一句话木马
  8. git入职第一天快速使用指南
  9. 打印可自定义的字母金字塔(python实现)
  10. 刷算法第五天——P5594 模拟赛
  11. sql语句基础-提升
  12. AutoCad二次开发:ObjectARX
  13. ibm服务器修改uefi和legacy,uefi和legacy的区别详细分析(附带uefi改legacy教程)
  14. vb.net 教程 20-4 库存管理系统3.14 出库单操作(FormStorageOutOrder)
  15. 你知道抖音的洗脑,却不知道他的产品设计有多牛
  16. 常用的分布式事务解决方案
  17. java姓名模糊查询_模糊查询(仅针对后端)
  18. word打不开,总提示进入安全模式 的解决方法
  19. PHP微商城开源代码实例
  20. 关于媒介广告投放类数据分析的思考

热门文章

  1. EasyRecovery如何恢复javascript文件
  2. Camtasia 2020软件的媒体库介绍
  3. Paragon NTFS Mac官网版的下载安装与激活教程分享
  4. 阿里云计算新增ODPS、SLS两款云产品
  5. IOS开发之支付功能概述
  6. Python Django chartit 多报表显示
  7. Ember.js 入门指南——model简介1
  8. 常见的SQL错误和解决方法
  9. Java线程同步之一--AQS
  10. 再谈“颠覆”冯.诺依曼计算机体系结构 —— 计算机的未来发展方向:去内存化...