Saltar al contenido

¿Cómo configuro ExternalDNS con Amazon EKS?

6 minutos de lectura
0

Quiero configurar ExternalDNS con mi Amazon Elastic Kubernetes Service (Amazon EKS).

Breve descripción

Para instalar ExternalDNS, utiliza los permisos de AWS Identity and Access Management (IAM) para conceder a Amazon EKS el acceso necesario para interactuar con Amazon Route 53.

Nota: Antes de comenzar con la siguiente resolución, asegúrate de tener un nombre de dominio y una zona alojada de Route 53.

Resolución

Configuración de los permisos de IAM y despliegue de ExternalDNS

Sigue estos pasos:

  1. Crea la siguiente política para configurar los permisos de IAM para conceder al pod ExternalDNS permisos para crear, actualizar y eliminar registros de Route 53 en tu cuenta de AWS:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "route53:ChangeResourceRecordSets"
          ],
          "Resource": [
            "arn:aws:route53:::hostedzone/*"
          ]
        },
        {
          "Effect": "Allow",
          "Action": [
            "route53:ListHostedZones",
            "route53:ListResourceRecordSets",
            "route53:ListTagsForResource"
          ],
          "Resource": [
            "*"
          ]
        }
      ]
    }

    Nota: Puedes modificar la política anterior para permitir las actualizaciones de los identificadores específicos de las zonas alojadas.

  2. Utiliza la política para crear un rol de IAM para la cuenta de servicio:

    eksctl create iamserviceaccount --name SERVICE_ACCOUNT_NAME --namespace NAMESPACE
    --cluster CLUSTER_NAME --attach-policy-arn IAM_POLICY_ARN --approve

    Nota: Sustituye SERVICE_ACCOUNT_NAME por el nombre de tu cuenta de servicio, NAMESPACE por tu espacio de nombres, CLUSTER_NAME por el nombre de tu clúster e IAM_POLICY_ARN por el ARN de tu política de IAM.
    Para comprobar el nombre de tu cuenta de servicio, ejecuta el comando siguiente:

    kubectl get sa

    En el resultado del ejemplo siguiente, external-dns es el nombre que se le ha puesto a la cuenta de servicio cuando se ha creado:

    NAME           SECRETS   AGE
    default        1         23h
    external-dns   1         23h
  3. Ejecuta el siguiente comando para determinar si el RBAC está activado en tu clúster de Amazon EKS:  

    kubectl api-versions | grep rbac.authorization.k8s.io

    Nota: En el comando anterior, comprueba la versión más reciente de ExternalDNS que esté disponible en el proyecto de GitHub.

  4. Ejecuta el siguiente comando para desplegar ExternalDNS:

    kubectl apply DEPLOYMENT_MANIFEST_FILE_NAME.yaml

    Nota: Sustituye DEPLOYMENT_MANIFEST_FILE_NAME por el nombre de archivo de tu manifiesto de despliegue.

    Si el RBAC está activado, utiliza el manifiesto siguiente para desplegar ExternalDNS:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: external-dns
      labels:
        app.kubernetes.io/name: external-dns
    rules:
      - apiGroups: [""]
        resources: ["services","endpoints","pods","nodes"]
        verbs: ["get","watch","list"]
      - apiGroups: ["extensions","networking.k8s.io"]
        resources: ["ingresses"]
        verbs: ["get","watch","list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: external-dns-viewer
      labels:
        app.kubernetes.io/name: external-dns
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: external-dns
    subjects:
      - kind: ServiceAccount
        name: external-dns
        namespace: default # change to desired namespace: externaldns, kube-addons
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: external-dns
      labels:
        app.kubernetes.io/name: external-dns
    spec:
      strategy:
        type: Recreate
      selector:
        matchLabels:
          app.kubernetes.io/name: external-dns
      template:
        metadata:
          labels:
            app.kubernetes.io/name: external-dns
        spec:
          serviceAccountName: external-dns
          containers:
            - name: external-dns
              image: registry.k8s.io/external-dns/external-dns:v0.14.0
              args:
                - --source=service
                - --source=ingress
                - --domain-filter=example.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
                - --provider=aws
                - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
                - --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
                - --registry=txt
                - --txt-owner-id=external-dns
              env:
                - name: AWS_DEFAULT_REGION
                  value: eu-west-1 # change to region where EKS is installed

    Si el RBAC no está activado, utiliza el manifiesto siguiente para desplegar ExternalDNS:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: external-dns
      labels:
        app.kubernetes.io/name: external-dns
    spec:
      strategy:
        type: Recreate
      selector:
        matchLabels:
          app.kubernetes.io/name: external-dns
      template:
        metadata:
          labels:
            app.kubernetes.io/name: external-dns
        spec:
          containers:
            - name: external-dns
              image: registry.k8s.io/external-dns/external-dns:v0.14.0
              args:
                - --source=service
                - --source=ingress
                - --domain-filter=example.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
                - --provider=aws
                - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
                - --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
                - --registry=txt
                - --txt-owner-id=my-hostedzone-identifier
              env:
                - name: AWS_DEFAULT_REGION
                  value: eu-west-1 # change to region where EKS is installed
  5. Ejecuta el siguiente comando para comprobar que el despliegue se ha realizado correctamente:

    kubectl get deployments

    Resultado del ejemplo:

    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    external-dns   1/1     1            1           85m

    O bien, consulta los registros para comprobar que están actualizados:

    kubectl logs external-dns-9f85d8d5b-sx5f

    Resultado del ejemplo:

    ....
    time="2023-12-14T17:16:16Z" level=info msg="Instantiating new Kubernetes client"
    time="2023-12-14T17:16:16Z" level=info msg="Using inCluster-config based on serviceaccount-token"
    time="2023-12-14T17:16:16Z" level=info msg="Created Kubernetes client https://10.100.0.1:443"
    time="2023-12-14T17:16:18Z" level=info msg="Applying provider record filter for domains: [xxxxx.people.aws.dev. .xxxxx.people.aws.dev. xxxxx.people.aws.dev. .xxxxx.people.aws.dev.]"
    time="2023-12-14T17:16:18Z" level=info msg="All records are already up to date"
    ....

Comprobación de ExternalDNS

Para confirmar que ExternalDNS está configurado correctamente, sigue estos pasos:

  1. Crea un servicio que esté expuesto como LoadBalancer. El servicio debe dirigirse externamente a través del nombre de dominio alojado en Route 53:

    kubectl apply SERVICE_MANIFEST_FILE_NAME.yaml
    
    Note: Replace SERVICE_MANIFEST_FILE_NAME with your service manifest's file name.
    
    Manifest:
    
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
      annotations:
        external-dns.alpha.kubernetes.io/hostname: nginx.xxxxx.people.aws.dev
    spec:
      ports:
        - port: 80
          targetPort: 80
          protocol: TCP
      type: LoadBalancer
      selector:
        app: nginx
    
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
            - image: nginx
              name: nginx
              ports:
                - containerPort: 80
                  name: http

    Nota: ExternalDNS usa la anotación external-dns.alpha.kubernetes.io/hostname en los servicios. También usa los valores asociados. Para asignar varios nombres a un servicio, configura la anotación external-dns.alpha.kubernetes.io/hostname con un separador de comas.

  2. Comprueba que el servicio NGINX se haya creado con el tipo LoadBalancer:

    kubectl get svc

    Resultado del ejemplo:

    NAME         TYPE           CLUSTER-IP      EXTERNAL-IP                                                              PORT(S)        AGE
    kubernetes   ClusterIP      10.100.0.1      <none>                                                                   443/TCP        05h
    nginx        LoadBalancer   10.100.254.68   xxxxyyyyzzzz-123456789.eu-west-1.elb.amazonaws.com   80:30792/TCP   74m
    

    Nota: El servicio crea automáticamente un registro de Route 53 para la zona alojada.

  3. Ejecuta el siguiente comando para ver los registros y confirma que el registro de Route 53 se creó correctamente:

    kubectl logs external-dns-9f85d8d5b-sx5fg

    Resultado del ejemplo:

    ...
    time="2023-12-14T17:19:19Z" level=info msg="Desired change: CREATE cname-nginx.xxxxx.people.aws.dev TXT [Id: /hostedzone/Z0786329GDVAZMXYZ]"
    time="2023-12-14T17:19:19Z" level=info msg="Desired change: CREATE nginx.xxxxx.people.aws.dev A [Id: /hostedzone/Z0786329GDVAZMXYZ]"
    time="2023-12-14T17:19:19Z" level=info msg="Desired change: CREATE nginx.xxxxx.people.aws.dev TXT [Id: /hostedzone/Z0786329GDVAZMXYZ]"
    time="2023-12-14T17:19:20Z" level=info msg="3 record(s) in zone xxxxx.people.aws.dev. [Id: /hostedzone/Z0786329GDVAZMXYZ] were successfully updated"
    ...