本文讲述如何在Docker和Kubernetes中部署 SpringBoot 应用。
创建 SpringBoot 应用
使用idea创建一个简单的SpringBoot应用。
package com.wyk.k8sDemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
在其中添加一个简单的web页面。
package com.wyk.k8sDemo.web;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@RequestMapping("/")
public String index() {
return "Hello Kubernetes";
}
}
本地运行,查看程序是否有问题。访问 http://localhost:8080 。
添加 Docker 支持
修改项目的pom.xml,添加docker插件 dockerfile-maven-plugin。
4.0.0
com.wyk
k8sdemo
1.0-SNAPSHOT
A custom project
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-starter-parent
2.1.4.RELEASE
org.springframework.boot
spring-boot-starter-web
junit
junit
4.11
test
org.springframework.boot
spring-boot-maven-plugin
com.spotify
dockerfile-maven-plugin
1.4.10
${project.artifactId}
./
${project.version}
target/${project.build.finalName}.jar
添加 Dockerfile
在SpringBoot应用的根目录下创建文件Dockerfile并添加如下内容。
# 基础镜像
FROM openjdk:8-jdk-alpine
# 对应pom.xml文件中的dockerfile-maven-plugin插件buildArgs配置项JAR_FILE的值
ARG JAR_FILE
# 复制打包完成后的jar文件到/opt目录下
COPY ${JAR_FILE} /opt/app.jar
# 启动容器时执行
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/opt/app.jar"]
# 使用端口8080
EXPOSE 8080
文件的大致含义为:本镜像基于openjdk:8-jdk-alpine镜像创建,然后获取pom.xml中的JAR_FILE参数,即生成的jar包文件名),并将该jar包拷贝至/opt/app.jar,然后在容器启动时执行java命令启动jar包。最后暴露8080端口,用于后面进行映射,访问SpringBoot应用。
部署SpringBoot 应用至 Docker
启动Docker Quick Start Terminal打开Docker,等待容器启动成功。需要注意的是Docker虚拟机的IP,后面访问应用会用到。
将目录切换到SpringBoot应用的根目录,执行如下命令。
mvn clean package docker:build
命令执行成功后即生成了Docker镜像。运行命令查看镜像。
$ docker images
REPOSITORY TAG IMAGE ID CREATED
VIRTUAL SIZE
k8sdemo 1.0-SNAPSHOT 2ea0d58678e0 8 hours ago
121.5 MB
openjdk 8-jdk-alpine bba097ee5ee1 5 months ago
104.8 MB
启动镜像。
$ docker run -idt -p 2345:8080 --name k8sdemo k8sdemo:1.0-SNAPSHOT
cdf8e84534331a10d037e073ed55a1703c8dca7b9b7248714fa0ed0d71f71494
查看镜像是否启动成功。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
cdf8e8453433 k8sdemo:1.0-SNAPSHOT "java -Djava.security" 2 seconds ag
o Up 4 seconds 0.0.0.0:2345->8080/tcp k8sdemo
本镜像已启动成功,可以看到8080端口映射到了Docker虚拟机的2345端口。
如果未启动成功可以通过docker ps -a 命令查看所有容器。然后通过docker logs -t --since=30m k8sdemo命令查看日志查找启动失败原因。
访问 http://192.168.99.105:2345 ,可以看到网页内容。
部署 SpringBoot 集群至 Kubernetes
下面以minikube为例介绍如何在Kubernetes中部署SpringBoot应用。
ps:本部分为了区分命令行的输入和输出我在所有输入前添加了$ ,其实Windows命令行下不会显示这个符号
启动 minikube
使用管理员权限打开命令提示符并启动 minikube。
$ minikube start
将 docker daemon 切换成 minikube 的。
$ minikube docker-env
SET DOCKER_TLS_VERIFY=1
SET DOCKER_HOST=tcp://192.168.99.107:2376
SET DOCKER_CERT_PATH=C:\Users\015422343\.minikube\certs
REM Run this command to configure your shell:
REM @FOR /f "tokens=*" %i IN ('minikube docker-env') DO @%i
根据提示运行命令。
$ @FOR /f "tokens=*" %i IN ('minikube docker-env') DO @%i
上传镜像至 minikube
然后打包镜像至minikube。
$ mvn clean package docker:build
这时候报了一个错误。
[ERROR] No plugin found for prefix 'docker' in the current project and in the pl
ugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the rep
ositories [local (C:\Users\015422343\.m2\repository), central (https://repo.mave
n.apache.org/maven2)] -> [Help 1]
错误原因是插件不在maven配置文件settings.xml中pluginGroups的白名单里面。
修改用户目录下.m2目录中的setting.xml文件(没有则需要添加),在
com.spotify
然后运行,又报错了。。。
[ERROR] Failed to execute goal com.spotify:docker-maven-plugin:1.2.1:build (defa
ult-cli) on project k8sdemo: Exception caught: Must specify baseImage if dockerD
irectory is null -> [Help 1]
这个错误是没找到镜像,研究了很久没明白,从网上看到一个方案,修改了下命令,将docker:build修改为dockerfile:build,dockerfile:build是dockerfile-maven-plugin插件的命令,二者具体有什么不同还是没太明白,后续还需研究。
$ mvn clean package dockerfile:build
构建镜像成功后进行验证。
$ docker images
REPOSITORY
TAG IMAGE ID CREATED VIRTUAL SIZE
k8sdemo
1.0-SNAPSHOT sha256:9fa31 41 seconds ago 121.5 MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver
v1.16.0 sha256:b3055 6 weeks ago 217.1 MB
...
部署 SpringBoot 集群
接下来编写部署的yaml文件k8sdemo-deployment.yaml。
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8sdemo-deployment
labels:
app: k8sdemo
spec:
replicas: 3
selector:
matchLabels:
app: k8sdemo
template:
metadata:
labels:
app: k8sdemo
spec:
containers:
- name: k8sdemo
image: k8sdemo:1.0-SNAPSHOT
ports:
- containerPort: 8080
接下来运行命令部署应用集群。
$ kubectl apply -f k8sdemo-deployment.yaml
Warning: kubectl apply should be used on resource created by either kubectl crea
te --save-config or kubectl apply
deployment.apps/k8sdemo-deployment configured
检查创建好的Pod。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
k8sdemo-deployment-7c76b4bf8f-8bn2n 1/1 Running 1 21h
k8sdemo-deployment-7c76b4bf8f-fnwfv 1/1 Running 1 21h
k8sdemo-deployment-7c76b4bf8f-v5wz6 1/1 Running 1 21h
如果创建的Pod存在问题,建议使用minikube logs查看一下相关日志。
访问SpringBoot集群
暴露集群的端口。
$ kubectl expose deployment k8sdemo-deploymen
t --type=NodePort
service/k8sdemo-deployment exposed
然后获取访问的URL。
$ minikube service k8sdemo-deployment --url
* http://192.168.99.107:30947
在浏览器中访问相关URL。