当前位置:   article > 正文

SpringBoot + K8S 中的滚动发布、优雅停机、弹性伸缩、应用监控、配置分离_springboot滚动更新

springboot滚动更新

hevc?url=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2F8KKrHK5ic6XA8Mo2nJmpHWU71jqIHGEfSibmuibEibealFHwePwibHrPygU3XPgxKx69lYDoic5Iwp4yJXs2K94Wcjibg%2F640%3Fwx_fmt%3Djpeg%26tp%3Dwxpic%26wxfrom%3D5%26wx_lazy%3D1%26wx_co%3D1&type=jpg


前言

K8s + SpringBoot实现零宕机发布:健康检查+滚动更新+优雅停机+弹性伸缩+Prometheus监控+配置分离(镜像复用)

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

配置

健康检查

  • 健康检查类型:就绪探针(readiness)+ 存活探针(liveness)

  • 探针类型:exec(进入容器执行脚本)、tcpSocket(探测端口)、httpGet(调用接口)

业务层面

项目依赖 pom.xml

  1. <dependency>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-starter-actuator</artifactId>
  4. </dependency>

定义访问端口、路径及权限 application.yaml

  1. management:
  2.   server:
  3.     port: 50000                         # 启用独立运维端口
  4.   endpoint:                             # 开启health端点
  5.     health:
  6.       probes:
  7.         enabled: true
  8.   endpoints:
  9.     web:
  10.       exposure:
  11.         base-path: /actuator            # 指定上下文路径,启用相应端点
  12.         include: health

将暴露/actuator/health/readiness/actuator/health/liveness两个接口,访问方式如下:

  1. http://127.0.0.1:50000/actuator/health/readiness
  2. http://127.0.0.1:50000/actuator/health/liveness

运维层面

k8s部署模版deployment.yaml

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. spec:
  4.   template:
  5.     spec:
  6.       containers:
  7.       - name: {APP_NAME}
  8.         image: {IMAGE_URL}
  9.         imagePullPolicy: Always
  10.         ports:
  11.         - containerPort: {APP_PORT}
  12.         - name: management-port
  13.           containerPort: 50000         # 应用管理端口
  14.         readinessProbe:                # 就绪探针
  15.           httpGet:
  16.             path: /actuator/health/readiness
  17.             port: management-port
  18.           initialDelaySeconds: 30      # 延迟加载时间
  19.           periodSeconds: 10            # 重试时间间隔
  20.           timeoutSeconds: 1            # 超时时间设置
  21.           successThreshold: 1          # 健康阈值
  22.           failureThreshold: 6          # 不健康阈值
  23.         livenessProbe:                 # 存活探针
  24.           httpGet:
  25.             path: /actuator/health/liveness
  26.             port: management-port
  27.           initialDelaySeconds: 30      # 延迟加载时间
  28.           periodSeconds: 10            # 重试时间间隔
  29.           timeoutSeconds: 1            # 超时时间设置
  30.           successThreshold: 1          # 健康阈值
  31.           failureThreshold: 6          # 不健康阈值

滚动更新

k8s资源调度之滚动更新策略,若要实现零宕机发布,需支持健康检查

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: {APP_NAME}
  5.   labels:
  6.     app: {APP_NAME}
  7. spec:
  8.   selector:
  9.     matchLabels:
  10.       app: {APP_NAME}
  11.   replicas: {REPLICAS}    # Pod副本数
  12.   strategy:
  13.     type: RollingUpdate    # 滚动更新策略
  14.     rollingUpdate:
  15.       maxSurge: 1                   # 升级过程中最多可以比原先设置的副本数多出的数量
  16.       maxUnavailable: 1             # 升级过程中最多有多少个POD处于无法提供服务的状态

优雅停机

在K8s中,当我们实现滚动升级之前,务必要实现应用级别的优雅停机。否则滚动升级时,还是会影响到业务。使应用关闭线程、释放连接资源后再停止服务

业务层面

项目依赖 pom.xml

  1. <dependency>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-starter-actuator</artifactId>
  4. </dependency>

