【解构云原生】K8s踩坑:Ingress四层负载均衡端口不可乱配

背景知识

ingress原生是仅支持七层负载均衡(基于路径)的,其中ingress-nginx通过configmap的方式也能做到四层(基于端口)的负载均衡。

在ingress-nginx 0.21.0版本中,作者原计划要移除对四层负载均衡的支持,参看PR#3197,原因主要有以下几点:

  • ingress的语义,原本就是仅支持7层负载均衡的,用它来实现四层负载均衡会显得很诡异
  • 四层的负载均衡有其他的解决方案,没必要通过ingress来实现。提到的是使用metallb替代,即创建loadbalancer类型的service。

然而,奈何顶不住众多人的吐槽,又在0.21.0把上述commit给revert了,具体参考Revert removal of support for TCP and UDP services。用户的理由是:

  • 他们已经有很多服务在依赖ingress-nginx的四层负载均衡了,有迁移成本
  • 他们的服务是在公有云上,假如每个服务都创建一个loadbalancer类型的service,成本太高,而且有lb数量限制
  • 恐吓型的,假如你们的ingress-controller不再支持四层负载均衡,那我们就只能去使用其他家的解决方案了

遇到的问题和原因分析

某个机房是没有VPC网络的,是物理网络环境,ingress-controller是使用的hostnetwork方式两副本部署的,并且通过keepalived vip漂移实现了ingress-controller的高可用。

用户配置了一个四层的负载均衡策略,使用的端口号是32712,导致新建的其他的ingress四层负载均衡不能够正常生效,并且老的ingress四层负载均衡规则不能够正常reload。

查看ingress-controller日志发现:

2020/06/13 09:22:51 [emerg] 57#57: bind() to 0.0.0.0:32712 failed (98: Address already in use)
2020/06/13 09:22:51 [emerg] 57#57: bind() to [::]:32712 failed (98: Address already in use)
2020/06/13 09:22:51 [emerg] 57#57: bind() to 0.0.0.0:32712 failed (98: Address already in use)
2020/06/13 09:22:51 [emerg] 57#57: bind() to [::]:32712 failed (98: Address already in use)
2020/06/13 09:22:51 [emerg] 57#57: bind() to 0.0.0.0:32712 failed (98: Address already in use)
2020/06/13 09:22:51 [emerg] 57#57: bind() to [::]:32712 failed (98: Address already in use)
2020/06/13 09:22:51 [emerg] 57#57: bind() to 0.0.0.0:32712 failed (98: Address already in use)
2020/06/13 09:22:51 [emerg] 57#57: bind() to [::]:32712 failed (98: Address already in use)
2020/06/13 09:22:51 [emerg] 57#57: bind() to 0.0.0.0:32712 failed (98: Address already in use)
2020/06/13 09:22:51 [emerg] 57#57: bind() to [::]:32712 failed (98: Address already in use)
2020/06/13 09:22:51 [emerg] 57#57: still could not bind()

原因是端口号32712已经被占用了。那是被谁占用的呢?后来发现是被nodeport service给占用了。不管是谁先占用的,只要发生了端口冲突,都会造成故障。

建议

在k8s集群中有几个端口范围一定要注意,稍有不慎就会触发上述故障:

  • service nodeport的端口:k8s会给每个nodeport类型和loadbalancer类型的service分配一个端口号,端口范围可以通过kube-apiserver的参数service-node-port-range配置,默认值是30000-32767,当前我们的配置是30000-34999。(默认端口范围太小了,不够用,这个范围是不支持后期修改的,因此前期规划一定要合理)
  • Linux的net.ipv4.ip_local_port_range,可以配置为 35000-60999
  • 如果pod是hostnetwork,那么端口范围不能与上面冲突
  • 考虑ingress-nginx pod 这种特殊服务:
    • 如果是hostNetwork:那么用户在配置四层负载均衡时,其端口范围不能与上述端口冲突,并且不能与其他普通hostnetwork pod端口冲突(这个是无法调度保证的,因为四层负载均衡是动态配置的)
    • 如果不是hostnetwork:那么没什么限制

相关阅读:【解构云原生】K8s 的 RBAC - 基于角色的访问控制

活动报名:1024,来网易北京研发中心,听网易、美团、贝壳、PingCAP、爱奇艺大咖分享云原生实践干货!

【解构云原生】K8s踩坑:Ingress四层负载均衡端口不可乱配_第1张图片

你可能感兴趣的:(云原生,kubernetes)