前言
在互联网时代,为了实现应用更快的开发迭代,和更好的弹性伸缩,互联网应用不再采用传统的三层架构,而是使用微服务的方式来实现软件系统的松耦合,跨部门开发以及快速交付等等目的。Docker定义容器技术标准使得容器技术的落地变得十分简单,应用可以稳定便携的运行在容器中
在工作过程中,我需要将开发的SpringBoot应用打包成Docker镜像部署到k8s集群中进行管理。本篇文章是我完成任务后的总结归纳,下面内容可供参考
一共有以下几个步骤
- springboot项目打成jar包(此次不做过多解释)
- 制作docker镜像
- 编写charts
- 容器化部署
一、将SpringBoot应用打包
首先保证springboot项目在本地成功运行,然后maven package打成jar包
二、制作Docker镜像
2.1 将jar包上传到服务器上,创建Dockerfile (必须是这个名字)和jar包放在同一目录下
代码如下(示例):
vim Dockerfile
2.2 编写Dockerfile
代码如下(示例):
# 拉取基础镜像
FROM java:8
# 设置作者信息
MAINTAINER xiaopeng "xiaopeng@baidu.com"
# 把warning-tool-0.0.1-SNAPSHOT.jar添加到容器里,并重命名为warning-tool.jar
# 因为jar和Dockerfile在同一个目录下,所以只写文件名即可
ADD warning-tool-0.0.1-SNAPSHOT.jar warning-tool.jar
# 设置端口号,此处只开放一个端口8089
EXPOSE 8089
# 执行命令,此处运行warning-tool.jar 指定配置文件
RUN bash -c 'touch /warning-tool.jar'
ENTRYPOINT ["java","-jar","warning-tool.jar","--spring.config.location=/config/application.properties"]
该处详细解释各个参数。
FROM:指定基础镜像,必需为第一个指令。FROM : tag可选
MAINTAINER:维护者信息
ADD:将本地文件添加到容器的指定目录中,tar类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似wget
EXPOSE:设置端口号,如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -P参数
RUN:构建镜像时执行的指令
注意:多行命令不要写多个RUN,原因是Dockerfile中每一个指令都会建立一层.
多少个RUN就构建了多少层镜像,会造成镜像的臃肿、多层,不仅仅增加了构件部署的时间,还容易出错。 RUN书写时的换行符是\
RUN是构建容器时就运行的命令以及提交运行结果
CMD是容器启动时执行的命令,在构建时并不运行,构建时指定了这个命令到底是个什么样子
LABEL:功能是为镜像指定标签
ENTRYPOINT:配置容器,使其可执行化。配合CMD可省去命令,只使用参数。
COPY:功能类似ADD,但是是不会自动解压文件,也不能访问网络资源。
VOLUME:用于指定持久化目录
2.3 打包镜像
运行一条命令即可(注意最后有个.号):
docker build -f Dockerfile -t registry.xxx.baidu.com/dev/warningtool:v1.0 .
-f:指定Dockerfile文件 注意:名字要起成这种registry.xxx.baidu.com/dev/…这种,不然上传不到仓库
-t:指定镜像的标签信息
2.4 检查镜像是否成功生成
docker images | grep warningtool
2.5 运行镜像
// -p后面有两个端口,分别是:宿主机端口:容器端口
docker run -p 8083:8083 --name=warningtool registry.xxx.baidu.com/dev/warningtool:v1.0
2.6 下载镜像
docker save -o warningtool.tar registry.xxx.baidu.com/dev/warningtool
三、编写Charts
k8s 部署服务可以采用两种方式
- 自己编写对应的资源控制yaml ,kubectl apply -f XX .yml部署
- 使用helm charts的方式部署
Helm 是 Deis 开发的一个用于 Kubernetes 应用的包管理工具,主要用来管理 Charts。
下图是通过helm create test的方式创建charts,以下为目录结构
文件夹下有三部分: Chart.yaml 、 templates文件夹 、 values.yaml
3.1 Charts.yaml文件
说明:Charts.yml 用于编写版本信息
示例:Charts.yaml
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: warningTool
version: 0.1.0
3.2 values.yaml文件
说明:values.yaml 用于编写整个charts应用的 参数信息 ,比如 image , service-type ,等可变信息。主要定义一些变量,赋值给其他的yaml。
示例:values.yaml。这里是按照nginx的charts作为模板进行修改
# Default values for nginx.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
warningtool:
# 定义应用的名字
fullname: warningtool-1-0-0
fullnameapp: nginx-app
# 定义应用副本数量
replicaCount: 1
liveinitialDelaySeconds: 5
readinitialDelaySeconds: 5
# 定义镜像的仓库地址 tag版本号
image:
repository: registry.det.baidu.com/xxx/warningtool
tag: v1.0
pullPolicy: IfNotPresent
hostPath:
# 设置是否开启站点模式、如果为true则将宿主机的/data目录通过站点模式映射出来。
enabled: true
path: /data
type: ''
nameOverride: ""
fullnameOverride: ""
# 定义service的类型和端口。
service:
type: NodePort
port: 8090
resources:
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 2
# memory: 1Gi
# 启动的最小要求,如不满足则无法启动。
requests:
cpu: 1
memory: 2Gi
# 指定pod分配到指定node节点。
nodeSelector: {}
# 节点亲和性(容忍)是pod的一种属性,它使pod被吸引到一类特定的节点。
tolerations: []
affinity: {}
# 存活探针,判断pod(中的应用容器)是否健康
livenessProbe:
periodSeconds: 5
timeoutSeconds: 20
successThreshold: 1
failureThreshold: 3
# 就绪探针,pod就绪我们可以理解为这个pod可以接手请求和访问
readinessProbe:
periodSeconds: 5
timeoutSeconds: 20
successThreshold: 3
failureThreshold: 1
3.3 templates文件夹
templates 目录是实际的 k8s资源控制部署文件 (重点关注)
template文件夹下有warning-cm.yaml、 warning-deployment,.yaml、 warning-service.yaml
configMap用于统一管理配置信息,service用于对外提供服务,deployment用于部署pod及系统升级更新。
3.3.1 configmap.yaml
说明:configMap用于统一管理配置信息, 文件名可以不固定。但示例文件中kind的类型应为ConfigMap(重点关注)
示例:warningtool-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Values.warningtool.fullname }}
namespace: {{ .Release.Namespace }}
data:
application.properties: |
server.port= 8089
phones= xxxxxxxx,xxxxxxxx
logging.level.root=INFO
logging.file.name=./logs/warningtool.log
logging.logback.rollingpolicy.max-file-size=50MB
参数详解:
name: 定义service名称 引用values.yaml定义的应用名称 namespace: 定义所在命名空间
application.properties: 类似于这种default.conf 这种 将配置挂载到cm,方便修改。包括端口、日志级别、日志生成路径等等
3.3.2 service.yaml
说明:Service可以看作是一组提供相同服务的Pod对外的访问接口。借助Service,应用可以方便地实现服务发现和负载均衡。
示例:warning-service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.warningtool.fullname }}
# 通过spec.selector字段确定这个Service将要使用哪些Label。
# 在本例,这个名warning-service的Service,将会管理所有具有标签app: warningtool的Pod。
spec:
type: {{ .Values.service.type }}
selector:
app: warningtool
version: warningtool-1.0.0
ports:
- port: 8089
nodePort: {{ .Values.service.port }}
targetPort: 8089
protocol: TCP
name: http
参数详解:
type: service类型 nodePort
有四种选项 1. ClusterIP 虚拟ip 集群内部访问
2.NodePort 将Service通过指定的Node上的端口暴露给外部
3.LoadBalancer 在 NodePort 的基础上,借助 cloud provider 创建一个外部的负载均衡器 此模式只能在云服务器
4.ExternalName 将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定)
selector: 需要和deployment的selector matchLabels保持一致,才能绑定到一起。(重点关注)
参数 | 含义 |
---|---|
port | kubernetes中的服务之间访问的端口 |
nodePort | 外部机器可访问的端口。比如一个Web应用需要被其他用户访问,那么需要配置type=NodePort |
targetPort | 容器的端口(最根本的端口入口),与制作容器时暴露的端口一致(DockerFile中EXPOSE),例如docker.io官方的nginx暴露的是80端口。 |
3.3.3 deployment.yaml
说明:deployment用于部署pod及系统升级更新。
示例:warning-deployment.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ .Values.warningtool.fullname }}
namespace: {{ .Release.Namespace }}
# deployment的标签 标签的键值对 app:warningtool
labels:
app: warningtool
version: warningtool-1.0.0
spec:
replicas: {{ .Values.warningtool.replicaCount }}
# 与service里的selector的标签对应上才可以对外提供服务
selector:
# 和下面的labels一致,否则会直接报错:选择的和模板标签不匹配
matchLabels:
app: warningtool
version: warningtool-1.0.0
template:
metadata:
# 为即将新建的pod附加label
labels:
app: warningtool
version: warningtool-1.0.0
spec:
containers:
- name: {{ .Values.warningtool.fullname }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
resources:
{{ toYaml .Values.resources | indent 12 }}
ports:
- name: http
containerPort: 8089
protocol: TCP
livenessProbe:
httpGet:
path: /healthcheck
port: 8089
initialDelaySeconds: {{ .Values.warningtool.liveinitialDelaySeconds }}
periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
successThreshold: {{ .Values.livenessProbe.successThreshold }}
failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
readinessProbe:
httpGet:
path: /healthcheck
port: 8089
initialDelaySeconds: {{ .Values.warningtool.readinitialDelaySeconds }}
periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
successThreshold: {{ .Values.readinessProbe.successThreshold }}
failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
# 映射到容器的位置
volumeMounts:
{{- if .Values.hostPath.enabled }}
- mountPath: /data
name: data
{{- end }}
- name: config
mountPath: /config/application.properties
subPath: application.properties
- name: log
mountPath: /logs
volumes:
- name: config
configMap:
name: {{ .Values.warningtool.fullname }}
{{- if .Values.hostPath.enabled }}
- name: data
hostPath:
path: {{ .Values.hostPath.path }}
type: {{ .Values.hostPath.type }}
- name: log
hostPath:
# 宿主机的目录
path: /data/logs
type: DirectoryOrCreate
{{- end }}
{{- if .Values.nodeSelector }}
# 指定pod分配到指定node节点,属于强制性的。如果我们的目标节点没有可用的资源,我们的pod就会一直处于Pending状态
nodeSelector:
{{ toYaml .Values.nodeSelector | indent 8 }}
{{- end }}
参数详解都写在注释上了。需要注意的点
四、容器化部署
4.1 导入镜像
docker load -i warningtool.tar
4.2 推送镜像
docker push registry.xxx.baidu.com/dev/warningtool:v1.0
4.3 查看镜像列表
docker images | grep warning
4.3 helm部署k8s应用
helm install warningtool -f values.yaml .
4.4 查看应用服务状态
kubectl get po | grep warning
以上就是从零开始进行docker镜像的制作和打包,制作Charts。使用helm方式部署到k8s集群。