跨集群部署 Ingress


本页面介绍如何部署跨多个 GKE 集群提供应用的 Ingress。如需详细了解多集群 Ingress,请参阅多集群 Ingress

如需查看多集群 Ingress (MCI)、多集群网关 (MCG) 与使用独立网络端点组(LB 和独立 NEG)的负载均衡器之间的详细比较,请参阅选择适用于 GKE 的多集群负载均衡 API

部署教程

在以下任务中,您将在两个集群中部署一个名为 whereami 的虚构应用和一个 MultiClusterIngress。Ingress 为应用部署提供共享虚拟 IP (VIP) 地址。

本页面基于您在设置多集群 Ingress 中完成的工作(也就是创建并注册了两个集群)构建。确认您有两个集群也已注册到队列

gcloud container clusters list

输出内容类似如下:

NAME    LOCATION        MASTER_VERSION  MASTER_IP       MACHINE_TYPE   NODE_VERSION     NUM_NODES  STATUS
gke-eu  europe-west1-b  1.16.8-gke.9    ***             e2-medium      1.16.8-gke.9     2          RUNNING
gke-us  us-central1-b   1.16.8-gke.9    ***             e2-medium      1.16.6-gke.13 *  2          RUNNING

创建命名空间

由于队列具有命名空间相同性的属性,我们建议您跨集群协调命名空间的创建和管理,以便相同的命名空间由同一群组拥有和管理。您可以按团队、环境、应用或应用组件创建命名空间。只要一个集群中的命名空间 ns1 与另一个集群中的 ns1 具有相同的含义和使用情况,命名空间就可以根据需要进行细化。

在此示例中,您将为每个集群中的每个应用创建一个 whereami 命名空间。

  1. 创建一个名为 namespace.yaml 且包含以下内容的文件:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: whereami
    
  2. 切换到 gke-us 上下文:

    kubectl config use-context gke-us
    
  3. 创建命名空间:

    kubectl apply -f namespace.yaml
    
  4. 切换到 gke-eu 上下文:

    kubectl config use-context gke-eu
    
  5. 创建命名空间:

    kubectl apply -f namespace.yaml
    

    输出内容类似如下:

    namespace/whereami created
    

部署应用

  1. 创建一个名为 deploy.yaml 且包含以下内容的文件:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whereami-deployment
      namespace: whereami
      labels:
        app: whereami
    spec:
      selector:
        matchLabels:
          app: whereami
      template:
        metadata:
          labels:
            app: whereami
        spec:
          containers:
          - name: frontend
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
            ports:
            - containerPort: 8080
    
  2. 切换到 gke-us 上下文:

    kubectl config use-context gke-us
    
  3. 部署 whereami 应用:

    kubectl apply -f deploy.yaml
    
  4. 切换到 gke-eu 上下文:

    kubectl config use-context gke-eu
    
  5. 部署 whereami 应用:

    kubectl apply -f deploy.yaml
    
  6. 验证 whereami 应用是否已在每个集群中成功部署:

    kubectl get deployment --namespace whereami
    

    两个集群中的输出应如下所示:

    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    whereami-deployment   1/1     1            1           12m
    

通过配置集群进行部署

在跨 gke-usgke-eu 部署应用后,您将通过在配置集群中部署 MultiClusterIngressMultiClusterService 资源来部署负载均衡器。它们是 Ingress 和 Service 资源的多集群等效项。

设置指南中,您已将 gke-us 集群配置为配置集群。配置集群用于跨所有集群部署和配置 Ingress。

  1. 将上下文设置为配置集群。

    kubectl config use-context gke-us
    

MultiClusterService

  1. 创建一个名为 mcs.yaml 且包含以下内容的文件:

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: whereami-mcs
      namespace: whereami
    spec:
      template:
        spec:
          selector:
            app: whereami
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
    
  2. 部署与 whereami 应用匹配的 MultiClusterService 资源:

    kubectl apply -f mcs.yaml
    
  3. 验证 whereami-mcs 资源是否已成功部署到配置集群中:

    kubectl get mcs -n whereami
    

    输出内容类似如下:

    NAME       AGE
    whereami-mcs   9m26s
    

    MultiClusterService 会在每个集群中创建一个将 Pod 与 app: whereami 进行比对的派生无头服务。您可以看到 gke-us 集群 kubectl get service -n whereami 中存在一项这样的服务。

    输出内容类似如下:

    NAME                                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
    mci-whereami-mcs-svc-lgq966x5mxwwvvum   ClusterIP   None          <none>        8080/TCP         4m59s
    

