方案思路

需求

保留客户端地址,k8s服务对外一个地址和53端口,负载均衡。

可能的方案

  • hostnetwork 针对pod级别(负载均衡可以放到外面做,我们不考虑。k8s的开发目标本身就是服务编排没必要自造轮子)

  • hostport也是,针对pod(原因如上)

  • kube port-forward命令
    k8s服务对外端口转发。不仅支持pod,现在支持service了。但目前不支持udp。社区有人开发出了,但没有approve。

  • ddns service type=cluster ip方式,默认保留客户端ip;只能集群内部访问。

  • ddns service type=cluster ip方式,对clusterip 设置static route,从外网访问,方案不好。

  • ddns service type=nodeport方式
    默认不保留。但service.spec.externalTrafficPolicy=local就可以了;
    nodeport端口默认30000以上,除非修改k8s源码修改到支持53端口,也有可能冲突等。
    前面加个负载均衡器nginx类似的可以做到对外一个ip地址。k8s社区采用以下的方案。

  • ddns service type=nodeport + keepalive-vip
    可以做到多个node的failover,高可用,但没有node的负载均衡。

  • ddns service type=loadbalancer方式
    默认不保留客户端IP地址。
    云厂商如google/aws支持保留客户端,
    对于开源的metallb(onpremis)

    • metallb:
      1. lay2 arp
        目前不支持保留客户端ip。保留客户端的方式 正在社区在开发中,时间不可估。
        metallb本身暂时不支持proxy protocol协议,我们ddns也暂时不支持proxy protocol协议。所以proxy protocol方式也不可以。
        注意:proxy protocol作用是在proxy与后端或者proxy间传递客户端ip地址信息的协议,一种保留客户单ip的方法。
        暂时本身只是支持failover不能负载均衡(why)。与keeplive-vip类似。
      2. BGP 方式
        支持保留客户端ip,真正的负载均衡
        咱们部署的时候需要BGP路由器,以便metalb的extra ip从internet可以路由到k8s集群。
        BGP本身复杂。
  • ingress nginx,nginx service type=nodeport,ddns service type clusterip方式
    保证了多个node的负载均衡,但是为了端口不是53,前面可能需要有个proxy或者keepalive等。
    nginx upd代理下保留客户端ip的方法有:

    1. proxy protocol:不支持udp,尽支持tcp。需要开发nginx和ddns的proxy protocol。
    2. proxy bind ip透明方式 container/pod后端和nginx端需要设置路由等
    3. dsr直接服务区返回,基于2.
      需要先熟悉基本的ingress nginx 然后探索方便的方法进行container端的网络设置(采用2/3)
      咨询了开发者,目前2/3暂时不能工作,需要摸索实现。
  • ingress nginx,nginx service type=loadbalancer, ddns service type clusterip方式
    前面加上metalb,如果上面proxy_bind or dsr 走通,就可以做到node本身负载均衡和保留客户端ip。

  • 其他ingress方式如haproxy,envoy,traefik 目前都不支持upd负载均衡。

  • 一种基于ecmp的方法
    https://github.com/Mirantis/k8s-externalipcontroller/blob/master/doc/ecmp-load-balancing.md
    有必要探索

一些tradeoff

  • 只一台机器

    • 不需要考虑node的failover和loadbalance,只考虑k8s内部的负载均衡。但要考虑到将来k8s扩容的需要和k8s本身的设计目标:服务编排,隐藏分布式系统的实现细节。
    • 建一个service,采用clusterip方式。kube port forward命令的方式,upd不支持。
    • 建一个service,采用nodeport方式,机器使用端口转发把53端口的流量转发到nodeport端口。
      • 可以采用,但将来要是再添加一个单机k8s集群,我们需要管理多个k8s集群,只利用了单机的功能,不能利用master的高可用,不能利用一个worker节点坏了自动调度其上得pod到其他节点上等功能,也不能利用多个worker节点的负载均衡功能等。而所有k8s已经考虑的问题需要我们在集群外考虑。)
      • 如果不是添加一个单机k8s集群,而是扩容的方式,这样就到了k8s多台机器的方式了。我们考虑多节点k8s的解决方案。
    • 建多个service,采用nodeport的方式,就是多个nodeport出现,需要引入外部负载均衡或者ingress nginx等对外才可能是一个53端口,也类似与多节点k8s的方案。
  • 多台机器

    • failover,没有多个节点的负载均衡
      • keepalive-vip + dns service(nodeport)

      • metallb layer2 (暂时不考虑)

    • lb
      • ingress nginx(udp的探索)
        需要考虑那个对外端口53

        1. 前面加一个负载均衡比如metalb,简单实用但bgp配置复杂可能还需要bgp路由成本。
        2. 如果加上个nginx反向代理也得考虑保留客户ip问题。
        3. 如果只用portforward,只能考虑单个机器。
        4. ingress nginx前部署keepalive-vip的方法,可以保证了服务的高可用,同时端口也能做到53。
      • metallb( BGP)

结论

  • 如果优先考虑多节点负载均衡的话,重点ingress nginx +keepalive-vip方案。如果BGP方案已有设备,也可以探索metallb的方案。
  • 如果优先考虑多节点failover,采用keepalive + dns service(nodeport)。
  • 如果只考虑多节点不考虑扩展性等,采用建一个service nodeport方式,机器使用端口转发把53端口的流量转发到nodeport端口。