如何调整 Webservice Ingress 超时与请求体大小

本文介绍如何配置 gitlab.webservice.ingress 下暴露的三个 NGINX Ingress 参数、何时需要调整它们,以及如何在其他 Ingress controller 上应用相同的意图。

适用场景:

  • 推送大型仓库、LFS 对象或容器镜像时失败,并返回 413 Request Entity Too Large
  • 对大型仓库执行 git clone / git push / 项目导入时,大约 ~10 分钟后超时,并返回 502 Bad Gateway
  • 在升级或重启 webservice 后,短暂出现 502 Bad Gateway

背景

GitLab webservice 通过 NGINX Ingress 暴露。随附的 Helm chart 会在 GitlabOfficial CR 的 spec.helmValues.gitlab.webservice.ingress 下公开三个参数。它们会被渲染为 <RELEASE>-webservice-default Ingress 对象上的 NGINX Ingress 注解:

apiVersion: operator.alaudadevops.io/v1alpha1
kind: GitlabOfficial
metadata:
  name: sample
spec:
  helmValues:
    gitlab:
      webservice:
        ingress:
          proxyConnectTimeout: 15    # seconds, -> nginx.ingress.kubernetes.io/proxy-connect-timeout
          proxyReadTimeout: 600      # seconds, -> nginx.ingress.kubernetes.io/proxy-read-timeout
          proxyBodySize: "512m"      # size,    -> nginx.ingress.kubernetes.io/proxy-body-size
参数含义默认值
proxyConnectTimeoutNGINX 等待与 webservice Pod 建立 TCP 连接的时间。15s
proxyReadTimeoutNGINX 等待来自上游 Pod 的两次连续读取之间的时间。600s
proxyBodySizeNGINX 允许接收并转发的客户端请求体最大大小。512m

这些默认值适用于大多数安装环境。三个参数之间高度相关——大型仓库通常既需要更大的请求体大小,也需要更长的读取超时时间——因此通常应当一起调整,而不是一次只调一个。

