| git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
这个git项目中有多个文件夹,本章源码在springbootsidecardemo这个文件夹下,如下图红框所示:
您也可以随本文一起来开发这个应用:
-
应用名为springbootsidecardemo,是用maven构建的,JDK使用1.8,Spring Boot版本2.1.0.RELEASE;
-
应用的pom.xml如下,为了构建Docker镜像使用了docker-maven-plugin插件,该插件具体的配置请参照下面的注释:
<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”>
4.0.0
com.bolingcavalry
springbootsidecardemo
0.0.1
jar
springbootsidecardemo
Demo project for Spring Boot sidecard demo in K8S
org.springframework.boot
spring-boot-starter-parent
2.1.0.RELEASE
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
app
org.springframework.boot
spring-boot-maven-plugin
com.spotify
docker-maven-plugin
0.4.12
bolingcavalry/${project.artifactId}
${project.version}
busybox
/
${project.build.directory}
app.jar
上面的配置有一处需要注意,就是基础镜像的选择(就是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
*/
@RestController
public 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/springbootsidecardemo
Step 1/2 : FROM busybox
—> 59788edf1f3e
Step 2/2 : ADD /app.jar //
—> 8105c9ac033b
Removing intermediate container fdc62513abf6
Successfully 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.1
IMAGE CREATED CREATED BY SIZE COMMENT
8105c9ac033b 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
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 -al
total 16276
drwxr-xr-x 9 root root 4096 Nov 6 05:08 .
drwxr-xr-x 5 root
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
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.original
drwxr-xr-x 3 root root 4096 Nov 6 05:08 classes
drwxr-xr-x 2 root root 4096 Nov 6 05:08 docker
drwxr-xr-x 3 root root 4096 Nov 6 05:08 generated-sources
drwxr-xr-x 3 root root 4096 Nov 6 05:08 generated-test-sources
drwxr-xr-x 2 root root 4096 Nov 6 05:08 maven-archiver
drwxr-xr-x 3 root root 4096 Nov 6 05:08 maven-status
drwxr-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 sidecar
bolingcavalry/springbootsidecardemo 0.0.2 f6ba01c33388 11 hours ago 17.8 MB
bolingcavalry/springbootsidecardemo 0.0.1 8105c9ac033b 11 hours ago 17.8 MB
现在镜像已经OK,该准备部署到kubernetes环境了;
编写yaml文件
- 在可以执行kubectl命令的机器上编写配置文件,Pod的配置javaweb-deploy.yaml文件内容如下:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: javaweb
spec:
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: v1
kind: Service
metadata:
name: javaweb
spec:
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,如果您发现我对官网的指导内容理解有误或有偏差,欢迎您的热心指正,谢谢!
参考文档
下面是文中涉及到的一些知识点的细节,欢迎点击参考:
- Docker下构建java应用镜像:
《maven构建docker镜像三部曲之二:编码和构建镜像》;
《maven构建docker镜像三部曲之三:推送到远程仓库(内网和阿里云)》;
- kubernetes环境: