Kubernetes从入门到精通系列——外部 DNS 和全局负载均衡

在本章中,我们将在第 4 章所学的基础上进一步探讨。我们将讨论某些负载均衡器功能的局限性,以及如何配置集群来解决这些局限性。

我们知道 Kubernetes 内置了一个 DNS 服务器,可以动态地为资源分配名称。这些名称用于集群内部应用程序之间的通信,或者说集群内部的通信。虽然此功能对集群内的通信非常有用,但它并不为外部工作负载提供 DNS 解析。既然 Kubernetes 提供了 DNS 解析功能,为什么我们还说它存在局限性呢?

在前一章中,我们使用动态分配的 IP 地址来测试我们的 LoadBalancer 服务工作负载。虽然这些示例适合学习,但在企业中,没人愿意通过 IP 地址来访问运行在集群上的工作负载。为了解决这一局限性,Kubernetes SIG 开发了一个名为 ExternalDNS 的项目,该项目能够为 LoadBalancer 服务动态创建 DNS 条目。

此外,在企业中,你通常会运行多个集群上的服务,为应用程序提供故障切换支持。到目前为止,我们讨论的选项无法解决故障切换场景。在本章中,我们将解释如何实施解决方案,为工作负载提供自动化故障切换,使它们在多个集群上实现高可用性。

在本章中,你将学习以下内容:

  • 外部 DNS 解析和全局负载均衡简介
  • 在 Kubernetes 集群中配置和部署 ExternalDNS
  • 自动化 DNS 名称注册
  • 将 ExternalDNS 集成到企业 DNS 服务器中
  • 使用 GSLB(全局服务器负载均衡)在多个集群之间提供全局负载均衡

现在,让我们开始本章的内容!

技术要求

本章的技术要求如下:

  • 一台运行 Docker 的 Ubuntu 22.04+ 服务器,最低需要 4 GB 内存,推荐 8 GB
  • 一个运行 MetalLB 的 KinD 集群 ------ 如果你已经完成了第 4 章的内容,你应该已经有一个运行 MetalLB 的集群
  • 来自本书 GitHub 仓库中的 chapter5 文件夹的脚本,你可以通过访问本书的 GitHub 仓库获取:github.com/PacktPublis...

使服务名称对外部可用

正如我们在介绍中提到的,你可能还记得,我们使用 IP 地址来测试创建的 LoadBalancer 服务,而对于 Ingress 示例,我们使用了域名。那么,为什么我们必须为 LoadBalancer 服务使用 IP 地址而不是主机名呢?

虽然 Kubernetes 的负载均衡器为服务分配了标准的 IP 地址,但它不会自动生成 DNS 名称供工作负载访问该服务。相反,你必须依赖 IP 地址来连接集群中的应用程序,这会变得既混乱又低效。此外,手动为每个由 MetalLB 分配的 IP 注册 DNS 名称是一个维护上的挑战。为了提供更接近云服务的体验,并简化 LoadBalancer 服务的名称解析,我们需要一个附加组件来解决这些限制。

与维护 KinD 的团队类似,有一个 Kubernetes 特别兴趣小组(SIG)正在为 Kubernetes 开发名为 ExternalDNS 的功能。该项目的主页面可以在 SIG 的 GitHub 上找到:github.com/kubernetes-...

在撰写本文时,ExternalDNS 项目支持 34 种兼容的 DNS 服务,包括以下几种:

  • AWS Cloud Map
  • 亚马逊的 Route 53
  • Azure DNS
  • Cloudflare
  • CoreDNS
  • Google Cloud DNS
  • Pi-hole
  • RFC2136

如何扩展 CoreDNS 来解析外部名称有多种选择,具体取决于你正在运行的主要 DNS 服务器。许多受支持的 DNS 服务器将会动态注册任何服务。ExternalDNS 会看到创建的资源,并使用本地调用自动注册服务,像 Amazon 的 Route 53 一样。但并非所有的 DNS 服务器默认支持这种类型的动态注册。

在这些情况下,你需要手动配置主要的 DNS 服务器,将所需的域请求转发到集群中运行的 CoreDNS 实例中。这正是我们将在本章示例中使用的方法。

我们目前的 Kubernetes 集群使用 CoreDNS 处理集群内的 DNS 名称解析。然而,可能不太为人所知的是,CoreDNS 不仅仅用于集群内部的 DNS 解析。它还可以扩展其功能来执行外部名称解析,有效地解析由 CoreDNS 部署管理的任何 DNS 区域的名称。

现在,让我们继续了解如何安装 ExternalDNS。

设置 ExternalDNS

目前,我们的 CoreDNS 仅用于解析集群内部的名称,因此我们需要为新的 LoadBalancer DNS 条目设置一个区域。

在我们的示例中,FooWidgets 公司希望所有 Kubernetes 服务都进入 foowidgets.k8s 域,因此我们将使用该域作为新的 DNS 区域。

集成 ExternalDNS 和 CoreDNS

ExternalDNS 并不是一个实际的 DNS 服务器,它是一个控制器,会监视那些请求新 DNS 条目的对象。一旦控制器检测到请求,它会将信息发送给实际的 DNS 服务器,如 CoreDNS 进行注册。

下图展示了服务如何被注册的流程。

在我们的示例中,我们使用 CoreDNS 作为 DNS 服务器;然而,如前所述,ExternalDNS 支持 34 种不同的 DNS 服务,并且支持的服务列表还在不断增长。由于我们将使用 CoreDNS 作为 DNS 服务器,因此需要添加一个组件来存储 DNS 记录。为此,我们需要在集群中部署一个 ETCD 服务器。

在我们的示例部署中,我们将使用 ETCD 的 Helm chart。

Helm 是一个为 Kubernetes 设计的工具,可以更轻松地部署和管理应用程序。它使用 Helm chart,这些模板包含了应用程序的必要配置和资源值。Helm 自动化了复杂应用程序的设置,确保它们被一致且可靠地配置。它是一个非常强大的工具,许多项目和供应商都默认使用 Helm charts 来提供其应用程序。你可以在其主页上阅读更多关于 Helm 的信息:v3.helm.sh/

Helm 强大的一个原因是它能够使用自定义选项,这些选项可以在运行 helm install 命令时声明。同样的选项也可以在文件中声明,并通过 -f 选项传递给安装过程。这些选项使得部署复杂系统变得更加容易且可复制,因为相同的 values 文件可以用于任何部署。

在我们的部署示例中,我们包含了一个 values.yaml 文件,位于 chapter5/etcd 目录中,我们将使用它来配置我们的 ETCD 部署。

现在,终于到了部署 ETCD 的时候!我们在 chapter5/etcd 目录中提供了一个名为 deploy-etcd.sh 的脚本,它将在名为 etcd-dns 的新命名空间中使用单副本部署 ETCD。请在 chapter5/etcd 目录中执行该脚本。

借助 Helm,该脚本只有两个命令 ------ 它将创建一个新命名空间,然后执行 helm install 命令来部署我们的 ETCD 实例。在实际应用中,你可能希望将副本数量更改为至少 3 个,以实现高可用的 ETCD 部署,但为了限制我们的 KinD 服务器的资源需求,我们使用单副本部署。

现在,我们已经有了用于 DNS 的 ETCD,接下来我们将把 CoreDNS 服务与新的 ETCD 部署集成。

向 CoreDNS 添加 ETCD 区域

如上节图示所示,CoreDNS 将把 DNS 记录存储在一个 ETCD 实例中。这需要我们配置一个 CoreDNS 服务器,指定我们希望注册名称的 DNS 区域以及存储记录的 ETCD 服务器。

为了降低资源需求,我们将使用大多数 Kubernetes 安装中包含的 CoreDNS 服务器来处理新域名的解析。在实际生产环境中,建议部署一个专用的 CoreDNS 服务器,仅处理 ExternalDNS 的注册。

在本节的最后,你将执行一个脚本,该脚本将部署一个完全配置好的 ExternalDNS 服务,包含本节讨论的所有选项和配置。本节中的命令仅供参考,你无需在集群上手动执行,因为脚本会为你处理所有步骤。

在我们能够集成 CoreDNS 之前,需要知道新的 ETCD 服务的 IP 地址。你可以通过使用 kubectl 命令列出 etcd-dns 命名空间中的服务来获取该地址:

arduino 复制代码
kubectl get svc etcd-dns -n etcd-dns

这将显示我们的 ETCD 服务及其 IP 地址:

scss 复制代码
NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
etcd-dns   ClusterIP   10.96.149.223   <none>        2379/TCP,2380/TCP   4m

服务列表中显示的 Cluster-IP 将用于配置新的 DNS 区域,以作为存储 DNS 记录的位置。

在部署 ExternalDNS 时,你可以通过以下两种方式配置 CoreDNS:

  1. 向 Kubernetes 集成的 CoreDNS 服务添加一个区域
  2. 部署一个新的 CoreDNS 服务,该服务将用于 ExternalDNS 注册

为了简化测试,我们将向 Kubernetes CoreDNS 服务添加一个区域。这需要我们编辑位于 kube-system 命名空间中的 CoreDNS ConfigMap。当你执行本节最后的脚本时,这些修改将会自动完成。下面的粗体部分是我们将要添加到 ConfigMap 中的部分:

yaml 复制代码
apiVersion: v1
data:
  Corefile: |
    .:53 {
      errors
      health {
         lameduck 5s
      }
      ready
      kubernetes cluster.local in-addr.arpa ip6.arpa {
         pods insecure
         fallthrough in-addr.arpa ip6.arpa
         ttl 30
      }
      prometheus :9153
      forward . /etc/resolv.conf
      **etcd foowidgets.k8s {
        stubzones
        path /skydns
        endpoint http://10.96.149.223:2379
      }**
      cache 30
      loop
      reload
      loadbalance
    }

添加的行配置了一个名为 foowidgets.k8s 的 ETCD 集成区域。我们添加的第一行告诉 CoreDNS,区域名称 foowidgets.k8s 与 ETCD 服务集成。

接下来的 stubzones 行告诉 CoreDNS 允许将 DNS 服务器设置为某个区域的"stub 解析器"。作为一个 stub 解析器,该 DNS 服务器直接查询特定区域的名称服务器,而无需在整个 DNS 层次结构中进行递归解析。

第三个添加的是 path /skydns 选项,这可能看起来有些困惑,因为它并没有提到 CoreDNS。尽管值是 skydns,它也是 CoreDNS 集成的默认路径。

最后一行告诉 CoreDNS 在何处存储记录。在我们的示例中,我们的 ETCD 服务运行在 IP 地址 10.96.149.223 上,使用默认的 ETCD 端口 2379。

你也可以在这里使用服务的主机名而不是 IP 地址。我们使用 IP 地址是为了展示 Pod 和服务之间的关系,但主机名 etcd-dns.etcd-dns.svc 也同样有效。选择哪种方式取决于具体情况。在我们的 KinD 集群中,我们不必担心丢失 IP 地址,因为集群是临时的。而在生产环境中,使用主机名可以避免因 IP 地址更改带来的问题。

现在你已经了解如何在 CoreDNS 中添加 ETCD 集成区域,下一步是更新 ExternalDNS 所需的部署选项,以便与 CoreDNS 集成。

ExternalDNS 配置选项

ExternalDNS 可以配置为注册 Ingress 或服务对象。这是通过 ExternalDNS 的部署文件中的 source 字段配置的。下面的示例显示了我们将在本章中使用的部署选项部分。

我们还需要配置 ExternalDNS 将使用的提供程序(provider),由于我们使用的是 CoreDNS,因此我们将 provider 设置为 coredns

最后一个选项是日志级别。我们将其设置为 info,这样可以使日志文件更小且易于阅读。以下是我们将使用的参数:

sql 复制代码
    spec:
      serviceAccountName: external-dns
      containers:
      - name: external-dns
        image: registry.k8s.io/external-dns/external-dns:v0.13.5
        args:
        - --source=service
        - --provider=coredns
        - --log-level=info

现在我们已经介绍了 ETCD 选项和部署,如何配置使用 ETCD 的新区域,以及如何配置 ExternalDNS 以使用 CoreDNS 作为提供程序,我们可以在集群中部署 ExternalDNS。

我们在 chapter5/externaldns 文件夹中包含了一个名为 deploy-externaldns.sh 的脚本。请在该目录中执行脚本,将 ExternalDNS 部署到你的 KinD 集群中。执行脚本时,它将完全配置并部署一个与 ETCD 集成的 ExternalDNS。

注意:

如果在脚本更新 ConfigMap 时看到警告,可以忽略它。由于我们的 kubectl 命令使用 apply 来更新对象,Kubernetes 会查找 last-applied-configuration 注解,如果设置了该注解。由于现有对象中可能没有这个注解,你会看到缺少它的警告。这只是一个警告,不会阻止 ConfigMap 的更新。你可以通过查看 kubectl update 命令的最后一行确认更新是否成功,输出会显示 ConfigMap 已更新:configmap/coredns configured

现在,我们已经添加了开发人员能够为其服务动态注册 DNS 名称的功能。接下来,让我们通过创建一个新的服务,看看它如何在 CoreDNS 服务器中自动注册。

创建与 ExternalDNS 集成的 LoadBalancer 服务

