为什么GCE负载平衡器的域名和IP地址会有所不同? [英] Why does GCE Load Balancer behave differently through the domain name and the IP address?

查看:97
本文介绍了为什么GCE负载平衡器的域名和IP地址会有所不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

后端服务恰巧在负载均衡器的运行状况检查路径上返回状态404.当浏览到负载均衡器的域名时,出现错误:服务器错误/服务器遇到临时错误",并且日志显示

A backend service happens to be returning Status 404 on the health check path of the Load Balancer. When I browse to the Load Balancer's domain name, I get "Error: Server Error/ The server encountered a temporary error", and the logs show

"type.googleapis.com/google.cloud.loadbalancing.type.LoadBalancerLogEntry" statusDetails: "failed_to_pick_backend",这很有意义.

"type.googleapis.com/google.cloud.loadbalancing.type.LoadBalancerLogEntry" statusDetails: "failed_to_pick_backend", which makes sense.

当我浏览到负载均衡器的静态IP时,我的浏览器显示404错误消息,底层的Kubernetes Pod返回了该消息,换句话说,尽管运行状况检查失败,负载均衡器还是通过了请求.

When I browse to the Load Balancer's Static IP, my browser shows the 404 Error Message which the underlying Kubernetes Pod returned, In other words the Load Balancer passed on the request despite the failed health check.

为什么这两种不同的行为?

Why these two different behaviors?

以下是创建负载均衡器的Ingress的Yaml:

Here is the yaml for the Ingress that created the Load Balancer:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress1
spec:
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          serviceName: myservice
          servicePort: 80

推荐答案

我对此进行了深入研究",并设法重现了我的GKE集群上的情况,所以现在我可以说这里有几处结合了

I did a "deep dive" into that and managed to reproduce the situation on my GKE cluster, so now I can tell that there are a few things combined here.

后端服务恰巧在负载均衡器的运行状况检查路径上返回状态404.

A backend service happens to be returning Status 404 on the health check path of the Load Balancer.

可能有2个选项(根据您提供的说明不清楚).

There could be 2 options (it is not clear from the description you have provided).

  • 类似的东西: "错误:服务器错误 服务器遇到临时错误,无法完成您的请求. 请在30秒后重试."
  • something like: "Error: Server Error The server encountered a temporary error and could not complete your request. Please try again in 30 seconds."

如果您的Pod的HealthCheck失败,那么您将从LoadBalancer获得此信息.关于GKE Ingress对象的官方文档表示

This one you are geting from LoadBalancer in case HealthCheck failed for pod. The official documentation on GKE Ingress object says that

通过Ingress公开的服务必须响应负载平衡器的运行状况检查.

a Service exposed through an Ingress must respond to health checks from the load balancer.

作为负载均衡流量的最终目的地的任何容器都必须执行以下一项操作,以表明其运行状况良好:

Any container that is the final destination of load-balanced traffic must do one of the following to indicate that it is healthy:

  • 将HTTP 200状态的响应提供给/路径上的GET请求.

  • Serve a response with an HTTP 200 status to GET requests on the / path.

配置.为准备就绪探针指定的path上的GET请求提供HTTP 200状态的响应.通过Ingress公开的服务必须指向启用了就绪探针的相同容器端口.

Configure an HTTP readiness probe. Serve a response with an HTTP 200 status to GET requests on the path specified by the readiness probe. The Service exposed through an Ingress must point to the same container port on which the readiness probe is enabled.

需要修复HealthCheck处理.您可以通过访问GCP控制台-网络服务-负载平衡来查看负载平衡器详细信息.

It is needed to fix HealthCheck handling. You can check Load balancer details by visiting GCP console - Network Services - Load Balancing.

  • "找不到404 -nginx/1.17.6"
  • "404 Not Found -- nginx/1.17.6"

这很清楚.那是端点myservice向其发送请求所返回的响应.好像那里的配置不正确.我的猜测是,pod不能完全满足该请求.可能是nginx网络服务器问题,等等.请检查配置以找出pod无法满足请求的原因.

This one is clear. That is the response returned by endpoint myservice is sending request to. It looks like something is misconfigured there. My guess is that pod merely can't serve that request properly. Can be nginx web-server issue, etc. Please check the configuration to find out why pod can't serve the request.

在进行设置时,我发现了图像检查请求是否已到达Pod并请求标头.

