Kubernetes中的真正负载平衡?

时间:2018-07-27 14:04:13

标签: amazon-web-services kubernetes load-balancing amazon-elb

什么是负载均衡器?

  

负载平衡可改善跨多个工作负载的分布   计算资源,例如计算机,计算机集群,网络   链接,中央处理器或磁盘驱动器

NodePort

NodePort不是负载平衡器。 (我知道kube-proxy会在群集中访问流量后在Pod之间实现负载平衡)。我的意思是,最终用户点击http://NODEIP:30111(例如)URL来访问应用程序。即使流量在POD之间是负载均衡的,用户仍然会命中单个节点,即K8的奴才所在的“节点”,而是真正的负载均衡器,对吧?

入口服务

这里也一样,想象一下部署了入口控制器和入口服务。我们在入口服务中指定的子域应指向K8s群集中的“ a”节点,然后入口控制器对Pod之间的流量进行负载平衡。在这里,最终用户还击中了K8的奴才,但真正的负载均衡器的单个节点,对吧?

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

我怀疑,云提供商的LB如何进行负载平衡?那些是将流量真正分发到已部署PODS的适当节点上,还是只是将流量转发到主节点或奴才?

如果以上几点为真。真正的负载平衡在Pod /适当节点之间的流量在哪里?

我可以在K8s中实现真正的负载平衡吗?我问了一个相关的question here

1 个答案:

答案 0 :(得分:1)

  

NodePort不是负载平衡器。

您在某种程度上是对的,是的,它并非旨在成为负载均衡器。

  

用户仍然会命中单个节点,即K8的小兵所在的“节点”,而是真正的负载均衡器,对吧?

使用NodePort,您可以随时一次击中一个节点,但是必须记住kube-proxy在所有节点上都在运行。因此,您可以在群集中的任何节点上(甚至是未在其上运行工作负载的节点上)命中NodePort,并且仍然可以命中要命中的端点。以后变得很重要。

  

我们在Ingress-service中指定的子域应指向K8s集群中的“ a”节点<​​/ p>

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

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

  

我不确定云提供商LB如何进行负载平衡?那些是将流量真正分发到已部署PODS的适当节点上,还是只是将流量转发到主节点或奴才?

如果您在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一样,它已将入口控制器容器上的端口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类型)实现真正的LoadBalancing,而入口仅使该服务更易于外界访问