ALB Ingress高可用实践

更新时间:
复制 MD 格式

在生产环境中,Pod发生滚动更新、弹性伸缩、故障迁移非常常见,如果在Pod创建、终止过程中缺乏完善的高可用机制,可能导致请求被转发到尚未就绪或已经终止的Pod,引发请求失败或响应延迟,影响用户体验。通过配置ALB健康检查、ReadinessGate、preStop Hook,可以实现流量的平滑迁移,保障业务持续高可用。

核心配置示例

  • 在工作负载中配置就绪门控readinessGate和停止前回调preStop:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: tea
    spec:
      ...
      template:
        ...
        spec:
          containers:
          - ...
            lifecycle:  # 设置preStop Hook函数,使Pod在收到SIGTERM前等待10秒。
              preStop:
                exec:  # 通过执行命令的方式实现preStop操作。
                  command:
                  - /bin/sh
                  - -c
                  - "sleep 10"  # 暂停10秒,为ALB Ingress留出时间。
          terminationGracePeriodSeconds: 45  # 设置Pod删除宽限期,需大于preStop等待时间。
          readinessGates:  # 配置ReadinessGate。
            - conditionType: target-health.alb.k8s.alibabacloud  # ALB Ingress自定义Condition。
  • 在Ingress中通过Annotations配置健康检查:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: tea-ingress
      annotations:
        alb.ingress.kubernetes.io/healthcheck-enabled: "true"            # 启用健康检查。
        alb.ingress.kubernetes.io/healthcheck-protocol: "TCP"            # 健康检查协议。
        alb.ingress.kubernetes.io/healthcheck-timeout-seconds: "5"       # 健康检查超时时间。
        alb.ingress.kubernetes.io/healthcheck-interval-seconds: "2"      # 健康检查间隔。
        alb.ingress.kubernetes.io/healthy-threshold-count: "3"           # 健康阈值。
        alb.ingress.kubernetes.io/unhealthy-threshold-count: "3"         # 不健康阈值。
    spec:
      ingressClassName: alb
      rules:
     - ... 

工作原理

就绪门控(ReadinessGate)

  • 未配置时:新Pod启动后会被自动标记为Ready并接受流量。但是,如果新Pod未能成功添加到ALB后端服务器组(例如超出ALB后端限额等原因),集群对该状况无法感知,Pod虽处于Ready状态但实际无法接收请求,造成客户端请求失败。

  • 配置后:确保只有当ALB Ingress Controller将Pod成功添加到ALB后端服务器组后,才标记Pod为Ready状态,避免出现ALB后端服务器组和集群Pod状态不同步的问题。

停止前回调(preStop Hook)

  • 未配置时:kubelet在Pod被标记为Terminating时,将立即向容器发送SIGTERM信号,容器将停止接收新连接。同时,ALB实例将Pod从后端服务器组中移除。在移除操作尚未完成时,可能还会有请求被转发到终止的Pod,导致502错误。

  • 配置后:SIGTERM信号将会在preStop Hook执行完成后再发送。使用preStop Hook,可以在容器收到SIGTERM信号前插入一段等待时间(例如10秒),使ALB实例有足够时间将Pod从后端服务器组中移除后再终止容器。

重要

删除宽限期(terminationGracePeriodSeconds)在Pod进入Terminating状态后就会开始计算,不论是否配置了preStop Hook。到达宽限期后,还未终止的容器将被发送SIGKILL信号强制终止。因此,使用preStop Hook时,请将terminationGracePeriodSeconds设置为大于preStop Hook花费时间的值,以确保preStop Hook执行完成后容器仍有足够时间处理剩余请求并优雅退出。

ALB健康检查

  • 未配置时:在异常场景中,可能出现Pod不可用后,变更无法同步到ALB后端服务器组的情况,导致ALB实例继续向不可用的Pod转发流量,使客户端收到5xx状态码。

  • 配置后:ALB实例进行主动探测,识别异常Pod并停止向其转发请求,降低请求失败风险。

验证ALB Ingress高可用配置

