• 基于 Spring Boot 框架的应用如何在 kubernetes 环境部署,是沿用 Docker 容器的做法还是另有其他?接下来咱们从理论到设计再到实战,一起来感受传统后台应用在容器环境的微妙变化;

Spring Boot 应用

  • 基于 Spring Boot 框架的应用,通常会构建成 XXX.jar 文件,执行 java -jar XXX.jar 来运行该应用;

Docker 下的 Spring Boot 应用镜像

  • Docker 环境下,通常用 Maven 的 docker-maven-plugin 插件将应用打包成镜像,例如以 java:8u111-jdk 作为基础镜像再加入 jar 文件,这样容器启动的时候执行 java -jar XXX.jar 就能将应用运行起来了;

传统思路

  • Spring Boot 应用镜像在 kubernetes 声明为 Pod,即可正常运行;

  • 但是,这是合适的做法么?去 K8S 官网需要一些理论上的指导吧;

寻找官方的理论依据

  • 官方文档地址:https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/

  • 其中对 Pod 中多个容器的关系描述如下:

  • 上图红框中提到一个容器基于共享资源对外提供服务,另一个"sidecar"容器负责更新这些共享资源;

  • 在 Kubernetes 中文社区的文档中也对此作了阐述,地址是:http://docs.kubernetes.org.cn/312.html

  • 在提到 Pod 中的 sidecar 模式时,官方文档用到"relatively advanced"来形容,进一步证实了当下该模式的正确性,如下图:

  • 具体的实现模型如下图:

Spring Boot 应用的 sidecar 设计

  • 根据 kubernetes 官方文档的指导,再结合 SpringBoot 应用的特点,我设计出的 sidecar 部署方式如下:

  • 该应用的业务服务被封装在一个 Pod 定义中,该 Pod 由两个容器组成;

  • 绿色容器是来自 OpenJDK 官方镜像:openjdk:8u181-jre-alpine3.8,用 docker history 命令查看体积,几十兆不算大:

[root@localhost work]# docker history openjdk:8u181-jre-alpine3.8IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT2e01f547f003        12 days ago         /bin/sh -c set -x  && apk add --no-cache  ...   78.6 MB             <missing>           12 days ago         /bin/sh -c #(nop)  ENV JAVA_ALPINE_VERSION...   0 B                 <missing>           12 days ago         /bin/sh -c #(nop)  ENV JAVA_VERSION=8u181       0 B                 <missing>           7 weeks ago         /bin/sh -c #(nop)  ENV PATH=/usr/local/sbi...   0 B                 <missing>           7 weeks ago         /bin/sh -c #(nop)  ENV JAVA_HOME=/usr/lib/...   0 B                 <missing>           7 weeks ago         /bin/sh -c {   echo '#!/bin/sh';   echo 's...   87 B                <missing>           7 weeks ago         /bin/sh -c #(nop)  ENV LANG=C.UTF-8             0 B                 <missing>           7 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/sh"]              0 B                 <missing>           7 weeks ago         /bin/sh -c #(nop) ADD file:25c10b1d1b41d46...   4.41 MB

复制代码

  • 之所以要用 jre-alpine 版本,是因为 8u181-jdk 版本相比之下大了很多,如下所示:

[root@localhost work]# docker history openjdk:8u181-jdkIMAGE               CREATED             CREATED BY                                      SIZE                COMMENT954739b8bdfb        7 days ago          /bin/sh -c /var/lib/dpkg/info/ca-certifica...   355 kB              <missing>           7 days ago          /bin/sh -c set -ex;   if [ ! -d /usr/share...   348 MB              <missing>           7 days ago          /bin/sh -c #(nop)  ENV CA_CERTIFICATES_JAV...   0 B                 <missing>           7 days ago          /bin/sh -c #(nop)  ENV JAVA_DEBIAN_VERSION...   0 B                 <missing>           3 weeks ago         /bin/sh -c #(nop)  ENV JAVA_VERSION=8u181       0 B                 <missing>           3 weeks ago         /bin/sh -c #(nop)  ENV JAVA_HOME=/docker-j...   0 B                 <missing>           3 weeks ago         /bin/sh -c ln -svT "/usr/lib/jvm/java-8-op...   33 B                <missing>           3 weeks ago         /bin/sh -c {   echo '#!/bin/sh';   echo 's...   87 B                <missing>           3 weeks ago         /bin/sh -c #(nop)  ENV LANG=C.UTF-8             0 B                 <missing>           3 weeks ago         /bin/sh -c apt-get update && apt-get insta...   2.21 MB             <missing>           3 weeks ago         /bin/sh -c apt-get update && apt-get insta...   142 MB              <missing>           3 weeks ago         /bin/sh -c set -ex;  if ! command -v gpg >...   7.8 MB              <missing>           3 weeks ago         /bin/sh -c apt-get update && apt-get insta...   23.2 MB             <missing>           3 weeks ago         /bin/sh -c #(nop)  CMD ["bash"]                 0 B                 <missing>           3 weeks ago         /bin/sh -c #(nop) ADD file:b3598c18dc39584...   101 MB  

