You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kubernetes Ingress Controller中实现Pod间的严格交替轮询

我来帮你梳理下实现严格A-B-A-B交替调度的可行方案,优先针对你已经在用的Nginx系列Ingress Controller,也会补充其他可选方案:

一、先解决核心问题:为什么默认轮询会出现连续请求?

你遇到的连续4次请求到同一Pod的情况,大概率是Nginx与后端Pod的长连接复用导致的——当Ingress Controller和Pod保持长连接时,同一个客户端的连续请求会复用这条连接,直接发给同一个Pod,跳过轮询逻辑。

所以第一步要做的,就是禁用Ingress与后端Pod的长连接,让每个请求都重新触发轮询调度。

二、针对Nginx系列Ingress Controller的配置调整

1. Kubernetes官方Nginx Ingress Controller

通过Ingress的Annotation禁用后端长连接,同时确保默认的轮询算法生效:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-test-ingress
  annotations:
    # 禁用与后端Pod的长连接,每个请求重新选择后端
    nginx.ingress.kubernetes.io/upstream-keepalive-connections: "0"
    nginx.ingress.kubernetes.io/upstream-keepalive-timeout: "0"
    # 明确指定轮询算法(默认就是round_robin,可加可不加)
    nginx.ingress.kubernetes.io/load-balance: "round_robin"
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: your-nodeport-service
            port:
              number: 80

2. F5 Nginx Kubernetes Ingress Controller

同样通过Annotation禁用长连接:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-test-ingress
  annotations:
    # 禁用后端长连接
    nginx.org/upstream-keepalive: "0"
    # 明确轮询策略
    nginx.org/load-balance: "round_robin"
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: your-nodeport-service
            port:
              number: 80

3. 测试脚本也要配合调整

确保你的curl脚本每次请求都新建连接,避免客户端与Ingress的长连接干扰测试:

#!/bin/bash
output_file="request-result.txt"
> $output_file # 清空文件

for i in {1..100}
do
  # --no-keepalive 强制每次新建连接
  curl --no-keepalive http://<你的Ingress访问IP>/ | grep -o "SERVER [AB]" >> $output_file
done

# 统计结果
echo "请求分布统计:"
echo "SERVER A: $(grep -c "SERVER A" $output_file)"
echo "SERVER B: $(grep -c "SERVER B" $output_file)"
三、如果还是不行?用Lua脚本实现强制交替调度

如果禁用长连接后仍有连续请求(极端场景),可以通过自定义Nginx配置+Lua脚本,强制跟踪上次选择的Pod,实现严格交替。

以官方Nginx Ingress为例,通过Annotation注入Lua逻辑:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: strict-roundrobin-ingress
  annotations:
    # 创建共享字典存储上次选择的后端索引
    nginx.ingress.kubernetes.io/server-snippet: |
      lua_shared_dict round_robin_state 10k;
    # 注入Lua调度逻辑
    nginx.ingress.kubernetes.io/configuration-snippet: |
      access_by_lua_block {
        local state = ngx.shared.round_robin_state
        -- 读取上次的索引,默认从0开始
        local last_idx = state:get("last_pod_idx") or 0
        -- 切换到下一个索引(1或2,对应两个Pod)
        local next_idx = last_idx == 1 and 2 or 1
        state:set("last_pod_idx", next_idx)
        -- 将索引传递给proxy_pass
        ngx.var.target_idx = next_idx
      }
      # 自定义upstream,直接指向两个Pod的IP(需要手动更新,适合固定Pod的测试场景)
      proxy_pass http://nginx-pod-$target_idx;
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: dummy-service # 占位用,实际会被proxy_pass覆盖
            port:
              number: 80

注意:这种方式需要你提前给两个Pod分配固定的Service或者直接写死Pod IP,适合测试场景,生产环境Pod动态变化时需要额外的逻辑维护。

四、其他可选Ingress Controller方案

如果Nginx系列的配置仍无法满足需求,可以尝试HAProxy Ingress Controller,它支持严格轮询+强制关闭连接复用:

  1. 部署HAProxy Ingress后,修改ConfigMap开启严格轮询:
apiVersion: v1
kind: ConfigMap
metadata:
  name: haproxy-ingress-config
data:
  balance: "roundrobin" # 严格轮询
  http-connection-close: "true" # 禁用连接复用,每个请求重新调度
  timeout-client: "30s"
  timeout-server: "30s"
  1. 配置常规Ingress规则指向你的NodePort Service即可,HAProxy会自动按严格轮询分配请求。

内容的提问来源于stack exchange,提问作者hiiamelliott

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 23:04:09