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

ExternalDNS自动管理Kubernetes集群中的外部DNS记录。部署后,ExternalDNS在后台运行,几乎不需要其他配置。无论何时创建或更改服务或Ingress,ExternalDNS都会立即更新记录。在本教程中,您将通过Helm将ExternalDNS安装到DigitalOcean Kubernetes集群,并配置为使用DigitalOcean作为DNS提供程序。

作者选择了自由和开源基金作为Write for DOnations计划的一部分进行捐赠。

介绍

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

为了解决这个问题, Kubernetes sig-network团队创建了ExternalDNS ,目的是从Kubernetes集群内自动管理外部DNS记录。 部署后,ExternalDNS在后台运行,几乎不需要其他配置。 无论何时创建或更改服务或Ingress,ExternalDNS都会立即更新记录。

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

先决条件

  • DigitalOcean Kubernetes集群,您的连接配置为kubectl默认值。 创建群集时,“ 连接到群集”步骤下会显示有关如何配置kubectl说明。 要在DigitalOcean上创建Kubernetes集群,请参阅Kubernetes快速入门

  • Helm软件包管理器安装在本地计算机上,并且Tiller安装在您的集群上。 为此,请使用Helm Package Manager教程完成如何在Kubernetes群集上安装软件的第1步和2。

  • 使用Helm在群集上安装Nginx Ingress Controller,以便将ExternalDNS与Ingress Resources一起使用。 为此,请按照如何使用Helm在DigitalOcean Kubernetes上设置Nginx Ingress 您需要根据第2步中的说明将publishService属性设置为true

  • 具有读写权限的DigitalOcean API密钥(个人访问令牌)。 要创建一个,请访问如何创建个人访问令牌

  • 完全注册的域名。 本教程将始终使用echo.example.com 您可以在Namecheap上购买域名,在Freenom上免费获取一个域名,或使用您选择的域名注册商。

第1步 - 使用Helm安装ExternalDNS

在本节中,您将使用Helm将ExternalDNS安装到您的群集,并将其配置为使用DigitalOcean DNS服务。

要覆盖ExternalDNS Helm图表的某些默认设置,您需要创建一个您在安装期间传入Helm的values.yaml文件。 在先前条件中用于访问群集的计算机上,通过运行以下命令创建文件:

nano externaldns-values.yaml

添加以下行:

externaldns-values.yaml
rbac:
  create: true

provider: digitalocean

digitalocean:
  apiToken: your_api_token

interval: "1m"

policy: sync # or upsert-only

# domainFilters: [ 'example.com' ]

在第一个块中,启用RBAC (基于角色的访问控制)清单创建,必须在支持RBAC的Kubernetes集群(如DigitalOcean)上启用该清单。 在下一行中,将DNS服务提供商设置为DigitalOcean。 然后,在下一个块中,您将通过替换your_api_token添加您的DigitalOcean API令牌。

下一行设置ExternalDNS将轮询更改为Ingress和Services的时间间隔。 您可以将其设置为较低的值,以更快地传播对DNS的更改。

policy设置确定ExternalDNS是仅插入DNS记录( upsert-only )还是根据需要创建和删除它们( sync )。 幸运的是,从版本0.3开始,ExternalDNS通过创建附带的TXT记录来支持所有权的概念,在该记录中它存储有关其创建的域的信息,将其操作范围仅限于它创建的域。

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

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

现在,通过运行以下命令将ExternalDNS安装到您的集群:

helm install stable/external-dns --name external-dns -f externaldns-values.yaml

输出类似于以下内容:

NAME:   external-dns
LAST DEPLOYED: ...
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Pod(related)
NAME                           READY  STATUS             RESTARTS  AGE
external-dns-69c545655f-xqjjf  0/1    ContainerCreating  0         0s

==> v1/Secret
NAME          TYPE    DATA  AGE
external-dns  Opaque  1     0s

==> v1/Service
NAME          TYPE       CLUSTER-IP    EXTERNAL-IP  PORT(S)   AGE
external-dns  ClusterIP  10.245.47.69  <none>       7979/TCP  0s

==> v1/ServiceAccount
NAME          SECRETS  AGE
external-dns  1        0s

==> v1beta1/ClusterRole
NAME          AGE
external-dns  0s

==> v1beta1/ClusterRoleBinding
NAME          AGE
external-dns  0s

==> v1beta1/Deployment
NAME          READY  UP-TO-DATE  AVAILABLE  AGE
external-dns  0/1    1           0          0s


NOTES:
...

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

kubectl --namespace=default get pods -l "app=external-dns,release=external-dns" -w
NAME                            READY   STATUS              RESTARTS   AGE
external-dns-69bfcf8ccb-7j4hp   0/1     ContainerCreating   0          3s

