Ingress configuration on Google Cloud


本页面概述了通过 Google Cloud 上的 Kubernetes Ingress 支持和可配置的内容。

特性比较

下表提供了 Google Cloud 上 Ingress 的受支持特性列表。同时指示推出特性的正式版 (GA) 或 Beta 版

Ingress 类 外部 Ingress 内部 Ingress 多集群 Ingress
Ingress 控制器 Google 托管的 Ingress 控制器 GKE Ingress 控制器。
Google Cloud 负载均衡器类型 外部 HTTP(S) 负载均衡器 内部 HTTP(S) 负载均衡器 外部 HTTP(S) 负载均衡器
集群范围 单集群 单集群 多集群
负载均衡器范围 全球 区域 Global
环境支持 GKE GKE GKE
共享 VPC 支持 GA GA GA
服务注释
容器原生负载均衡 (NEG) GA GA GA
从负载均衡器到后端的 HTTPS GA GA GA
HTTP/2 GA GA
仅限 TLS
GA
Ingress 注释
静态 IP 地址 GA GA GA
基于 Kubernetes Secrets 的证书 GA GA GA
自行管理的 SSL 证书 GA GA GA
Google 代管式 SSL 证书 GA GA
FrontendConfig
SSL 政策 GA GA
从 HTTP 到 HTTPS 的重定向 GA
1.17.13-gke.2600+GA
GA
BackendConfig
后端服务超时 GA GA GA
Cloud CDN GA GA
连接排空超时 GA GA GA
自定义负载均衡器健康检查配置 GA GA GA
Google Cloud Armor 安全政策 GA
1.19.10-gke.700G
GA
HTTP 访问日志记录配置 GA GA GA
Identity-Aware Proxy (IAP) GA GA GA
会话亲和性 GA GA GA
用户定义的请求标头 GA GA
自定义响应标头 GA GA

B从指定版本开始,此特性在 Beta 版中可用。所有可用的 GKE 和 GKE Enterprise 版本均支持未列出版本的特性。

G从指定版本开始支持将此特性用作 GA。

使用默认控制器配置 Ingress

您无法使用 Google Cloud SDK 或 Google Cloud 控制台手动配置 LoadBalancer 功能。您必须使用 BackendConfig 或 FrontendConfig Kubernetes 资源。

使用默认控制器创建 Ingress 时,您可以通过使用 Ingress 对象上的注解来选择负载均衡器的类型(外部应用负载均衡器或内部应用负载均衡器)。您可以选择是 GKE 创建区域 NEG 还是它通过对每个 Service 对象使用注释来使用实例组。

FrontendConfig 和 BackendConfig 自定义资源定义 (CRD) 允许您进一步自定义负载均衡器。这些 CRD 允许您以分层方式定义其他负载均衡器特性,分层方式比注释更具结构化。如需使用 Ingress(以及这些 CRD),您必须启用 HTTP 负载均衡插件。GKE 集群默认启用了 HTTP 负载均衡;您不得将其停用。

FrontendConfig 在 Ingress 对象中引用,并且只能与外部 Ingress 搭配使用。BackendConfig 由 Service 对象引用。多个 Service 或 Ingress 对象可以引用相同的 CRD,以实现配置一致性。FrontendConfig 和 BackendConfig CRD 与其对应的 Ingress 和 Service 资源具有相同的生命周期,并且通常一起部署。

下图说明了具体方法:

  • 对 Ingress 或 MultiClusterIngress 对象的注释引用了 FrontendConfig CRD。FrontendConfig CRD 引用了 Google Cloud SSL 政策。

  • 对 Service 或 MultiClusterService 对象的注释引用了 BackendConfig CRD。BackendConfig CRD 为相应后端服务的健康检查指定自定义设置。

BackendConfig 和 FrontendConfig 概览
:BackendConfig 和 FrontendConfig 概览

将 FrontendConfig 与 Ingress 关联

FrontendConfig 只能与外部 Ingress 搭配使用。

您可以将一个 FrontendConfig 与一个 Ingress 或 MultiClusterIngress 关联。

Ingress

使用 networking.gke.io/v1beta1.FrontendConfig 注解:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    networking.gke.io/v1beta1.FrontendConfig: "FRONTENDCONFIG_NAME"
...

FRONTENDCONFIG_NAME 替换为您的 FrontendConfig 名称。

MultiClusterIngress

使用 networking.gke.io/frontend-config 注解:

apiVersion: networking.gke.io/v1
kind: MultiClusterIngress
metadata:
  annotations:
    networking.gke.io/frontend-config: "FRONTENDCONFIG_NAME"
...

FRONTENDCONFIG_NAME 替换为您的 FrontendConfig 名称。

将 BackendConfig 与 Ingress 关联

您可以使用 cloud.google.com/backend-configbeta.cloud.google.com/backend-config 注释来指定 BackendConfig 的名称。

所有 Service 端口使用相同的 BackendConfig

如需对所有端口使用相同的 BackendConfig,请在注释中使用 default 键。每次创建负载均衡器后端服务以引用 Service 的其中一个端口时,Ingress 控制器都会使用相同的 BackendConfig。

您可以将 default 键用于 Ingress 和 MultiClusterIngress 资源。
apiVersion: v1
kind: Service
metadata:
  annotations:
    cloud.google.com/backend-config: '{"default": "my-backendconfig"}'
...

每个 Service 端口拥有唯一的 BackendConfig

对于 Ingress 和 MultiClusterIngress,您可以使用与端口名称或编号匹配的密钥,为一个或多个端口指定自定义 BackendConfig。Ingress 控制器在为引用的 Service 端口创建负载均衡器后端服务时会使用这些特定的 BackendConfig。
apiVersion: v1
kind: Service
metadata:
  annotations:
    cloud.google.com/backend-config: '{"ports": {
    "SERVICE_REFERENCE_A":"BACKENDCONFIG_REFERENCE_A",
    "SERVICE_REFERENCE_B":"BACKENDCONFIG_REFERENCE_B"
    }}'