gke-eu 中也将存在一个类似的无头服务。这些本地服务用于动态选择 Pod 端点,以通过后端对全局 Ingress 负载均衡器进行编程。

MultiClusterIngress

  1. 创建一个名为 mci.yaml 且包含以下内容的文件:

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: whereami-ingress
      namespace: whereami
    spec:
      template:
        spec:
          backend:
            serviceName: whereami-mcs
            servicePort: 8080
    

    请注意,此配置会将所有流量都路由到 whereami 命名空间中存在的 MultiClusterService(名为 whereami-mcs)。

  2. 部署将 whereami-mcs 作为后端进行引用的 MultiClusterIngress 资源:

    kubectl apply -f mci.yaml
    

    输出内容类似如下:

    multiclusteringress.networking.gke.io/whereami-ingress created
    

    请注意,MultiClusterIngress 与 Kubernetes Ingress 具有相同的架构。Ingress 资源语义也相同,但 backend.serviceName 字段除外。

MultiClusterIngress 中的 backend.serviceName 字段引用 Fleet API 中的 MultiClusterService,而不是 Kubernetes 集群中的 Service。这意味着 Ingress 的任何设置(如 TLS 终止)都可以采用相同的方式进行配置。

验证部署状态是否为成功

Google Cloud 负载均衡器部署可能需要几分钟才能完成新负载均衡器的部署。更新现有负载均衡器的速度更快,因为不需要部署新资源。MultiClusterIngress 资源详细说明了代表 MultiClusterIngress 创建的底层 Compute Engine 资源。

  1. 验证部署是否成功:

    kubectl describe mci whereami-ingress -n whereami
    

    输出内容类似如下:

    Name:         whereami-ingress
    Namespace:    whereami
    Labels:       <none>
    Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                    {"apiVersion":"networking.gke.io/v1","kind":"MultiClusterIngress","metadata":{"annotations":{},"name":"whereami-ingress","namespace":"whe...
    API Version:  networking.gke.io/v1
    Kind:         MultiClusterIngress
    Metadata:
      Creation Timestamp:  2020-04-10T23:35:10Z
      Finalizers:
        mci.finalizer.networking.gke.io
      Generation:        2
      Resource Version:  26458887
      Self Link:         /apis/networking.gke.io/v1/namespaces/whereami/multiclusteringresses/whereami-ingress
      UID:               62bec0a4-8a08-4cd8-86b2-d60bc2bda63d
    Spec:
      Template:
        Spec:
          Backend:
            Service Name:  whereami-mcs
            Service Port:  8080
    Status:
      Cloud Resources:
        Backend Services:
          mci-8se3df-8080-whereami-whereami-mcs
        Firewalls:
          mci-8se3df-default-l7
        Forwarding Rules:
          mci-8se3df-fw-whereami-whereami-ingress
        Health Checks:
          mci-8se3df-8080-whereami-whereami-mcs
        Network Endpoint Groups:
          zones/europe-west1-b/networkEndpointGroups/k8s1-e4adffe6-whereami-mci-whereami-mcs-svc-lgq966x5m-808-88670678
          zones/us-central1-b/networkEndpointGroups/k8s1-a6b112b6-whereami-mci-whereami-mcs-svc-lgq966x5m-808-609ab6c6
        Target Proxies:
          mci-8se3df-whereami-whereami-ingress
        URL Map:  mci-8se3df-whereami-whereami-ingress
      VIP:        34.98.102.37
    Events:
      Type    Reason  Age                    From                              Message
      ----    ------  ----                   ----                              -------
      Normal  ADD     3m35s                  multi-cluster-ingress-controller  whereami/whereami-ingress
      Normal  UPDATE  3m10s (x2 over 3m34s)  multi-cluster-ingress-controller  whereami/whereami-ingress
    

    有几个字段指示此 Ingress 部署的状态:

    • 首先检查 Events。如果发生错误,则会在这里列出。

    • Cloud Resource 列出了多集群 Ingress 控制器创建的 Compute Engine 资源,例如转发规则、后端服务和防火墙规则。如果未列出,则表示尚未创建。您可以使用控制台或 gcloud 命令检查各个 Compute Engine 资源以获取其状态。

    • VIP 会列出 IP 地址(如果已分配)。请注意,即使存在 VIP,负载均衡器也可能尚未处理流量。如果您在几分钟后没有看到 VIP,或者负载均衡器在 10 分钟内未提供 200 响应,请参阅问题排查和操作

    如果输出事件为 Normal,则 MultiClusterIngress 部署可能是成功的,但确定完整流量路径是否正常运行的唯一方法是对其进行测试。

  2. 验证应用是否正在通过 /ping 端点在 VIP 上提供服务:

    curl INGRESS_VIP/ping
    

    INGRESS_VIP 替换为虚拟 IP (VIP) 地址。

    输出内容类似如下:

    {
    "cluster_name": "gke-us",
    "host_header": "34.120.175.141",
    "pod_name": "whereami-deployment-954cbf78-mtlpf",
    "pod_name_emoji": "😎",
    "project_id": "my-project",
    "timestamp": "2021-11-29T17:01:59",
    "zone": "us-central1-b"
    }
    

    输出应指明应用的地区和后端。

  3. 您还可以转到浏览器中的 http://INGRESS_VIP 网址,查看应用的图形版本,其中显示了应用的来源地区。

    流量要转发到哪个集群取决于您的位置。GCLB 旨在将客户端流量转发到距离最近并且有可用容量的后端。

资源规范

MultiClusterService 规范

MultiClusterService 定义由两部分组成:

  1. template 部分,定义要在 Kubernetes 集群中创建的 Service。请注意,虽然 template 部分包含典型 Service 中支持的字段,但 MultiClusterService 仅支持两个字段:selectorports。其他字段会被忽略。

  2. 可选的 clusters 部分,定义哪些集群接收流量以及每个集群的负载均衡属性。如果未指定 clusters 部分,或者未列出任何集群,则默认使用所有集群。

以下清单描述了一个标准 MultiClusterService

apiVersion: networking.gke.io/v1
kind: MultiClusterService
metadata:
  name: NAME
  namespace: NAMESPACE
spec:
  template:
    spec:
      selector:
        app: POD_LABEL
      ports:
      - name: web
        protocol: TCP
        port: PORT
        targetPort: TARGET_PORT

替换以下内容:

  • NAMEMultiClusterService 的名称。此名称由 MultiClusterIngress 资源中的 serviceName 字段引用。
  • NAMESPACE:在其中部署了 MultiClusterService 的 Kubernetes 命名空间。它必须与舰队内所有集群中的 MultiClusterIngress 和 Pod 位于同一命名空间中。
  • POD_LABEL:一个标签,用于确定在舰队的所有集群中选择哪些 pod 作为此 MultiClusterService 的后端。
  • PORT:必须与引用此 MultiClusterServiceMultiClusterIngress 所引用的端口匹配。
  • TARGET_PORT:用于从 GCLB 将流量发送到 Pod 的端口。系统会在每个集群中创建一个 NEG,并将此端口用作其服务端口。

MultiClusterIngress 规范

以下 mci.yaml 描述了负载均衡器前端:

apiVersion: networking.gke.io/v1
kind: MultiClusterIngress
metadata:
  name: NAME
  namespace: NAMESPACE
spec:
  template:
    spec:
      backend:
       serviceName: DEFAULT_SERVICE
       servicePort: PORT
      rules:
        - host: HOST_HEADER
          http:
            paths:
            - path: PATH
              backend:
                serviceName: SERVICE
                servicePort: PORT

替换以下内容:

  • NAMEMultiClusterIngress 资源的名称。
  • NAMESPACE:在其中部署了 MultiClusterIngress 的 Kubernetes 命名空间。它必须与舰队中所有集群的 MultiClusterService 和 Pod 位于同一命名空间中。
  • DEFAULT_SERVICE:充当与任何主机或路径规则不匹配的所有流量的默认后端。这是必填字段,即使配置了其他主机或路径匹配项,也必须在 MultiClusterIngress 中指定默认后端。
  • PORT:任何有效的端口号。此字段必须与 MultiClusterService 资源的 port 字段匹配。
  • HOST_HEADER:按 HTTP 主机标头字段匹配流量。host 字段为可选字段。
  • PATH:按 HTTP 网址的路径匹配流量。path 字段为可选字段。
  • SERVICE:与此 MultiClusterIngress 部署在同一命名空间和配置集群中的 MultiClusterService 的名称。

多集群 Ingress 功能

本部分介绍如何配置其他多集群 Ingress 功能。

集群选择

默认情况下,源自多集群 Ingress 的 Service 会安排在每个成员集群上。不过,您可能需要将入站流量规则应用于特定集群。一些使用场景包括:

  • 将多集群 Ingress 应用于除配置集群以外的所有集群,以隔离配置集群。
  • 以蓝绿部署方式在集群之间迁移工作负载。
  • 路由到仅存在于部分集群中的应用后端。
  • 使用单个 L7 VIP 将主机或路径路由到不同集群上的后端。

借助集群选择功能,您可以在 MultiClusterService 对象中按区域或名称选择集群。这将控制您的 MultiClusterIngress 指向哪些集群以及将在哪些位置安排派生的 Service。同一舰队和区域中的集群不得同名,这样就可以独一无二地引用集群。

  1. 打开mcs.yaml

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: whereami-mcs
      namespace: whereami
    spec:
      template:
        spec:
          selector:
            app: whereami
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
    

    此规范会在所有集群中创建派生 Service,这是默认行为。

  2. 在“clusters”部分附加以下几行:

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: whereami-mcs
      namespace: whereami
    spec:
      template:
        spec:
          selector:
            app: whereami
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
      clusters:
      - link: "us-central1-b/gke-us"
      - link: "europe-west1-b/gke-eu"
    

    此示例仅在 gke-us 和 gke-eu 集群中创建派生 Service 资源。您必须选择集群才能有选择地应用入站流量规则。如果未指定 MultiClusterService 的“clusters”部分,或未列出任何集群,则会解释为默认的“所有”集群。

HTTPS 支持

Kubernetes Secret 支持 HTTPS。在启用 HTTPS 支持之前,您必须先创建静态 IP 地址。此静态 IP 允许 HTTP 和 HTTPS 共享同一 IP 地址。如需了解详情,请参阅创建静态 IP 地址

创建静态 IP 地址后,您就可以创建 Secret 了。

  1. 创建 Secret:

    kubectl -n whereami create secret tls SECRET_NAME --key PATH_TO_KEYFILE --cert PATH_TO_CERTFILE
    

    替换以下内容:

    • SECRET_NAME 替换为您的 Secret 名称。
    • PATH_TO_KEYFILE 替换为 TLS 密钥文件的路径。
    • PATH_TO_CERTFILE 替换为 TLS 证书文件的路径。
  2. 使用 Secret 名称更新 mci.yaml 文件:

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: whereami-ingress
      namespace: whereami
      annotations:
        networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: whereami-mcs
            servicePort: 8080
          tls:
          - secretName: SECRET_NAME
    

    SECRET_NAME 替换为您的 Secret 的名称。STATIC_IP_ADDRESS 是您在创建静态 IP 部分中所分配的地址的 IP 地址或者完整网址。

  3. 重新部署 MultiClusterIngress 资源:

    kubectl apply -f mci.yaml
    

    输出内容类似如下:

    multiclusteringress.networking.gke.io/whereami-ingress configured
    

BackendConfig 支持

借助以下 BackendConfig CRD,您可以自定义 Compute Engine BackendService 资源的设置:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: whereami-health-check-cfg
  namespace: whereami
spec:
  healthCheck:
    checkIntervalSec: [int]
    timeoutSec: [int]
    healthyThreshold: [int]
    unhealthyThreshold: [int]
    type: [HTTP | HTTPS | HTTP2 | TCP]
    port: [int]
    requestPath: [string]
  timeoutSec: [int]
  connectionDraining:
    drainingTimeoutSec: [int]
  sessionAffinity:
    affinityType: [CLIENT_IP | CLIENT_IP_PORT_PROTO | CLIENT_IP_PROTO | GENERATED_COOKIE | HEADER_FIELD | HTTP_COOKIE | NONE]
    affinityCookieTtlSec: [int]
  cdn:
    enabled: [bool]
    cachePolicy:
      includeHost: [bool]
      includeQueryString: [bool]
      includeProtocol: [bool]
      queryStringBlacklist: [string list]
      queryStringWhitelist: [string list]
  securityPolicy:
    name: ca-how-to-security-policy
  logging:
    enable: [bool]
    sampleRate: [float]
  iap:
    enabled: [bool]
    oauthclientCredentials:
      secretName: [string]

如需使用 BackendConfig,请使用注解将其附加到 MultiClusterService 资源:

apiVersion: networking.gke.io/v1
kind: MultiClusterService
metadata:
  name: whereami-mcs
  namespace: whereami
  annotations:
    cloud.google.com/backend-config: '{"ports": {"8080":"whereami-health-check-cfg"}}'
spec:
 template:
   spec:
     selector:
       app: whereami
     ports:
     - name: web
       protocol: TCP
       port: 8080
       targetPort: 8080

如需详细了解 BackendConfig 语义,请参阅将 Service 端口与 BackendConfig 进行关联

gRPC 支持

在多集群 Ingress 中配置 gRPC 应用需要非常具体的设置。以下提示可帮您确保正确配置负载均衡器:

  1. 确保从负载均衡器到您的应用的流量是 HTTP/2。请使用应用协议进行配置。
  2. 由于这是 HTTP/2 的要求,因此请确保您的应用已针对 SSL 进行了正确的配置。请注意,您可以使用自签名证书。
  3. 您必须关闭应用上的 mTLS,因为系统不支持 mTLS 用于 L7 外部负载均衡器。

资源生命周期

配置变更

MultiClusterIngressMultiClusterService 资源作为标准 Kubernetes 对象运行,因此对象的变更会异步反映在系统中。任何导致配置无效的变更都会导致关联的 Google Cloud 对象保持不变,并在对象事件流中引发错误。与配置相关的错误将报告为事件。

管理 Kubernetes 资源

删除 Ingress 对象会删除 HTTP(S) 负载均衡器,以便不再将流量转发到任何已定义的 MultiClusterService

删除 MultiClusterService 即会移除每个集群中关联的派生 Service。

管理集群

可通过在舰队中添加集群或从舰队中移除集群来更改负载均衡器所定位的那组集群。

例如,如需移除 gke-eu 集群的资格,使其不再是 Ingress 的后端,请运行以下命令:

gcloud container fleet memberships unregister CLUSTER_NAME \
  --gke-uri=URI

替换以下内容:

  • CLUSTER_NAME:您的集群的名称。
  • URI:GKE 集群的 URI。

如需在欧洲添加集群,请运行以下命令:

gcloud container fleet memberships register europe-cluster \
  --context=europe-cluster --enable-workload-identity

您可以在注册 GKE 集群中找到有关集群注册选项的更多信息。

请注意,注册或取消注册集群后,它的状态将发生变化,它将不再是所有 Ingress 的后端。取消注册 gke-eu 集群会移除其资格,使其不再是您创建的所有 Ingress 的可用后端。注册新集群的效果正好相反。

停用多集群 Ingress

在停用多集群 Ingress 之前,您必须先删除 MultiClusterIngressMultiClusterService 资源,并验证所有关联的网络资源都已删除。

然后,如需停用多集群 Ingress,请使用以下命令:

gcloud container fleet ingress disable

如果您没有在停用多集群 Ingress 之前删除 MultiClusterIngressMultiClusterService 资源,则可能会遇到如下所示的错误:

Feature has associated resources that should be cleaned up before deletion.

如果要强制停用多集群 Ingress,请使用以下命令:

gcloud container fleet ingress disable --force

注释

MultiClusterIngressMultiClusterService 资源支持以下注解。

MultiClusterIngress 注解

注解 说明
networking.gke.io/frontend-config 引用与 MultiClusterIngress 资源相同的命名空间中的 FrontendConfig 资源
networking.gke.io/static-ip 引用全局静态 IP 地址的文本 IP 地址。
networking.gke.io/pre-shared-certs 引用全局 SSLCertificate 资源。

MultiClusterService 注解

注解 说明
networking.gke.io/app-protocols 使用此注解可设置负载均衡器与应用之间的通信协议。可能的协议有 HTTP、HTTPS 和 HTTP/2。 请参阅负载均衡器与应用之间的 HTTPS使用 Ingress 进行负载均衡的 HTTP/2
cloud.google.com/backend-config 使用此注解配置与 servicePort 关联的后端服务。如需了解详情,请参阅 Ingress 配置

SSL 政策和 HTTPS 重定向

您可以使用 FrontendConfig 资源配置 SSL 政策和 HTTPS 重定向。通过 SSL 政策,您可以指定负载均衡器接受的加密套件和 TLS 版本。通过 HTTPS 重定向,您可以强制执行从 HTTP 或端口 80 到 HTTPS 或端口 443 的重定向。以下步骤将配置 SSL 政策和 HTTPS 重定向。请注意,可单独配置它们。

  1. 创建 SSL 政策,以拒绝使用低于 TLS v1.2 的版本的请求。

    gcloud compute ssl-policies create tls-12-policy \
     --profile MODERN \
     --min-tls-version 1.2 \
     --project=PROJECT_ID
    

    PROJECT_ID 替换为在其中运行 GKE 集群的项目的 ID。

  2. 查看您的政策以确保它已创建。

    gcloud compute ssl-policies list --project=PROJECT_ID
    

    输出类似于以下内容:

    NAME           PROFILE  MIN_TLS_VERSION
    tls-12-policy  MODERN   TLS_1_2
    
  3. foo.example.com 创建证书,如示例所示。获取 key.pemcert.pem 后,请将这些凭据存储为将由 MultiClusterIngress 资源引用的 Secret。

    kubectl -n whereami create secret tls SECRET_NAME --key key.pem --cert cert.pem
    
  4. 将以下 FrontendConfig 资源保存为 frontendconfig.yaml。如需详细了解 FrontendConfig 中支持的字段,请参阅配置 FrontendConfig 资源

    apiVersion: networking.gke.io/v1beta1
    kind: FrontendConfig
    metadata:
      name: frontend-redirect-tls-policy
      namespace: whereami
    spec:
      sslPolicy: tls-12-policy
      redirectToHttps:
        enabled: true
    

    此 FrontendConfig 将启用 HTTPS 重定向,以及强制执行最低 TLS 版本 1.2 的 SSL 政策。

  5. frontendconfig.yaml 部署到配置集群中。

    kubectl apply -f frontendconfig.yaml --context MCI_CONFIG_CLUSTER
    

    MCI_CONFIG_CLUSTER 替换为您的配置集群的名称。

  6. 将以下 MultiClusterIngress 保存为 mci-frontendconfig.yaml

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: foo-ingress
      namespace: whereami
      annotations:
        networking.gke.io/frontend-config: frontend-redirect-tls-policy
        networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: default-backend
            servicePort: 8080
          rules:
          - host: foo.example.com
            http:
              paths:
                - backend:
                    serviceName: whereami-mcs
                    servicePort: 8080
          tls:
          - secretName: SECRET_NAME
    
    • STATIC_IP_ADDRESS 替换为已预配的静态全球 IP 地址。
    • SECRET_NAME 替换为存储 foo.example.com 证书的 Secret。

    启用 HTTPS 重定向时有两个要求:

    • 必须通过 spec.tls 字段或预共享证书注解 networking.gke.io/pre-shared-certs 启用 TLS。如果启用了 HTTPS 重定向,但未启用 HTTPS,则不会部署 MultiClusterIngress。
    • 必须通过 networking.gke.io/static-ip 注解引用静态 IP 地址。在 MultiClusterIngress 上启用 HTTPS 时需要静态 IP 地址。
  7. 将 MultiClusterIngress 部署到配置集群。

    kubectl apply -f mci-frontendconfig.yaml --context MCI_CONFIG_CLUSTER
    
  8. 等待一两分钟,然后检查 foo-ingress

    kubectl describe mci foo-ingress --context MCI_CONFIG_CLUSTER
    

    成功的输出如下所示:

    • Cloud Resources 状态填充了资源名称
    • VIP 字段使用负载均衡器 IP 地址填充
    Name:         foobar-ingress
    Namespace:    whereami
    
    ...
    
    Status:
      Cloud Resources:
        Backend Services:
          mci-otn9zt-8080-whereami-bar
          mci-otn9zt-8080-whereami-default-backend
          mci-otn9zt-8080-whereami-foo
        Firewalls:
          mci-otn9zt-default-l7
        Forwarding Rules:
          mci-otn9zt-fw-whereami-foobar-ingress
          mci-otn9zt-fws-whereami-foobar-ingress
        Health Checks:
          mci-otn9zt-8080-whereami-bar
          mci-otn9zt-8080-whereami-default-backend
          mci-otn9zt-8080-whereami-foo
        Network Endpoint Groups:
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluste-mci-default-backend-svc--80-9e362e3d
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluster--mci-bar-svc-067a3lzs8-808-89846515
          zones/europe-west1-b/networkEndpointGroups/k8s1-1869d397-multi-cluster--mci-foo-svc-820zw3izx-808-8bbcb1de
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluste-mci-default-backend-svc--80-a528cc75
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluster--mci-bar-svc-067a3lzs8-808-36281739
          zones/us-central1-b/networkEndpointGroups/k8s1-a63e24a6-multi-cluster--mci-foo-svc-820zw3izx-808-ac733579
        Target Proxies:
          mci-otn9zt-whereami-foobar-ingress
          mci-otn9zt-whereami-foobar-ingress
        URL Map:  mci-otn9zt-rm-whereami-foobar-ingress
      VIP:        34.149.29.76
    Events:
      Type     Reason  Age                From                              Message
      ----     ------  ----               ----                              -------
      Normal   UPDATE  38m (x5 over 62m)  multi-cluster-ingress-controller  whereami/foobar-ingress
    
  9. 通过 curl 发送 HTTP 请求来验证 HTTPS 重定向是否正常运行。

    curl VIP
    

    VIP 替换为 MultiClusterIngress IP 地址。

    输出应显示请求已重定向到 HTTPS 端口,这表示重定向正常运行。

  10. 使用 TLS 1.1 版发送 HTTPS 请求来验证 TLS 政策是否正常运行。由于没有为此网域配置 DNS,因此请使用 --resolve 选项指示 curl 直接解析 IP 地址。

    curl https://foo.example.com --resolve foo.example.com:443:VIP --cacert CERT_FILE -v
    

    此步骤需要使用用于保护 MultiClusterIngress 的证书 PEM 文件。成功的输出将如下所示:

    ...
    * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: O=example; CN=foo.example.com
    *  start date: Sep  1 10:32:03 2021 GMT
    *  expire date: Aug 27 10:32:03 2022 GMT
    *  common name: foo.example.com (matched)
    *  issuer: O=example; CN=foo.example.com
    *  SSL certificate verify ok.
    * Using HTTP2, server supports multi-use
    * Connection state changed (HTTP/2 confirmed)
    * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
    * Using Stream ID: 1 (easy handle 0x7fa10f00e400)
    > GET / HTTP/2
    > Host: foo.example.com
    > User-Agent: curl/7.64.1
    > Accept: */*
    >
    * Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
    < HTTP/2 200
    < content-type: application/json
    < content-length: 308
    < access-control-allow-origin: *
    < server: Werkzeug/1.0.1 Python/3.8.6
    < date: Wed, 01 Sep 2021 11:39:06 GMT
    < via: 1.1 google
    < alt-svc: clear
    <
    {"cluster_name":"gke-us","host_header":"foo.example.com","metadata":"foo","node_name":"gke-gke-us-default-pool-22cb07b1-r5r0.c.mark-church-project.internal","pod_name":"foo-75ccd9c96d-dkg8t","pod_name_emoji":"👞","project_id":"mark-church-project","timestamp":"2021-09-01T11:39:06","zone":"us-central1-b"}
    * Connection #0 to host foo.example.com left intact
    * Closing connection 0
    

    响应代码为 200,并且使用了 TLSv1.2,这表示一切正常。

    接下来,您可以通过尝试与 TLS 1.1 连接来验证 SSL 政策是否强制执行正确的 TLS 版本。您的 SSL 政策必须至少配置为 1.2 版,才能执行此步骤。

  11. 发送上一步中的相同请求,但强制执行 TLS 版本 1.1。

    curl https://foo.example.com --resolve foo.example.com:443:VIP -v \
      --cacert CERT_FILE \
      --tls-max 1.1
    

    成功的输出将如下所示:

    * Added foo.example.com:443:34.149.29.76 to DNS cache
    * Hostname foo.example.com was found in DNS cache
    *   Trying 34.149.29.76...
    * TCP_NODELAY set
    * Connected to foo.example.com (34.149.29.76) port 443 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *   CAfile: cert.pem
      CApath: none
    * TLSv1.1 (OUT), TLS handshake, Client hello (1):
    * TLSv1.1 (IN), TLS alert, protocol version (582):
    * error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert protocol version
    * Closing connection 0
    curl: (35) error:1400442E:SSL routines:CONNECT_CR_SRVR_HELLO:tlsv1 alert protocol version
    

    如果未能完成 TLS 握手,则表示 SSL 政策已成功阻止 TLS 1.1。

创建静态 IP 地址

  1. 分配静态 IP 地址:

    gcloud compute addresses create ADDRESS_NAME --global
    

    ADDRESS_NAME 替换为要分配的静态 IP 地址的名称。

    输出包含您创建的地址的完整网址,如下所示:

    Created [https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/addresses/ADDRESS_NAME].
    
  2. 查看您刚创建的 IP 地址:

    gcloud compute addresses list
    

    输出内容类似如下:

    NAME          ADDRESS/RANGE  TYPE      STATUS
    ADDRESS_NAME  STATIC_IP_ADDRESS  EXTERNAL  RESERVED
    

    此输出包括:

    • 您定义的 ADDRESS_NAME
    • 已分配 STATIC_IP_ADDRESS
  3. 使用静态 IP 地址更新 mci.yaml 文件:

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: whereami-ingress
      namespace: whereami
      annotations:
        networking.gke.io/static-ip: STATIC_IP_ADDRESS
    spec:
      template:
        spec:
          backend:
            serviceName: whereami-mcs
            servicePort: 8080
    

    STATIC_IP_ADDRESS 替换为:

    • 分配的 IP 地址,类似于:34.102.201.47
    • 您创建的地址的完整网址,类似于:"https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/addresses/ADDRESS_NAME"

    STATIC_IP_ADDRESS 不是资源名称 (ADDRESS_NAME)。

  4. 重新部署 MultiClusterIngress 资源:

    kubectl apply -f mci.yaml
    

    输出内容类似如下:

    multiclusteringress.networking.gke.io/whereami-ingress configured
    
  5. 按照验证成功部署状态中的步骤操作,验证部署是否正在 STATIC_IP_ADDRESS 上提供服务。

预共享证书

预共享证书是上传到 Google Cloud 以供负载均衡器用于 TLS 终止的证书,而不是存储在 Kubernetes Secret 中的证书。这些证书会从 GKE 带外上传到 Google Cloud,并由 MultiClusterIngress 资源引用。此外,系统还支持多份证书(通过预共享证书或 Kubernetes Secret 形式)。

在多集群 Ingress 中使用证书需要使用 networking.gke.io/pre-shared-certs 注解和证书名称。为给定的 MultiClusterIngress 指定多种证书时,系统会按照预定顺序控制向客端户呈现哪种证书。

您可以通过运行以下命令列出可用的 SSL 证书:

gcloud compute ssl-certificates list

以下示例描述了流向与预共享证书的公用名匹配的一个指定主机的客户端流量,因此,系统将呈现与域名匹配的相应证书。

kind: MultiClusterIngress
metadata:
  name: shopping-service
  namespace: whereami
  annotations:
    networking.gke.io/pre-shared-certs: "domain1-cert, domain2-cert"
spec:
  template:
    spec:
      rules:
      - host: my-domain1.gcp.com
        http:
          paths:
          - backend:
              serviceName: domain1-svc
              servicePort: 443
      - host: my-domain2.gcp.com
        http:
          paths:
          - backend:
              serviceName: domain2-svc
              servicePort: 443

Google 管理的证书

MultiClusterIngress 支持通过 networking.gke.io/pre-shared-certs 注解使用 Google 管理的证书。多集群 Ingress 支持将 Google 管理的证书附加到 MultiClusterIngress 资源,但与单集群 Ingress 不同,Kubernetes ManagedCertificate 资源的声明式生成不受 MultiClusterIngress 资源支持。您必须通过 compute ssl-certificates create API 直接完成 Google 管理的证书的原始创建,然后才能将其附加到 MultiClusterIngress。具体步骤如下:

  1. 按照第 1 步中的说明创建 Google 管理的证书。请勿转到第 2 步,因为多集群 Ingress 会为您附加此证书。

    gcloud compute ssl-certificates create my-google-managed-cert \
        --domains=my-domain.gcp.com \
        --global
    
  2. 使用 networking.gke.io/pre-shared-certs 注解在 MultiClusterIngress 中引用证书的名称。

    kind: MultiClusterIngress
    metadata:
    name: shopping-service
    namespace: whereami
    annotations:
      networking.gke.io/pre-shared-certs: "my-google-managed-cert"
    spec:
    template:
      spec:
        rules:
        - host: my-domain.gcp.com
          http:
            paths:
            - backend:
                serviceName: my-domain-svc
                servicePort: 8080
    

上述清单将证书附加到 MultiClusterIngress,以便终止后端 GKE 集群的流量。Google Cloud 会在证书到期之前自动续订证书。续订以透明方式进行,不需要对多集群 Ingress 进行任何更新。

应用协议

默认情况下,从负载均衡器代理到应用的连接使用 HTTP。使用 networking.gke.io/app-protocols 注解,您可以将负载均衡器配置为在将请求转发到应用时使用 HTTPS 或 HTTP/2。在以下示例的 annotation 字段中,http2 表示 MultiClusterService 端口名称,HTTP2 表示负载均衡器使用的协议。

kind: MultiClusterService
metadata:
  name: shopping-service
  namespace: whereami
  annotations:
    networking.gke.io/app-protocols: '{"http2":"HTTP2"}'
spec:
  template:
    spec:
      ports:
      - port: 443
        name: http2

BackendConfig

请参阅上述部分,了解如何配置注解。

后续步骤