复制代码

  • 红色容器的镜像是用 Spring Boot 应用构建出来的,稍后再详细整个过程;

  • 在 kubernetes 环境,这两个容器会挂载同一个 Volume,红色容器将 jar 放在此处,绿色容器使用此处的 jar;

  • 红色容器用来提供 jar,没有进程需要保持运行状态,很适合设置为 Init Container 类型;

  • 绿色容器的 java 进程是长久运行的;

  • 以上就是整体设计思路,接下来咱们就来实战吧,分三步完成:

实战步骤列举

  • 本次实战分为以下几部分组成:

  • 开发 Spring Boot 应用;

  • 制作 Docker 镜像,做两个版本,以便验证升级;

  • 编写 yaml 文件;

  • 在 kubernetes 环境部署,验证;

  • 升级版本,验证;

环境和版本信息

  1. 编译构建的 jdk 和运行的 jre 都用 1.8 版本;

  2. maven:3.3.3;

  3. spring boot:2.1.0.RELEASE;

  4. docker:1.13.1;

  5. kubernetes:1.12.2;

  • 本次实战一共有四台 CentOS7 机器,基本信息如下:

  • kubernetes 环境由 localhost、node1、node2 三台机器组成,maven 负责编译构建、生成镜像、上传到镜像仓库等操作;

开发 Spring Boot 应用

  • 这是个简单的 Spring Boot 应用,对外提供一个 http 接口,返回一个字符串;

  • 您可以选择直接从 GitHub 下载这个工程的源码,地址和链接信息如下表所示:

  • 这个 git 项目中有多个文件夹,本章源码在 springbootsidecardemo 这个文件夹下,如下图红框所示:

  • 您也可以随本文一起来开发这个应用:

  • 应用名为 springbootsidecardemo,是用 maven 构建的,JDK 使用 1.8,Spring Boot 版本 2.1.0.RELEASE;

  • 应用的 pom.xml 如下,为了构建 Docker 镜像使用了 docker-maven-plugin 插件,该插件具体的配置请参照下面的注释:

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>
    <groupId>com.bolingcavalry</groupId>    <artifactId>springbootsidecardemo</artifactId>    <version>0.0.1</version>    <packaging>jar</packaging>
    <name>springbootsidecardemo</name>    <description>Demo project for Spring Boot sidecard demo in K8S</description>
    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.1.0.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>
    <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>        <java.version>1.8</java.version>    </properties>
    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>
        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>    </dependencies>
    <build>        <finalName>app</finalName>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>
            <!--新增的docker maven插件-->            <plugin>                <groupId>com.spotify</groupId>                <artifactId>docker-maven-plugin</artifactId>                <version>0.4.12</version>                <!--docker镜像相关的配置信息-->                <configuration>                    <!--镜像名,这里用工程名-->                    <imageName>bolingcavalry/${project.artifactId}</imageName>                    <!--TAG,这里用工程版本号-->                    <imageTags>                        <imageTag>${project.version}</imageTag>                    </imageTags>                    <!--镜像的FROM,使用busybox-->                    <baseImage>busybox</baseImage>                    <!--构建镜像的配置信息-->                    <resources>                        <resource>                            <targetPath>/</targetPath>                            <directory>${project.build.directory}</directory>                            <include>app.jar</include>                        </resource>                    </resources>                </configuration>            </plugin>        </plugins>    </build></project>

复制代码

  • 上面的配置有一处需要注意,就是基础镜像的选择(就是 baseImage 节点中的内容),我用了 busybox,用它是因为够小,来看 docker 镜像仓库中的描述,地址是 https://hub.docker.com/_/busybox/:

  • 看到这里,可能会有朋友问"为什么不用 scratch?它比 busybox 更小",scratch 虽小,但不带基本的 shell 命令,例如 cp 命令,而后容器启动时要用 cp 命令对文件做复制操作,因此只能选择 busybox 了;

  • Controller 类的代码也很简单:

package com.bolingcavalry.springbootsidecardemo.controller;
import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/** * @Description: 一个最普通的Controller,hello接口返回一个字符串并带上当前时间 * @author: willzhao E-mail: zq2599@gmail.com * @date: 2018/11/6 14:15 */@RestControllerpublic class HelloController {
    @RequestMapping(value = "/hello")    public String hello(){        return "Hello version 1.0 " + new Date();    }}

