使用 Ingress 设置外部应用负载均衡器


本教程介绍如何通过配置 Ingress 资源在使用外部应用负载均衡器的情况下运行 Web 应用。

背景

Google Kubernetes Engine (GKE) 为可公开访问的应用提供了对两种类型的 Cloud Load Balancing 的集成支持:

  1. 入站流量

  2. 外部直通式网络负载均衡器

在本教程中,您将使用 Ingress

Ingress

在资源清单中指定 kind: Ingress 时,您需要指示 GKE 来创建 Ingress 资源。通过添加注释并支持工作负载和 Service,您可以创建自定义 Ingress 控制器。否则,GKE 会进行适当的 Google Cloud API 调用,以创建外部应用负载均衡器。负载均衡器的网址映射的主机规则和路径匹配器会引用一个或多个后端服务,其中,每个后端服务对应于一个类型为 NodePort 的 GKE Service,如 Ingress 中引用的那样。每个后端服务的后端是实例组或网络端点组 (NEG)。在配置 Ingress 的过程中,配置容器原生负载均衡时,系统会创建 NEG。对于每个后端服务,GKE 都会根据相应 GKE Service 引用的工作负载的就绪性探测设置创建 Google Cloud 健康检查。

如果要公开在 GKE 上托管的 HTTP(S) 服务,则建议使用 HTTP(S) 负载平衡方法来实现负载平衡。

目标

  • 创建 GKE 集群。
  • 将示例 Web 应用部署到集群。
  • 将外部应用负载均衡器后的示例应用公开到互联网。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理

准备工作

请按照以下步骤启用 Kubernetes Engine API:
  1. 访问 Google Cloud 控制台中的 Kubernetes Engine 页面
  2. 创建或选择项目。
  3. 稍作等待,让 API 和相关服务完成启用过程。 此过程可能耗时几分钟。
  4. 确保您的 Google Cloud 项目已启用结算功能

安装本教程中使用的以下命令行工具:

  • gcloud 用于创建和删除 Kubernetes Engine 集群。gcloud 包含在 gcloud CLI 中。
  • kubectl 用于管理 Kubernetes(即 Kubernetes Engine 使用的集群编排系统)。您可以使用 gcloud 安装 kubectl
    gcloud components install kubectl

从 GitHub 克隆示例代码:

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/networking/load-balancing

gcloud 命令行工具设置默认值

如需节省在 gcloud 命令行工具中输入项目 IDCompute Engine 地区选项的时间,您可以设置以下默认值:
gcloud config set project project-id
gcloud config set compute/zone compute-zone

创建 GKE 集群

创建 GKE Autopilot 集群:

gcloud container clusters create-auto loadbalancedcluster

部署 Web 应用

下面的清单描述了了一个在端口 8080 的 HTTP 服务器上运行示例 Web 应用容器映像的 Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: default
spec:
  selector:
    matchLabels:
      run: web
  template:
    metadata:
      labels:
        run: web
    spec:
      containers:
      - image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
        imagePullPolicy: IfNotPresent
        name: web
        ports:
        - containerPort: 8080
          protocol: TCP

将资源应用到集群:

kubectl apply -f web-deployment.yaml

在集群内公开 Deployment

下面的清单描述了了使 web 部署可在容器集群中访问的 Service

apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: default
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: web
  type: NodePort
  1. 将资源应用到集群:

    kubectl apply -f web-service.yaml
    

    使用此命令创建 NodePort 类型的 Service 时,GKE 会使您的 Service 在集群中所有节点上随机选择的较大端口号(例如 32640)上可用。

  2. 验证是否已创建 Service 以及是否分配了节点端口:

    kubectl get service web
    
    输出:
    NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
    web       NodePort   10.35.245.219   <none>        8080:32640/TCP   5m
    

    在示例输出结果中,web Service 的节点端口是 32640。另请注意,我们未为此 Service 分配外部 IP 地址。由于默认情况下无法从外部访问 GKE 节点,因此创建此 Service 后,仍无法通过互联网访问您的应用。

要使 HTTP(S) 网络服务器应用可公开访问,您必须创建 Ingress 资源。

创建 Ingress 资源

Ingress 是一种 Kubernetes 资源,它封装了一系列规则和配置,可将外部 HTTP(S) 流量路由到内部服务。

在 GKE 上,Ingress 是使用 Cloud Load Balancing 实现的。当您在集群中创建 Ingress 时,GKE 会创建一个 HTTP(S) 负载均衡器,并将其配置为将流量路由到您的应用。

下面的清单描述了将流量定向到 web Service 的 Ingress 资源:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: basic-ingress
spec:
  defaultBackend:
    service:
      name: web
      port:
        number: 8080

将资源应用到集群:

kubectl apply -f basic-ingress.yaml

部署此清单后,Kubernetes 会在您的集群上创建一个 Ingress 资源。GKE Ingress 控制器根据 Ingress 中的信息创建并配置 HTTP(S) 负载均衡器,将端口 80 上的所有外部 HTTP 流量路由到您公开的 web NodePort Service。