ExternalDNS 会监视所有服务,查找包含所需 DNS 名称的注解。该注解的格式为 external-dns.alpha.kubernetes.io/hostname,其值是你想要注册的 DNS 名称。在我们的示例中,我们希望注册 nginx.foowidgets.k8s 这个名称,因此我们会将注解添加到 NGINX 服务中:external-dns.alpha.kubernetes.io/hostname: nginx.foowidgets.k8s

chapter5/externaldns 目录中,我们包含了一个 manifest 文件,它将使用包含注解的 LoadBalancer 服务来部署一个 NGINX Web 服务器以注册 DNS 名称。

使用以下命令部署 manifest,该命令会将资源部署到默认的命名空间中:

lua 复制代码
kubectl create -f nginx-lb.yaml

该部署是一个标准的 NGINX 部署,但服务包含了所需的注解,告诉 ExternalDNS 服务你希望注册一个新的 DNS 名称。服务的 manifest 文件如下所示,注解部分用粗体标出:

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  annotations:
    external-dns.alpha.kubernetes.io/hostname: nginx.foowidgets.k8s
  name: nginx-ext-dns
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: LoadBalancer

当 ExternalDNS 看到该注解时,它会在指定区域中注册请求的名称。注解中的主机名将在 ExternalDNS pod 中记录一个条目,下面展示了 nginx.foowidgets.k8s 的注册信息:

sql 复制代码
time="2023-08-04T19:16:00Z" level=debug msg="Getting service (&{ 0 10 0 "heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/nginx-ext-dns" false 0 1  /skydns/k8s/foowidgets/a-nginx/39ca730e}) with service host ()"
time="2023-08-04T19:16:00Z" level=debug msg="Getting service (&{172.18.200.101 0 10 0 "heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/nginx-ext-dns" false 0 1  /skydns/k8s/foowidgets/nginx/02b5d1d5}) with service host (172.18.200.101)"
time="2023-08-04T19:16:00Z" level=debug msg="Creating new ep (nginx.foowidgets.k8s 0 IN A  172.18.200.101 []) with new service host (172.18.200.101)"

正如日志的最后一行所示,记录被添加为 DNS 服务器中的 A 记录,指向 IP 地址 172.18.200.101

确认 ExternalDNS 完全正常工作的最后一步是测试与应用程序的连接。由于我们使用的是 KinD 集群,必须在集群中的 pod 进行测试。如果需要将新域名提供给外部资源,需要将主 DNS 服务器配置为将 foowidgets.k8s 域的请求转发到 CoreDNS 服务器。我们将在本节末展示如何将 Windows DNS 服务器(或网络中的任何主 DNS 服务器)与 Kubernetes CoreDNS 服务器集成。

现在,我们可以使用注解中的 DNS 名称来测试 NGINX 部署。由于你没有使用 CoreDNS 服务器作为主 DNS 提供程序,我们需要在集群中的容器中测试名称解析。这里有一个名为 Netshoot 的很棒的实用工具,包含了许多有用的故障排除工具;这是一个非常好的工具,用于测试和排查集群和 pod 的问题。

要运行一个 Netshoot 容器,可以使用 kubectl run 命令。我们只需在使用该 pod 进行集群测试时运行它,因此可以通过 kubectl run 命令以交互式 shell 方式运行,并在退出后删除该 pod。运行 Netshoot 的命令如下:

bash 复制代码
kubectl run tmp-shell --rm -i --tty --image nicolaka/netshoot -- /bin/bash

pod 启动可能需要一两分钟,但一旦启动,你会看到一个 tmp-shell 提示符。在该提示符下,我们可以使用 nslookup 来验证 DNS 条目是否成功添加。如果你尝试查找 nginx.foowidgets.k8s,应该会收到包含服务 IP 地址的回复。

nslookup nginx.foowidgets.k8s

你的回复应该类似于以下示例:

yaml 复制代码
Server:		10.96.0.10
Address:	10.96.0.10#53
Name:   nginx.foowidgets.k8s
Address: 172.18.200.101

这确认了我们的注解是成功的,ExternalDNS 已经在 CoreDNS 服务器中注册了我们的主机名。

nslookup 只证明了 nginx.foowidgets.k8s 的条目存在,它并没有测试应用程序。为了验证我们有一个成功的部署,并且当用户在浏览器中输入该名称时可以正常工作,我们可以使用 Netshoot 中包含的 curl 实用工具进行测试。

curl 输出确认我们可以使用动态创建的服务名称来访问 NGINX Web 服务器。

我们意识到,这些测试中的一些可能不那么直观和有趣,因为你无法通过标准浏览器进行测试。为了使 CoreDNS 在集群外部可用,我们需要将 CoreDNS 与主 DNS 服务器集成,该服务器需要将某些区域的所有权委派给 CoreDNS。当你委派一个区域时,任何对主 DNS 服务器的该区域内主机的请求都会被转发到包含该区域的 DNS 服务器。

在接下来的部分中,我们将把运行在集群中的 CoreDNS 与 Windows DNS 服务器集成。虽然我们使用的是 Windows DNS 服务器,但不同操作系统和 DNS 服务器之间的区域委派概念基本相同。

将 CoreDNS 与企业 DNS 服务器集成

本节将展示如何使用主 DNS 服务器将 foowidgets.k8s 区域的名称解析请求转发到 Kubernetes 集群中运行的 CoreDNS 服务器。

此处提供的步骤是将企业 DNS 服务器与 Kubernetes DNS 服务集成的示例。由于外部 DNS 需求和额外的设置,步骤仅供参考,不应在你的 KinD 集群上执行

要在委派的区域中查找记录,主 DNS 服务器使用一种称为递归查询的过程。递归查询是指由 DNS 解析器发起的 DNS 查询,该解析器代表用户进行操作。在递归查询过程中,DNS 解析器负责以分层方式与多个 DNS 服务器通信,目的是找到请求域的权威 DNS 服务器,并启动请求的 DNS 记录的检索。

下图展示了通过将区域委派给企业环境中的 CoreDNS 服务器来提供 DNS 解析的流程。

  1. 本地客户端会先检查其 DNS 缓存中是否有请求的名称。

  2. 如果名称不在本地缓存中,客户端会向主 DNS 服务器请求 nginx.foowidgets.k8s

  3. DNS 服务器接收到查询请求,并检查它所知道的区域。它发现 foowidgets.k8s 区域,并且看到该区域已被委派给运行在 192.168.1.200 的 CoreDNS。

  4. 主 DNS 服务器将查询发送给被委派的 CoreDNS 服务器。

  5. CoreDNS 在 foowidgets.k8s 区域中查找名称 nginx

  6. CoreDNS 将 foowidgets.k8s 的 IP 地址返回给主 DNS 服务器。

  7. 主 DNS 服务器将包含 nginx.foowidgets.k8s 地址的回复发送给客户端。

  8. 客户端使用从 CoreDNS 返回的 IP 地址连接到 NGINX 服务器。