spec:
  ports:
  - name: PORT_NAME_1
    port: PORT_NUMBER_1
    protocol: TCP
    targetPort: 50000
  - name: PORT_NAME_2
    port: PORT_NUMBER_2
    protocol: TCP
    targetPort: 8080
...

替换以下内容:

  • BACKENDCONFIG_REFERENCE_A:现有 BackendConfig 的名称。
  • BACKENDCONFIG_REFERENCE_B:现有 BackendConfig 的名称。
  • SERVICE_REFERENCE_A:使用 PORT_NUMBER_1PORT_NAME_1 的值。这是因为 Service 的 BackendConfig 注释可以引用端口的名称 (spec.ports[].name) 或端口的编号 (spec.ports[].port)。
  • SERVICE_REFERENCE_B:使用 PORT_NUMBER_2PORT_NAME_2 的值。这是因为 Service 的 BackendConfig 注释可以引用端口的名称 (spec.ports[].name) 或端口的编号 (spec.ports[].port)。

按端口号引用 Service 的端口时,必须使用 port 值,而不是 targetPort 值。此处使用的端口号仅用于绑定 BackendConfig;它不控制负载均衡器向哪个端口发送流量或健康检查探测:

  • 使用容器原生负载均衡时,负载均衡器会将流量发送到引用的 Service 端口 targetPort(必须与服务 Pod 的 containerPort 匹配)上的网络端点组中的某个端点(与 Pod 的 IP 地址匹配)。否则,负载均衡器会将流量发送到引用的 Service 端口 nodePort 上的节点 IP 地址。

  • 使用 BackendConfig 提供自定义负载均衡器健康检查时,用于负载均衡器健康检查的端口号可以与 Service 的 spec.ports[].port 端口号不同。如需详细了解健康检查的端口号,请参阅自定义健康检查配置

通过 FrontendConfig 参数配置 Ingress 特性

以下部分介绍如何设置 FrontendConfig 以启用特定 Ingress 特性。

SSL 政策

SSL 政策允许您指定一组 TLS 版本和密码,负载均衡器使用这些版本和密码终止来自客户端的 HTTPS 流量。必须先在 GKE 外部创建 SSL 政策。创建后,可以在 FrontendConfig CRD 中引用它。

FrontendConfig 中的 sslPolicy 字段引用与 GKE 集群相同的 Google Cloud 项目中的 SSL 政策名称。它将 SSL 政策附加到目标 HTTPS 代理,后者是 Ingress 为外部 HTTP(S) 负载均衡器创建的。多个 Ingress 资源可以引用同一个 FrontendConfig 资源和 SSL 政策。如果引用的 SSL 政策发生更改,则更改会传播到为 Ingress 创建的外部 HTTP(S)负载均衡器提供支持的 Google Front End (GFE)。

以下 FrontendConfig 清单启用名为 gke-ingress-ssl-policy 的 SSL 政策:

apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
  name: my-frontend-config
spec:
  sslPolicy: gke-ingress-ssl-policy

从 HTTP 到 HTTPS 的重定向

外部 HTTP 负载均衡器可以将未加密的 HTTP 请求重定向到使用同一 IP 地址的 HTTPS 负载均衡器。当您在创建启用了从 HTTP 到 HTTPS 的重定向的 Ingress 时,系统会自动创建这两个负载均衡器。对端口 80 上 Ingress 的外部 IP 地址的请求会自动重定向到端口 443 上的同一外部 IP 地址。此功能构建于 Cloud Load Balancing 提供的从 HTTP 到 HTTPS 的重定向之上。

如需支持 HTTP 到 HTTPS 重定向,必须配置 Ingress 以同时提供 HTTP 和 HTTPS 流量。如果停用 HTTP 或 HTTPS,则重定向将不起作用。

HTTP 到 HTTPS 重定向使用 FrontendConfig 自定义资源中的 redirectToHttps 字段进行配置。系统会对整个 Ingress 资源启用重定向功能,以便 Ingress 引用的所有服务都将启用 HTTPS 重定向功能。

以下 FrontendConfig 清单允许从 HTTP 到 HTTPS 的重定向。将 spec.redirectToHttps.enabled 字段设置为 true 以启用 HTTPS 重定向功能。spec.responseCodeName 字段为可选字段。如果省略此项,则系统会使用 301 Moved Permanently 重定向。

apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
  name: my-frontend-config
spec:
  redirectToHttps:
    enabled: true
    responseCodeName: RESPONSE_CODE

RESPONSE_CODE 替换为以下项之一:

  • MOVED_PERMANENTLY_DEFAULT,用于返回 301 重定向响应代码(如果未指定 responseCodeName,则默认为此项)。
  • FOUND,用于返回 302 重定向响应代码。
  • SEE_OTHER,用于返回 303 重定向响应代码。
  • TEMPORARY_REDIRECT,用于返回 307 重定向响应代码。
  • PERMANENT_REDIRECT,用于返回 308 重定向响应代码。

启用重定向后,Ingress 控制器会创建负载均衡器,如下图所示:

仅限重定向的外部 HTTP 负载均衡器,其中包含转发规则、目标 HTTP 代理,以及使用后端服务重定向到完整 HTTPS 负载均衡器的网址映射

如需验证重定向是否正常工作,请使用 curl 命令:

curl http://IP_ADDRESS

IP_ADDRESS 替换为 Ingress 的 IP 地址。

该响应会显示您配置的重定向响应代码。例如,以下示例展示了配置了 301: MovedPermanently 重定向的 FrontendConfig

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://35.244.160.59/">here</A>.</BODY></HTML>

通过 BackendConfig 参数配置 Ingress 特性

以下部分演示如何设置 BackendConfig 以启用特定 Ingress 特性。系统会不断协调对 BackendConfig 资源的更改,因此您无需删除并重新创建 Ingress 就可以看到 BackendConfig 的更改反映出来。

如需了解 BackendConfig 限制,请参阅限制部分。

后端服务超时

