Spring Boot项目使用Docker和Kubernetes(k8s)进行容器化部署

Spring Boot项目的结构

项目名称是Test

  1. 项目根据环境不同需要读取不同的application.yml
  2. 项目使用logback作为日志工具,需要读取一个logback-spring.xml的配置文件。
  3. 项目还需要读取一个properties文件。
  4. 为方便,所有Kubernetes资源均在default namespace下。
namespace

Kubernetes的许多资源对象都隶属于某个namespace,namespace是对资源的逻辑划分,不同namespace下的资源可以做到简单隔离。

准备工作

镜像

针对项目jar包,我们需要将其打成一个Docker镜像,而Dockerfile就是打包过程的指导文件,类似于make过程中的Makefile

jar->Docker镜像

以下是Dockerfile的内容。


  1. FROM表示要生产的镜像的基础镜像,我们使用jdk8。
  2. VOLUME表示定义一个匿名卷,也可以理解为创建一个目录,这里的/tmp是由于tomcat的需要。
  3. ADD表示将项目编译后的jar包拷贝到镜像里,默认为根目录/
  4. ENTRYPOINT表示入口点,即容器启动时执行的命令,通过上述组合,实际执行的命令为:java -Djava.security.egd=file:/dev/./urandom -jar -Dspring.config.location=/etc/config/application.yml -Dlogging.config=/etc/config/logback-spring.xml -DconfPath=/etc/config /test.jar
    注意这里的配置路径/etc/config还不存在,下文中会创建和用到。

配置

Kubernetes ConfigMap

ConfigMap可以用来保存单个的键值对,也可以保存配置文件。

配置文件->ConfigMap

针对项目配置,需要做的改造就是把配置文件(应用、日志、业务)转化成ConfigMap对象,从而让Kubernetes化后的应用能够读取。

以下是test-config.yml的内容。


  1. 注意配置文件按照yaml规范缩进。
  2. data属性里记录实际的配置,本质上仍是键值对,如第一个数据的key为application-yml,内容为其配置内容。

应用部署定义

Kubernetes Deployment

Deployment是一种控制容器组的对象,在Deployment中定义一个期望的容器组的数量,Deployment在创建后会维持这个数量,当数量少于期望时会新建容器组,反之会停止超额的容器组。

部署->Deployment

针对本项目,对应的Deployment配置如下。

test-deployment.yml内容如下。


  1. replicas即为此Deployment期望的容器组的数量。
  2. metadata.labels用于跟下文中的Service对接。
  3. spec.selector.matchLabels与容器组的spec.template.metadata.labels对接。
  4. spec.template.spec.volumes定义了一些卷,name为卷名。
    • 如果定义了configMap属性,则items属性的key对应上文中ConfigMap对象的名称,path则为要输出的文件,如第一个item的行为是读取ConfigMap对象test-config的第一个数据的内容(key=application-yml),并将其保存为application.yml配置文件。
    • 如果定义了hostPath属性,则是宿主机上的同名目录,如此处将容器日志输出到宿主机的/var/log/test路路径。
  5. spec.template.spec.containers定义了容器组中的容器,包括容器名、镜像、容器暴露的端口,以及要挂载的卷,在volumeMounts中,name为上述卷名,mountPath为挂载路径,从而容器内部存在/etc/config路径,且可以读取到上述配置文件。

服务定义

Kubernetes Service

默认情况下,Kubernetes集群内的容器是不能被集群外访问的。此时我们需要将应用连接到Service,Service可以对集群内部暴露,也可以对外暴露宿主机端口,还能通过LB VIP暴露服务。

外部访问->Service

针对本项目,对应的Service配置如下。

test-service.yml内容如下。


  1. spec.selector用于连接容器组,与上文中Deployment定义的容器组的labels对应。
  2. spec.type定义Service的暴露方式,NodePort为对集群外暴露,用户通过宿主机端口访问应用,即:
    • 用户->宿主机IP:30777->Service:7777->容器:7777

部署工作

编译jar包

不论使用Maven还是Gradle,生成jar包,此处不细说。

生成Docker镜像

使用以下命令生成Docker镜像,当然,前提是生成镜像的机器上需要有基础镜像openjdk:8-jdk-alpine


同时,需要让所有Kubernetes的Node能获取到该镜像,有两种途径:

  1. 将该镜像打包并在所有Node上加载。

  2. 将该镜像推送到所有Node均能访问的镜像仓库里。
创建Kubernetes资源

分别创建ConfigMap、Deployment、Service。


验证

查看资源对象是否正常。


访问服务。


+2

发表评论

您的电子邮箱地址不会被公开。