访问应用

通过运行以下命令找出为应用提供服务的负载均衡器的外部 IP 地址:

kubectl get ingress basic-ingress
输出:
NAME            HOSTS     ADDRESS         PORTS     AGE
basic-ingress   *         203.0.113.12    80        2m

在浏览器中打开应用的外部 IP 地址,查看纯文本 HTTP 响应,如下所示:

Hello, world!
Version: 1.0.0
Hostname: web-6498765b79-fq5q5

您可以访问 Google Cloud 控制台上的负载均衡,并检查 GKE Ingress 控制器创建的网络资源。

(可选)配置静态 IP 地址

在域名上公开网络服务器时,您需要确保应用的外部 IP 地址是不会更改的静态 IP。

默认情况下,GKE 会为通过 Ingress 公开的 HTTP 应用分配临时外部 IP 地址。 临时地址随时可能更改。如果您打算长时间运行应用,则必须使用静态外部 IP 地址

请注意,为 Ingress 资源配置静态 IP 地址后,删除 Ingress 时将不会删除与之关联的静态 IP 地址。如果不再打算再次使用所配置的静态 IP 地址,请务必清理该 IP 地址。

如需配置静态 IP 地址,请完成以下步骤:

  1. 预留名为 web-static-ip静态外部 IP 地址

    gcloud

    gcloud compute addresses create web-static-ip --global
    

    Config Connector

    注意:此步骤需要使用配置连接器。按照安装说明在您的集群上安装配置连接器。

    apiVersion: compute.cnrm.cloud.google.com/v1beta1
    kind: ComputeAddress
    metadata:
      name: web-static-ip
    spec:
      location: global
    如需部署此清单,请将它以 compute-address.yaml 的形式下载到您的机器上,然后运行以下命令:
    kubectl apply -f compute-address.yaml

  2. basic-ingress-static.yaml 清单会在 Ingress 中添加注释,以使用名为 web-static-ip 的静态 IP 地址资源:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: basic-ingress
      annotations:
        kubernetes.io/ingress.global-static-ip-name: "web-static-ip"
    spec:
      defaultBackend:
        service:
          name: web
          port:
            number: 8080

    查看清单:

    cat basic-ingress-static.yaml
    
  3. 将资源应用到集群:

    kubectl apply -f basic-ingress-static.yaml
    
  4. 检查外部 IP 地址:

    kubectl get ingress basic-ingress
    

    等待应用的 IP 地址发生更改,以使用 web-static-ip 资源的预留 IP 地址。

    更新现有 Ingress 资源、重新配置负载均衡器并在全球范围传播负载均衡规则可能需要几分钟的时间。完成此操作后,GKE 会释放之前分配给应用的临时 IP 地址。

(可选)在负载均衡器上处理多个应用

您可以通过对 Ingress 配置路由规则,在单个负载均衡器和公共 IP 上运行多个服务。通过在同一 Ingress 上托管多个服务,您就不必为公开给互联网的每一个 Service 创建额外的负载均衡器(此为计费资源)。

下面的清单描述了同一 Web 应用的 2.0 版 Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web2
  namespace: default
spec:
  selector:
    matchLabels:
      run: web2
  template:
    metadata:
      labels:
        run: web2
    spec:
      containers:
      - image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0
        imagePullPolicy: IfNotPresent
        name: web2
        ports:
        - containerPort: 8080
          protocol: TCP

将资源应用到集群:

kubectl apply -f web-deployment-v2.yaml

下面的清单描述了一个在内部将 web2 公开给名为 web2 的 NodePort Service 上的集群:

apiVersion: v1
kind: Service
metadata:
  name: web2
  namespace: default
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: web2
  type: NodePort

将资源应用到集群:

kubectl apply -f web-service-v2.yaml