您可以使用 BackendConfig 来设置后端服务超时时间段(以秒为单位)。如果未指定值,则默认值为 30 秒。

以下 BackendConfig 清单指定 40 秒的超时:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backendconfig
spec:
  timeoutSec: 40

Cloud CDN

您可以使用 BackendConfig 来启用Cloud CDN

以下 BackendConfig 清单显示了启用 Cloud CDN 时可用的所有字段:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backendconfig
spec:
  cdn:
    enabled: CDN_ENABLED
    cachePolicy:
      includeHost: INCLUDE_HOST
      includeProtocol: INCLUDE_PROTOCOL
      includeQueryString: INCLUDE_QUERY_STRING
      queryStringBlacklist: QUERY_STRING_DENYLIST
      queryStringWhitelist: QUERY_STRING_ALLOWLIST
    cacheMode: CACHE_MODE
    clientTtl: CLIENT_TTL
    defaultTtl: DEFAULT_TTL
    maxTtl: MAX_TTL
    negativeCaching: NEGATIVE_CACHING
    negativeCachingPolicy:
      code: NEGATIVE_CACHING_CODE
      ttl: NEGATIVE_CACHING_TTL
    requestCoalescing: REQ_COALESCING
    serveWhileStale: SERVE_WHILE_STALE
    signedUrlCacheMaxAgeSec: SIGNED_MAX_AGE
    signedUrlKeys:
      keyName: KEY_NAME
      keyValue: KEY_VALUE
      secretName: SECRET_NAME

替换以下内容:

  • CDN_ENABLED:如果设置为 true,则会为此 Ingress 后端启用 Cloud CDN。
  • INCLUDE_HOST:如果设置为 true,则会分别缓存对不同主机的请求。
  • INCLUDE_PROTOCOL:如果设置为 true,则会分别缓存 HTTP 和 HTTPS 请求。
  • INCLUDE_QUERY_STRING:如果设置为 true,则会根据 queryStringBlacklistqueryStringWhitelist 将查询字符串参数包含在缓存键中。如果两者都未设置,则包括整个查询字符串。如果设置为 false,则会从缓存键中排除整个缓存字符串。
  • QUERY_STRING_DENYLIST:指定含有要从缓存键中排除的查询字符串参数名称的字符串数组。包括所有其他参数。您可以指定 queryStringBlacklistqueryStringWhitelist,但不能同时指定这两者。
  • QUERY_STRING_ALLOWLIST:指定含有要包含在缓存键中的查询字符串参数名称的字符串数组。排除所有其他参数。您可以指定 queryStringBlacklistqueryStringWhitelist,但不能同时指定这两者。

只有使用 GKE Ingress 的 GKE 版本 1.23.3-gke.900 及更高版本支持以下字段。使用多集群 Ingress 的版本支持它们:

  • CACHE_MODE缓存模式
  • CLIENT_TTLDEFAULT_TTLMAX_TTL:TTL 配置。如需了解详情,请参阅使用 TTL 设置和替换
  • NEGATIVE_CACHING:如果设置为 true,则会启用负缓存。如需了解详情,请参阅使用负缓存
  • NEGATIVE_CACHING_CODENEGATIVE_CACHING_TTL:负缓存配置。如需了解详情,请参阅使用负缓存
  • REQ_COALESCING:如果设置为 true,则启用折叠功能。如需了解详情,请参阅请求折叠(合并)
  • SERVE_WHILE_STALE:响应过期后 Cloud CDN 继续提供过时版本的时间(以秒为单位)。如需了解详情,请参阅提供过时内容
  • SIGNED_MAX_AGE:可以缓存响应的最长时间(以秒为单位)。如需了解详情,请参阅选择性地自定义最长缓存时间
  • KEY_NAMEKEY_VALUESECRET_NAME:签名网址密钥配置。如需了解详情,请参阅创建签名请求密钥

展开以下部分即可看到通过 Ingress 部署 Cloud CDN,然后验证应用内容是否缓存的示例。

连接排空超时

您可以使用 BackendConfig 来配置连接排空超时。连接排空超时是指等待连接排空的时间(以秒为单位)。在指定的超时持续时间内,系统会为对已移除后端发出的现有请求留出一定的时间,让这些请求可以完成。负载均衡器不会向已移除的后端发送新请求。达到超时持续时间之后,系统会关闭与该后端的所有剩余连接。超时持续时间可以介于 0 到 3600 秒之间。默认值为 0,此值也会停用连接排空。

以下 BackendConfig 清单指定 60 秒的连接排空超时:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backendconfig
spec:
  connectionDraining:
    drainingTimeoutSec: 60

自定义健康检查配置

通过 Ingress 进行部署时,GKE 有多种方法配置 Google Cloud 负载均衡器健康检查。如需详细了解 GKE Ingress 如何部署健康检查,请参阅 Ingress 健康检查

借助 BackendConfig,您可以精确控制负载均衡器的健康检查设置。

您可以配置多个 GKE 服务,以将同一个 BackendConfig 作为可重复使用的模板引用。对于 healthCheck 参数,系统会为与每个 GKE 服务对应的每个后端服务创建唯一的 Google Cloud 健康检查。

以下 BackendConfig 清单显示了配置 BackendConfig 健康检查时可用的所有字段:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backendconfig
spec:
  healthCheck:
    checkIntervalSec: INTERVAL
    timeoutSec: TIMEOUT
    healthyThreshold: HEALTH_THRESHOLD
    unhealthyThreshold: UNHEALTHY_THRESHOLD
    type: PROTOCOL
    requestPath: PATH
    port: PORT

