Kubernetes SpringCloud微服务容器云之路

SpringCloud微服务容器云之路

  1. Springboot应用配合Actuator开启:监控检查优雅停机监控metrics等endpoints
  2. 根据Dockerfile定义制作Docker镜像并上传Harbor私有Docker Registry
  3. 渲染K8S部署模板文件并完成应用部署,同时应该考虑快速回滚等保障机制

Tips: 步骤2 - 可使用Maven Plugin dockerfile-maven集成到Maven流程中,命令如: mvn dockerfile:build, mvn dockerfile:push, 详见官方文档

1、Springboot配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
spring:
application:
name: spring-produce
profiles:
active: ${ENVIRONMENT:pro}
server:
port: 10080
management:
endpoints:
web:
base-path: /actuator/
exposure:
include: health,shutdown,prometheus # 监控检查,优雅停机,监控metrics
endpoint:
shutdown:
enabled: true
metrics:
tags:
application: ${spring.application.name} # 监控metrics Tag
eureka:
instance:
preferIpAddress: true
client:
serviceUrl:
defaultZone: http://eureka-0.eureka.micro-public.svc.cluster.local:8761/eureka,http://eureka-1.eureka.micro-public.svc.cluster.local:8761/eureka,http://eureka-2.eureka.micro-public.svc.cluster.local:8761/eureka
logging:
file:
max-size: 200MB
max-history: 7
path: /opt/logs
name: /opt/logs/${HOSTNAME}.${spring.application.name}.log

注意:actuator开启prometheus需要添加依赖

1
2
3
4
5
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
<version>${micrometer.version}</version>
</dependency>

2、Dockerfile

在项目根目录下创建Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# base镜像 - JDK发行版
FROM adoptopenjdk:8u252-b09-jdk-hotspot
# 署名
MAINTAINER Boer Zhang <boer0924@gmail.com>
# 工作目录 - 即jar包所在目录
WORKDIR /opt
# mvn clean package -Dmaven.test.skip=true
## 服务版本
COPY target/produce-1.0.1.jar .
# 更改镜像时区
RUN echo "Asia/Chongqing" > /etc/timezone
# 暴露服务端口
EXPOSE 10080
# 服务启动命令
## 1、${JVM_OPTS} - JVM配置,如:-Xms768m -Xmx768m -javaagent:/usr/skywalking/agent/skywalking-agent.jar
## 2、${APP_OPTS} - APP配置,如:--spring.profiles.active=dev --spring.kafka.consumer.group-id=xxx.group
CMD [ "sh", "-c", "java ${JVM_OPTS} -jar produce-1.0.1.jar ${APP_OPTS}" ]

3、K8S容器云部署文件模板

在项目根目录下创建manifests目录,在目录下创建文件k8s.yaml

  1. 服务名称 - 全局替换<change-me>为您的服务名称
  2. 服务端口 - 全局替换10080为您的服务端口
  3. 服务资源 - 注意resources字段服务所申请的资源
  4. 服务域名 - 根据实际情况,选择是否需要对外暴露Ingress
  5. 服务版本 - 根据项目pom文件version字段,同时修改Dockerfile中jar包版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
apiVersion: apps/v1
kind: Deployment
metadata:
name: <change-me>-deployment # deployment名称
annotations:
kubernetes.io/change-cause: <CHANGE_CAUSE> # 版本说明 - 用于回滚等
spec:
selector:
matchLabels:
app: <change-me> # 标签选择器,与下面[Flag_label]对应
replicas: 1 # 多实例
template:
metadata:
labels:
app: <change-me> # [Flag_label]
spec:
initContainers: # skywalking-agent initContainer
- image: registry.boer.xyz/public/skywalking-agent:8.1.0
name: skywalking-agent
imagePullPolicy: IfNotPresent
command: ['sh']
args: ['-c','cp -r /usr/skywalking/agent/* /skywalking/agent']
volumeMounts:
- mountPath: /skywalking/agent
name: skywalking-agent
containers:
- name: <change-me> # EFK日志系统日志查询tag
image: <IMAGE>:<IMAGE_TAG> # 镜像地址:版本
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /usr/skywalking/agent # 挂载skywalking-agent到pod
name: skywalking-agent
- mountPath: /opt/logs # 挂载app-logs到node
name: app-logs
ports:
- containerPort: 10080 # 服务暴露端口
resources: # 服务所需资源申请
requests:
memory: "512Mi"
cpu: "200m"
limits:
memory: "1Gi"
cpu: "600m"
env: # 环境变量
- name: ENVIRONMENT
value: "pro"
- name: APP_OPTS
value: "--spring.kafka.consumer.group-id=consumer.group"
- name: JVM_OPTS
value: "-Xms512m -Xmx512m -javaagent:/usr/skywalking/agent/skywalking-agent.jar"
livenessProbe: # 存活探针
httpGet:
path: /actuator/health
port: 10080
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 5
readinessProbe: # 就绪探针
httpGet:
path: /actuator/health
port: 10080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
lifecycle:
preStop: # pod停止前Hook - 优雅停机
exec:
command:
- "curl"
- "-XPOST"
- "http://127.0.0.1:10080/actuator/shutdown"
imagePullSecrets:
- name: regcred
volumes:
- name: skywalking-agent
emptyDir: {}
- name: app-logs
hostPath:
path: /opt/app-logs/<change-me>
type: DirectoryOrCreate
---
apiVersion: v1
kind: Service
metadata:
name: <change-me>-service # 服务名称
annotations:
prometheus.io/path: /actuator/prometheus # 应用监控metrics路径 - 对应配置文件开启prometheus
prometheus.io/port: "10080"
prometheus.io/scrape: "true"
labels:
app: <change-me>
spec:
type: ClusterIP
ports:
- port: 10080
targetPort: 10080
selector:
app: <change-me>
---
# 请根据实际情况,选择是否需要对外暴露Ingress
## 在微服务架构中,一般通过Gateway网关统一对外提供服务,微服务单独对外暴露Ingress情况请谨慎选择
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: <change-me>-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/load-balance: "ip_hash" # session保持
nginx.ingress.kubernetes.io/upstream-hash-by: "$request_uri" # 配合ip_hash使用
spec:
rules:
- host: <change-me>.boer.xyz # Ingress 域名
http:
paths:
- path: /
backend:
serviceName: <change-me>-service
servicePort: 10080

4、K8S发布

此过程已通过Jenkins Pipeline自动化CICD方式实现

  1. Git clone/pull代码git clone git://gitea.boer.xyz/spring-produce.git
  2. Junit单元测试mvn test # 普通程序员都没有单元测试?
  3. Maven编译打包mvn clean package -Dmaven.test.skip=true
  4. Docker打包镜像docker build -t ${image}:${imageTag} .
  5. Harbor镜像推送docker push ${image}:${imageTag}
  6. Sed渲染模板
    1
    2
    3
    sed -i "s|<CHANGE_CAUSE>|${changeCause}|g" manifests/k8s.yaml
    sed -i "s|<IMAGE>|${image}|g" manifests/k8s.yaml
    sed -i "s|<IMAGE_TAG>|${imageTag}|g" manifests/k8s.yaml
  7. Kubectl部署应用kubectl --kubeconfig $kubeconfig apply -f manifests/k8s.yaml -n ${NAMESPACE}
  8. Rollout快速回滚kubectl --kubeconfig ${kubeconfig} rollout undo deployment consume-deployment -n ${NAMESPACE}

Kubernetes SpringCloud微服务容器云之路
https://www.boer.xyz/2020/07/22/k8s-springcloud-fly/
作者
boer
发布于
2020年7月22日
许可协议