如何调优 Webservice Ingress 超时时间和正文大小

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

适用场景:

  • 推送大型仓库、LFS 对象或 container 镜像时失败,并报 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>)。
  • 只有在集群使用 community ingress-nginx controller (kubernetes/ingress-nginx)时, proxyConnectTimeout / proxyReadTimeout / proxyBodySize 字段才会生效, 因为该 chart 会将它们渲染到 nginx.ingress.kubernetes.io/* 注解命名空间下。对于其他 controller,请参见下文 配置其他 Ingress controller
  • 检查请求路径中的每一跳。 如果 GitLab 自身的 Ingress 前面还有平台级 LB 或反向代理, 那些位置也必须提高相同的限制——实际生效的限制是整条链路中的最小值。

面向大型仓库 / 上传的调优(ingress-nginx)

对于承载大型仓库、LFS 对象或 container/package 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(当 Pods 变为 Ready 后消失)。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
Container / Package Registry5g ~ 10g1800 ~ 3600

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

proxyBodySize 仅控制 Ingress 层。 GitLab 本身在 Admin Area → Settings → General → Account and limit 下也配置了应用层限制(max push sizemax attachment sizemax import size 等)。如有需要,请同步提高这些限制。

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

配置其他 Ingress controller

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

  • 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 根本不支持为这些限制 配置 per-Ingress 注解,则应在 controller 本身上进行配置。

验证已应用的配置

更新 CR 并等待 reconciliation 之后,请检查 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 是否已成功完成 reconciliation: kubectl describe gitlabofficial <NAME> -n <NS>
  • 验证 GitLab 自身 Ingress 前是否没有上游 Ingress / LB 在强制更严格的限制。

更大的值总是更好吗?

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

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

参考