请替换以下内容:

  • INTERVAL:为每个健康检查探测器指定 check-interval(以秒为单位)。这是指从探测器检查开始到下一次检查开始的时间。如果您省略此参数,则会使用 Google Cloud 默认值 5 秒。如需其他实现详情,请参阅多重探测和频率
  • TIMEOUT:指定 Google Cloud 等待探测响应的时间量。TIMEOUT 的值必须小于或等于 INTERVAL。该时间以秒为单位。每个探测都要求在探测超时之前传送 HTTP 200 (OK) 响应代码。
  • HEALTH_THRESHOLDUNHEALTHY_THRESHOLD:指定至少一个探测器必须进行的成功或失败顺序连接尝试次数,以便将运行状况从运行状况良好更改为运行状况不佳,反之亦然。如果您省略其中一个参数,Google Cloud 会使用默认值 2。
  • PROTOCOL:指定探测系统用于健康检查的协议BackendConfig 仅支持使用 HTTP、HTTPS 或 HTTP2 协议来创建健康检查。如需了解详情,请参阅 HTTP、HTTPS、HTTP/2 成功标准。您不能省略此参数。
  • PATH:对于 HTTP、HTTPS 或 HTTP2 健康检查,指定探测系统应连接到的 request-path。如果您省略此参数,Google Cloud 将使用默认值 /
  • PORT:BackendConfig 仅支持使用端口号指定负载均衡器的健康检查端口。如果您省略此参数,Google Cloud 将使用默认值 80

    • 使用容器原生负载均衡时,您应选择与服务 Pod 的 containerPort 匹配的端口(无论 containerPort 是否被 Service 的 targetPort 引用)。由于负载均衡器将探测直接发送到 Pod 的 IP 地址,因此您并非只能使用 Service 的 targetPort 引用的 containerPort。健康检查探测系统会连接到指定端口上服务 Pod 的 IP 地址。

    • 对于实例组后端,您必须选择与 Service 公开的 nodePort 匹配的端口。之后,健康检查探测系统便会连接到该端口上的每个节点。

如需使用自定义 HTTP 健康检查设置 GKE Ingress,请参阅具有自定义 HTTP 健康检查功能的 GKE Ingress

Google Cloud Armor Ingress 安全政策

Google Cloud Armor 安全政策有助于保护您的负载均衡应用免遭 Web 攻击。配置 Google Cloud Armor 安全政策后,您可以使用 BackendConfig 来引用该政策。

将安全政策的名称添加到 BackendConfig。以下 BackendConfig 清单指定了名为 example-security-policy 的安全政策:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  namespace: cloud-armor-how-to
  name: my-backendconfig
spec:
  securityPolicy:
    name: "example-security-policy"

下表显示了 GKE Ingress 控制器对 BackendConfig 中的 securityPolicy 字段的响应行为。

BackendConfig 字段 行为
spec.securityPolicy.name CloudArmorPolicyName GKE Ingress 控制器将名为 CloudArmorPolicyName 的 Google Cloud Armor 政策设置为负载均衡器。
spec.securityPolicy.name 空字符串 ("") GKE Ingress 控制器会从负载均衡器中移除任何已配置的 Google Cloud Armor 政策。

如需使用 Google Cloud Armor 保护设置 GKE Ingress,请参阅启用 Google Cloud Armor 的 Ingress

HTTP 访问日志记录

Ingress 可以将来自客户端的所有 HTTP 请求记录到 Cloud Logging 中。您可以通过使用 BackendConfig 以及设置访问日志记录采样率来启用和停用访问日志记录

要配置访问日志记录,请使用 BackendConfig 中的 logging 字段。如果省略 logging,则访问日志记录将采用默认行为。这取决于 GKE 版本。

您可以配置以下字段:

  • enable:如果设置为 true,系统将为此 Ingress 启用访问日志记录功能,并且日志可在 Cloud Logging 中获得。否则,系统会为此 Ingress 停用访问日志记录。
  • sampleRate:指定一个介于 0.0 到 1.0 之间的值,其中 0.0 表示不记录数据包,1.0 表示记录所有数据包。只有当 enable 设置为 true 时,此字段才相关。sampleRate 是可选字段,但如果已配置,则必须设置 enable: true,否则将被解读为 enable: false

以下 BackendConfig 清单启用访问日志记录,并将采样率设置为指定 Ingress 资源 HTTP 请求的 50%。

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backendconfig
spec:
  logging:
    enable: true
    sampleRate: 0.5

Identity-Aware Proxy

要为 Identity-Aware Proxy IAP 配置 BackendConfig,您需要将 enabledsecretName 值指定为 BackendConfig 中的 iap 块。要指定这些值,请确保您拥有 compute.backendServices.update 权限

以下 BackendConfig 清单启用 Identity-Aware Proxy:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name:  my-backendconfig
spec:
  iap:
    enabled: true
    oauthclientCredentials:
      secretName: my-secret

如需查看完整说明,请参阅 IAP 文档中的为 GKE 启用 IAP

具有内部 Ingress 的 Identity-Aware Proxy

如需为 IAP 配置内部 Ingress,您必须使用高级层级。如果您不使用高级层级,则无法使用 Identity-Aware Proxy 查看或创建内部应用负载均衡器。您还必须拥有 BeyondCorp Enterprise 订阅,才能将内部 Ingress 用于 IAP。

如需使用基于 Identity-Aware Proxy 的身份验证设置安全的 GKE Ingress,请参阅示例:启用 IAP 的 Ingress

会话亲和性

您可以使用 BackendConfig 将会话亲和性设置为客户端 IP 或生成的 Cookie。

客户端 IP 亲和性

要使用 BackendConfig 设置客户端 IP 亲和性,请将 affinityType 设置为 "CLIENT_IP",如以下示例所示:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backendconfig
spec:
  sessionAffinity:
    affinityType: "CLIENT_IP"

要使用 BackendConfig 设置生成的 Cookie 亲和性,请在 BackendConfig 清单中将 affinityType 设置为GENERATED_COOKIE。您还可以使用 affinityCookieTtlSec 来设置 Cookie 保持活动的时间段。

以下清单将亲和性类型设置为生成的 Cookie 并为 Cookie 设置 50 秒的 TTL:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backendconfig
spec:
  sessionAffinity:
    affinityType: "GENERATED_COOKIE"
    affinityCookieTtlSec: 50

用户定义的请求标头

您可以使用 BackendConfig 来配置用户定义的请求标头。负载均衡器会将您指定的标头添加至它转发到后端的请求。

