如何使用 ExternalDNS 从 DigitalOcean Kubernetes 自动管理 DNS 记录

作者选择了自由和开放源码基金作为为国家写作计划的一部分接受捐赠。

简介

在 Kubernetes 上部署 Web 应用程序时,您通常会使用 Services 和 Ingresses 将应用程序暴露在所需域的集群之外。这不仅需要手动配置 Ingress,还需要手动配置提供商的 DNS 记录,这可能是一个耗时且容易出错的过程。随着应用程序复杂性的增加,这可能会成为一个障碍;当外部 IP 发生变化时,有必要相应地更新 DNS 记录。

为了解决这个问题,Kubernetes sig-network 团队 创建了ExternalDNS,用于在 Kubernetes 集群内自动管理外部 DNS 记录。ExternalDNS 一旦部署,就会在后台运行,几乎不需要额外配置。无论何时创建或更改服务或入口,ExternalDNS 都会立即更新记录。

在本教程中,你将通过Helm在DigitalOcean Kubernetes集群中安装ExternalDNS,并将其配置为使用DigitalOcean作为DNS提供商。然后,您将使用 Ingress 部署一个示例 Web 应用程序,并使用 ExternalDNS 将其指向您的域名。最后,您将拥有一个适用于服务和 Ingresses 的自动化 DNS 记录管理系统。

先决条件

步骤 1 - 使用 Helm 安装 ExternalDNS

本节将使用 Helm 为集群安装 ExternalDNS,并将其配置为与 DigitalOcean DNS 服务协同工作。

为了覆盖 ExternalDNS Helm 图表的某些默认设置,您需要创建一个 values.yaml 文件,并在安装过程中将其传递给 Helm。在先决条件中用于访问群集的计算机上,运行以下命令创建该文件:

1nano externaldns-values.yaml

添加以下几行

 1[label externaldns-values.yaml]
 2provider: digitalocean
 3
 4digitalocean:
 5  apiToken: your_api_token
 6
 7interval: "1m"
 8
 9policy: sync # or upsert-only
10
11# domainFilters: [ 'your_domain' ]

在第一个代码块中,将 DNS 服务提供商设置为 DigitalOcean。然后,在下一个代码块中,替换 "your_api_token",定义你的 DigitalOcean API 令牌。

下一行设置 ExternalDNS 轮询入口和服务变更的时间间隔。默认值为 1 分钟,您可以将其设置为较低值,以便更快地将更改传播到您的 DNS。

策略 "设置决定了 ExternalDNS 是只插入 DNS 记录("upsert-only"),还是根据需要创建和删除 DNS 记录("sync")。幸运的是,从 0.3 版开始,ExternalDNS 通过创建附带的 TXT 记录来支持所有权概念,在这些记录中存储了它所创建的域的信息,从而将其作用范围限制在它所创建的域上。

domainFilters "参数用于限制 ExternalDNS 可管理的域名。您可以取消注释,以字符串数组的形式输入域,但这并非必要。

编辑完成后,保存并关闭文件。

ExternalDNS Helm图表是Bitnami图表库的一部分。运行以下命令将其添加到 Helm 安装中:

1helm repo add bitnami https://charts.bitnami.com/bitnami

然后,刷新舵手的缓存以下载其内容:

1helm repo update

最后,运行以下命令为集群安装 ExternalDNS:

1helm install external-dns bitnami/external-dns -f externaldns-values.yaml

输出结果类似于下面的内容:

 1[secondary_label Output]
 2NAME: external-dns
 3LAST DEPLOYED: ...
 4NAMESPACE: default
 5STATUS: deployed
 6REVISION: 1
 7TEST SUITE: None
 8NOTES:
 9** Please be patient while the chart is being deployed **
10
11To verify that external-dns has started, run:
12
13  kubectl --namespace=default get pods -l "app.kubernetes.io/name=external-dns,app.kubernetes.io/instance=external-dns"

您可以运行以下命令来验证 ExternalDNS 的创建:

1kubectl --namespace=default get pods -l "app.kubernetes.io/name=external-dns,app.kubernetes.io/instance=external-dns"
1[secondary_label Output]
2NAME READY STATUS RESTARTS AGE
3external-dns-56c85ff66b-2vm88 1/1 Running 0 24s

您已经在 Kubernetes 集群中安装了 ExternalDNS。接下来,您将部署一个示例 Web 应用程序,使用 Nginx Ingress 将其公开,并让 ExternalDNS 自动将您的域名指向相应的负载平衡器。

第 2 步 - 部署和公开示例网络应用程序

在本节中,您将在集群中部署一个虚拟网络应用程序,以便使用 Ingress 将其公开。然后,您将设置 ExternalDNS 为您自动配置 DNS 记录。最后,您的域名 DNS 记录将指向 Ingress 的负载平衡器。

您要部署的虚拟网络应用程序是 Hashicorp 的 http-echo。它是一个内存网络服务器,会回传你给它的信息。你将把它的 Kubernetes 清单存储在一个名为 echo.yaml 的文件中。创建并打开该文件进行编辑:

1nano echo.yaml

在文件中添加以下几行:

 1[label echo.yaml]
 2apiVersion: networking.k8s.io/v1
 3kind: Ingress
 4metadata:
 5  name: echo-ingress
 6  annotations:
 7    kubernetes.io/ingress.class: nginx
 8spec:
 9  rules:
10  - host: "echo.your_domain"
11    http:
12      paths:
13      - pathType: Prefix
14        path: "/"
15        backend:
16          service:
17            name: echo
18            port:
19              number: 80
20---
21apiVersion: v1
22kind: Service
23metadata:
24  name: echo
25spec:
26  ports:
27  - port: 80
28    targetPort: 5678
29  selector:
30    app: echo
31---
32apiVersion: apps/v1
33kind: Deployment
34metadata:
35  name: echo
36spec:
37  selector:
38    matchLabels:
39      app: echo
40  replicas: 3
41  template:
42    metadata:
43      labels:
44        app: echo
45    spec:
46      containers:
47      - name: echo
48        image: hashicorp/http-echo
49        args:
50        - "-text=Echo!"
51        ports:
52        - containerPort: 5678

在此配置中,您定义了一个部署、一个入口和一个服务。部署由 http-echo 应用程序的三个副本组成,其中传递了一条自定义消息(Echo!)。服务的定义是允许通过端口 80访问部署中的 Pod。入口被配置为在您的域中公开该服务。

echo.your_domain 替换为您的域名,然后保存并关闭文件。

现在,您无需手动配置域的 DNS 记录。只要将配置应用到 Kubernetes,ExternalDNS 就会自动完成配置。

要应用配置,请运行以下命令:

1kubectl create -f echo.yaml

您将收到以下输出结果:

1[secondary_label Output]
2ingress.extensions/echo-ingress created
3service/echo created
4deployment.apps/echo created

您需要等待一小段时间,ExternalDNS 才会注意到这些变化并创建相应的 DNS 记录。Helm 图表中的 interval 设置决定了创建 DNS 记录所需的等待时间。在 externaldns-values.yaml 中,时间间隔长度默认设置为 1 分钟。

您可以访问 DigitalOcean 控制面板,查找 A 和 TXT 记录。

控制面板 - 生成的 DNS 记录](assets/kubernetes_externaldns/externaldns.png)

一旦指定的时间间隔过去,或者您在控制面板中找到记录,就可以使用 curl 访问您的域名:

1curl echo.your_domain

您将收到以下输出:

1[secondary_label Output]
2Echo!

该信息确认你已配置 ExternalDNS 并创建了必要的 DNS 记录,以指向 Nginx 入口控制器的负载平衡器。如果出现错误信息,请稍等片刻。或者,你可以尝试从浏览器访问你的域,你会收到 "Echo!"。

你已经通过部署一个带有 Ingress 的示例应用程序对 ExternalDNS 进行了测试。你还可以在DigitalOcean控制面板中观察到新的DNS记录。下一步,你将在域名上公开服务。

第 3 步 -(可选)使用服务公开应用程序

在这部分可选内容中,您将使用 ExternalDNS 服务来代替 Ingresses。ExternalDNS 允许你向 DNS 服务器提供不同的 Kubernetes 资源。使用服务的过程与 Ingresses 类似,只是针对这种备用资源修改了配置。

<$>[注] 注: 执行此步骤将删除您刚刚创建的 DNS 记录。 <$>

由于您将自定义 echo.yaml 中的服务,因此不再需要 echo-ingress 。使用以下命令删除它:

1kubectl delete ing echo-ingress

输出结果将是

1[secondary_label Output]
2ingress.extensions/echo-ingress deleted

ExternalDNS 会删除上一步创建的现有 DNS 记录。在剩余的步骤中,你可以使用与之前相同的域名。

接下来,打开 echo.yaml 文件进行编辑:

1nano echo.yaml

用以下几行替换文件内容:

 1[label echo.yaml]
 2apiVersion: v1
 3kind: Service
 4metadata:
 5  name: echo
 6  annotations:
 7    external-dns.alpha.kubernetes.io/hostname: echo.your_domain
 8spec:
 9  type: LoadBalancer
10  ports:
11  - port: 80
12    targetPort: 5678
13  selector:
14    app: echo
15---
16apiVersion: apps/v1
17kind: Deployment
18metadata:
19  name: echo
20spec:
21  selector:
22    matchLabels:
23      app: echo
24  replicas: 3
25  template:
26    metadata:
27      labels:
28        app: echo
29    spec:
30      containers:
31      - name: echo
32        image: hashicorp/http-echo
33        args:
34        - "-text=Echo!"
35        ports:
36        - containerPort: 5678

您从文件中删除了之前设置的 Ingress,并将服务类型更改为 "LoadBalancer"。此外,您还添加了一个注释,为 ExternalDNS 指定了域名。

运行以下命令,将更改应用到群集:

1kubectl apply -f echo.yaml

输出结果将是

1[secondary_label Output]
2...
3service/echo configured
4deployment.apps/echo configured

您可以通过运行以下操作来检查服务的负载平衡器是否可用:

1kubectl get svc echo -w
1[secondary_label Output]
2NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)        AGE
3echo LoadBalancer 10.245.81.235   <pending>     80:31814/TCP 8s
4...

与上一步一样,您需要等待一段时间来创建和传播 DNS 记录。完成后,"curl "您指定的域:

1curl echo.your_domain

输出结果与上一步相同:

1[secondary_label Output]
2Echo!

如果出现错误,请稍等片刻,或者尝试其他域名。由于 DNS 记录会缓存在客户端系统中,因此更改可能需要很长时间才能真正传播。

在此步骤中,您创建了一个服务(类型为 "LoadBalancer"),并使用 ExternalDNS 将其指向您的域名。

结论

ExternalDNS 可在后台悄无声息地运行,提供无摩擦的体验。您的 Kubernetes 集群已成为域名的核心信息源。您无需再手动更新 DNS 记录。

从持续交付系统创建测试环境时,ExternalDNS 的真正威力就会显现出来。如果你想在 Kubernetes 集群上建立这样一个系统,请访问 如何在 DigitalOcean Kubernetes 上使用 Spinnaker 建立 CD 管道

Published At
Categories with 技术
comments powered by Disqus