复制代码

制作应用的 Docker 镜像

  • 请确保您当前环境的 maven 和 Docker 都已经 OK 了;

  • 在应用的 pom.xml 所在目录执行如下命令即可构建 Docker 镜像:

mvn clean package -U -DskipTests docker:build

复制代码

  • 构建成功的控制台输出如下:

[INFO] Building image bolingcavalry/springbootsidecardemo[INFO] Building image bolingcavalry/springbootsidecardemoStep 1/2 : FROM busybox ---> 59788edf1f3eStep 2/2 : ADD /app.jar // ---> 8105c9ac033bRemoving intermediate container fdc62513abf6Successfully built 8105c9ac033b[INFO] Built bolingcavalry/springbootsidecardemo[INFO] Tagging bolingcavalry/springbootsidecardemo with 0.0.1[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 5.354 s[INFO] Finished at: 2018-11-06T05:07:08-08:00[INFO] Final Memory: 42M/225M[INFO] ------------------------------------------------------------------------

复制代码

  • 构建成功后用 docker history 命令查看镜像,如下,三个 layer 组成:

root@maven:~# docker history bolingcavalry/springbootsidecardemo:0.0.1IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT8105c9ac033b        46 minutes ago      /bin/sh -c #(nop) ADD file:909ca8e9c8898cd...   16.6 MB             59788edf1f3e        4 weeks ago         /bin/sh -c #(nop)  CMD ["sh"]                   0 B                 <missing>           4 weeks ago         /bin/sh -c #(nop) ADD file:63eebd629a5f755...   1.15 MB

复制代码

  • 去工程的 target 目录下看看构建的 app.jar 文件,如下所示,也是 16 兆,所以这个镜像已经被做到最小了,相对于以前那种 JAVA 环境+jar 文件的镜像,这个镜像更易于下载和上传:

root@maven:/usr/local/work/github/blog_demos/springbootsidecardemo/target# ls -altotal 16276drwxr-xr-x 9 root root     4096 Nov  6 05:08 .drwxr-xr-x 5 root root     4096 Nov  6 05:29 ..-rw-r--r-- 1 root root 16621351 Nov  6 05:08 app.jar-rw-r--r-- 1 root root     4432 Nov  6 05:08 app.jar.originaldrwxr-xr-x 3 root root     4096 Nov  6 05:08 classesdrwxr-xr-x 2 root root     4096 Nov  6 05:08 dockerdrwxr-xr-x 3 root root     4096 Nov  6 05:08 generated-sourcesdrwxr-xr-x 3 root root     4096 Nov  6 05:08 generated-test-sourcesdrwxr-xr-x 2 root root     4096 Nov  6 05:08 maven-archiverdrwxr-xr-x 3 root root     4096 Nov  6 05:08 maven-statusdrwxr-xr-x 3 root root     4096 Nov  6 05:08 test-classes

复制代码

  • 执行 docker push 命令,将镜像推送到镜像仓库中,我这里是推送到了 hub.docker.com,您可以根据实际情况来执行,例如私有仓库、阿里云等都可以,当然了,如果当前机器就是 K8S 的机器就不用推送了,毕竟此镜像就是在 K8S 环境用的;

  • 如果觉得推送到仓库太慢,或者从仓库下载太慢,也可以使用文件导入导出的方式,具体操作如下:

#将镜像导出为tar文件docker save 2e01f547f003 > 1.tar
###将tar文件还原为镜像docker load < 1.tar
###还原后的镜像的名称和tag都不对,要用tag命令来设置docker tag 8105c9ac033b bolingcavalry/springbootsidecardemo:0.0.1

复制代码

制作应用升级版的 Docker 镜像

  • 为了验证 K8S 下的应用升级,做好 tag 为 0.0.1 的镜像之后,我们改动应用代码,把 pom.xml 中的版本改成 0.0.2,然后再做个镜像,这样稍后在 K8S 就能验证 Pod 升级了;

  • 修改 HelloController.java 的源码,hello 方法返回的字符串,之前是 Hello version 1.0,现在改成 Hello version 2.0

  • 修改 pom.xml 中的 version 节点,之前是 0.0.1,现在改成 0.0.2,由于我们已配置了镜像 tag 就是工程版本,因此新构建的镜像 tag 会是 0.0.2;

  • 再次执行 maven 命令构建,然后推送到镜像仓库;

  • 此时我们有两个镜像了:

root@maven:~# docker images | grep sidecarbolingcavalry/springbootsidecardemo                                 0.0.2        f6ba01c33388        11 hours ago        17.8 MBbolingcavalry/springbootsidecardemo                                 0.0.1        8105c9ac033b        11 hours ago        17.8 MB

复制代码

  • 现在镜像已经 OK,该准备部署到 kubernetes 环境了;

编写 yaml 文件

  • 在可以执行 kubectl 命令的机器上编写配置文件,Pod 的配置 javaweb-deploy.yaml 文件内容如下:

apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: javawebspec:  replicas: 1  template:    metadata:     labels:      name: javaweb    spec:     initContainers:     - image: bolingcavalry/springbootsidecardemo:0.0.1       name: appjar       command: ["cp", "/app.jar", "/app"]       volumeMounts:       - mountPath: /app         name: app-volume     containers:     - image: openjdk:8u181-jre-alpine3.8       name: openjdk8u181       command: ["java","-jar","/webapp/app.jar"]       volumeMounts:       - mountPath: /webapp         name: app-volume       ports:       - containerPort: 8080     volumes:     - name: app-volume       emptyDir: {}

复制代码

  • 从上述配置中,有两处需要注意:

  • 第一,应用镜像被设置为 initConteiners 类型的容器,被设置执行 cp 命令将自己的 app.jar 文件复制到共享的 Volume;

  • 第二,一直运行用于提供服务的容器,来自 openjdk 镜像的 java 进程,该进程加载的 jar 文件就是共享的 Volume 中的 app.jar;

  • 为了能在浏览器上访问该应用,再部署个 service,其配置文件 javaweb-svc.yaml 的内容如下:

apiVersion: v1kind: Servicemetadata:  name: javawebspec:  type: NodePort  ports:       - port: 8080         nodePort: 30008  selector:    name: javaweb

复制代码

  • 启动 pod 和 service,在前面的 yaml 文件所在目录执行命令如下:

kubectl create -f javaweb-deploy.yaml \&& kubectl create -f javaweb-svc.yaml

复制代码

  • service 的类型是 NodePort,因此可以通过 Node 节点的 IP 地址访问服务,我这边 Node 地址为 192.168.119.159,因此访问地址就是:http://192.168.119.159:30008/hello ,在浏览器访问返回如下内容:

  • 符合预期,证明主容器加 sidecar 容器的组合方式是可以正常工作的,接下来试试升级;

升级版本

  • 接下来模拟生产环境的应用升级,前面准好了两个版本的应用镜像:0.0.1 和 0.0.2,现在 K8S 环境运行的是 0.0.1,咱们将其升级为 0.0.2:

  • 修改 javaweb-deploy.yaml 文件中镜像的 tag,从 0.0.1 改成 0.0.2,如下图红框所示:

  • 在 javaweb-deploy.yaml 文件所在目录执行如下命令即可完成升级:

kubectl apply -f javaweb-deploy.yaml

复制代码

  • 在浏览器访问 http://192.168.119.159:30008/hello,返回如下内容,可见的确是修改后的应用逻辑:

  • 升级成功,符合预期;

小结

  • sidecar 模式下,仅需更新应用 jar 打包的镜像,这个镜像可以做到极小;

  • 提供 java 进程的镜像是固定的,在 K8S 环境下,一个 Node 上实际运行着多种 pod,如果他们的 java 进程都由一个镜像提供,其好处是不言而喻的;

  • Spring Boot 应用的运行,是由 java 进程与应用 jar 文件组成的,很适合 sidecar 模式,通过容器解耦,通过 pod 对外服务;

  • 至此,Spring Boot 应用在 kubernetes 的 sidecar 设计与实战就全部完成了,希望此文能助您将应用以 sidecar 模式部署在 kubernetes,如果您发现我对官网的指导内容理解有误或有偏差,欢迎您的热心指正,谢谢!