要启用用户定义的请求标头,您需要在 BackendConfig 资源的 customRequestHeaders 属性中指定标头列表。您可以将每个标头指定为 header-name:header-value 字符串。

以下 BackendConfig 清单添加了三个请求标头:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backendconfig
spec:
  customRequestHeaders:
    headers:
    - "X-Client-Region:{client_region}"
    - "X-Client-City:{client_city}"
    - "X-Client-CityLatLong:{client_city_lat_long}"

自定义响应标头

要启用自定义响应标头,您需要在 BackendConfig 资源的 customResponseHeaders 属性中指定标头列表。您可以将每个标头指定为 header-name:header-value 字符串。

以下 BackendConfig 清单是一个添加 HSTS(严格传输安全协议)响应标头的示例:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backendconfig
spec:
  customResponseHeaders:
    headers:
    - "hsts:True"
    - "hsts-include-subdomains: True"
    - "hsts-max-age: 28800"

练习:使用后端服务设置 Ingress 超时

以下练习展示了使用具有 BackendConfig 资源的 Ingress 配置超时和连接排空所需的步骤。

要配置 Ingress 的后端属性,请完成以下任务:

  1. 创建一个 Deployment
  2. 创建 BackendConfig
  3. 创建一个 Service,并将它的一个端口与 BackendConfig 关联
  4. 创建一个 Ingress,并将该 Ingress 与(Service, 端口)对关联
  5. 验证后端服务的属性
  6. 清理.

创建 Deployment

在创建 BackendConfig 和 Service 之前,您需要创建一个 Deployment

以下示例清单适用于名为 my-deployment.yaml 的 Deployment:

# my-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  selector:
    matchLabels:
      purpose: bsc-config-demo
  replicas: 2
  template:
    metadata:
      labels:
        purpose: bsc-config-demo
    spec:
      containers:
      - name: hello-app-container
        image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0

通过运行以下命令以创建 Deployment:

kubectl apply -f my-deployment.yaml

创建 BackendConfig

使用 BackendConfig 指定要使用的 Ingress 特性。

这个名为 my-backendconfig.yaml 的 BackendConfig 清单指定了以下内容:

  • 超时时间为 40 秒。
  • 连接排空超时为 60 秒。
# my-backendconfig.yaml
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backendconfig
spec:
  timeoutSec: 40
  connectionDraining:
    drainingTimeoutSec: 60

运行以下命令以创建 BackendConfig:

kubectl apply -f my-backendconfig.yaml

创建 Service

即使 Service 具有多个端口,BackendConfig 也会与单个 Service-Port 组合相对应。每个端口都可以与单个 BackendConfig CRD 相关联。如果 Ingress 引用了某一 Service 端口,并且该 Service 端口与 BackendConfig 相关联,则 HTTP(S) 负载均衡后端服务会从 BackendConfig 中获取其部分配置。

以下是一个名为 my-service.yaml 的 Service 清单文件示例:

# my-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
  labels:
    purpose: bsc-config-demo
  annotations:
    cloud.google.com/backend-config: '{"ports": {"80":"my-backendconfig"}}'
    cloud.google.com/neg: '{"ingress": true}'
spec:
  type: ClusterIP
  selector:
    purpose: bsc-config-demo
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080

cloud.google.com/backend-config 注释指定端口与 BackendConfig 对象之间的映射。在 my-service.yaml 中:

  • 具有 purpose: bsc-config-demo 标签的任何 Pod 都是 Service 的成员。
  • Service 的 TCP 端口 80 与名为 my-backendconfig 的 BackendConfig 相关联。这是由 cloud.google.com/backend-config 注释指定的。
  • 发送到 Service 端口 80 的请求被转发到端口 8080 上的一个成员 Pod。

要创建 Service,请运行以下命令:

kubectl apply -f my-service.yaml

创建 Ingress

以下是一个名为 my-ingress.yaml. 的 Ingress 清单。在此示例中,传入请求路由到名为 my-service 的 Service 的端口 80。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        pathType: ImplementationSpecific
        backend:
          service:
            name: my-service
            port:
              number: 80

要创建 Ingress,请运行以下命令:

kubectl apply -f my-ingress.yaml

等待几分钟,以便 Ingress 控制器配置外部应用负载均衡器以及关联的后端服务。此操作完成后,将 Ingress 配置为使用 40 秒超时,并将连接排空超时设置为 60 秒。

验证后端服务属性

您可以通过 BackendConfig 验证是否已应用正确的负载均衡器设置。为此,请确定 Ingress 已部署的后端服务并检查其设置,以验证它们是否与 Deployment 清单匹配。

首先,描述列出与 Ingress 关联的后端服务的 my-ingress 资源和过滤条件。例如:

kubectl describe ingress my-ingress | grep ingress.kubernetes.io/backends

您将看到如下所示的输出:

ingress.kubernetes.io/backends: '{"k8s1-27fde173-default-my-service-80-8d4ca500":"HEALTHY","k8s1-27fde173-kube-system-default-http-backend-80-18dfe76c":"HEALTHY"}

输出会提供后端服务的相关信息。例如,此注释包含两个后端服务:

  • "k8s1-27fde173-default-my-service-80-8d4ca500":"HEALTHY" 针对与 my-service Kubernetes Service 关联的后端服务提供相关信息。
    • k8s1-27fde173 是用于描述集群的哈希值。
    • default 是 Kubernetes 命名空间。
    • HEALTHY 表示后端运行状况良好。
  • "k8s1-27fde173-kube-system-default-http-backend-80-18dfe76c":"HEALTHY" 针对与默认后端(404 服务器)关联的后端服务提供相关信息。
    • k8s1-27fde173 是用于描述集群的哈希值。
    • kube-system 是命名空间。
    • default-http-backend 是 Kubernetes Service 名称。
    • 80 是主机端口。
    • HEALTHY 表示后端运行状况良好。

接下来,使用 gcloud 检查与 my-service 关联的后端服务。过滤 "drainingTimeoutSec""timeoutSec",以确认是否已在 Google Cloud 负载均衡器控制层面中设置它们。例如:

# Optionally, set a variable
export BES=k8s1-27fde173-default-my-service-80-8d4ca500

# Filter for drainingTimeoutSec and timeoutSec
gcloud compute backend-services describe ${BES} --global | grep -e "drainingTimeoutSec" -e "timeoutSec"

输出:

  drainingTimeoutSec: 60
  timeoutSec: 40

如果在输出中看到 drainingTimeoutSectimeoutSec,则确认它们的值已通过 BackendConfig 正确设置。

清理

为了防止您的账号产生不必要的费用,请删除您为此练习创建的 Kubernetes 对象:

kubectl delete ingress my-ingress
kubectl delete service my-service
kubectl delete backendconfig my-backendconfig
kubectl delete deployment my-deployment

BackendConfig 限制

BackendConfig 存在以下限制:

  • 一个(Service,端口)对只能使用一个 BackendConfig,即使多个 Ingress 对象都引用该(Service,端口)对也是如此。这意味着,引用相同(Service,端口)对的所有 Ingress 对象都必须对 Cloud Armor、IAP 和 Cloud CDN 使用相同的配置。
  • 无法为同一 HTTP(S) 负载均衡后端服务启用 IAP 和 Cloud CDN。这意味着您不能在同一 BackendConfig 中同时配置 IAP 和 Cloud CDN。
  • 您必须使用 kubectl 1.7 或更高版本与 BackendConfig 进行交互。

移除在 FrontendConfig 或 BackendConfig 中指定的配置

要撤消某个 Ingress 特性,必须在 FrontendConfig 或 BackendConfig CRD 中明确停用特性配置。Ingress 控制器仅与这些 CRD 中指定的配置协调。

要清除或停用先前启用的配置,请将字段的值设置为空字符串 ("") 或布尔值 false,具体取决于字段类型。

以下 BackendConfig 清单会停用 Google Cloud Armor 安全政策和 Cloud CDN:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: my-backendconfig
spec:
  cdn:
    enabled: false
  securityPolicy:
    name: ""

删除 FrontendConfig 或 BackendConfig

FrontendConfig

如需删除 FrontendConfig,请按照下列步骤进行操作:

  1. 从 Ingress 清单中的 networking.gke.io/v1beta1.FrontendConfig 注释中移除 FrontendConfig 的名称。

  2. 将更改后的 Ingress 清单应用到集群。例如,使用 kubectl apply

  3. 删除 FrontendConfig。例如,使用 kubectl delete frontendconfig config my-frontendconfig

BackendConfig

如需删除 BackedConfig,请按照下列步骤进行操作:

  1. 从 Service 清单中的 cloud.google.com/backend-config 注释中移除 BackendConfig 的名称。

  2. 将更改后的 Service 清单应用到集群。例如,使用 kubectl apply

  3. 删除 BackendConfig。例如,使用 kubectl delete backendconfig my-backendconfig

问题排查

您可以使用 Ingress 诊断工具检测常见错误配置。 您还应确保所有健康检查都配置正确。

找不到 BackendConfig

如果在 Service 注解中指定了 Service 端口的 BackendConfig,但找不到实际 BackendConfig 资源,那么就会发生这种错误。

要评估 Kubernetes 事件,请运行以下命令:

kubectl get event

以下示例输出表明找不到 BackendConfig:

KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: error getting BackendConfig for port 80 on service "default/my-service":
no BackendConfig for service port exists

如需解决此问题,请确保您没有在错误的命名空间中创建 BackendConfig 资源,或在 Service 注释中拼错了其引用名称。

找不到 Ingress 安全政策

Ingress 对象创建完毕后,如果安全政策未与 LoadBalancer Service 正确关联,请评估 Kubernetes 事件以了解是否存在配置错误。如果您的 BackendConfig 指定了不存在的安全政策,则系统会定期发出警告事件。

要评估 Kubernetes 事件,请运行以下命令:

kubectl get event

以下示例输出表示找不到安全政策:

KIND    ... SOURCE
Ingress ... loadbalancer-controller

MESSAGE
Error during sync: The given security policy "my-policy" does not exist.

如需解决此问题,请在 BackendConfig 中指定正确的安全政策名称。

解决在 GKE 中扩缩工作负载时出现的 NEG 500 系列错误

具体情况:

使用 GKE 预配的 NEG 进行负载均衡时,在工作负载缩容时,服务可能会遇到 502 或 503 错误。如果 Pod 在现有连接关闭之前终止,会发生 502 错误;如果流量被定向到已删除的 Pod,会发生 503 错误。

如果您使用的是使用 NEG 的 GKE 托管负载均衡产品(包括网关、Ingress 和独立 NEG),此问题可能会影响集群。如果您频繁扩缩工作负载,则集群受影响的风险很高。

诊断:

在 Kubernetes 中移除 Pod 而不排空其端点并先从 NEG 中移除 Pod 会导致 500 系列错误。为避免 Pod 终止期间出现问题,您必须考虑操作顺序。下图显示了未设置 BackendService Drain Timeout 且使用 BackendConfig 设置了 BackendService Drain Timeout 的场景。

场景 1:未设置 BackendService Drain Timeout

下图显示了未设置 BackendService Drain Timeout 的场景。

未设置 BackendService Drain Timeout

场景 2:设置了 BackendService Drain Timeout

下图显示设置了 BackendService Drain Timeout 的场景。

设置了 BackendService Drain Timeout

500 系列错误发生的确切时间取决于以下因素:

  • NEG API 分离延迟:NEG API 分离延迟表示分离操作在 Google Cloud 中最终完成所花费的当前时间。此问题受 Kubernetes 之外的各种因素的影响,包括负载均衡器的类型和特定可用区。

  • 排空延迟:排空延迟时间表示负载均衡器开始引导流量离开系统的特定部分所需的时间。排空启动后,负载均衡器会停止向端点发送新请求,但触发排空仍有延迟(排空延迟),如果 Pod 不再存在,这可能会导致暂时的 503 错误。

  • 健康检查配置:更敏感的健康检查阈值可以缩短 503 错误的持续时间,因为它可以指示负载均衡器停止向端点发送请求,即使分离操作尚未完成也是如此。

  • 终止宽限期:终止宽限期决定了 Pod 获得的最大退出时长。但是,Pod 可以在终止宽限期结束之前退出。如果 Pod 超过此期限,则会在此期限结束时被强制退出。这是 Pod 上的设置,需要在工作负载定义中进行配置。

可能的解决方法

为防止出现这些 5XX 错误,请应用以下设置。超时值是建议的值,您可能需要针对特定应用进行调整。以下部分将引导您完成自定义过程。

下图显示了如何使用 preStopHook 使 Pod 保持活跃状态:

设置了 BackendService Drain Timeout

为避免 500 系列错误,请执行以下步骤:

  1. 将服务的 BackendService Drain Timeout 设置为 1 分钟。

  2. 延长 Pod 上的 terminationGracePeriod

    将 Pod 上的 terminationGracePeriodSeconds 设置为 3.5 分钟。当此设置与推荐的设置结合使用时,在 Pod 的端点从 NEG 中移除后,Pod 可以获得 30 到 45 秒的安全关停窗口。如果您需要更多时间来进行安全关停,则可以延长宽限期,或者按照自定义超时部分中的说明操作。

    以下 BackendConfig 清单指定 210 秒(3.5 分钟)的连接排空超时:

    apiVersion: v1
    kind: BackendConfig
    metadata:
      name: my-backendconfig
    spec:
      terminationGracePeriodSeconds: 210
      containers:
      - name: my-app
        image: my-app-image:latest
        ports:
        - containerPort: 80
    
  3. preStopHook 应用于所有容器。

    应用 preStopHook,确保当 Pod 的端点在负载均衡器中排空并且端点从 NEG 中移除时,Pod 的活跃时间延长 120 秒。

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      containers:
      - name: my-app
        # Container configuration details...
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "sleep 120s"]
    

自定义超时

为了确保 Pod 连续性和防止 500 系列错误,Pod 必须在端点从 NEG 中移除之前保持活跃状态。特别是,为了防止 502 和 503 错误,请考虑同时设置超时和 preStopHook

如需延长 Pod 在关停过程中的活跃时间,请向 Pod 添加 preStopHook。在 Pod 被指示退出之前运行 preStopHook,以使 preStopHook 能被用于保留 Pod,直到其相应的端点从 NEG 中移除。

如需延长 Pod 在关停过程中的活跃时间,请按如下所示在 Pod 配置中插入 preStopHook

spec:
  containers:
  - name: my-app
    ...
    lifecycle:
      preStopHook:
        exec:
          command: ["/bin/sh", "-c", "sleep <latency time>"]

您可以配置超时和相关设置,以管理工作负载缩容期间 Pod 的安全关停。您可以根据具体用例调整超时。我们建议您先设置较长的超时,并根据需要缩短时长。您可以通过以下方式配置与超时相关的参数和 preStopHook,以自定义超时:

后端服务排空超时

默认情况下,Backend Service Drain Timeout 参数未设置,因此没有任何影响。如果您设置并激活了 Backend Service Drain Timeout 参数,则负载均衡器会停止将新请求路由到端点并等待超时,然后终止现有连接。

如需设置 Backend Service Drain Timeout 参数,您可以将 BackendConfig 与 Ingress 搭配使用,将 GCPBackendPolicy 与 Gateway 搭配使用,或者在独立 NEG 的 BackendService 上手动设置。超时应为处理请求所需时长的 1.5 到 2 倍。如果请求正好在排空开始之前传入,这样可确保请求将在超时完成之前完成。将 Backend Service Drain Timeout 参数设置为大于 0 的值有助于减少 503 错误,因为不会向计划移除的端点发送新请求。为使此超时生效,您必须将它与 preStopHook 搭配使用,以确保 Pod 在排空期间保持活跃状态。如果不这样结合使用,未完成的现有请求将会收到 502 错误。

preStopHook 时间

preStopHook 必须充分延迟 Pod 关停,使排空延迟和后端服务排空超时完成,从而确保在 Pod 关停之前正确排空连接并从 NEG 中年移除端点。

为获得最佳结果,请确保您的 preStopHook 执行时间小于或等于 Backend Service Drain Timeout 和排空延迟的总和。

计算公式如下:

preStopHook >= Backend Service Drain Timeout + Drain Latency

我们建议将排空延迟设置为 1 分钟。如果 500 错误仍然存在,请估算总持续时长,并在延迟时间中加上该时间的两倍。这可确保 Pod 有足够的时间来安全排空,然后再从服务中移除。如果这个值对于您的特定用例而言太长,您可以进行调整。

或者,您也可以通过在 Cloud Audit Logs 中查看 Pod 的删除时间戳以及从 NEG 中移除端点的时间戳来估算时间。

“终止宽限期”参数

您配置的 terminationGracePeriod 参数值必须提供足够的时间使 preStopHook 完成并且 Pod 安全关停。

如果未明确设置,terminationGracePeriod 默认为 30 秒。您可以使用以下公式计算最佳 terminationGracePeriod

terminationGracePeriod >= preStopHook Time + Pod shutdown time

按如下所示在 Pod 的配置中定义 terminationGracePeriod

  spec:
    terminationGracePeriodSeconds: <terminationGracePeriod>
    containers:
    - name: my-app
      ...
    ...

创建内部 Ingress 资源时找不到 NEG

当您在 GKE 中创建内部 Ingress 时,可能会发生以下错误:

Error syncing: error running backend syncing routine: googleapi: Error 404: The resource 'projects/PROJECT_ID/zones/ZONE/networkEndpointGroups/NEG' was not found, notFound

发生此错误的原因是内部应用负载均衡器的 Ingress 需要网络端点组 (NEG) 作为后端。

