如何在为Kubernetes Ingress提供服务的GCE L7负载均衡器中获取自定义健康检查路径?

18

我正在尝试在GCE上的Kubernetes(服务器1.6.4)中部署grafana实例。我正在使用以下清单:

部署 (完整版本):

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: grafana
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: grafana
    spec:
      initContainers:
                                        
      containers:
        - name: grafana
          image: grafana/grafana
          readinessProbe:
            httpGet:
              path: /login
              port: 3000
          

服务:

apiVersion: v1
kind: Service
metadata:
  name: grafana
spec:
  selector:
    name: grafana
  ports:
    - protocol: TCP
      port: 3000
  type: NodePort
Ingress

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: grafana
spec:
  tls:
    - secretName: grafana.example.com
  backend:
    serviceName: grafana
    servicePort: 3000

结果发现Grafana在/路径下提供了302响应,但默认的GCE Ingress健康检查需要/返回200 (源代码)。可以看到,在Deployment(第22行)中有一个自定义的readinessProbe

一旦我将这些资源发布到kube-apiserver,所有内容都会成功创建。具体来说,Ingress获得了公共IPv4地址,但健康检查仍然使用默认的/路径,而不是在readinessProbe中配置的自定义路径。因此,如果我curl Ingress的公共IPv4地址,则会返回502。

问题可以通过在GCE控制台中手动更改探测路径为/login来解决。


3
+1相同的问题。比登录页面更好,实际上有一个/api/health端点 - JCotton
4个回答

16

引用自这里

GLBC要求您在Pod规范中定义端口(在您的情况下为3000)。

解决方法是在ports中声明用于健康检查的端口,除此之外还需添加自定义的readinessProbe

containers:
  - name: grafana
    readinessProbe:
      httpGet:
        path: /login
        port: 3000
    ports:
      - name: grafana
        containerPort: 3000
    

值得指出的是,一旦“后端服务的健康检查参数是从运行 Pod 的可用性探针中推断出来,GKE 就不会保持可用性探针和健康检查同步”。因此,更新 readinessProbe 不会自动纠正健康检查。 - ggordan

9

定制健康检查

使用GLBC插件

从您的问题中不太清楚,但如果您正在使用GCE负载均衡控制器(GLBC)集群插件,则可以自定义健康检查路径

目前,所有服务后端必须满足以下要求之一,才能通过GCE负载均衡器发送的HTTP(S)健康检查:

  • '/'上响应200。内容无关紧要。
  • 将任意URL公开为支持服务的Pod的就绪探针。

Ingress控制器首先查找兼容的就绪探测,如果找到,则采用它作为GCE负载均衡器的HTTP(S)健康检查。如果没有就绪探测,或者就绪探测需要特殊的HTTP头,则Ingress控制器将GCE负载均衡器的HTTP健康检查指向'/'。这是一个示例,说明了Ingress如何采用来自端点的就绪探测作为其健康检查。

GLBC插件页面在限制部分中提到:

所有Kubernetes服务都必须在'/'上提供200页,或者您通过GLBC的--health-check-path参数指定的任何自定义值。

不使用GLBC插件

如果您没有使用该插件,则目前Kubernetes要求您对/路径的GET请求提供200以进行成功的健康检查,否则后端将无法获得任何流量。

有关此问题的一些背景,请参见此错误

Google容器引擎(GKE)

如果您使用的是Google容器引擎(GKE),则同样适用于健康检查的默认Kubernetes要求也适用于GKE

通过Ingress公开的服务必须在路径“/”上对GET请求返回HTTP 200状态的响应,这用于健康检查。如果您的应用程序没有在“/”上提供HTTP 200,则后端将被标记为不健康,将无法获得流量。
回答您实际的问题
话虽如此,正如您(@mmoya)在您的答案中指出的那样,将用于就绪探针的相同端口添加为Pod中的端口之一可解决您的问题,因为该端口本身未公开到Pod外部。这导致Kubernetes依赖于来自“/”的健康检查。

这个回答基本上是说“你不能”,但实际上是可以的。请看我的回答。 - mmoya
1
@mmoya - 感谢提供链接。我现在已经从GLBC存储库中添加了文档链接,其中描述了为什么某些情况下可以使用“/”,以及何时可以使用就绪探针进行健康检查。由于您在问题中没有提到GLBC,所以我最初给出了一个通用答案,涵盖了多种情况。您的问题似乎是您没有将端口暴露到Pod之外,这就是为什么它依赖于路径“/”进行健康检查而不是使用就绪探针的原因。 - Tuxdude

3
在创建Ingress时,推断健康检查的条件为:

Ingress后端服务端口引用了一个Service端口,该端口匹配Pod规范中的containers[].readinessProbe.httpGet.port,并且Service的targetPort引用了提供服务的Pod的containers[].spec.ports.containerPort。

2020年中期,GKE引入了一个注释和自定义资源定义BackendConfig来明确配置健康检查,请参见concepts/ingress#health_checks
注意:如果您再次更改readinessProbe,对于推断的健康检查,GKE不会将就绪探针和健康检查保持同步。它只会在Ingress(重新)创建时再次推断。
要直接编辑外部负载均衡器的健康检查(用于自定义http路径),请使用
gcloud compute backend-services list
gcloud compute backend-services get-health BACKEND_SERVICE_NAME --global
gcloud compute health-checks describe
gcloud compute health-checks update http BACKEND_SERVICE_NAME --request-path=/api/health

这拯救了我的一天,对于描述命令还要添加BACKEND_SERVICE_NAME。 - Nithya

0

这适用于1.9版本。设置httpHeaders也可以避免在ALLOWED_HOSTS设置中添加额外的主机名。

readinessProbe:
  httpGet:
    path: /login
    port: 3000 # Must be same as containerPort
    httpHeaders:
    - name: Host
      value: yourdomain.com

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接