如何在服务于 Kubernetes Ingress 的 GCE L7 平衡器中获取自定义健康检查路径?
How to get a custom healthcheck path in a GCE L7 balancer serving a Kubernetes Ingress?
我正在尝试在 GCE 的 Kubernetes(服务器 1.6.4)中部署一个 grafana 实例。我正在使用以下清单:
部署 (full version):
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
入口:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: grafana
spec:
tls:
- secretName: grafana.example.com
backend:
serviceName: grafana
servicePort: 3000
事实证明,grafana 在 /
上提供 302,但默认的 GCE 入口健康检查期望在 /
上提供 200(source). As you can see, there is a custom readinessProbe in the Deployment(第 22 行)。
一旦我post这些资源到kube-apiserver,一切都创建无误。具体来说,Ingress 获得了一个 public ip4 地址,但是 healtcheck 设置了默认的 /
路径,而不是在中配置的自定义路径readinessProbe
。因此,如果我 curl
Ingress 的 public ip4 地址,我会得到 502。
通过在 GCE 控制台中手动将探测路径更改为 /login
可以解决此问题。
自定义健康检查
使用 GLBC 插件
从你的问题来看不是很清楚,但是如果你使用的是 GCE Load-Balancer Controller (GLBC) Cluster Addon
, you can customize the health check path。
Currently, all service backends must satisfy either of the following
requirements to pass the HTTP(S) health checks sent to it from the GCE
loadbalancer:
- Respond with a
200
on '/'
. The content does not matter.
- Expose an arbitrary url as a readiness probe on the pods backing the Service.
The Ingress controller looks for a compatible readiness probe first,
if it finds one, it adopts it as the GCE loadbalancer's HTTP(S) health
check. If there's no readiness probe, or the readiness probe requires
special HTTP headers, the Ingress controller points the GCE
loadbalancer's HTTP health check at '/'. This is an example of an
Ingress that adopts the readiness probe from the endpoints as its
health check.
GLBC 插件页面在 Limitations section:
中提到了这一点
All Kubernetes services must serve a 200
page on '/'
, or whatever
custom value you've specified through GLBC's --health-check-path
argument.
没有 GLBC 插件
如果您没有使用该插件,目前 Kubernetes 确实要求您在 /
路径上为 GET
请求服务 200
以成功进行健康检查,否则后端将无法获取任何流量。
这个 bug.
中有一些背景知识
Google 容器引擎 (GKE)
如果您使用的是 Google 容器引擎 (GKE),则相同的默认 Kubernetes 健康检查要求 apply there too。
Services exposed through an Ingress must serve a response with HTTP
200
status to the GET
requests on /
path. This is used for health
checking. If your application does not serve HTTP 200
on /
, the
backend will be marked unhealthy and will not get traffic.
回答你真正的问题
说了这么多,正如您 (@mmoya) 在您的回答中指出的那样,添加用于就绪探测的相同端口作为 pod 中的端口之一解决了您的问题,因为端口否则本身不会暴露在吊舱外。这导致 Kubernetes 改为依赖 /
的健康检查。
引用自here:
The GLBC requires that you define the port (in your case 3000) within the Pod specification.
除了添加自定义 readinessProbe
:
之外,解决方案是在 ports
中声明用于健康检查的端口
containers:
- name: grafana
readinessProbe:
httpGet:
path: /login
port: 3000
ports:
- name: grafana
containerPort: 3000
…
推断 Ingress 创建健康检查的条件是
an Ingress backend.servicePort references a Service port, matching a Pods spec.containers[].readinessProbe.httpGet.port and the Service's targetPort references the serving Pod's 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
这适用于 1.9。设置 httpHeaders
也消除了在 ALLOWED_HOSTS
设置中添加额外主机名的必要性。
readinessProbe:
httpGet:
path: /login
port: 3000 # Must be same as containerPort
httpHeaders:
- name: Host
value: yourdomain.com
我正在尝试在 GCE 的 Kubernetes(服务器 1.6.4)中部署一个 grafana 实例。我正在使用以下清单:
部署 (full version):
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
入口:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: grafana
spec:
tls:
- secretName: grafana.example.com
backend:
serviceName: grafana
servicePort: 3000
事实证明,grafana 在 /
上提供 302,但默认的 GCE 入口健康检查期望在 /
上提供 200(source). As you can see, there is a custom readinessProbe in the Deployment(第 22 行)。
一旦我post这些资源到kube-apiserver,一切都创建无误。具体来说,Ingress 获得了一个 public ip4 地址,但是 healtcheck 设置了默认的 /
路径,而不是在中配置的自定义路径readinessProbe
。因此,如果我 curl
Ingress 的 public ip4 地址,我会得到 502。
通过在 GCE 控制台中手动将探测路径更改为 /login
可以解决此问题。
自定义健康检查
使用 GLBC 插件
从你的问题来看不是很清楚,但是如果你使用的是 GCE Load-Balancer Controller (GLBC) Cluster Addon
, you can customize the health check path。
Currently, all service backends must satisfy either of the following requirements to pass the HTTP(S) health checks sent to it from the GCE loadbalancer:
- Respond with a
200
on'/'
. The content does not matter.- Expose an arbitrary url as a readiness probe on the pods backing the Service.
The Ingress controller looks for a compatible readiness probe first, if it finds one, it adopts it as the GCE loadbalancer's HTTP(S) health check. If there's no readiness probe, or the readiness probe requires special HTTP headers, the Ingress controller points the GCE loadbalancer's HTTP health check at '/'. This is an example of an Ingress that adopts the readiness probe from the endpoints as its health check.
GLBC 插件页面在 Limitations section:
中提到了这一点All Kubernetes services must serve a
200
page on'/'
, or whatever custom value you've specified through GLBC's--health-check-path
argument.
没有 GLBC 插件
如果您没有使用该插件,目前 Kubernetes 确实要求您在 /
路径上为 GET
请求服务 200
以成功进行健康检查,否则后端将无法获取任何流量。
这个 bug.
中有一些背景知识Google 容器引擎 (GKE)
如果您使用的是 Google 容器引擎 (GKE),则相同的默认 Kubernetes 健康检查要求 apply there too。
Services exposed through an Ingress must serve a response with
HTTP 200
status to theGET
requests on/
path. This is used for health checking. If your application does not serveHTTP 200
on/
, the backend will be marked unhealthy and will not get traffic.
回答你真正的问题
说了这么多,正如您 (@mmoya) 在您的回答中指出的那样,添加用于就绪探测的相同端口作为 pod 中的端口之一解决了您的问题,因为端口否则本身不会暴露在吊舱外。这导致 Kubernetes 改为依赖 /
的健康检查。
引用自here:
The GLBC requires that you define the port (in your case 3000) within the Pod specification.
除了添加自定义 readinessProbe
:
ports
中声明用于健康检查的端口
containers:
- name: grafana
readinessProbe:
httpGet:
path: /login
port: 3000
ports:
- name: grafana
containerPort: 3000
…
推断 Ingress 创建健康检查的条件是
an Ingress backend.servicePort references a Service port, matching a Pods spec.containers[].readinessProbe.httpGet.port and the Service's targetPort references the serving Pod's 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
这适用于 1.9。设置 httpHeaders
也消除了在 ALLOWED_HOSTS
设置中添加额外主机名的必要性。
readinessProbe:
httpGet:
path: /login
port: 3000 # Must be same as containerPort
httpHeaders:
- name: Host
value: yourdomain.com