现在,我们来看一个实际的例子。在我们的场景中,主 DNS 服务器运行在 Windows 2019 服务器上,并且我们将一个区域委派给 CoreDNS 服务器。

部署的组件如下:

  • 我们的网络子网是 10.2.1.0/24
  • 运行 DNS 的 Windows 2019 或更高版本的服务器
  • 一个 Kubernetes 集群
  • 一个 MetalLB 地址池,范围为 10.2.1.70-10.2.1.75
  • 集群中部署的 CoreDNS 实例,使用 LoadBalancer 服务,分配了来自 IP 池的 10.2.1.74 地址
  • 本章配置的附加组件,包括 ExternalDNS、CoreDNS 的 ETCD 部署以及一个新的 CoreDNS ETCD 集成区域
  • 用于测试委派的 Bitnami NGINX 部署

现在,让我们逐步完成集成 DNS 服务器的配置步骤。

将 CoreDNS 暴露给外部请求

我们已经介绍了如何部署大部分集成所需的资源 ------ ETCD、ExternalDNS,以及配置了 ETCD 集成的新 CoreDNS 区域。为了使 CoreDNS 对外部访问,我们需要创建一个新的服务,将 CoreDNS 暴露在 TCP 和 UDP 的 53 端口上。完整的服务 manifest 如下所示:

yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: CoreDNS
  name: kube-dns-ext
  namespace: kube-system   
spec:
  ports:
  - name: dns
    port: 53
    protocol: UDP
    targetPort: 53
  selector:
    k8s-app: kube-dns
  type: LoadBalancer
  loadBalancerIP: 10.2.1.74

此服务中有一个我们尚未讨论的新选项 ------ 我们在部署中添加了 spec.loadBalancerIP。此选项允许你为服务分配一个 IP 地址,使其拥有一个稳定的 IP 地址,即使服务被重新创建也不会改变。我们需要一个静态 IP,因为我们需要从主 DNS 服务器启用到 Kubernetes 集群中 CoreDNS 服务器的转发。

一旦 CoreDNS 使用 LoadBalancer 在 53 端口上暴露后,我们可以配置主 DNS 服务器,将 foowidgets.k8s 域中的主机请求转发到我们的 CoreDNS 服务器。

配置主 DNS 服务器

在我们的主 DNS 服务器上,首先要做的是为运行 CoreDNS pod 的节点创建一个条件转发器。

在 Windows DNS 主机上,我们需要为 foowidgets.k8s 创建一个新的条件转发器,指向我们为新的 CoreDNS 服务分配的 IP 地址。在我们的示例中,CoreDNS 服务被分配到主机 10.2.1.74

这将配置 Windows DNS 服务器,将任何 foowidgets.k8s 域中主机的请求转发到运行在 IP 地址 10.2.1.74 上的 CoreDNS 服务。

测试 DNS 转发到 CoreDNS

为了测试配置,我们将在主网络上使用已配置使用 Windows DNS 服务器的工作站。

我们将运行的第一个测试是对通过 MetalLB 注解创建的 NGINX 记录进行 nslookup 查询:

在命令提示符下,执行以下命令:

nslookup nginx.foowidgets.k8s

输出示例如下:

makefile 复制代码
Server:  AD2.hyper-vplanet.com
Address:  10.2.1.14
Name:    nginx.foowidgets.k8s
Address:  10.2.1.75

由于查询返回了我们预期的记录 IP 地址,可以确认 Windows DNS 服务器正在正确地将请求转发到 CoreDNS。

我们还可以从笔记本电脑的浏览器中进一步测试 NGINX。在 Chrome 浏览器中,我们可以使用 CoreDNS 中注册的 URL:nginx.foowidgets.k8s 进行访问。

一次测试确认了转发工作正常,但我们希望创建一个额外的部署来验证系统是否完全正常运行。

为了测试一个新的服务,我们部署了一个名为 microbot 的不同的 NGINX 服务器,其服务带有一个注解,分配名称为 microbot.foowidgets.k8s。MetalLB 为该服务分配了 IP 地址 10.2.1.65

与之前的测试一样,我们使用 nslookup 来测试名称解析:

makefile 复制代码
Name:    AD2.hyper-vplanet.com
Address:  10.2.1.65

为了确认 Web 服务器运行正常,我们可以从工作站浏览器访问该 URL 进行验证。

成功!我们现在已经将企业 DNS 服务器与运行在 Kubernetes 集群中的 CoreDNS 服务器集成。此集成为用户提供了通过在服务中简单添加注解动态注册服务名称的能力。

在多个集群之间实现负载均衡

在多个集群中运行服务可以通过多种方式配置,通常涉及复杂且昂贵的附加组件,比如全局负载均衡器。全局负载均衡器可以被视为一个交通指挥员 ------ 它知道如何在多个端点之间引导传入流量。

从高层次来看,你可以创建一个新的 DNS 条目,由全局负载均衡器控制。这个新条目将会把后端系统添加到端点列表中,并根据健康状况、连接数量或带宽等因素,将流量引导到相应的端点节点。如果某个端点由于某种原因不可用,负载均衡器将其从端点列表中移除。通过将其移除,流量只会被发送到健康的节点,从而为终端用户提供平稳的使用体验。对于用户来说,没有什么比访问网站时遇到 "网站无法找到" 错误更糟糕的了。

上图展示了一个健康的工作流程,其中两个集群都在运行我们在集群之间进行负载均衡的应用程序。当请求到达负载均衡器时,它会以轮询的方式在两个集群之间分配流量。nginx.foowidgets.k8s 请求最终会将流量发送到 nginx.clustera.k8snginx.clusterb.k8s

图 5.8 中,集群 B 中的 NGINX 工作负载出现故障。由于全局负载均衡器对正在运行的工作负载进行了健康检查,它将会从 nginx.foowidgets.k8s 条目中移除集群 B 的端点。

现在,任何请求 nginx.foowidgets.k8s 的流量都会被负载均衡器引导到集群 A 上的唯一可用端点。一旦集群 B 的问题解决,负载均衡器会自动将集群 B 的端点重新添加到 nginx.foowidgets.k8s 记录中。

这种解决方案在企业中非常常见,许多组织使用 F5、Citrix、Kemp 和 A10 等公司的产品,以及 CSP 原生的解决方案(如 Route 53 和 Traffic Director)来管理多个集群中的工作负载。然而,也有一些与 Kubernetes 集成且成本较低甚至免费的项目。虽然这些项目可能没有一些供应商解决方案的全部功能,但它们通常能满足大多数用例需求,无需昂贵的功能集。

其中一个这样的项目是 K8GB,一个创新的开源项目,它将全球服务器负载均衡(GSLB)带入 Kubernetes。通过 K8GB,组织可以轻松地将传入的网络流量分布到位于不同地理位置的多个 Kubernetes 集群中。通过智能路由请求,K8GB 保证了低延迟、最佳响应时间和冗余性,是企业的一种出色解决方案。

