背景

kubernetes 中部署了grpc长连接服务, 通过ingress-nginx方式对外暴露服务,在使用过程中grpc长连接没有定时发送心跳消息,在没有数据传输的情况下,grpc连接会在60s后自动断开连接。

GRPC 超时配置

出现连接超时问题,首先想到的就是ingress-nginx 配置限制导致的连接超时。
通过查询ingress-nginx官方对于grpc超时时间的配置信息,如下:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#custom-timeouts

官方解释:对于后端协议为GRPC或GRPCS,则继承proxy timeout de peizhi .

  • grpc_connect_timeout=5s: from nginx.ingress.kubernetes.io/proxy-connect-timeout
  • grpc_send_timeout=60s: from nginx.ingress.kubernetes.io/proxy-send-timeout
  • grpc_read_timeout=60s: from nginx.ingress.kubernetes.io/proxy-read-timeout

增加如下配置:

nginx.ingress.kubernetes.io/proxy-connect-timeout: 5 # 建立 TCP 连接的超时时间
nginx.ingress.kubernetes.io/proxy-send-timeout: 60 # 请求发送阶段的超时
nginx.ingress.kubernetes.io/proxy-read-timeout: 60 # 响应接收阶段的超时

结果验证

配置完成后发现并没有解决问题。 问题出在哪里呢。
开始查看nginx配置文件。

                        proxy_connect_timeout                   5s;
                        proxy_send_timeout                      60s;
                        proxy_read_timeout                      60s;

                        proxy_buffering                         off;
                        proxy_buffer_size                       4k;
                        proxy_buffers                           4 4k;

                        proxy_max_temp_file_size                1024m;

                        proxy_request_buffering                 on;
                        proxy_http_version                      1.1;

                        proxy_cookie_domain                     off;
                        proxy_cookie_path                       off;

proxy time 的相关配置是正常的。 但是没有grpc timeout相关的配置, 预期与ingress-nginx官网的说法不同。 问题出现在哪了呢??

查询差异

配置问题?

在ingress-nginx中。 nginx.conf 的配置文件是通过模版的方式对ingress配置进行渲染后生成的,所以通过查看模版文件来进一步的查看grpc配置的生成逻辑。 模版文件的默认路径为/etc/nginx/template/nginx.tmpl。

            proxy_connect_timeout                   {{ $location.Proxy.ConnectTimeout }}s;
            proxy_send_timeout                      {{ $location.Proxy.SendTimeout }}s;
            proxy_read_timeout                      {{ $location.Proxy.ReadTimeout }}s;

            proxy_buffering                         {{ $location.Proxy.ProxyBuffering }};
            proxy_buffer_size                       {{ $location.Proxy.BufferSize }};
            proxy_buffers                           {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }};
            {{ if isValidByteSize $location.Proxy.ProxyMaxTempFileSize true }}
            proxy_max_temp_file_size                {{ $location.Proxy.ProxyMaxTempFileSize }};
            {{ end }}
            proxy_request_buffering                 {{ $location.Proxy.RequestBuffering }};
            proxy_http_version                      {{ $location.Proxy.ProxyHTTPVersion }};

            proxy_cookie_domain                     {{ $location.Proxy.CookieDomain }};
            proxy_cookie_path                       {{ $location.Proxy.CookiePath }};

通过模版发现并没有grpc相关的配置模版, 进而怀疑是版本问题开始比对版本。

版本问题!!!!

通过查看ingress-nginx deployment 配置镜像信息得到controller版本:

  • image: registry.k8s.io/ingress-nginx/controller:v1.10.1

通过登录pod后执行nginx -v 得到nginx版本(当然这步没啥用):

  • nginx version: nginx/1.25.3

对比github https://github.com/kubernetes/ingress-nginx, 当前版本确实是个老版本了。 难道有更新差异?
进一步查看 更新说明 ( https://github.com/kubernetes/ingress-nginx/releases?page=3) ,
发现在1.11.0 版本有个更新: https://github.com/kubernetes/ingress-nginx/pull/11258,添加了 grpc 超时注释 。

到此,定位到是版本差异导致的配置没有生效,那怎么办呢。 升级版本还是??

再次GRPC超时配置

既然GRPC timeout在 1.11.0 以下版本不支持。 但也有其他方式来实现。
参考官网:https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#allow-snippet-annotations
首先前提条件是通过配置ingress-nginx configmap, 添加如下参数开启代码片段注释的支持:allow-snippet-annotations
然后配置annotations

支持多种自定义配置。 这里列举了三种。

  • nginx.ingress.kubernetes.io/configuration-snippet: 全局http块,影响所有虚拟主机和请求处理。
  • nginx.ingress.kubernetes.io/server-snippet: 特定域名的server块,仅影响当前 Ingress 规则的域名。
  • nginx.ingress.kubernetes.io/stream-snippet: 添加自定义的stream配置。
    nginx.ingress.kubernetes.io/server-snippet: |
      # gRPC连接超时配置
      proxy_connect_timeout 10s;        # 连接超时
      proxy_send_timeout 600s;          # 发送超时
      proxy_read_timeout 600s;          # 读取超时

待验证。 等我验证完补充。

参考

github issues:

  • https://github.com/kubernetes/ingress-nginx/issues/9063
  • https://github.com/kubernetes/ingress-nginx/issues/11250

更多推荐