首页 > 服务器维护 > 服务器其它

阿里云k8s服务springboot项目应用升级时出现502错误

发布时间:2022-6-1 11:20 作者:Oops!

随着小步快跑、快速迭代的开发模式被越来越多的互联网企业认同和采用,应用的变更、升级频率变得越来越频繁。为了应对不同的升级需求,保证升级过程平稳顺利地进行,诞生了一系列的部署发布模式。

随着越来越多的应用被容器化,如何方便地让容器应用平稳顺利升级受到了广泛关注。本文将介绍 k8s 中不同部署形式下应用的升级方法,并重点介绍如何对 Deployment 中的应用实施滚动发布(本文所作的调研基于k8s 1.13)。

K8s 应用升级

在 k8s 中,pod 是部署和升级的基本单位。一般来说,一个 pod 代表一个应用实例,而 pod 又会以 Deployment、StatefulSet、DaemonSet、Job 等形式部署运行,下面依次介绍在这些部署形式下 pod 的升级方法。

Deployment

Deployment 是 pod 最常见的部署形式,这里将以基于 spring boot 的 java 应用为例进行介绍。该应用是基于真实应用抽象出来的简单版本,非常具有代表性,它有如下特点:

参数配置

为了让具有上述特点的应用实现零宕机时间和无生产中断的升级,需要精心地配置 Deployment 中的相关参数。这里和升级有关的配置如下(完整配置参见 spring-boot-probes-v1.yaml)。

kind: Deployment
...
spec:
  replicas: 8
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 3
      maxUnavailable: 2
  minReadySeconds: 120
  ...
  template:
    ...
    spec:
      containers:
      - name: spring-boot-probes
        image: registry.cn-hangzhou.aliyuncs.com/log-service/spring-boot-probes:1.0.0
        ports:
        - containerPort: 8080
        terminationGracePeriodSeconds: 60
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          successThreshold: 1
          failureThreshold: 1
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 40
          periodSeconds: 20
          successThreshold: 1
          failureThreshold: 3
        ...

配置 strategy

通过 strategy 可以配置 pod 的替换策略,主要参数如下。

通过调节 maxSurge 和 maxUnavailable,可以满足不同场景下的升级需求。

样例选择了一个折中方案,将 maxSurge 设置为 3,将 maxUnavailable 设置为 2,平衡了稳定性、资源消耗和升级速度。

配置探针

K8s 提供以下两类探针:

探针的配置非常灵活,用户可以指定探针的探测频率、探测成功阈值、探测失败阈值等。各参数的含义和配置方法可参考文档 Configure Liveness and Readiness Probes。

样例为目标容器配置了就绪探针和活性探针:

配置 minReadySeconds

默认情况下,一旦新创建的 pod 变成就绪状态 k8s 就会认为该 pod 是可用的,从而将老的 pod 删除掉。但有时问题可能会在新 pod 真正处理用户请求时才暴露,因此一个更稳健的做法是当某个新 pod 就绪后对其观察一段时间再删掉老的 pod。

参数 minReadySeconds 可以控制 pod 处于就绪状态的观察时间。如果 pod 中的容器在这段时间内都能正常运行,k8s 才会认为新 pod 可用,从而将老的 pod 删除掉。在配置该参数时,需要仔细权衡,如果设置得过小,可能造成观察不充分,如果设置得过大,又会拖慢升级进度。样例将 minReadySeconds 设置成了 120 秒,这样能保证处于就绪状态的 pod 能经历一个完整的活性探测周期。

配置 terminationGracePeriodSeconds

当 k8s 准备删除一个 pod 时,会向该 pod 中的容器发送 TERM 信号并同时将 pod 从 service 的 endpoint 列表中移除。如果容器无法在规定时间(默认 30 秒)内终止,k8s 会向容器发送 SIGKILL 信号强制终止进程。Pod 终止的详细流程可参考文档 Termination of Pods。

由于应用处理请求最长耗时 40 秒,为了让其在关闭前能够处理完已到达服务端的请求,样例设置了 60 秒的优雅关闭时间。针对不同的应用,您可以根据实际情况调整 terminationGracePeriodSeconds 的取值。

观察升级行为

上述配置能够保证目标应用的平滑升级。我们可以通过更改 Deployment 中 PodTemplateSpec 的任意字段触发 pod 升级,并通过运行命令kubectl get rs -w观察升级行为。这里观察到的新老版本的 pod 副本数的变化情况如下:

失败回滚

应用的升级并不总会一帆风顺,在升级过程中或升级完成后都有可能遇到新版本行为不符合预期需要回滚到稳定版本的情况。K8s 会将 PodTemplateSpec 的每一次变更(如果更新模板标签或容器镜像)都记录下来。这样,如果新版本出现问题,就可以根据版本号方便地回滚到稳定版本。回滚 Deployment 的详细操作步骤可参考文档 Rolling Back a Deployment。

StatefulSet

StatefulSet 是针对有状态 pod 常用的部署形式。针对这类 pod,k8s 同样提供了许多参数用于灵活地控制它们的升级行为。好消息是这些参数大部分都和升级 Deployment 中的 pod 相同。这里重点介绍两者存在差异的地方。

策略类型

在 k8s 1.7 及之后的版本中,StatefulSet 支持 OnDelete 和 RollingUpdate 两种策略类型。

Partition

可以通过参数.spec.updateStrategy.rollingUpdate.partition实现只升级部分 pod 的目的。在配置了 partition 后,只有序号大于或等于 partition 的 pod 才会进行滚动升级,其余 pod 将保持不变。

Partition 的另一个应用是可以通过不断减少 partition 的取值实现金丝雀升级。具体操作方法可参考文档 Rolling Out a Canary。

DaemonSet

DaemonSet 保证在全部(或者一些)k8s 工作节点上运行一个 pod 的副本,常用来运行监控或日志收集程序。对于 DaemonSet 中的 pod,用于控制它们升级行为的参数与 Deployment 几乎一致,只是在策略类型方面略有差异。DaemonSet 支持 OnDelete 和 RollingUpdate 两种策略类型。

滚动更新 DaemonSet 的具体操作步骤可参考文档 Perform a Rolling Update on a DaemonSet。

Job

Deployment、StatefulSet、DaemonSet 一般用于部署运行常驻进程,而 Job 中的 pod 在执行完特定任务后就会退出,因此不存在滚动更新的概念。当您更改了一个 Job 中的 PodTemplateSpec 后,需要手动删掉老的 Job 和 pod,并以新的配置重新运行该 job。

总结

K8s 提供的功能可以让大部分应用实现零宕机时间和无生产中断的升级,但也存在一些没有解决的问题,主要包括以下几点:

实例配置:

livenessProbe:
  failureThreshold: 3
  httpGet:
    path: /user/service/test
    port: 8080
    scheme: HTTP
  initialDelaySeconds: 40
  periodSeconds: 20
  successThreshold: 1
  timeoutSeconds: 1
name: dataline-dev
ports:
  - containerPort: 8080
    protocol: TCP
readinessProbe:
  failureThreshold: 1
  httpGet:
    path: /user/service/test
    port: 8080
    scheme: HTTP
  initialDelaySeconds: 30
  periodSeconds: 10
  successThreshold: 1
  timeoutSeconds: 1

经测试 , 再对sprintboot 应用进行更新时, 访问不再出现502的报错。

更多关于阿里云k8s服务springboot项目应用升级时出现502错误技术文章请查看下面的相关链接

原文出处:https://www.cnblogs.com/weifeng1463/p/10431736.html

您可能感兴趣的文章: