如何调整 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>)。
  • 只有在集群使用 Community ingress-nginx controller (kubernetes/ingress-nginx) 时,才会应用 proxyConnectTimeout / proxyReadTimeout / proxyBodySize 字段, 因为 chart 会在 nginx.ingress.kubernetes.io/* 注解命名空间下渲染这些字段。对于其他 controller,请参阅下方的 配置其他 Ingress controller。
  • 检查请求路径中的每一跳。 如果平台级 LB 或反向代理位于 GitLab 自有 Ingress 的前面,则还必须在那里提高相同的限制——实际生效的限制取决于整个链路中的最小值。

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

对于托管大型仓库、LFS 对象或容器/软件包 Registry 的安装,通常会同时出现以下三种现象,并且它们需要采用相同的修复方法——同时提高这三个参数:

现象要提高的参数
在 git push / UI 上传 / LFS / Registry 中出现 413 Request Entity Too Large。日志:client intended to send too large body。proxyBodySize
git clone / git push / 项目导入挂起约 10 分钟后失败,并显示 502 或 RPC failed。日志:upstream timed out (110: Connection timed out)。proxyReadTimeout
webservice rollout 期间短暂出现 502 Bad Gateway(Pod 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
容器 / Package Registry5g ~ 10g1800 ~ 3600

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

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

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

配置其他 Ingress Controller

上面的三个顶级字段仅会在 nginx.ingress.kubernetes.io/* 命名空间中生成 annotation,以下组件会忽略这些字段:

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

对于这些 controller,请直接通过 gitlab.webservice.ingress.annotations 设置等效的 annotation;这些 annotation 会合并到渲染后的 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 中;timeout 应在 IngressRoute / EntryPoint 层级进行配置,而不是通过每个 Ingress 的 annotation 进行配置。 请单独定义这些资源,并可选择通过 traefik.ingress.kubernetes.io/router.middlewares 在 annotations 中引用它们。

当 global.ingress.provider 被设置为非 nginx 的值时,不会注入 nginx.ingress.kubernetes.io/* annotation,但 Ingress 资源仍会被渲染——来自 annotations 的值会保留。如果所选 controller 完全不支持针对这些限制的每个 Ingress annotation,请在 controller 自身上进行配置。

验证已应用的配置

更新 CR 并等待 reconciliation 后,检查 Ingress 对象上的 annotation:

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 前方没有其他 upstream Ingress / LB 正在强制执行更严格的限制。

更大的值总是更好吗?

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

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

参考


GitLab 是 GitLab Inc. 的商标。

Alauda 是独立供应商。本产品与 GitLab Inc. 没有关联,也未获得其认可或赞助。所有商标均归其各自所有者所有,本文仅将其用于标识目的。