步骤一:准备工作

  1. 将集群版本升级到1.18或更高。

  2. 安装ALB Ingress Controller组件。

  3. 获取集群KubeConfig并通过kubectl工具连接集群。

  4. 将下方示例保存到tea-deploy-basic.yaml,然后执行kubectl apply -f tea-deploy-basic.yaml。

    示例中未包含preStop Hook、ReadinessGate和健康检查配置。
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: tea
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: tea
      template:
        metadata:
          labels:
            app: tea
        spec:
          containers:
          - name: tea
            image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginxdemos:latest
            ports:
            - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: tea-svc
    spec:
      ports:
      - port: 80
        targetPort: 80
        protocol: TCP
      selector:
        app: tea
      type: NodePort
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: tea-ingress
    spec:
      ingressClassName: alb
      rules:
       - http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: tea-svc
                port:
                  number: 80
  5. 获取ALB实例的DNS域名。

    kubectl get ingress tea-ingress -o jsonpath='{.status.loadBalancer.ingress[0].hostname}{"\n"}'
  6. 将下方示例保存到test.sh文件。

    示例脚本按五秒一次的频率触发Pod滚动升级。
    #!/bin/bash
    while true; do
      kubectl rollout restart deploy tea
      sleep 5
    done
  7. 执行bash test.sh滚动更新Pod,同时在另一个终端中执行压测命令:

    hey -z 30s -c 100 http://ALB_URL/

    观察结果:出现部分502、504状态码,说明未配置高可用机制时应用无法正常处理业务请求。

步骤二:在工作负载中配置preStop Hook和ReadinessGate

  1. 将下方示例保存到tea-deploy.yaml文件,然后执行kubectl apply -f tea-deploy.yaml。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: tea
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: tea
      template:
        metadata:
          labels:
            app: tea
        spec:
          containers:
          - name: tea
            image: registry.cn-hangzhou.aliyuncs.com/acs-sample/nginxdemos:latest
            ports:
            - containerPort: 80
            lifecycle:  # 设置preStop Hook函数,使Pod在收到SIGTERM前等待10秒。
              preStop:
                exec:  # 通过执行命令的方式实现preStop操作。
                  command:
                  - /bin/sh
                  - -c
                  - "sleep 10"  # 暂停10秒,为ALB Ingress留出时间。
          terminationGracePeriodSeconds: 45  # 设置Pod删除宽限期,需大于preStop等待时间。
          readinessGates:  # 配置ReadinessGate。
            - conditionType: target-health.alb.k8s.alibabacloud  # ALB Ingress自定义Condition。
  2. 执行bash test.sh滚动更新Pod,同时在另一个终端中执行压测命令:

    hey -z 30s -c 100 http://ALB_URL/

    观察结果:状态码全部为200,502和504状态码消失,表明preStop Hook和ReadinessGate配置成功。

  3. 执行kubectl scale deployment tea --replicas=1对Deployment进行缩容,同时在另一个终端中执行压测命令:

    hey -z 30s -c 100 http://ALB_URL/

    观察结果:出现少量502和504状态码,这是因为在未配置健康检查的情况下,ALB实例仍旧会向进入终止流程的不可用Pod转发流量,导致请求错误。

步骤三:在Ingress中配置健康检查

  1. 执行kubectl scale deployment tea --replicas=3,恢复工作负载Pod数量。

  2. 将下方示例保存到tea-ingress.yaml文件,然后执行kubectl apply -f tea-ingress.yaml。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: tea-ingress
      annotations:
        alb.ingress.kubernetes.io/healthcheck-enabled: "true"            # 启用健康检查。
        alb.ingress.kubernetes.io/healthcheck-protocol: "TCP"            # 健康检查协议。
        alb.ingress.kubernetes.io/healthcheck-timeout-seconds: "5"       # 健康检查超时时间。
        alb.ingress.kubernetes.io/healthcheck-interval-seconds: "2"      # 健康检查间隔。
        alb.ingress.kubernetes.io/healthy-threshold-count: "3"           # 健康阈值。
        alb.ingress.kubernetes.io/unhealthy-threshold-count: "3"         # 不健康阈值。
    spec:
      ingressClassName: alb
      rules:
       - http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: tea-svc
                port:
                  number: 80
  3. 执行kubectl scale deployment tea --replicas=1,对Deployment进行缩容。同时在另一个终端中执行压测命令:

    hey -z 30s -c 100 http://ALB_URL/

    观察结果:状态码应全部为200,无502、504等错误,表明ALB Ingress高可用配置成功。

相关文档