NodePort 不是负载均衡器。
从某种程度上来说,你是对的,是的,它并不是被设计成负载均衡器的。
用户仍然访问单个节点,即“Node”,它是 K8s 的 minion,但却是真正的负载均衡器,对吧?
有了 NodePort,您have随时命中单个节点,但您必须记住这一点kube-proxy
在所有节点上运行。因此,您可以访问集群中任何节点上的 NodePort(甚至是未运行工作负载的节点),并且您仍然会访问您想要访问的端点。这一点稍后会变得很重要。
我们在 ingress-service 中指定的子域应该指向 K8s 集群中的“a”节点
不,事情不是这样的。
您的入口控制器仍然需要暴露在外部。如果您使用云提供商,常用的模式是通过以下服务公开您的入口控制器Type=LoadBalancer
。负载平衡仍然发生在服务中,但 Ingress 允许您以更用户友好的方式使用该服务。不要将入口与负载平衡混淆。
我有一个疑问云提供商LB如何进行负载平衡?这些是否真的将流量分配到部署 PODS 的适当节点,或者只是将流量转发到主节点或 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
最后,如果您查看集群中的节点数量,您会发现它实际上是all已添加到LoadBalancer的节点:
kubectl get nodes -l "node-role.kubernetes.io/node=" --no-headers=true | wc -l
8
所以,总而言之 - Kubernetesdoes使用服务(无论是 NodePort 还是 LoadBalancer 类型)实现真正的 LoadBalancing,入口只是使该服务更容易被外界访问