本节将向你介绍 K8GB 。如果你想了解更多该项目的详情,可以访问其主页 www.k8gb.io

由于我们使用的是 KinD 和单个主机的集群,本书的这一部分旨在介绍该项目及其提供的优势。该部分仅供参考,因为这是一个复杂的主题,涉及多个组件,其中一些超出了 Kubernetes 的范围。如果你决定自己实施一个解决方案,我们在书的仓库中提供了示例文档和脚本,位于 chapter5/k8gs-example 目录下。

K8GB 是一个 CNCF 沙盒项目,这意味着它还处于早期阶段,在本章撰写之后的任何新版本中,可能会对对象和配置进行更改。

介绍 Kubernetes 全球负载均衡器

为什么你应该关注像 K8GB 这样的项目呢?

让我们以内部企业云为例,它在生产站点运行一个 Kubernetes 集群,并在灾难恢复站点运行另一个集群。为了确保顺畅的用户体验,重要的是使应用程序能够在这些数据中心之间无缝切换,而无需在灾难恢复事件中进行任何手动干预。挑战在于满足企业对微服务高可用性的需求,当多个集群同时为这些应用程序提供服务时,我们需要有效解决跨多个地理分散的 Kubernetes 集群的持续和不间断服务需求。

这正是 K8GB 发挥作用的地方。

**K8GB 为什么是满足高可用性需求的理想解决方案?**根据其网站上的文档,关键功能包括:

  • 通过非常可靠的、适用于全球部署的 DNS 协议提供负载均衡
  • 不需要管理集群
  • 没有单点故障
  • 使用 Kubernetes 原生健康检查来进行负载均衡决策
  • 配置简单,仅需一个 Kubernetes CRD
  • 适用于任何 Kubernetes 集群 ------ 无论是本地还是云端
  • 免费!

正如你将在本节中看到的,K8GB 提供了简单直观的配置,使得为你的组织提供全球负载均衡变得轻而易举。尽管它看起来功能简单,但在幕后它提供了许多高级功能,包括:

  • 全球负载均衡:将传入的网络流量分配到位于不同地理区域的多个 Kubernetes 集群,从而实现优化的应用程序交付,确保降低延迟并提升用户体验。
  • 智能流量路由:利用复杂的路由算法,根据接近度、服务器健康状况和应用程序特定规则,将客户端请求智能地引导至最接近或最适合的 Kubernetes 集群。这种方法确保了高效、快速响应的流量管理,优化了应用程序性能。
  • 高可用性和冗余:通过自动重定向流量,保证应用程序的高可用性和容错能力,在集群、应用程序或数据中心发生故障时实现故障切换。此故障切换机制最大限度地减少灾难恢复场景中的停机时间,确保用户的服务不间断交付。
  • 自动故障切换:通过启用数据中心之间的自动故障切换简化操作,消除了人为触发的灾难恢复(DR)事件或任务的需求,确保快速、不间断的服务交付和简化的操作。
  • 与 Kubernetes 集成:提供与 Kubernetes 的无缝集成,简化了在集群上部署应用程序的全球服务器负载均衡(GSLB)的设置和配置。通过利用 Kubernetes 的原生能力,K8GB 提供了一个可扩展的解决方案,增强了全球负载均衡操作的整体管理和效率。
  • 本地和云提供商支持:为企业提供有效管理多个 Kubernetes 集群 GSLB 的方法,使其能够轻松处理复杂的多区域部署和混合云场景。这确保了不同环境中的优化应用程序交付,提升了基础设施的整体性能和弹性。
  • 定制化和灵活性:为用户提供定义个性化流量路由规则和策略的自由,允许组织根据其特定需求精确定制 GSLB 配置。这使企业能够根据其具体需求优化流量管理,确保无缝适应不断变化的应用程序需求。
  • 监控、指标和追踪:包括监控、指标和追踪功能,使管理员能够访问跨多个集群的流量模式、健康状况和性能指标的洞察。这提供了增强的可见性,使管理员能够做出明智的决策并优化 GSLB 设置的整体性能和可靠性。

现在我们已经讨论了 K8GB 的主要功能,接下来让我们深入了解其详细内容。

K8GB 的要求

对于像全球负载均衡这样复杂功能的产品,K8GB 并不需要大量基础设施或资源来为集群提供负载均衡。到本章撰写时,最新版本是 0.12.2,它只有少量的几个要求:

  • CoreDNS 服务器的负载均衡 IP 地址 ,位于主 DNS 区域中,使用命名标准 gslb-ns-<k8gb-name>-gb.foowidgets.k8s,例如 gslb-ns-us-nyc-gb.foowidgets.k8sgslb-ns-us-buf-gb.foowidgets.k8s

  • 如果你在使用 K8GB 时采用了像 Route 53InfobloxNS1 等服务,CoreDNS 服务器将会自动添加到域中。由于我们的示例使用了运行在 Windows 2019 服务器上的本地 DNS 服务器,因此我们需要手动创建这些记录。

  • Ingress 控制器

  • 在集群中部署的 K8GB 控制器,它将部署:

    • K8GB 控制器
    • 带有 CoreDNS CRD 插件配置的 CoreDNS 服务器(此项包含在 K8GB 的部署中)。

由于我们已经在之前的章节中探讨了 NGINX Ingress 控制器,现在我们将重点放在额外的需求上:在集群中部署和配置 K8GB 控制器。

在接下来的部分中,我们将讨论实施 K8GB 的步骤。

将 K8GB 部署到集群

我们在 GitHub 仓库的 chapter5/k8gb-example 目录下包含了示例文件。脚本基于本章剩余部分的示例。如果你决定在开发集群中使用这些文件,你需要满足以下要求:

  • 两个 Kubernetes 集群(每个集群可以是单节点的 kubeadm 集群)
  • 每个集群中部署了 CoreDNS
  • 每个集群中部署了 K8GB
  • 一个边缘 DNS 服务器,用于委派 K8GB 的域

安装 K8GB 非常简单 ------ 你只需要使用配置好的 values.yaml 文件部署单个 Helm chart。

要安装 K8GB,你需要将 K8GB 仓库添加到 Helm 仓库列表中,然后更新 chart:

csharp 复制代码
helm repo add k8gb https://www.k8gb.io
helm repo update

在执行 helm install 命令之前,我们需要为每个集群部署自定义 values.yaml 文件。我们在 chapter5/k8gb-example 目录中为示例中的两个集群分别包含了 k8gb-buff-values.yamlk8gb-nyc-values.yaml 文件。在 自定义 Helm chart 配置 部分将讨论这些文件中的选项。

了解 K8GB 的负载均衡选项

