跨集群部署 Ingress

本页面介绍如何部署跨多个 GKE 集群提供应用的 Ingress。

部署教程

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

本页面基于您在设置 Ingress for Anthos 中完成的工作(也就是创建并注册了两个集群)构建。此时,您应该有两个也已经向 Hub 注册的集群:

$ gcloud container clusters list
NAME    LOCATION        MASTER_VERSION  MASTER_IP       MACHINE_TYPE   NODE_VERSION     NUM_NODES  STATUS
gke-eu  europe-west1-c  1.16.8-gke.9    ***             e2-medium      1.16.8-gke.9     2          RUNNING
gke-us  us-central1-a   1.16.8-gke.9    ***             e2-medium      1.16.6-gke.13 *  2          RUNNING

创建命名空间

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

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

  1. 通过以下清单创建 namespace.yaml

    apiVersion: v1
    kind: Namespace
    metadata:
      name: zoneprinter
    
  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
    

部署应用

  1. 通过以下清单创建 deploy.yaml

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: zone-ingress
      namespace: zoneprinter
      labels:
        app: zoneprinter
    spec:
      selector:
        matchLabels:
          app: zoneprinter
      template:
        metadata:
          labels:
            app: zoneprinter
        spec:
          containers:
          - name: frontend
            image: gcr.io/google-samples/zone-printer:0.2
            ports:
            - containerPort: 8080
    
  2. 切换到 gke-us 上下文:

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

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

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

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

    kubectl get deployment --namespace zoneprinter
    

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

    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    zone-ingress   2/2     2            2           12m
    

通过配置集群进行部署

在应用已跨 gke-usgke-eu 进行部署后,您将通过在配置集群中部署 MultiClusterIngress (MCI) 和 MultiClusterService (MCS) 资源来部署负载平衡器。MCI 和 MCS 是自定义资源 (CRD),这些资源是 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: zone-mcs
      namespace: zoneprinter
    spec:
      template:
        spec:
          selector:
            app: zoneprinter
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
    
  2. 部署与 zoneprinter 应用匹配的 MultiClusterService 资源:

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

    kubectl get mcs -n zoneprinter
    

    输出类似于以下内容:

    NAME       AGE
    zone-mcs   9m26s
    

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

    输出类似于以下内容:

    NAME                                TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
    mci-zone-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: zone-ingress
      namespace: zoneprinter
    spec:
      template:
        spec:
          backend:
            serviceName: zone-mcs
            servicePort: 8080
    

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

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

    kubectl apply -f mci.yaml
    

    输出类似于以下内容:

    multiclusteringress.networking.gke.io/zone-mci created
    

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

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

