Joh*_*röm 7 load-balancing kubernetes google-kubernetes-engine grpc kubernetes-ingress
我有一个 API 最近开始接收更多流量,大约是 1.5 倍。这也导致延迟加倍:
这让我感到惊讶,因为我设置了节点和 Pod 的自动缩放以及 GKE 内部负载平衡。
我的外部 API 将请求传递到使用大量 CPU 的内部服务器。查看我的 VM 实例,似乎所有流量都发送到我的两个 VM 实例之一(也称为 Kubernetes 节点):
通过负载平衡,我预计 CPU 使用率会在节点之间更加均匀地分配。
查看我的部署,第一个节点上有一个 pod:
第二个节点上有两个 pod:
我的服务配置:
$ kubectl describe service model-service
Name: model-service
Namespace: default
Labels: app=model-server
Annotations: networking.gke.io/load-balancer-type: Internal
Selector: app=model-server
Type: LoadBalancer
IP Families: <none>
IP: 10.3.249.180
IPs: 10.3.249.180
LoadBalancer Ingress: 10.128.0.18
Port: rest-api 8501/TCP
TargetPort: 8501/TCP
NodePort: rest-api 30406/TCP
Endpoints: 10.0.0.145:8501,10.0.0.152:8501,10.0.1.135:8501
Port: grpc-api 8500/TCP
TargetPort: 8500/TCP
NodePort: grpc-api 31336/TCP
Endpoints: 10.0.0.145:8500,10.0.0.152:8500,10.0.1.135:8500
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal UpdatedLoadBalancer 6m30s (x2 over 28m) service-controller Updated load balancer with new hosts
Run Code Online (Sandbox Code Playgroud)
Kubernetes 启动了一个新的 pod,这一事实似乎表明 Kubernetes 自动缩放功能正在发挥作用。但第二个虚拟机上的 Pod 不会收到任何流量。如何让 GKE 更均匀地平衡负载?
Goli的回答让我认为这与模型服务的设置有关。该服务公开 REST API 和 GRPC API,但 GRPC API 是接收流量的 API。
我的服务有对应的转发规则:
$ gcloud compute forwarding-rules list --filter="loadBalancingScheme=INTERNAL"
NAME REGION IP_ADDRESS IP_PROTOCOL TARGET
aab8065908ed4474fb1212c7bd01d1c1 us-central1 10.128.0.18 TCP us-central1/backendServices/aab8065908ed4474fb1212c7bd01d1c1
Run Code Online (Sandbox Code Playgroud)
其中指向后端服务:
$ gcloud compute backend-services describe aab8065908ed4474fb1212c7bd01d1c1
backends:
- balancingMode: CONNECTION
group: https://www.googleapis.com/compute/v1/projects/questions-279902/zones/us-central1-a/instanceGroups/k8s-ig--42ce3e0a56e1558c
connectionDraining:
drainingTimeoutSec: 0
creationTimestamp: '2021-02-21T20:45:33.505-08:00'
description: '{"kubernetes.io/service-name":"default/model-service"}'
fingerprint: lA2-fz1kYug=
healthChecks:
- https://www.googleapis.com/compute/v1/projects/questions-279902/global/healthChecks/k8s-42ce3e0a56e1558c-node
id: '2651722917806508034'
kind: compute#backendService
loadBalancingScheme: INTERNAL
name: aab8065908ed4474fb1212c7bd01d1c1
protocol: TCP
region: https://www.googleapis.com/compute/v1/projects/questions-279902/regions/us-central1
selfLink: https://www.googleapis.com/compute/v1/projects/questions-279902/regions/us-central1/backendServices/aab8065908ed4474fb1212c7bd01d1c1
sessionAffinity: NONE
timeoutSec: 30
Run Code Online (Sandbox Code Playgroud)
其中有健康检查:
$ gcloud compute health-checks describe k8s-42ce3e0a56e1558c-node
checkIntervalSec: 8
creationTimestamp: '2021-02-21T20:45:18.913-08:00'
description: ''
healthyThreshold: 1
httpHealthCheck:
host: ''
port: 10256
proxyHeader: NONE
requestPath: /healthz
id: '7949377052344223793'
kind: compute#healthCheck
logConfig:
enable: true
name: k8s-42ce3e0a56e1558c-node
selfLink: https://www.googleapis.com/compute/v1/projects/questions-279902/global/healthChecks/k8s-42ce3e0a56e1558c-node
timeoutSec: 1
type: HTTP
unhealthyThreshold: 3
Run Code Online (Sandbox Code Playgroud)
我的 Pod 列表:
kubectl get pods
NAME READY STATUS RESTARTS AGE
api-server-deployment-6747f9c484-6srjb 2/2 Running 3 3d22h
label-server-deployment-6f8494cb6f-79g9w 2/2 Running 4 38d
model-server-deployment-55c947cf5f-nvcpw 0/1 Evicted 0 22d
model-server-deployment-55c947cf5f-q8tl7 0/1 Evicted 0 18d
model-server-deployment-766946bc4f-8q298 1/1 Running 0 4d5h
model-server-deployment-766946bc4f-hvwc9 0/1 Evicted 0 6d15h
model-server-deployment-766946bc4f-k4ktk 1/1 Running 0 7h3m
model-server-deployment-766946bc4f-kk7hs 1/1 Running 0 9h
model-server-deployment-766946bc4f-tw2wn 0/1 Evicted 0 7d15h
model-server-deployment-7f579d459d-52j5f 0/1 Evicted 0 35d
model-server-deployment-7f579d459d-bpk77 0/1 Evicted 0 29d
model-server-deployment-7f579d459d-cs8rg 0/1 Evicted 0 37d
Run Code Online (Sandbox Code Playgroud)
IA) 如何确认此健康检查实际上显示 2/3 后端不健康?B) 配置运行状况检查以将流量发送到我的所有后端?
在发现过去有几个 Pod 由于 RAM 太少而被驱逐后,我将这些 Pod 迁移到了新的节点池。旧的节点池虚拟机有 4 个 CPU 和 4GB 内存,新的节点池虚拟机有 2 个 CPU 和 8GB 内存。这似乎已经解决了逐出/内存问题,但负载均衡器仍然一次只向一个 pod 发送流量。
节点 1 上的 Pod 1:
节点 2 上的 Pod 2:
看起来负载均衡器根本没有分割流量,而只是随机选择一个 GRPC 模型服务器并向那里发送 100% 的流量。是否有一些我错过的配置导致了这种行为?这和我使用GRPC有关吗?
事实证明,答案是您无法使用 GKE 负载平衡器对 gRPC 请求进行负载平衡。
每次形成新的 TCP 连接时,GKE 负载均衡器(以及 Kubernetes 的默认负载均衡器)都会选择一个新的后端。对于常规 HTTP 1.1 请求,每个请求都会获得一个新的 TCP 连接,并且负载均衡器工作正常。对于 gRPC(基于 HTTP 2),TCP 连接仅建立一次,所有请求都在同一连接上复用。
这篇博文中有更多详细信息。
要启用 gRPC 负载平衡,我必须:
curl -fsL https://run.linkerd.io/install | sh
linkerd install | kubectl apply -f -
Run Code Online (Sandbox Code Playgroud)
kubectl apply -f api_server_deployment.yaml
kubectl apply -f model_server_deployment.yaml
Run Code Online (Sandbox Code Playgroud)
kubectl expose deployment/model-server-deployment
Run Code Online (Sandbox Code Playgroud)
kubectl apply -f api_server_deployment.yaml
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1077 次 |
最近记录: |