在我们的示例中,我们将 K8GB 配置为两个本地集群之间的故障切换负载均衡器。然而,K8GB 并不仅限于故障切换。与大多数负载均衡器一样,K8GB 提供了多种解决方案,可根据不同负载均衡的 URL 进行不同的配置。它提供了最常用的策略,包括轮询、加权轮询、故障切换和 GeoIP。

每种策略如下所述:

  • 轮询:如果未指定策略,默认将使用简单的轮询负载均衡配置。使用轮询意味着请求将分配到配置的集群 ------ 请求 1 将发送到集群 1,请求 2 将发送到集群 2,依此类推。

  • 加权轮询:与轮询类似,此策略允许指定发送到某个集群的流量百分比。例如,75% 的流量将发送到集群 1,15% 的流量将发送到集群 2。

  • 故障切换:所有流量将发送到主集群,除非主集群的所有 pod 均不可用。如果集群 1 中的所有 pod 均停止运行,集群 2 将接管工作负载,直到集群 1 中的 pod 恢复,此时集群 1 将重新成为主集群。

  • GeoIP :将请求引导到距离客户端最近的集群。如果最近的主机宕机,将使用类似于故障切换策略的其他集群。要使用此策略,你需要创建一个 GeoIP 数据库(示例见此处),并且你的 DNS 服务器需要支持 EDNS0 扩展。

    EDNS0 基于 RFC 2671,描述了 EDNS0 的工作原理及其各种组件,包括启用 EDNS0 的 DNS 消息格式、EDNS0 选项结构以及其实现指南。RFC 2671 的目标是提供一个标准化的方法,以扩展 DNS 协议的功能,超越其原有的限制,允许整合新功能、选项和增强功能。

现在你已经了解了可用的策略,接下来我们将介绍我们的集群基础设施示例:

集群/服务器详细信息

详细信息 说明
企业 DNS 服务器 -- 纽约市 IP: 10.2.1.14
主企业区域 foowidgets.k8s
CoreDNS 服务器的主机记录 gslb-ns-us-nyc-gb.foowidgets.k8sgslb-ns-us-buf-gb.foowidgets.k8s
全局域配置,委派给集群中的 CoreDNS 服务器 gb.foowidgets.k8s
纽约市,纽约 -- 集群 1 主站点
CoreDNS LB IP 10.2.1.221
Ingress IP 10.2.1.98
使用 HostPort 暴露的 NGINX Ingress 控制器
使用 MetalLB 暴露的 CoreDNS 部署
布法罗,纽约 -- 集群 2 次要站点
CoreDNS LB IP 10.2.1.224
Ingress IP 10.2.1.167
使用 HostPort 暴露的 NGINX Ingress 控制器
使用 MetalLB 暴露的 CoreDNS 部署

表 5.1:集群详细信息

我们将使用上表中的详细信息来解释如何在我们的示例基础设施中部署 K8GB。

有了基础设施的详细信息后,我们可以为每次部署创建 Helm values.yaml 文件。在接下来的部分中,我们将展示如何使用示例基础设施来配置这些值,并解释每个值的含义。

自定义 Helm chart 配置

每个集群将有类似的 values.yaml 文件,主要的变化是我们使用的标记值。下面是纽约市集群的 values.yaml 文件示例:

yaml 复制代码
k8gb:
  dnsZone: "gb.foowidgets.k8s" 
  edgeDNSZone: "foowidgets.k8s" 
  edgeDNSServers:
    - 10.2.1.14     
  clusterGeoTag: "us-buf" 
  extGslbClustersGeoTags: "us-nyc"
coredns:
  isClusterService: false
  deployment:
    skipConfig: true
  image:
    repository: absaoss/k8s_crd
    tag: v0.0.11
  serviceAccount:
    create: true
    name: coredns
  serviceType: LoadBalancer

纽约市集群(NYC 集群)文件的 clusterGeoTagextGslbClustersGeoTags 值需要设置为:

vbnet 复制代码
clusterGeoTag: "us-nyc"
extGslbClustersGeoTags: "us-buf"

如你所见,配置并不复杂,只需要少量选项即可配置一个通常较为复杂的全球负载均衡设置。

主要配置细节解释

我们将解释 K8GB 部分中的值,这些值配置了 K8GB 将用于负载均衡的所有选项:

配置项 描述
dnsZone 这是 K8GB 将使用的 DNS 区域,主要用于存储我们全球负载均衡的 DNS 记录。
edgeDNSZone 主 DNS 区域,包含 CoreDNS 服务器的 DNS 记录,这些记录由 dnsZone 使用。
edgeDNSServers 边缘 DNS 服务器,通常是用于名称解析的主 DNS 服务器。
clusterGeoTag 如果你有多个 K8GB 控制器,此标记用于区分不同实例。在我们的示例中,我们将其设置为 us-bufus-nyc,对应我们的集群。
extGslbClustersGeoTags 指定要配对的其他 K8GB 控制器。在我们的示例中,每个集群添加了另一个集群的 clusterGeoTag
isClusterService 设置为 truefalse,用于服务升级。
exposeCoreDNS 如果设置为 true,将创建一个 LoadBalancer 服务,暴露在 K8GB 命名空间内的 CoreDNS 服务,使用 53/UDP 端口进行外部访问。
deployment.skipConfig 设置为 truefalse。设置为 false 时,将使用 K8GB 内置的 CoreDNS。
image.repository 配置 CoreDNS 镜像的仓库。
image.tag 配置拉取镜像时使用的标签。
serviceAccount.create 设置为 truefalse。如果设置为 true,将创建一个服务账户。
serviceAccount.name 设置服务账户的名称。
serviceType 配置 CoreDNS 的服务类型。

使用 Helm 安装 K8GB

在了解了 K8GB 的 Helm 配置文件后,我们可以继续在集群中安装 K8GB。我们在 chapter5/k8gb-example/k8gb 目录下提供了用于在布法罗和纽约集群中部署 K8GB 的脚本。你会看到两个脚本 deploy-k8gb-buf.shdeploy-k8gb-nyc.sh,应分别在相应的集群中运行。

该脚本将执行以下步骤:

  1. 将 K8GB Helm 仓库添加到服务器的仓库列表中。
  2. 更新仓库。
  3. 使用相应的 Helm 配置文件部署 K8GB。
  4. 创建一个 Gslb 记录(在下一部分介绍)。
  5. 在名为 demo 的命名空间中创建一个用于测试的部署。

一旦部署完成,你将在 k8gb 命名空间中看到两个正在运行的 pod,一个是 K8GB 控制器,另一个是将用于解析负载均衡名称的 CoreDNS 服务器:

sql 复制代码
NAME                           READY   STATUS    RESTARTS    AGE
k8gb-8d8b4cb7c-mhglb           1/1     Running   0           7h58m
k8gb-coredns-7995d54db5-ngdb2  1/1     Running   0           7h37m