验证部署状态是否为成功

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

  1. 验证部署是否成功:

    kubectl describe mci zone-ingress -n zoneprinter
    

    输出类似于以下内容:

    Name:         zone-ingress
    Namespace:    zoneprinter
    Labels:       <none>
    Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                    {"apiVersion":"networking.gke.io/v1","kind":"MultiClusterIngress","metadata":{"annotations":{},"name":"zone-ingress","namespace":"zon...
    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/zoneprinter/multiclusteringresses/zone-ingress
      UID:               62bec0a4-8a08-4cd8-86b2-d60bc2bda63d
    Spec:
      Template:
        Spec:
          Backend:
            Service Name:  zone-mcs
            Service Port:  8080
    Status:
      Cloud Resources:
        Backend Services:
          mci-8se3df-8080-zoneprinter-zone-mcs
        Firewalls:
          mci-8se3df-default-l7
        Forwarding Rules:
          mci-8se3df-fw-zoneprinter-zone-ingress
        Health Checks:
          mci-8se3df-8080-zoneprinter-zone-mcs
        Network Endpoint Groups:
          zones/europe-west1-c/networkEndpointGroups/k8s1-e4adffe6-zoneprint-mci-zone-mcs-svc-lgq966x5m-808-88670678
          zones/us-central1-a/networkEndpointGroups/k8s1-a6b112b6-zoneprint-mci-zone-mcs-svc-lgq966x5m-808-609ab6c6
        Target Proxies:
          mci-8se3df-zoneprinter-zone-ingress
        URL Map:  mci-8se3df-zoneprinter-zone-ingress
      VIP:        ingress-vip
    Events:
      Type    Reason  Age                    From                              Message
      ----    ------  ----                   ----                              -------
      Normal  ADD     3m35s                  multi-cluster-ingress-controller  zoneprinter/zone-ingress
      Normal  UPDATE  3m10s (x2 over 3m34s)  multi-cluster-ingress-controller  zoneprinter/zone-ingress
    

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

  • 首先检查 Events。如果发生错误,则会在这里列出。
  • Cloud Resource 列出了 Anthos Ingress 控制器创建的 Compute Engine 资源,例如转发规则、后端服务和防火墙规则。如果未列出,则表示尚未创建。您可以使用控制台或 gcloud 命令检查各个 Compute Engine 资源以获取其状态。
  • VIP 会列出 IP 地址(如果已分配)。请注意,即使存在 VIP,负载平衡器也可能尚未处理流量。如果您在几分钟后没有看到 VIP,或者负载平衡器在 10 分钟内未提供 200 响应,请参阅问题排查和操作

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

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

    curl ingress-vip/ping
    

    输出类似于以下内容:

    {"Hostname":"34.98.102.37","Version":"1.0","GCPZone":"us-central1-a","Backend":"zone-ingress-5554bb95b4-svv5d"}
    

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

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

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

资源规范

MultiClusterService 规范

MultiClusterService 定义由两部分组成:

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

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

以下清单描述了一个标准 MCS:

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

其中:

  • name 是 MCS 的名称。此名称由 MCI 资源中的 serviceName 字段引用。
  • namespace 是在其中部署了 MCS 的 Kubernetes 命名空间。它必须与 Environ 环境内所有集群中的 MCI 和 Pod 位于同一命名空间中。
  • pod-label 是一个标签,用于确定在 Environ 环境内的所有集群中选择哪些 pod 作为此 MCS 的后端。
  • port 必须与引用此 MCS 的 MCI 所引用的端口匹配。
  • 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

其中:

  • name 是 MCI 资源的名称。
  • namespace 是在其中部署了 MCI 的 Kubernetes 命名空间。它必须与 Environ 环境内所有集群中的 MCS 和 Pod 位于同一命名空间中。
  • default-service 充当与任何主机或路径规则不匹配的所有流量的默认后端。这是必填字段,即使配置了其他主机或路径匹配项,也必须在 MCI 中指定默认后端。
  • port 是任何有效的端口号。此字段必须与 MCS 资源的 port 字段匹配。
  • host-header 按 HTTP 主机标头字段匹配流量。host 字段为可选字段。
  • path 按 HTTP 网址的路径匹配流量。path 字段为可选字段。
  • service 是与此 MCI 部署在同一命名空间和配置集群中的 MCS 的名称。

Ingress for Anthos 功能

本部分介绍如何配置其他 Ingress for Anthos 功能。

集群选择

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

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

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

  1. 打开 mcs.yaml

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

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

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

    apiVersion: networking.gke.io/v1
    kind: MultiClusterService
    metadata:
      name: zone-mcs
      namespace: zoneprinter
    spec:
      template:
        spec:
          selector:
            app: zoneprinter
          ports:
          - name: web
            protocol: TCP
            port: 8080
            targetPort: 8080
      clusters:
      - link: "us-central1-a/gke-us"
      - link: "europe-west1-c/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 prod create secret tls secret-name --key /path/to/keyfile --cert/path/to/certfile
    

    其中,secret-name 是您的 Secret 的名称。

  2. 使用静态 IP 地址和 Secret 更新 mci.yaml 文件:

    apiVersion: networking.gke.io/v1
    kind: MultiClusterIngress
    metadata:
      name: zone-ingress
      namespace: zoneprinter
      annotations:
        networking.gke.io/static-ip: static-ip-address
    spec:
      template:
        spec:
          backend:
            serviceName: zone-mcs
            servicePort: 8080
          tls:
          - secretName: secret-name
    

BackendConfig 支持

借助 BackendConfig CRD,您可以自定义 Compute Engine BackendService 资源的设置。支持的规范如下:

apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
  name: zone-health-check-cfg
  namespace: zoneprinter
spec:
  healthCheck:
    checkIntervalSec: [int]
    timeoutSec: [int]
    healthyThreshold: [int]
    unhealthyThreshold: [int]
    type: [HTTP | HTTPS | HTTP2]
    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: zone-mcs
  namespace: zoneprinter
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"8080":"zone-health-check-cfg"}}'
spec:
 template:
   spec:
     selector:
       app: zoneprinter
     ports:
     - name: web
       protocol: TCP
       port: 8080
       targetPort: 8080

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