定义访问端口、路径及权限 application.yaml

  1. spring:
  2.   application:
  3.     name: <xxx>
  4.   profiles:
  5.     active: @profileActive@
  6.   lifecycle:
  7.     timeout-per-shutdown-phase: 30s     # 停机过程超时时长设置30s,超过30s,直接停机
  8. server:
  9.   port: 8080
  10.   shutdown: graceful                    # 默认为IMMEDIATE,表示立即关机;GRACEFUL表示优雅关机
  11. management:
  12.   server:
  13.     port: 50000                         # 启用独立运维端口
  14.   endpoint:                             # 开启shutdown和health端点
  15.     shutdown:
  16.       enabled: true
  17.     health:
  18.       probes:
  19.         enabled: true
  20.   endpoints:
  21.     web:
  22.       exposure:
  23.         base-path: /actuator            # 指定上下文路径,启用相应端点
  24.         include: health,shutdown

将暴露/actuator/shutdown接口,调用方式如下:

curl -X POST 127.0.0.1:50000/actuator/shutdown

运维层面

确保dockerfile模版集成curl工具,否则无法使用curl命令

  1. FROM openjdk:8-jdk-alpine
  2. #构建参数
  3. ARG JAR_FILE
  4. ARG WORK_PATH="/app"
  5. ARG EXPOSE_PORT=8080
  6. #环境变量
  7. ENV JAVA_OPTS=""\
  8.     JAR_FILE=${JAR_FILE}
  9. #设置时区
  10. RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
  11. RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories  \
  12.     && apk add --no-cache curl
  13. #将maven目录的jar包拷贝到docker中,并命名为for_docker.jar
  14. COPY target/$JAR_FILE $WORK_PATH/
  15. #设置工作目录
  16. WORKDIR $WORK_PATH
  17. > 基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
  18. >
  19. > * 项目地址:<https://github.com/YunaiV/yudao-cloud>
  20. > * 视频教程:<https://doc.iocoder.cn/video/>
  21. # 指定于外界交互的端口
  22. EXPOSE $EXPOSE_PORT
  23. # 配置容器,使其可执行化
  24. ENTRYPOINT exec java $JAVA_OPTS -jar $JAR_FILE

k8s部署模版deployment.yaml

注:经验证,java项目可省略结束回调钩子的配置

此外,若需使用回调钩子,需保证镜像中包含curl工具,且需注意应用管理端口(50000)不能暴露到公网

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. spec:
  4.   template:
  5.     spec:
  6.       containers:
  7.       - name: {APP_NAME}
  8.         image: {IMAGE_URL}
  9.         imagePullPolicy: Always
  10.         ports:
  11.         - containerPort: {APP_PORT}
  12.         - containerPort: 50000
  13.         lifecycle:
  14.           preStop:       # 结束回调钩子
  15.             exec:
  16.               command: ["curl""-XPOST""127.0.0.1:50000/actuator/shutdown"]

弹性伸缩

为pod设置资源限制后,创建HPA

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: {APP_NAME}
  5.   labels:
  6.     app: {APP_NAME}
  7. spec:
  8.   template:
  9.     spec:
  10.       containers:
  11.       - name: {APP_NAME}
  12.         image: {IMAGE_URL}
  13.         imagePullPolicy: Always
  14.         resources:                     # 容器资源管理
  15.           limits:                      # 资源限制(监控使用情况)
  16.             cpu: 0.5
  17.             memory: 1Gi
  18.           requests:                    # 最小可用资源(灵活调度)
  19.             cpu: 0.15
  20.             memory: 300Mi
  21. ---
  22. kind: HorizontalPodAutoscaler            # 弹性伸缩控制器
  23. apiVersion: autoscaling/v2beta2
  24. metadata:
  25.   name: {APP_NAME}
  26. spec:
  27.   scaleTargetRef:
  28.     apiVersion: apps/v1
  29.     kind: Deployment
  30.     name: {APP_NAME}
  31.   minReplicas: {REPLICAS}                # 缩放范围
  32.   maxReplicas: 6
  33.   metrics:
  34.     - type: Resource
  35.       resource:
  36.         name: cpu                        # 指定资源指标
  37.         target:
  38.           type: Utilization
  39.           averageUtilization: 50

Prometheus集成

业务层面

项目依赖 pom.xml

  1. <!-- 引入Spring boot的监控机制-->
  2. <dependency>
  3.     <groupId>org.springframework.boot</groupId>
  4.     <artifactId>spring-boot-starter-actuator</artifactId>
  5. </dependency>
  6. <dependency>
  7.     <groupId>io.micrometer</groupId>
  8.     <artifactId>micrometer-registry-prometheus</artifactId>
  9. </dependency>