我们还可以验证服务是否已创建以处理传入的 DNS 请求。由于我们使用了 LoadBalancer 类型的服务,我们会看到一个使用 UDP 协议的 53 端口的 LoadBalancer 服务:

scss 复制代码
NAME		TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)		AGE   
k8gb-coredns	LoadBalancer   10.96.185.56   10.2.1.224    53:32696/UDP	2d18h

在两个集群中成功部署并验证了 K8GB 后,接下来我们将解释如何为我们的负载均衡区域创建边缘委派。

委派我们的负载均衡区域

在我们的示例中,我们使用 Windows 服务器作为边缘 DNS 服务器,K8s 的 DNS 名称将在这里注册。在 DNS 方面,我们需要为我们的 CoreDNS 服务器添加两个 DNS 记录,然后将负载均衡区域委派给这些服务器。

这两个 A 记录需要位于主边缘 DNS 区域中。在我们的示例中,主区域是 foowidgets.k8s。在此区域中,我们需要为通过 LoadBalancer 服务暴露的 CoreDNS 服务器添加两个条目:

rust 复制代码
gslb-ns-us-nyc-gb.foowidgets.k8s -> 10.2.1.221
gslb-ns-us-buf-gb.foowidgets.k8s -> 10.2.1.224

这些记录将告诉 DNS 系统,当请求 foowidgets.k8s 区域中的名称时,应该将请求转发到这两个 CoreDNS 服务器。下一步是将 gb.foowidgets.k8s 区域的管理权委派给这两个服务器。这样,所有指向 gb.foowidgets.k8s 的请求都将由 CoreDNS 服务器处理,确保请求能够在不同的 Kubernetes 集群之间进行负载均衡。

接下来,我们需要创建一个新的委派区域,该区域将用于我们的负载均衡服务名称。在 Windows 中,可以通过右键点击区域并选择"新建委派"(New Delegation)来完成此操作。在委派向导中,系统会要求输入"委派域名"(Delegated domain)。在我们的示例中,我们将 gb 作为要委派的域。

在输入区域名称并点击"下一步"后,您将看到一个用于添加委派域名的 DNS 服务器的新页面;当您点击"添加"时,您将输入 CoreDNS 服务器的 DNS 名称。请记住,我们在主域 foowidgets.com 中创建了两个 A 记录。当您添加条目时,Windows 会验证输入的名称是否正确解析,并确保 DNS 查询正常工作。一旦您添加了两个 CoreDNS 服务器,摘要页面将显示它们的名称和对应的 IP 地址。

这就完成了边缘服务器的配置。对于某些边缘服务器,K8GB 会自动创建委派记录,但只有少数服务器兼容该功能。对于不能自动创建委派记录的边缘服务器,您需要像本节中所做的那样手动创建它们。

现在我们已经在集群中配置了 CoreDNS,并委派了负载均衡区域,接下来我们将部署一个具有全球负载均衡功能的应用程序,以测试我们的配置。

使用 K8GB 部署高可用应用程序

要为应用程序启用全球负载均衡,有两种方法:您可以使用 K8GB 提供的自定义资源创建新记录,或者可以为 Ingress 规则添加注解。为了演示 K8GB 的功能,我们将部署一个简单的 NGINX Web 服务器到集群,并使用 K8GB 原生支持的自定义资源将其添加到 K8GB 中。

使用自定义资源将应用程序添加到 K8GB

当我们部署 K8GB 时,集群中添加了一个名为 Gslb 的自定义资源定义(CRD)。该 CRD 负责管理标记为全球负载均衡的应用程序。在 Gslb 对象中,我们为 Ingress 名称定义了一个规范,格式与常规 Ingress 对象类似。标准 Ingress 和 Gslb 对象之间唯一的区别在于清单的最后部分,即策略(strategy)。

策略定义了我们要使用的负载均衡类型,在我们的示例中为故障转移(failover),以及对象要使用的主要 GeoTag。在我们的示例中,纽约集群是主集群,因此我们的 Gslb 对象将设置为 us-buf

要部署利用负载均衡的应用程序,我们需要在两个集群中创建以下内容:

  • 应用程序的标准部署和服务。我们将其命名为 nginx,使用标准的 NGINX 镜像。
  • 每个集群中的一个 Gslb 对象。在我们的示例中,我们将使用下面的清单来声明 Ingress 规则,并将策略设置为故障转移,主 K8GB 设置为 us-buf。由于 Gslb 对象包含了 Ingress 规则的信息,因此不需要单独创建 Ingress 规则;Gslb 会为我们创建 Ingress 对象。以下是一个示例:
yaml 复制代码
apiVersion: k8gb.absa.oss/v1beta1
kind: Gslb
metadata:
  name: gslb-failover-buf
  namespace: demo
spec:
  ingress:
    ingressClassName: nginx
    rules:
    - host: fe.gb.foowidgets.k8s      # 需要启用 GSLB 的 FQDN
      http:
        paths:
        - backend:
            service:
              name: nginx             # 启用 GSLB 的服务名称
              port:
                number: 80
          path: /
          pathType: Prefix
  strategy:
    type: failover                    # 全球负载均衡策略
    primaryGeoTag: us-buf             # 主集群地理标签

当您部署 Gslb 对象的清单时,它会创建两个 Kubernetes 对象:Gslb 对象和 Ingress 对象。

如果我们查看布法罗集群中 demo 命名空间下的 Gslb 对象,我们会看到如下信息:

vbnet 复制代码
NAMESPACE   NAME                STRATEGY   GEOTAG
demo        gslb-failover-buf   failover   us-buf

如果我们查看纽约集群中的 Ingress 对象,我们会看到:

css 复制代码
NAME                CLASS   HOSTS                  ADDRESS      PORTS   AGE
gslb-failover-buf   nginx   fe.gb.foowidgets.k8s   10.2.1.167   80      15h

在纽约集群中我们也会有类似的对象,在后续的"了解 K8GB 如何提供全球负载均衡"部分,我们将详细解释这一点。

使用 Ingress 注解将应用程序添加到 K8GB

将应用程序添加到 K8GB 的第二种方法是向标准 Ingress 规则添加两个注解,主要用于让开发人员将现有的 Ingress 规则添加到 K8GB。要将 Ingress 对象添加到全球负载均衡列表中,您只需向 Ingress 对象添加两个注解:strategyprimary-geotag。以下是注解的示例:

bash 复制代码
k8gb.io/strategy: "failover"
k8gb.io/primary-geotag: "us-buf"

这将使用 failover 策略和 us-buf 作为主要标签,将该 Ingress 添加到 K8GB。

现在我们已经部署了所有所需的基础设施组件和对象,以便为应用程序启用全球负载均衡,接下来让我们看看它是如何运作的。

