# ExternalDNS for Managed Kubernetes

## Overview

[<mark style="color:blue;">ExternalDNS</mark>](https://github.com/kubernetes-sigs/external-dns#externaldns) is a Kubernetes add-on that automates the management of public DNS records for Kubernetes resources, such as services and ingresses exposed outside the cluster. Unlike Kubernetes' internal DNS management, which is limited to internal cluster communication, ExternalDNS extends this functionality by delegating DNS record management to external DNS providers, such as IONOS Cloud DNS.

The ExternalDNS solution offers the following capabilities:

* Empowers developers to manage DNS resources traditionally handled manually by infrastructure teams.
* Ensures that DNS records are synchronized with the current state of the Kubernetes cluster.
* Automates the management of many DNS records, reducing manual effort.
* Simplifies DNS management while improving security.

By integrating ExternalDNS with the IONOS Cloud webhook, you can manage your IONOS Cloud domains directly within your Kubernetes cluster. This integration requires an IONOS Cloud API key or token from the account managing your domains. The following tutorial provides detailed technical instructions for deploying ExternalDNS with the IONOS Cloud webhook using the Helm chart.

## Target audience

This tutorial is intended to help both developers and technical decision-makers.

## What you will learn

The following tutorial provides detailed technical instructions for deploying ExternalDNS with the IONOS Cloud webhook using the Helm chart.

## Before you begin

Ensure that you have the following before you begin:

* A domain name registered with your domain provider, domain registrar, or a subdomain under your control.
* A token from a [<mark style="color:blue;">user with privileges</mark>](https://docs.ionos.com/cloud/network-services/cloud-dns/api-how-tos/set-user-privileges-api) to manage zones and records with Cloud DNS.
* An IONOS Cloud Managed Kubernetes cluster.
* The [<mark style="color:blue;">kubectl</mark>](https://kubernetes.io/docs/tasks/tools/) installed on your local machine.
* The Helm tool for installing a Helm chart.

## Procedure

Follow these steps to set up ExternalDNS for your [<mark style="color:blue;">Managed Kubernetes</mark>](https://docs.ionos.com/cloud/containers/managed-kubernetes) with [<mark style="color:blue;">IONOS Cloud DNS Provider</mark>](https://docs.ionos.com/cloud/network-services/cloud-dns):

{% stepper %}
{% step %}

#### Create a domain name

You must first [<mark style="color:blue;">Create a Primary Zone</mark>](https://docs.ionos.com/cloud/network-services/cloud-dns/api-how-tos/create-primary-zone) for your domain name with Cloud DNS and then [<mark style="color:blue;">Connect Domain Name to Cloud DNS</mark>](https://docs.ionos.com/cloud/network-services/cloud-dns/api-how-tos/connect-domain-name-to-cloud-dns).
{% endstep %}

{% step %}

#### Add Helm chart

Add the external-dns Helm repository, which contains the official `external-dns` Helm chart.

```bash
helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/
```

{% endstep %}

{% step %}

#### Create a Kubernetes secret

Create a Kubernetes secret to store your IONOS Cloud API token using the following command:

```bash
kubectl create secret generic ionos-cloud-credentials --from-literal=api-key='<IONOS Cloud Token>'
```

{% hint style="info" %}
**Note:** Replace the `IONOS Cloud Token` with your actual IONOS Cloud token. For more information on managing authentication tokens, see [<mark style="color:blue;">Token Manager</mark>](https://docs.ionos.com/cloud/management/identity-access-management/token-manager). Remember to refresh the token for automatic certificate renewal.
{% endhint %}
{% endstep %}

{% step %}

#### Create configuration

Create a Helm values file for the ExternalDNS Helm chart that includes the webhook configuration. In this example, the values file is called `external-dns-ionos-cloud-values.yaml`.

```bash
---
# -- ExternalDNS Log level.
logLevel: debug # reduce in production

# -- if true, ExternalDNS will run in a namespaced scope (Role and Rolebinding will be namespaced too).
namespaced: false
triggerLoopOnEvent: true # if true, ExternalDNS will trigger a loop on every event (create/update/delete) on the resources it watches.
# -- Kubernetes resources to monitor for DNS entries.
sources:
  - ingress
  - service

provider:
  name: webhook
  webhook:
    image:
      repository: ghcr.io/ionos-cloud/external-dns-ionos-webhook
      tag: latest
      pullPolicy: IfNotPresent
    env:
    - name: LOG_LEVEL
      value: debug
    - name: IONOS_CLOUD_API_KEY
      valueFrom:
        secretKeyRef:
          name: ionos-cloud-credentials
          key: api-key
    # The webhook server listens on localhost by default. Otherwise, you can set SERVER_HOST.
    - name: SERVER_PORT
      value: "8888" # default and recommended port for exposing webhook provider EPs
    # The exposed server listens on all interfaces (0.0.0.0) by default. Otherwise, you can set METRICS_HOST.
    - name: METRICS_PORT
      value: "8080" # default and recommended port for exposing metrics and health EPs
    - name: IONOS_CLOUD_DEBUG
      value: "false" # change to "true" if you want see details of the http requests
    - name: DRY_RUN
      value: "false" # set to "false" when you want to allow making changes to your DNS resources
```

{% endstep %}

{% step %}

#### Install ExternalDNS

To install ExternalDNS with the helm chart, use the following command:

```bash
helm upgrade external-dns-ionos-cloud external-dns/external-dns -f external-dns-ionos-cloud-values.yaml --install \
```

{% endstep %}

{% step %}

#### Create application manifest

Execute the following command to create an echo server application manifest in the `echoserver_app.yaml` file.

```bash
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echoserver
  namespace: echoserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echoserver
  template:
    metadata:
      labels:
        app: echoserver
    spec:
      containers:
      - image: ealen/echo-server:latest
        imagePullPolicy: IfNotPresent
        name: echoserver
        ports:
        - containerPort: 80
        env:
        - name: PORT
          value: "80"
```

{% endstep %}

{% step %}

#### Create echoserver namespace

Issue the following command to create a `echoserver` namespace:

```bash
kubectl create namespace echoserver
```

{% endstep %}

{% step %}

#### Apply echo server application manifest

Execute the following command to apply the `Deployment` resource to your Kubernetes cluster:

```bash
kubectl apply -f echoserver_app.yaml
```

You can check the pods of `echoserver` deployment by running the following command:

```bash
kubectl get pods -n echoserver -l app=echoserver
```

{% endstep %}

{% step %}

#### Create service for echo server application

Use the following content to create a `Service` manifest in the `echoserver-svc.yaml` file:

```bash
---
apiVersion: v1
kind: Service
metadata:
  name: echoserver
  namespace: echoserver
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: ClusterIP
  selector:
    app: echoserver
```

{% endstep %}

{% step %}

#### Apply service resource

Apply the `Service` resource to your Kubernetes cluster by running the following command:

```bash
kubectl apply -f echoserver-svc.yaml
```

{% endstep %}

{% step %}

#### Install NGINX Ingress Controller

Execute the following commands to install the NGINX ingress controller in your cluster:

```bash
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx --create-namespace
```

{% endstep %}

{% step %}

#### Create Ingress resource

Using the following content, create a `Ingress` manifest in the `echoserver-ingress.yaml` file:

```bash
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echoserver
  namespace: echoserver
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: app.example1.com #This is your subdomain / record name
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: echoserver
            port:
              number: 80
```

{% hint style="info" %}
**Note:** The `host` field in the ingress resource must be defined according to the primary zone you have configured in IONOS Cloud DNS. For example, if your primary zone is `example1.com`, you can use a subdomain like `app.example1.com`.
{% endhint %}
{% endstep %}

{% step %}

#### Apply Ingress resource

Apply the `Ingress` resource to your Kubernetes cluster by running the following command:

```bash
kubectl apply -f echoserver-ingress.yaml
```

{% endstep %}
{% endstepper %}

### Final result

The deployment of ExternalDNS on Managed Kubernetes is complete. You can verify that the application deployed is functioning as expected using one of the following options:

{% tabs %}
{% tab title="Access Application" %}
Check that the echo server app runs on the subdomain you have specified by using the following command:

```bash
curl -I app.example1.com/?echo\_code=404-300
```

{% hint style="success" %}
**Result:**

```bash
HTTP/1.1 404 Not Found 
HTTP/1.1 300 Multiple Choices
```

{% endhint %}
{% endtab %}

{% tab title="Check DNS Records" %}
Use the following command to ensure that new A and TXT records are created:

```bash
curl --location --request GET 'https://dns.de-fra.ionos.com/records?filter.name=app' \ --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJraWQiOiI4MmE5' \ --data ''
```

{% endtab %}
{% endtabs %}

## Conclusion

By following this tutorial, you have successfully deployed ExternalDNS with the IONOS Cloud webhook on a Managed Kubernetes cluster, enabling automated DNS record management for your applications. This integration streamlines DNS operations, reduces manual intervention, and ensures your DNS records stay synchronized with your cluster resources. You can now confidently manage DNS for your Kubernetes workloads using IONOS Cloud DNS.