定义访问端口、路径及权限 application.yaml

  1. management:
  2.   server:
  3.     port: 50000                         # 启用独立运维端口
  4.   metrics:
  5.     tags:
  6.       application: ${spring.application.name}
  7.   endpoints:
  8.     web:
  9.       exposure:
  10.         base-path: /actuator            # 指定上下文路径,启用相应端点
  11.         include: metrics,prometheus

将暴露/actuator/metric/actuator/prometheus接口,访问方式如下:

  1. http://127.0.0.1:50000/actuator/metric
  2. http://127.0.0.1:50000/actuator/prometheus

运维层面

deployment.yaml

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. spec:
  4.   template:
  5.     metadata:
  6.       annotations:
  7.         prometheus:io/port: "50000"
  8.         prometheus.io/path: /actuator/prometheus  # 在流水线中赋值
  9.         prometheus.io/scrape: "true"              # 基于pod的服务发现

配置分离

方案:通过configmap挂载外部配置文件,并指定激活环境运行

作用:配置分离,避免敏感信息泄露;镜像复用,提高交付效率

通过文件生成configmap

  1. # 通过dry-run的方式生成yaml文件
  2. kubectl create cm -n <namespace> <APP_NAME> --from-file=application-test.yaml --dry-run=1 -oyaml > configmap.yaml
  3. # 更新
  4. kubectl apply -f configmap.yaml

挂载configmap并指定激活环境

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: {APP_NAME}
  5.   labels:
  6.     app: {APP_NAME}
  7. spec:
  8.   template:
  9.     spec:
  10.       containers:
  11.       - name: {APP_NAME}
  12.         image: {IMAGE_URL}
  13.         imagePullPolicy: Always
  14.         env:
  15.           - name: SPRING_PROFILES_ACTIVE   # 指定激活环境
  16.             value: test
  17.         volumeMounts:                      # 挂载configmap
  18.         - name: conf
  19.           mountPath: "/app/config"         # 与Dockerfile中工作目录一致
  20.           readOnly: true
  21.       volumes:
  22.       - name: conf
  23.         configMap:
  24.           name: {APP_NAME}

汇总配置

业务层面

项目依赖 pom.xml

  1. <!-- 引入Spring boot的监控机制-->
  2. <dependency>
  3.     <groupId>org.springframework.boot</groupId>
  4.     <artifactId>spring-boot-starter-actuator</artifactId>
  5. </dependency>
  6. <dependency>
  7.     <groupId>io.micrometer</groupId>
  8.     <artifactId>micrometer-registry-prometheus</artifactId>
  9. </dependency>

定义访问端口、路径及权限 application.yaml

  1. spring:
  2.   application:
  3.     name: project-sample
  4.   profiles:
  5.     active: @profileActive@
  6.   lifecycle:
  7.     timeout-per-shutdown-phase: 30s     # 停机过程超时时长设置30s,超过30s,直接停机
  8. server:
  9.   port: 8080
  10.   shutdown: graceful                    # 默认为IMMEDIATE,表示立即关机;GRACEFUL表示优雅关机
  11. management:
  12.   server:
  13.     port: 50000                         # 启用独立运维端口
  14.   metrics:
  15.     tags:
  16.       application: ${spring.application.name}
  17.   endpoint:                             # 开启shutdown和health端点
  18.     shutdown:
  19.       enabled: true
  20.     health:
  21.       probes:
  22.         enabled: true
  23.   endpoints:
  24.     web:
  25.       exposure:
  26.         base-path: /actuator            # 指定上下文路径,启用相应端点
  27.         include: health,shutdown,metrics,prometheus

运维层面

确保dockerfile模版集成curl工具,否则无法使用curl命令

  1. FROM openjdk:8-jdk-alpine
  2. #构建参数
  3. ARG JAR_FILE
  4. ARG WORK_PATH="/app"
  5. ARG EXPOSE_PORT=8080
  6. #环境变量
  7. ENV JAVA_OPTS=""\
  8.     JAR_FILE=${JAR_FILE}
  9. #设置时区
  10. RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
  11. RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories  \
  12.     && apk add --no-cache curl
  13. #将maven目录的jar包拷贝到docker中,并命名为for_docker.jar
  14. COPY target/$JAR_FILE $WORK_PATH/
  15. #设置工作目录
  16. WORKDIR $WORK_PATH
  17. # 指定于外界交互的端口
  18. EXPOSE $EXPOSE_PORT
  19. # 配置容器,使其可执行化
  20. ENTRYPOINT exec java $JAVA_OPTS -jar $JAR_FILE

