Kubernetes 中真正的负载平衡?

True LoadBalancing in Kubernetes?

什么是负载均衡器?

Load balancing improves the distribution of workloads across multiple computing resources, such as computers, a computer cluster, network links, central processing units, or disk drives

NodePort

NodePort 不是负载均衡器。 (我知道一旦流量在集群内部,kube-proxy 负载平衡 pod 之间的流量)我的意思是,最终用户点击 http://NODEIP:30111(例如)URL 来访问应用程序。即使流量在 POD 之间进行了负载均衡,用户仍然会访问单个节点,即 "Node",它是 K8s 的 minion,但却是真正的负载均衡器,对吧?

Ingress 服务

这里也一样,假设入口控制器和入口服务也已部署。我们在ingress-service中指定的子域应该指向K8s集群中的"a"节点,然后ingress-controller在pods之间进行流量负载均衡。这里也有终端用户访问单个节点,它是 K8s 的附属但真正的负载均衡器,对吧?

来自云提供商的负载均衡器(例如 AWS ELB)

我有疑问,云提供商的LB是如何做负载均衡的?那些真的是将流量分发到部署了 PODS 的适当节点,还是只是将流量转发到主节点或小节点?

如果以上观点成立。 pods/appropriate 节点之间流量的真正负载平衡在哪里。

能否在K8s中实现真正的负载均衡?我问了一个相关的

NodePort is not load balancer.

从某种意义上说,您是对的,是的,它并非设计为负载平衡器。

users still hits a single node i.e. the "Node" which is K8s's minion but a real Load Balancer, right?

使用 NodePort,您 必须 在任何时候点击一个节点,但您必须记住 kube-proxy 在所有节点上都是 运行 .因此,您可以在集群中的任何节点上访问 NodePort(即使是负载未 运行 的节点),您仍然会访问您想要访问的端点。这在以后变得很重要。

The sub-domain that we specify in ingress-service should points to "a" node in K8s cluster

不,这不是它的工作原理。

您的入口控制器仍然需要暴露在外部。如果您使用的是云提供商,一个常用的模式是使用 Type=LoadBalancer 的服务公开您的入口控制器。 LoadBalancing 仍然发生在 Services 上,但 Ingress 允许您以更加用户友好的方式使用该 Service。不要混淆入口和负载平衡。

I'm having a doubt how cloud provider LB does the load balancing? Are those really distribute the traffic to appropriate Node which PODS are deployed or just forwarding the traffic to master node or minion?

如果您查看 Kubernetes 中的预配服务,您就会明白为什么它有意义。

这是 LoadBalancer 类型的服务:

kubectl get svc nginx-ingress-controller -n kube-system                                                                    
NAME                       TYPE           CLUSTER-IP      EXTERNAL-IP        PORT(S)                      AGE
nginx-ingress-controller   LoadBalancer   <redacted>   internal-a4c8...   80:32394/TCP,443:31281/TCP   147d

您可以看到我已经部署了一个 LoadBalancer 类型的入口控制器。这已经创建了一个 AWS ELB,但也请注意,例如 NodePort 它将入口控制器 pod 上的端口 80 映射到端口 32394.

那么,让我们看看 AWS 中实际的 LoadBalancer:

aws elb describe-load-balancers --load-balancer-names a4c80f4eb1d7c11e886d80652b702125