While playing with the setup I have find an image that allows you to check if request has reached the pod and requests headers.

因此可以创建一个像这样的吊舱:

so it is possible to create a pod like:

apiVersion: v1
kind: Pod
metadata:
  annotations:
    run: fake-web
  name: fake-default-knp
#  namespace: kube-system
spec:
  containers:
  - image: mendhak/http-https-echo
    imagePullPolicy: IfNotPresent
    name: fake-web
    ports:
    - containerPort: 8080
      protocol: TCP

能够查看传入请求(kubectl logs -f fake-default-knp)中的所有标头.

to be able to see all the headers that were in incoming requests (kubectl logs -f fake-default-knp ).

当我浏览到负载均衡器的静态IP时,我的浏览器会显示基础Kubernetes Pod返回的404错误消息.

When I browse to the Load Balancer's Static IP, my browser shows the 404 Error Message which the underlying Kubernetes Pod returned.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress1
spec:
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          serviceName: myservice
          servicePort: 80

创建此类Ingress对象后,GKE集群中将至少有2个后端. -创建Ingress时指定的后端(myservice一个) -默认值(在创建集群时创建).

Upon creation of such an Ingress object, there will be at least 2 backends in GKE cluster. - the backend you have specified upon Ingress creation ( myservice one) - the default one (created upon cluster creation).

kubectl get pods -n kube-system -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP       
l7-default-backend-xyz     1/1     Running   0          20d   10.52.0.7

请注意,myservice仅提供 请求,这些请求的Host标头设置为example.com.其余请求将发送到默认后端".这就是为什么浏览到LoadBalancer的IP地址时会收到默认后端-404"错误消息的原因.

Please note that myservice serves only requests that have Host header set to example.com . The rest of requests are sent to "default backend" . That is the reason why you are receiving "default backend - 404" error message upon browsing to LoadBalancer's IP address.

从技术上讲,有一个default-http-backend服务以l7-default-backend-xyz作为端点.

Technically there is a default-http-backend service that has l7-default-backend-xyz as an EndPoint.

kubectl get svc -n kube-system -o wide 
NAME                   TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)         AGE   SELECTOR
default-http-backend   NodePort    10.0.6.134    <none>        80:31806/TCP    20d   k8s-app=glbc

kubectl get ep -n kube-system
NAME                   ENDPOINTS       AGE
default-http-backend   10.52.0.7:8080  20d

同样,对于主机"标头不等于您在Ingress中指定的请求的请求,该对象"返回默认后端-404"错误.

Again, that's the "object" that returns the "default backend - 404" error for the requests with "Host" header not equal to the one you specified in Ingress.

希望它可以阐明这个问题:)

Hope that it sheds a light on the issue :)

myservice仅服务于将Host标头设置为example.com的请求."那么,您说的是,仅当存在主机标头时,请求才转到LB?

myservice serves only requests that have Host header set to example.com." So you are saying that requests go to the LB only when there is a host header?

不完全是. LB接收所有请求,并根据主机"标头值传递请求.具有example.com主机标头的请求将在myservice后端上提供.

Not exactly. The LB receives all the requests and passes requests in accordance to "Host" header value. Requests with example.com Host header are going to be served on myservice backend .

简单地说,逻辑如下:

  1. 请求到达;
  2. 系统检查主机标头(以确定用户的后端)
  3. 如果有合适的用户后端(根据Ingress配置)且该后端运行状况良好,则可以满足
  4. 请求,否则为"错误:服务器错误.服务器遇到临时错误,无法完成您的请求.请在30秒后重试."如果后端处于不健康状态,则抛出该异常;
  5. 如果请求的Host标头与Ingress规范中的任何主机都不匹配,则会将请求发送到l7-default-backend-xyz后端(而不是Ingress配置中提到的主机).该后端回复:默认后端-404"错误.
  1. request arrives;
  2. system checks the Host header (to determine user's backend)
  3. request is served if there is a suitable user's backend ( according to the Ingress config) and that backend is healthy , otherwise "Error: Server Error The server encountered a temporary error and could not complete your request. Please try again in 30 seconds." is thrown if backend is in non-healthy state;
  4. if request's Host header doesn't match any host in Ingress spec, request is sent to l7-default-backend-xyz backend (not the one that is mentioned in Ingress config). That backend replies with: "default backend - 404" error .

希望这很清楚.

这篇关于为什么GCE负载平衡器的域名和IP地址会有所不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