您已将ExternalDNS安装到Kubernetes集群。 接下来,您将部署一个示例Web应用程序,使用Nginx Ingress公开它,并让ExternalDNS自动将您的域名指向适当的Load Balancer。

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

在本节中,您将为您的群集部署虚拟Web应用程序,以便使用您的Ingress公开它。 然后,您将设置ExternalDNS以自动为您配置DNS记录。 最后,您的域名的DNS记录将指向Ingress的Load Balancer。

您将部署的虚拟Web应用程序是Hashicorp的http-echo 它是一个内存中的Web服务器,可以回显您提供的消息。 您将其Ku​​bernetes清单存储在名为echo.yaml的文件中。 创建它并打开它进行编辑:

nano echo.yaml

将以下行添加到您的文件中:

echo.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: echo-ingress
spec:
  rules:
  - host: echo.example.com
    http:
      paths:
      - backend:
          serviceName: echo
          servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: echo
spec:
  ports:
  - port: 80
    targetPort: 5678
  selector:
    app: echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo
spec:
  selector:
    matchLabels:
      app: echo
  replicas: 3
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: echo
        image: hashicorp/http-echo
        args:
        - "-text=Echo!"
        ports:
        - containerPort: 5678

在此配置中,您可以定义Deployment,Ingress和Service。 部署包含http-echo应用程序的三个副本,并传入自定义消息( Echo! )。服务定义为允许通过端口80访问部署中的Pod。 Ingress配置为在您的域中公开服务。

echo.example.com替换为您的域,然后保存并关闭该文件。

现在,您无需手动配置域的DNS记录。 只要将配置应用于Kubernetes,ExternalDNS就会自动执行此操作。

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

kubectl create -f echo.yaml

您将看到以下输出:

ingress.extensions/echo-ingress created
service/echo created
deployment.apps/echo created

您需要等待很短的时间让ExternalDNS注意到更改并创建相应的DNS记录。 Helm图表中的interval设置决定了您需要等待DNS记录创建所需的时间长度。 values.yaml ,间隔长度默认设置为1分钟。

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

控制面板 - 生成的DNS记录

指定的时间间隔过后,使用curl访问您的域:

curl echo.example.com

您将看到以下输出:

Echo!

此消息确认您已配置ExternalDNS并创建必要的DNS记录以指向Nginx入口控制器的负载均衡器。 如果您看到错误消息,请给它一些时间。 或者,您可以尝试从浏览器访问您的域,您将看到Echo!

您已通过使用Ingress部署示例应用程序来测试ExternalDNS。 您还可以在DigitalOcean控制面板中观察新的DNS记录。 在下一步中,您将使用您的域名公开服务。

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

在此可选部分中,您将使用Services with ExternalDNS而不是Ingresses。 ExternalDNS允许您为DNS服务器提供不同的Kubernetes资源。 使用服务是与Ingresses类似的过程,其中包含为此备用资源修改的配置。

注意:执行此步骤将删除刚刚创建的DNS记录。

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

kubectl delete ing echo-ingress

输出将是:

ingress.extensions/echo-ingress deleted

ExternalDNS将删除它在上一步中创建的现有DNS记录。 在该步骤的其余部分中,您可以使用之前使用的相同域。

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

nano echo.yaml

用以下行替换文件内容:

echo.yaml
apiVersion: v1
kind: Service
metadata:
  name: echo
  annotations:
    external-dns.alpha.kubernetes.io/hostname: echo.example.com
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 5678
  selector:
    app: echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo
spec:
  selector:
    matchLabels:
      app: echo
  replicas: 3
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: echo
        image: hashicorp/http-echo
        args:
        - "-text=Echo!"
        ports:
        - containerPort: 5678

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

通过运行以下命令将更改应用于您的群集:

kubectl apply -f echo.yaml

输出将是:

service/echo configured
deployment.apps/echo configured

您可以通过运行以下方式观察服务的负载均衡器:

kubectl get svc echo -w

您将看到类似于以下内容的输出:

NAME   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
echo   LoadBalancer   10.245.81.235   <pending>     80:31814/TCP   8s
...

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

curl echo.example.com

输出将与上一步相同:

Echo!

如果您收到错误,请稍等一会儿,或者您可以尝试使用其他域名。 由于DNS记录缓存在客户端系统上,因此实际传播更改可能需要很长时间。

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

结论

ExternalDNS在后台静默工作,提供无摩擦体验。 您的Kubernetes集群刚刚成为域名的真正核心来源。 您不必再手动更新DNS记录。

从Continuous Delivery系统创建测试环境时,ExternalDNS的真正威力将变得明显。 如果要在Kubernetes群集上设置一个此类系统,请在DigitalOcean Kubernetes上访问如何使用Spinnaker设置CD管道