下面的清单描述了具备以下特点的 Ingress 资源:

  • 使用以 /v2/ 开头的路径将请求路由到 web2 Service
  • 将其他所有请求路由到 web Service
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: fanout-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        pathType: ImplementationSpecific
        backend:
          service:
            name: web
            port:
              number: 8080
      - path: /v2/*
        pathType: ImplementationSpecific
        backend:
          service:
            name: web2
            port:
              number: 8080

将资源应用到集群:

kubectl create -f fanout-ingress.yaml

部署 Ingress 后,请运行 kubectl get ingress fanout-ingress 来查找集群的公共 IP 地址。

然后,访问该 IP 地址,确定能否在同一负载均衡器上访问这两个应用:

  • 访问 http://<IP_ADDRESS>/ 并注意响应包含 Version: 1.0.0(因为该请求被路由到 web Service)
  • 访问 http://<IP_ADDRESS>/v2/ 并注意响应包含 Version: 2.0.0(因为该请求被路由到 web2 Service)

Ingress 的 path 字段唯一支持的通配符是 * 字符。* 字符必须紧跟在正斜线 (/) 之后,并且必须是格式中的最后一个字符。例如,/*/foo/*/foo/bar/* 是有效格式,但 */foo/bar*/foo/*/bar 不是有效格式。

较具体的格式优先于不太具体的格式。如果您同时拥有 /foo/*/foo/bar/*,则选择 /foo/bar/bat 来匹配 /foo/bar/*

如需详细了解路径限制和格式匹配,请参阅网址映射文档

(可选)监控服务的可用性和延迟时间

Google Cloud 拨测从用户的角度对应用进行黑盒监控,确定从多个外部 IP 到负载均衡器 IP 地址的延迟时间和可用性。相比之下,Google Cloud 健康检查会对 Pod IP 执行内部检查,确定实例级层的可用性。这两项检查是相辅相成的,它们可让您全面了解应用的运行状况。

您可以使用 Google Cloud 控制台、Cloud Monitoring API 或使用 Cloud Monitoring 客户端库来创建拨测。 如需了解相关信息,请参阅管理拨测。 如需使用 Google Cloud 控制台创建拨测,请执行以下操作:

  1. 转到 Google Cloud 控制台中的 Service 和 Ingress 页面。

    打开“Service 和 Ingress”

  2. 点击要为其创建拨测的 Service 的名称。

  3. 点击创建拨测

  4. 创建拨测窗格中,输入拨测的标题,然后点击下一步前往目标设置。

    拨测的目标字段自动填充 Service 负载平衡器中的信息。

    如需查看有关拨测中所有字段的完整文档,请参阅创建拨测

  5. 点击下一步前往响应验证设置。

  6. 点击下一步前往提醒和通知部分。

    如需监控拨测,您可以创建一个提醒政策或查看拨测信息中心。如果您的正常运行时间检查失败,提醒政策可以通过电子邮件或其他渠道通知您。如需了解有关提醒政策的常规信息,请参阅提醒简介

  7. 点击创建

备注

默认情况下,Ingress 通过在 / 路径上发出 GET 请求来执行定期健康检查,以确定应用的健康状况,并预期获得 HTTP 200 响应。如果要检查其他路径或预期获得其他响应代码,您可以使用自定义健康检查路径

Ingress 支持更高级的用例,例如:

  • 基于名称的虚拟托管:您可以使用 Ingress 对多个域名、子域名重复使用负载均衡器,并在单个 IP 地址和负载均衡器上公开多个 Service。如需了解如何为这些任务配置 Ingress,请查看简单扇出基于名称的虚拟托管示例。

  • HTTPS 终止:您可使用 Cloud Load Balancing 负载均衡器配置 Ingress 来终止 HTTPS 流量。

删除 Ingress 后,GKE Ingress 控制器会自动清理相关资源(预留的静态 IP 地址除外)。

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

  1. 删除所有手动创建的转发规则和引用 Ingress 的目标代理:

    引用 Ingress 控制器托管的网址映射的悬垂目标代理将导致 GKE 1.15.4-gke.22+ 版本中的 GKE Ingress 删除失败。您可以检查 Ingress 资源,以查找包含类似于以下内容的错误消息的事件:

     Error during GC: error running load balancer garbage collection routine: googleapi: Error 400: The url_map resource 'projects/project-id/global/urlMaps/k8s2-um-tlw9rhgp-default-my-ingress-9ifnni82' is already being used by 'projects/project-id/global/targetHttpsProxies/k8s2-um-tlw9rhgp-default-my82-target-proxy', resourceInUseByAnotherResource
     

    在上面的错误消息中,k8s2-um-tlw9rhgp-default-my82-target-proxy 是一个手动创建的目标 https 代理,该代理仍然引用由 Ingress 控制器创建和管理的网址映射 k8s2-um-tlw9rhgp-default-my-ingress-9ifnni82

    在删除 Ingress 之前,必须先删除这些手动创建的前端资源(包括转发规则和目标代理)。

  2. 删除 Ingress:此步骤将释放临时外部 IP 地址和与您的应用关联的负载均衡资源:

    kubectl delete ingress basic-ingress

    如果您遵循可选的步骤创建 Ingress 以按路径路由请求,则请删除 Ingress:

    kubectl delete ingress fanout-ingress

  3. 删除静态 IP 地址:仅在您遵循了可选步骤来创建静态 IP 地址时,才需要完成此步骤。

    • 如果您已按照“选项 1”将现有临时 IP 地址转换为静态 IP 地址,请访问 Google Cloud 控制台来删除该静态 IP 地址。

    • 如果您已按照“选项 2”创建新的静态 IP 地址,请运行以下命令来删除静态 IP 地址:

      gcloud compute addresses delete web-static-ip --global
  4. 删除集群:此步骤将删除容器集群的计算节点以及集群中的 Deployment 等其他资源:

    gcloud container clusters delete loadbalancedcluster

后续步骤