gRPC 支持

在 Ingress for Anthos 上配置 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 hub memberships unregister cluster-name \
  --gke-uri=uri

其中

  • cluster-name 是集群的名称。
  • uri 是 GKE 集群的 URI。

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

gcloud container hub memberships register europe-cluster \
  --context=europe-cluster --service-account-key-file=/path/to/service-account-key-file

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

停用 Ingress for Anthos

在 Beta 版中,停用 Ingress for Anthos 会形成孤立的网络资源。为避免出现这种情况,请删除您的 MultiClusterIngressMultiClusterService 资源,并验证所有关联的网络资源都已删除。

停用 Ingress for Anthos:

gcloud alpha container hub ingress disable

注释

创建静态 IP 地址

  1. 分配静态 IP 地址:

    gcloud compute addresses create address-name --global
    

    其中,address-name 是要创建的地址的名称。

    输出类似于以下内容:

    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  34.102.201.47  EXTERNAL  RESERVED
    
  3. 通过更新 mci.yaml 来应用静态 IP 地址:

    kubectl get mci zone-mci -o yaml
    

    输出类似于以下内容:

    kind: MultiClusterIngress
    metadata:
      name: shopping-service
      namespace: prod
      annotations:
        networking.gke.io/static-ip: static-ip-address
    spec:
      template:
        spec:
           backend:
             serviceName: shopping-service
              servicePort: 80
    

预共享证书

预共享证书是上传到 Google Cloud 以供负载平衡器用于 TLS 终止的证书,而不是存储在 Kubernetes Secret 中的证书。这些证书会从 GKE 带外上传到 Google Cloud,并由 Ingress for Anthos 对象引用。此外,还支持多个证书(通过预共享证书或 Kubernetes Secret 形式)。

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

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

gcloud compute ssl-certificates list

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

kind: MultiClusterIngress
metadata:
  name: shopping-service
  namespace: prod
  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

应用协议

默认情况下,从负载平衡器代理到应用的连接使用 HTTP。使用 networking.gke.io/app-protocols 注释,您可以将负载平衡器配置为在将请求转发到应用时使用 HTTPS 或 HTTP/2。

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

BackendConfig

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

已知问题、产品限制和指导

以下是关于 Ingress for Anthos 行为的重要限制或注意事项,它们决定了安全和可接受的使用情况。如果您有任何疑问,请联系您的客户支持团队或 gke-mci-feedback@google.com。

  • 创建 Compute Engine 负载平衡器资源时所用的名称包含前缀 mci-[6 char hash]。项目中由 Ingress for Anthos 管理的所有资源都使用相同的前缀。此前缀用于对 Ingress for Anthos 部署的 Compute Engine 资源进行管理和垃圾回收。由于此前缀包含生成的哈希值,因此项目不太可能在 Ingress 大区之外包含具有相同前缀的 Compute Engine 资源。但是,同一项目中不是由 Ingress for Anthos 管理的 Compute Engine 负载平衡器不应该使用此前缀,否则将被删除。

  • Ingress for Anthos 仅支持同一项目中的集群。每个项目只能部署一个 Ingress for Anthos 实例,但可以通过集群选择控制集群的范围。这允许仅将 MultiClusterService 资源部署到项目中的特定集群子集。

  • Ingress for Anthos 和 Hub 预先配置了每个项目最多 15 个集群这一配额。必要时,可以增加此配额。如果您需要注册更多集群,请与您的客户支持团队联系,请求提高每个项目的集群限制。

  • Ingress for Anthos 预先配置了每个项目 50 个 MultiClusterIngress 和 100 个 MultiClusterService 资源这一配额。这允许在配置集群中为任意数量的后端集群(最高可达每个项目的集群数上限)创建多达 50 个 MCI 和 100 个 MCS 资源。必要时,可以增加此配额。如果您需要更大的规模,请与您的客户支持团队联系,请求增加每个项目的 MCI 和 MCS 配额。

  • 配置 HTTPS 时需要预先分配的静态 IP 地址。临时 IP 地址目前不支持 HTTPS。

后续步骤