k8s部署模版deployment.yaml

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: {APP_NAME}
  5.   labels:
  6.     app: {APP_NAME}
  7. spec:
  8.   selector:
  9.     matchLabels:
  10.       app: {APP_NAME}
  11.   replicas: {REPLICAS}                            # Pod副本数
  12.   strategy:
  13.     type: RollingUpdate                           # 滚动更新策略
  14.     rollingUpdate:
  15.       maxSurge: 1
  16.       maxUnavailable: 0
  17.   template:
  18.     metadata:
  19.       name: {APP_NAME}
  20.       labels:
  21.         app: {APP_NAME}
  22.       annotations:
  23.         timestamp: {TIMESTAMP}
  24.         prometheus.io/port: "50000"               # 不能动态赋值
  25.         prometheus.io/path: /actuator/prometheus
  26.         prometheus.io/scrape: "true"              # 基于pod的服务发现
  27.     spec:
  28.       affinity:                                   # 设置调度策略,采取多主机/多可用区部署
  29.         podAntiAffinity:
  30.           preferredDuringSchedulingIgnoredDuringExecution:
  31.           - weight: 100
  32.             podAffinityTerm:
  33.               labelSelector:
  34.                 matchExpressions:
  35.                 - key: app
  36.                   operator: In
  37.                   values:
  38.                   - {APP_NAME}
  39.               topologyKey: "kubernetes.io/hostname" # 多可用区为"topology.kubernetes.io/zone"
  40.       terminationGracePeriodSeconds: 30             # 优雅终止宽限期
  41.       containers:
  42.       - name: {APP_NAME}
  43.         image: {IMAGE_URL}
  44.         imagePullPolicy: Always
  45.         ports:
  46.         - containerPort: {APP_PORT}
  47.         - name: management-port
  48.           containerPort: 50000         # 应用管理端口
  49.         readinessProbe:                # 就绪探针
  50.           httpGet:
  51.             path: /actuator/health/readiness
  52.             port: management-port
  53.           initialDelaySeconds: 30      # 延迟加载时间
  54.           periodSeconds: 10            # 重试时间间隔
  55.           timeoutSeconds: 1            # 超时时间设置
  56.           successThreshold: 1          # 健康阈值
  57.           failureThreshold: 9          # 不健康阈值
  58.         livenessProbe:                 # 存活探针
  59.           httpGet:
  60.             path: /actuator/health/liveness
  61.             port: management-port
  62.           initialDelaySeconds: 30      # 延迟加载时间
  63.           periodSeconds: 10            # 重试时间间隔
  64.           timeoutSeconds: 1            # 超时时间设置
  65.           successThreshold: 1          # 健康阈值
  66.           failureThreshold: 6          # 不健康阈值
  67.         resources:                     # 容器资源管理
  68.           limits:                      # 资源限制(监控使用情况)
  69.             cpu: 0.5
  70.             memory: 1Gi
  71.           requests:                    # 最小可用资源(灵活调度)
  72.             cpu: 0.1
  73.             memory: 200Mi
  74.         env:
  75.           - name: TZ
  76.             value: Asia/Shanghai
  77. ---
  78. kind: HorizontalPodAutoscaler            # 弹性伸缩控制器
  79. apiVersion: autoscaling/v2beta2
  80. metadata:
  81.   name: {APP_NAME}
  82. spec:
  83.   scaleTargetRef:
  84.     apiVersion: apps/v1
  85.     kind: Deployment
  86.     name: {APP_NAME}
  87.   minReplicas: {REPLICAS}                # 缩放范围
  88.   maxReplicas: 6
  89.   metrics:
  90.     - type: Resource
  91.       resource:
  92.         name: cpu                        # 指定资源指标
  93.         target:
  94.           type: Utilization
  95.           averageUtilization: 50
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/708599
推荐阅读
相关标签
  

闽ICP备14008679号