在共享 VPC 环境或启用了网络政策的集群中,向 Service 清单添加注解 cloud.google.com/neg: '{"ingress": true}'

504 网关超时:上游请求超时

从 GKE 中的内部 Ingress 访问 Service 时,可能会发生以下错误:

HTTP/1.1 504 Gateway Timeout
content-length: 24
content-type: text/plain

upsteam request timeout

发生此错误的原因是发送到内部应用负载均衡器的流量通过代理专用子网范围内的 envoy 代理来代理。

如需允许来自代理专用子网范围的流量,请在 Service 的 targetPort创建防火墙规则

错误 400:字段“resource.target”的值无效

从 GKE 中的内部 Ingress 访问 Service 时,可能会发生以下错误:

Error syncing:LB_NAME does not exist: googleapi: Error 400: Invalid value for field 'resource.target': 'https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION_NAME/targetHttpProxies/LB_NAME. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.

如需解决此问题,请创建代理专用子网

同步时出错:运行负载均衡器同步例程时出错:负载均衡器不存在

在 GKE 控制层面升级或修改 Ingress 对象时,可能会发生以下错误之一:

"Error during sync: error running load balancer syncing routine: loadbalancer
INGRESS_NAME does not exist: invalid ingress frontend configuration, please
check your usage of the 'kubernetes.io/ingress.allow-http' annotation."

或:

Error during sync: error running load balancer syncing routine: loadbalancer LOAD_BALANCER_NAME does not exist:
googleapi: Error 400: Invalid value for field 'resource.IPAddress':'INGRESS_VIP'. Specified IP address is in-use and would result in a conflict., invalid

如需解决这些问题,请尝试以下步骤:

  • 在 Ingress 清单的 tls 部分中添加 hosts 字段,然后删除 Ingress。等待 5 分钟,让 GKE 删除未使用的 Ingress 资源。然后,重新创建 Ingress。如需了解详情,请参阅 Ingress 对象的主机字段
  • 还原您对 Ingress 所做的更改。然后,使用注解或 Kubernetes Secret 添加证书。

已知问题

无法通过 V1 Ingress 命名方案启用 HTTPS 重定向

您无法在 GKE 1.16.8-gke.12 及更低版本上创建的 GKE Ingress 资源上启用 HTTPS 重定向。您必须先重新创建 Ingress,然后才能启用 HTTPS 重定向;或者系统会创建一个错误事件,并且 Ingress 不会同步。

错误事件消息类似于以下内容:

Error syncing: error running load balancer syncing routine: loadbalancer lb-name does not exist: ensureRedirectUrlMap() = error: cannot enable HTTPS Redirects with the V1 Ingress naming scheme. Please recreate your ingress to use the newest naming scheme.

从 BackendConfig 中移除 Google Cloud Armor 安全政策字段

存在一个已知问题,即使用 v1beta1 API 更新 BackendConfig 资源会从其 Service 中移除活跃的 Google Cloud Armor 安全政策。此问题会影响以下 GKE 版本:

  • 1.18.19-gke.1400 到 1.18.20-gke.5099
  • 1.19.10-gke.700 到 1.19.14-gke.299
  • 1.20.6-gke.700 到 1.20.9-gke.899

如果您未通过 BackendConfig 在 Ingress 资源上配置 Google Cloud Armor,则此问题不会影响您的集群。

对于通过 BackendConfig 配置 Google Cloud Armor 的 GKE 集群,强烈建议仅使用 v1 API 更新 BackendConfig 资源。将 BackendConfig 应用于使用 v1beta1 BackendConfig 资源的集群将会从其引用的 Service 中移除 Google Cloud Armor 安全政策。

为了缓解此问题,只能使用 v1 BackendConfig API 更新 BackendConfig。v1 BackendConfig 支持与 v1beta1 相同的所有字段,并且不做破坏性更改,因此可以透明地更新 API 字段。将所有活跃 BackendConfig 清单的 apiVersion 字段替换为 cloud.google.com/v1,不使用 cloud.google.com/v1beta1。以下示例清单描述了使用 v1 API 的 BackendConfig 资源:

  apiVersion: cloud.google.com/v1
  kind: BackendConfig
  metadata:
    name: my-backend-config
  spec:
    securityPolicy:
      name: "ca-how-to-security-policy"

如果您有定期更新 BackendConfig 资源的 CI : 持续集成/CD : 持续交付系统或工具,请确保您在这些系统中使用 cloud.google.com/v1 API 组。

如果您已使用 v1beta1 API 更新了 BackendConfig,则您的 Google Cloud Armor 安全政策可能已被移除。您可以通过运行以下命令来确定是否发生了这种情况:

kubectl get backendconfigs -A -o json | jq -r '.items[] | select(.spec.securityPolicy == {}) | .metadata | "\(.namespace)/\(.name)"'

如果响应返回输出,则您的集群会受到问题的影响。此命令的输出将返回受此问题影响的 BackendConfig 资源 (<namespace>/<name>) 列表。如果输出为空,则说明由于该问题的出现,BackendConfig 尚未使用 v1beta1 API 更新了。BackendConfig 的任何未来更新都应仅使用 v1

如果您的 Google Cloud Armor 安全政策已移除,您可以使用以下 Logging 查询来确定该政策何时被移除:

resource.type="gce_backend_service"
protoPayload.methodName="v1.compute.backendServices.setSecurityPolicy"
protoPayload.authenticationInfo.principalEmail:"container-engine-robot.iam.gserviceaccount.com"
protoPayload.response.status = "RUNNING"
NOT protoPayload.authorizationInfo.permission:"compute.securityPolicies.use"

如果您的任何集群受到影响,则可以通过推送对使用 v1 API 的 BackendConfig 资源的更新来解决此问题。

将 GKE 控制平面升级到以下更新版本之一,该版本可以修补此问题并允许安全使用 v1beta1 BackendConfig 资源:

  • 1.18.20-gke.5100 及更高版本
  • 1.19.14-gke.300 及更高版本
  • 1.20.9-gke.900 及更高版本

后续步骤