了解 K8GB 如何提供全球负载均衡

K8GB 的设计比较复杂,但一旦您部署了应用程序并了解 K8GB 如何维护区域文件,整个过程就会变得更易于理解。这是一个相对复杂的主题,假设您对 DNS 的工作原理有一定了解,但在本节结束时,您应该能够解释 K8GB 的工作原理。

保持 K8GB CoreDNS 服务器同步

首先要讨论的是 K8GB 如何管理两个或多个区域文件的同步,以便为我们的部署提供无缝的故障转移。无缝故障转移是一种过程,确保即使在系统问题或故障期间,应用程序仍能顺利运行。它自动切换到备份系统或资源,保持不间断的用户体验。

如前所述,每个集群中的 K8GB CoreDNS 服务器必须在主 DNS 服务器中有一个条目。这是我们在 values.yaml 文件中配置的 edge 值所对应的 DNS 服务器和区域:

vbnet 复制代码
edgeDNSZone: "foowidgets.k8s"
edgeDNSServer: "10.2.1.14"

因此,在边缘 DNS 服务器 (10.2.1.14) 中,我们为每个 CoreDNS 服务器创建了一个主机记录,使用了 K8GB 所需的命名约定:

  • gslb-ns-us-nyc-gb.gb.foowidgets.k8s 10.2.1.221 (纽约 CoreDNS 负载均衡 IP)
  • gslb-ns-us-buf-gb.gb.foowidgets.k8s 10.2.1.224 (布法罗 CoreDNS 负载均衡 IP)

K8GB 会在所有 CoreDNS 服务器之间进行通信,并更新因添加、删除或更新而需要更改的记录。

使用示例说明 K8GB

使用我们集群的示例,我们已经部署了一个 NGINX Web 服务器,并在两个集群中创建了所有必需的对象。部署完成后,每个集群中都会有一个 Gslb 和 Ingress 对象,如下所示:

集群:纽约

  • 部署:nginx
  • Gslb:gslb-failover-nyc
  • Ingress:fe.gb.foowidgets.k8s
  • NGINX Ingress IP:10.2.1.98

集群:布法罗(主集群)

  • 部署:nginx
  • Gslb:gslb-failover-buf
  • Ingress:fe.gb.foowidgets.k8s
  • NGINX Ingress IP:10.2.1.167

由于两个集群中的部署都处于健康状态,CoreDNS 服务器将为 fe.gb.foowidgets.k8s 创建一个记录,使用主集群的 IP 地址 10.2.1.167。我们可以通过在任何使用边缘 DNS 服务器 (10.2.1.14) 的客户端机器上运行 dig 命令来验证这一点:

yaml 复制代码
; <<>> DiG 9.16.23-RH <<>> fe.gb.foowidgets.k8s
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6654
;; ANSWER SECTION:
fe.gb.foowidgets.k8s.   30      IN      A       10.2.1.167

如果我们使用 curl 命令请求 DNS 名称,布法罗集群中的 NGINX 服务器将返回响应:

css 复制代码
# curl fe.gb.foowidgets.k8s
<html>
<h1>Welcome</h1>
</br>
<h1>Hi! This is a webserver in Buffalo for our K8GB example... </h1>
</html>

模拟故障

我们将通过缩放布法罗集群中的部署副本到 0 来模拟故障,这将使 K8GB 认为应用程序失败。当纽约集群中的 K8GB 控制器检测到应用程序没有健康的端点时,它会更新 CoreDNS 记录,将服务故障转移到次要集群。缩放完成后,我们可以再次使用 dig 验证主机返回的结果:

ini 复制代码
; <<>> DiG 9.16.23-RH <<>> fe.gb.foowidgets.k8s
;; ANSWER SECTION:
fe.gb.foowidgets.k8s.   27      IN      A       10.2.1.98

此时,curl 将显示工作负载已移至纽约集群:

css 复制代码
# curl fe.gb.foowidgets.k8s
<html>
<h1>Welcome</h1>
</br>
<h1>Hi! This is a webserver in NYC for our K8GB example... </h1>
</html>

当主集群恢复健康后,K8GB 将更新 CoreDNS 并将请求解析回主集群。我们将布法罗的部署缩放回 1,进行最后一次测试:

css 复制代码
# curl fe.gb.foowidgets.k8s
<html>
<h1>Welcome</h1>
</br>
<h1>Hi! This is a webserver in Buffalo for our K8GB example... </h1>
</html>

这证明了 K8GB 正常工作,并为我们提供了一个由 Kubernetes 控制的全球负载均衡器。

K8GB 是 CNCF 的一个独特且令人印象深刻的项目,它提供了类似于许多昂贵产品的全球负载均衡功能。如果您需要跨多个集群部署应用程序,建议您关注 K8GB 项目。

总结

在本章中,您学习了如何为使用 LoadBalancer 服务的任何服务提供自动 DNS 注册。您还学习了如何使用 CNCF 项目 K8GB 部署高度可用的服务,该项目为 Kubernetes 集群提供全球负载均衡功能。

这些项目已成为众多企业的核心工具,赋予用户以前需要多个团队协作和大量文书工作才能实现的能力,让应用程序更快地交付给客户。如今,您的团队可以使用标准的敏捷实践迅速部署和更新应用程序,为您的组织带来竞争优势。

在下一章《将身份验证集成到您的集群中》中,我们将探讨在 Kubernetes 中实施安全身份验证的最佳方法和实践。您将学习如何使用 OpenID Connect 协议集成企业身份验证,以及如何使用 Kubernetes 模拟功能。我们还将讨论在集群中管理凭据的挑战,并提供针对用户和流水线进行身份验证的实用解决方案。

相关推荐
小钟不想敲代码20 分钟前
Docker部署Sentinel
docker·容器·sentinel
上海运维Q先生23 分钟前
面试题整理17----K8s中request和limit资源限制是如何实现的
服务器·云原生·kubernetes
胖毁青春,瘦解百病2 小时前
Docker镜像源设置不生效问题排查
docker·容器
CloudPilotAI2 小时前
15条 Karpenter 最佳实践,轻松掌握弹性伸缩
kubernetes·弹性伸缩·karpenter
会飞的土拨鼠呀2 小时前
Flannel是什么,如何安装Flannel
运维·云原生·kubernetes
ether-lin3 小时前
DevOps实战:用Kubernetes和Argo打造自动化CI/CD流程(1)
ci/cd·kubernetes·devops
Carry_NJ4 小时前
docker-compose样例
运维·docker·容器
勇-子4 小时前
K8s 常用资源介绍
云原生·容器·kubernetes
大G哥4 小时前
k8s创建单例redis设置密码
数据库·redis·云原生·容器·kubernetes
勇-子7 小时前
K8s DaemonSet的介绍
云原生·容器·kubernetes