ingress-nginx的keepalive不可用

问题

  • ingress-nginx节点的timewait较多,占用的端口数也随着流量上涨而上涨且接近饱和。
  • 抓包发现nginx发起的到upstream连接中只有一个请求,http头中connection字段是close,连接是被upstream主动断开的。但configmap的配置中已启用了长连接:upstream-keepalive-connections: “32”
  • 查看ingress-nginx的模板文件nginx.tmpl发现是不管是否配置长连接,都设置为close,这显然不符合要求。
    map $http_upgrade $connection_upgrade {
        default          upgrade;
        ''               close;
    }
    
  • 查看新版本ingress-nginx的配置,发现是有相关支持的,再找发现是当前版本(0.9.0)存在bug,因此导致nginx转发给upstream的请求都是一个请求新建一个连接,降低响应速度以及快速消耗端口资源。

解决:

  • 临时措施:调大端口范围,将portrange从默认的 32768-61000调整为1024-64000(ingress-nginx的pod节点上只有80端口在用)
    sysctl -w net.ipv4.ip_local_port_range="1024 64000"
    
  • bug修复: 修改nginx-ingress镜像中的配置模板/etc/nginx/template/nginx.tmpl,将: map $http_upgrade $connection_upgrade { default upgrade; '’ close; } 修改为: map $http_upgrade $connection_upgrade { default upgrade; {{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} # See http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive '’ ‘'; {{ else }} '’ close; {{ end }} } 需配合使用configmap,设置upstream-keepalive-connections: “32”,一旦检测到该值大于0即可支持长连接。 该bug在0.20后得到更新:https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md

效果

经过上述调整后,达到预期效果,如下:

$ kubectl get cm -n ingress-nginx  nginx-configuration -o yaml |grep keep
  keep-alive: "60"
  keep-alive-requests: "2000"
  upstream-keepalive-connections: "100"
  • upstream-keepalive-connections: “100”
    • 每个Pod上最多保持 100 个长连接,连接总数无限制,可以超过 100 个,超出的连接会在请求结束后被回收;
  • keep-alive-requests: “2000”
    • 每个长连接总共承接 2000 个请求,长连接处理的请求总数达到 2000 后,连接被回收;
  • keep-alive: “60”:
    • 每个长连接的超时时间为 60 秒,长连接中没有请求的持续时间达到 60s 后,连接被回收;