{
    "LoadBalancerDescriptions": [
        {
            "LoadBalancerName": "a4c80f4eb1d7c11e886d80652b702125",
            "DNSName": "internal-a4c8<redacted>",
            "CanonicalHostedZoneNameID": "<redacted>",
            "ListenerDescriptions": [
                {
                    "Listener": {
                        "Protocol": "TCP",
                        "LoadBalancerPort": 443,
                        "InstanceProtocol": "TCP",
                        "InstancePort": 31281
                    },
                    "PolicyNames": []
                },
                {
                    "Listener": {
                        "Protocol": "HTTP",
                        "LoadBalancerPort": 80,
                        "InstanceProtocol": "HTTP",
                        "InstancePort": 32394
                    },
                    "PolicyNames": []
                }
            ],
            "Policies": {
                "AppCookieStickinessPolicies": [],
                "LBCookieStickinessPolicies": [],
                "OtherPolicies": []
            },
            "BackendServerDescriptions": [],
            "AvailabilityZones": [
                "us-west-2a",
                "us-west-2b",
                "us-west-2c"
            ],
            "Subnets": [
                "<redacted>",
                "<redacted>",
                "<redacted>"
            ],
            "VPCId": "<redacted>",
            "Instances": [
                {
                    "InstanceId": "<redacted>"
                },
                {
                    "InstanceId": "<redacted>"
                },
                {
                    "InstanceId": "<redacted>"
                },
                {
                    "InstanceId": "<redacted>"
                },
                {
                    "InstanceId": "<redacted>"
                },
                {
                    "InstanceId": "<redacted>"
                },
                {
                    "InstanceId": "<redacted>"
                },
                {
                    "InstanceId": "<redacted>"
                }
            ],
            "HealthCheck": {
                "Target": "TCP:32394",
                "Interval": 10,
                "Timeout": 5,
                "UnhealthyThreshold": 6,
                "HealthyThreshold": 2
            },
            "SourceSecurityGroup": {
                "OwnerAlias": "337287630927",
                "GroupName": "k8s-elb-a4c80f4eb1d7c11e886d80652b702125"
            },
            "SecurityGroups": [
                "sg-8e0749f1"
            ],
            "CreatedTime": "2018-03-01T18:13:53.990Z",
            "Scheme": "internal"
        }
    ]
}

这里要注意的最重要的事情是:

LoadBalancer 正在将 ELB 中的端口 80 映射到 NodePort:

{
                "Listener": {
                    "Protocol": "HTTP",
                    "LoadBalancerPort": 80,
                    "InstanceProtocol": "HTTP",
                    "InstancePort": 32394
                },
                "PolicyNames": []
 }

您还会看到有多个目标 Instances,而不是一个:

aws elb describe-load-balancers --load-balancer-names a4c80f4eb1d7c11e886d80652b702125 | jq '.LoadBalancerDescriptions[].Instances | length'
8

最后,如果您查看我的集群中的节点数,您会发现它实际上是 所有 已添加到 LoadBalancer 的节点:

kubectl get nodes -l "node-role.kubernetes.io/node=" --no-headers=true | wc -l                                             
8

因此,总而言之 - Kubernetes 确实 为服务(无论是 NodePort 还是 LoadBalancer 类型)实现了真正的负载平衡,入口只是让外界更容易访问该服务

从你说的和我用K8S研究了2个月。当你 运行 只有 1 个实例时,这里似乎没有负载平衡器。当我们扩展工作负载时,我们需要扩展 EVERYTHING 包括 Pods.

  • 这里我们有服务,默认情况下它将LOAD-BALANCE (Round-Robin) [之间的流量] =12=]Replica-Set 个 Pods。这才是真正的Heavy-TasksOff-loading。就 高可用性 而言,每个节点应至少包含 1 个副本 Pod.
  • 对于 Ingress Controller,示例:NGINX。 NGINX 本质上启用 Load-Balancing 到其目的地的网络流量。但是您只将 1 条入口规则指向 1 个特定服务。比如,谁他妈的有人将这个带有 Ingress 规则的 NGINX 指向具有相同功能的 2 个服务???你不能!!! 因为 Ingress Controller 只会获取 每 1 条规则 只有一项服务的详细信息。并为 Pods 负载平衡 使用服务端点。这是 Load-BalancingIngress Controller 启用的功能。
  • 对于云提供商环境中的 服务 [Type=LoadBalancer]。它将创建一个负载均衡器实例,并使用来自 集群服务的信息(包括所有 pods 详细信息) 因此,启用 Load-Balancing 到集群中的每个 Pods。
  • 入口控制器 [Type=LoadBalancer] 怎么样?好吧,因为您的 Ingress Controller 可以在多个节点中 运行。每个对 外部负载平衡器 的请求都会 Load-Balance 对 入口控制器 的所有 Pods 的请求。这些 Ingress Controller 将继续 Load-Balance 向所有 服务端点发出请求,也称为 pods.