Spring Boot 应用在 kubernetes 的 sidecar 设计与实战相关推荐

  1. 基于spring boot的邮件微服务消息中间件设计与实现 毕业论文+系统功能图v1.0.vsdx+项目源码

    下载地址:https://download.csdn.net/download/m0_63680064/36065411 项目介绍: 基于spring boot的邮件微服务消息中间件设计与实现 毕业论 ...

  2. Spring Boot+Vue/前后端分离/高并发/秒杀实战课程之spring Security快速搭建oauth2 内存版身份认证

    Springboot快速搭建oauth2 内存版身份认证 环境准备 点击[Create New Project]创建一个新的项目 项目环境配置 配置Thymeleaf 搭建oauth2认证,加入两个依 ...

  3. 计算机签到程序,基于spring boot技术的签到管理系统的设计与实现计算机专业.doc...

    目 录 TOC \o "1-3" \h \z \u 13408 摘 要 I 26422 Abstract II 22690 引 言 1 24521 1 相关技术 3 3204 1. ...

  4. spring boot电商系统前端界面设计与浏览器兼容性研究 毕业设计-附源码231058

    摘  要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势:对于电商系统前端界面设计与浏览器兼容性研究当然也不能排除在外,随着网络技术的不断成熟,带动了电商系统前 ...

  5. 基于 java Spring Boot 框架的人事管理系统的设计与实现 附完整代码+论文+ppt

    内容摘要: 人事管理在政府机关和企事业单位中占有极其重要的地位,各部门岗位之间协作和工效的提高,是人事管理的基本要求.本设计旨在实现微型人事管理信息系统,功能主要由人事在线通信.员工资料.人事信息管理 ...

  6. 基于Spring Boot+Vue博客系统的设计与实现(附源码)

    摘要 中文博客第一次映入眼帘是在2002年,那时候的个人终端还是人们眼中的香饽饽,随着科技的不断进步和制造业的蓬勃发展,个人计算机终端开始逐渐变得普及,实现了人手一台电脑,在这种趋势中,博客系统走入了 ...

  7. 【Spring Boot+Thymeleaf+MyBatis+mysql】实现电子商务平台实战(附源码)持续更新~~ 包括sql语句、java、html代码

    源码请点赞关注收藏后评论区留言和私信博主 开发环境:Web服务器使用Servlet容器,数据库采用mysql,集成开发环境为Spring Tool Suite(STS) 一.系统设计 电子商务平台分为 ...

  8. Spring Boot 2.3.x 分层构建 Docker 镜像实战

    目录 一.什么是镜像分层 二.SpringBoot 2.3.x 新增对分层的支持 三.创建测试的 SpringBoot 应用 1.Maven 中引入相关依赖和插件 2.创建测试的 Controller ...

  9. spring boot web项目_SpringBoot2.x入门到项目实战课程系列(第四章)

    项目源码:https://github.com/wenMN1994/SpringBoot 第4章 Spring Boot 日志配置 在市场上存在非常多的日志框架: Spring Boot 采用了 sl ...

  10. spring boot admin 2.2 获取日志失败_SB实战20-Spring Boot的日志和报告

    上篇我们学习了<SB实战19-Spring Boot的外部配置>,本篇我们学习Spring Boot的日志和报告. 4 日志和报告 4.1 日志 日志是对应用运行时进行调试和分析的重要工具 ...

最新文章

  1. 这个AI能帮你快速搜监控:文字定位关键画面,24小时录像10分钟处理完
  2. Django介绍工程搭建
  3. HDU ACM 1065 I Think I Need a Houseboat
  4. SWF反编译神器ASV2013功能展示(下)
  5. Python 小白从零开始 PyQt5 项目实战(7)折叠侧边栏的实现
  6. BZOJ4448:[SCO2015]情报传递
  7. 除了随机还要进化——对Infinity进一步的想法
  8. 性能优化之页面缓存(以Javascript方式缓存页面部件)
  9. Anaconda Python3.6 OpenCV4.1.0 Ubuntu 16.04源码编译
  10. .NET利用委托实现动态查询
  11. python方向是干什么的_Python有哪些应用方向 在数据分析上有什么优势
  12. 关于全球同服和亚马逊Global Accelerating
  13. 使用IDEA开发Android程序(二)第一个简单的程序并运行
  14. IP地址聚合-路由汇聚
  15. 服务器风扇端子型号,出几样物品-相机连接头,服务器风扇,滤波器,接线端子等等如图...
  16. 1415-2个人读后感作业
  17. 卷积神经网络(CNN)超详细介绍
  18. K480N解决安装win10键盘失灵的方法
  19. python使用pyecharts绘制地图
  20. vue跳转链接(新页签)

热门文章

  1. workbench应力应变曲线_ANSYS WORKBENCH后处理中各种应力结果的详细说明
  2. 搞懂 PEM、ANS、PFX、P12、p8、CER、X509 等证书相关文件格式 后缀
  3. 熵、互信息与相对熵的关系
  4. Mybatis 缓存配置 ,如何禁用缓存与一些细节
  5. 分布式图数据库-JanusGraph简介
  6. 鸟哥的linux私房菜中推荐的linux学习网站
  7. python3之http.server模块
  8. 3D打印经验分享导航
  9. 无线ac管理服务器调试方法,AC功能管理无线AP设置步骤
  10. 连点器android版本,连点器安卓手机版