前提条件

  • 具备编辑 GitlabOfficial CR 的权限
    kubectl edit gitlabofficial <NAME> -n <NS>)。
  • 只有当集群使用社区版 ingress-nginx controller
    (kubernetes/ingress-nginx) 时,proxyConnectTimeout / proxyReadTimeout / proxyBodySize 字段才会生效,因为 chart 会将它们渲染到 nginx.ingress.kubernetes.io/* 注解命名空间下。对于其他 controller,请参见下面的 配置其他 Ingress controller
  • 检查请求路径中的每一跳。 如果 GitLab 自身的 Ingress 前面还有平台级 LB 或反向代理,那么也必须在这些位置提高相同的限制——实际生效的限制是整条链路中的最小值。

针对大型仓库/上传的调优(ingress-nginx)

对于托管大型仓库、LFS 对象或容器/包 Registry 流量的安装环境,通常会同时出现以下三种症状,而且它们有相同的修复方式——将这三个参数一起调大:

症状需要调高的参数
git push / UI 上传 / LFS / Registry 时返回 413 Request Entity Too Large。日志:client intended to send too large bodyproxyBodySize
git clone / git push / 项目导入卡住约 ~10 分钟,然后失败并返回 502RPC failed。日志:upstream timed out (110: Connection timed out)proxyReadTimeout
webservice rollout 期间短暂出现 502 Bad Gateway(Pod 就绪后会消失)。proxyConnectTimeout

对于拥有大型仓库 / LFS / Registry 的 GitLab 实例,建议的起点如下:

spec:
  helmValues:
    gitlab:
      webservice:
        ingress:
          proxyConnectTimeout: 30      # 15 -> 30; modest bump to absorb pod-restart jitter
          proxyReadTimeout: 1800       # 600 -> 1800; 30 min for large clone/push/import
          proxyBodySize: "5g"          # 512m -> 5g;  fits LFS / registry blobs

请根据实际使用情况选择数值:

使用场景proxyBodySizeproxyReadTimeout
仅源码,小型仓库512m(默认)600(默认)
Git LFS / 大型二进制资产2g ~ 5g1800
容器 / 包 Registry5g ~ 10g1800 ~ 3600

proxyConnectTimeout 通常是症状,而不是调节旋钮。 rollout 期间短暂出现 502,通常意味着 webservice Pod 启动较慢,或者 readiness probe 配置不正确——应先修复这些问题。只有在环境中 TCP 建连确实较慢时,例如跨 AZ 网络,才应将其提高到 30–60s。将其设置为 600 之类的大值只会掩盖真实的后端故障,并堆积 NGINX worker 线程。

proxyBodySize 只作用于 Ingress 层。 GitLab 本身还配置了应用层限制,位于 Admin Area → Settings → General → Account and limitmax push sizemax attachment sizemax import size,等等)。如有需要,请同步提高这些限制。

提示: 对于非常大的 Git 操作,优先使用 SSH(git@)而不是 HTTPS。SSH 流量不会经过 HTTP Ingress,因此不受这三个参数的影响。

配置其他 Ingress controller

上面的三个顶层字段只会在 nginx.ingress.kubernetes.io/* 命名空间中生成注解,并会被以下 controller 忽略:

  • Traefik、HAProxy、Contour、Istio Gateway,以及其他非 NGINX controller。
  • F5 NGINX Inc. 的 nginxinc/kubernetes-ingress——它使用不同的注解命名空间(nginx.org/*)。

对于这些 controller,请通过 gitlab.webservice.ingress.annotations 直接设置等效注解;这些注解会合并到渲染后的 Ingress 对象上。

F5 NGINX Inc.(nginx.org/*)示例:

spec:
  helmValues:
    gitlab:
      webservice:
        ingress:
          annotations:
            nginx.org/client-max-body-size: "5g"
            nginx.org/proxy-read-timeout: "1800s"
            nginx.org/proxy-connect-timeout: "30s"

对于 Traefik,proxyBodySize 的等效项是 Middleware 资源的 buffering.maxRequestBodyBytes,而超时则是在 IngressRoute / EntryPoint 层面配置,而不是通过每个 Ingress 的注解配置。请单独定义这些资源,并且(可选地)在 annotations 中通过 traefik.ingress.kubernetes.io/router.middlewares 引用它们。

global.ingress.provider 设置为 nginx 以外的值时,nginx.ingress.kubernetes.io/* 注解不会被注入,但 Ingress 资源本身仍会被渲染——annotations 中的值会保留。如果所选 controller 根本不支持这些限制的按 Ingress 注解,则应在 controller 本身上进行配置。

验证已应用的配置

更新 CR 并等待协调完成后,检查 Ingress 对象上的注解:

kubectl -n <NAMESPACE> get ingress <RELEASE>-webservice-default \
  -o jsonpath='{.metadata.annotations}' | tr ',' '\n' \
  | grep -E 'body-size|read-timeout|connect-timeout'

预期输出(ingress-nginx 示例):

"nginx.ingress.kubernetes.io/proxy-body-size":"5g"
"nginx.ingress.kubernetes.io/proxy-connect-timeout":"30"
"nginx.ingress.kubernetes.io/proxy-read-timeout":"1800"

如果这些值不匹配:

  • 确认 CR 已在 spec.helmValues.gitlab.webservice.ingress 下更新(而不是在 spec.helmValues.nginx-ingress.controller.* 下,后者属于不同层)。
  • 检查 operator 是否已成功协调:
    kubectl describe gitlabofficial <NAME> -n <NS>
  • 验证 GitLab 自身的 Ingress 前面是否存在上游 Ingress / LB,并且它是否在强制执行更严格的限制。

更大的值总是更好吗?

不是。每个参数都有代价:

  • proxyBodySize 过大 —— NGINX 会缓冲(或流式处理)整个请求体;单个超大上传可能会使 Ingress Controller 节点的内存和磁盘使用量激增。应将其设置为略高于真实最大值,而不是任意设得很大。
  • proxyReadTimeout 过大 —— 缓慢或卡住的上游连接会长时间占用 NGINX worker 插槽,降低其他用户可用的并发能力。应选择与最大合法请求相匹配的值,而不是“越大越好”。
  • proxyConnectTimeout 过大 —— 通过在返回错误前等待数分钟来掩盖真实的后端故障(Pod 未就绪、网络故障)。应保持较小值(15–60s),并修复后端问题。

参考