Home

Awesome

ExternalDNS - Hetzner Webhook

⚠️ This software is experimental. ⚠️

ExternalDNS is a Kubernetes add-on for automatically DNS records for Kubernetes services using different providers. By default, Kubernetes manages DNS records internally, but ExternalDNS takes this functionality a step further by delegating the management of DNS records to an external DNS provider such as this one. This webhook allows you to manage your Hetzner domains inside your kubernetes cluster.

ℹ️ If you are upgrading to 0.7.x from 0.6.x read the Upgrading from previous versions section.

Requirements

An API token for the account managing your domains is required for this webhook to work properly.

This webhook can be used in conjunction with ExternalDNS v0.14.0 or higher, configured for using the webhook interface. Some examples for a working configuration are shown in the next section.

Kubernetes Deployment

The Hetzner webhook is provided as a regular Open Container Initiative (OCI) image released in the GitHub container registry. The deployment can be performed in every way Kubernetes supports.

Here are provided examples using the External DNS chart and the Bitnami chart.

In either case, a secret that stores the Hetzner API key is required:

kubectl create secret generic hetzner-credentials --from-literal=api-key='<EXAMPLE_PLEASE_REPLACE>' -n external-dns

Using the ExternalDNS chart

Skip this step if you already have the ExternalDNS repository added:

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

Update your helm chart repositories:

helm repo update

You can then create the helm values file, for example external-dns-hetzner-values.yaml:

namespace: external-dns
policy: sync
provider:
  name: webhook
  webhook:
    image:
      repository: ghcr.io/mconfalonieri/external-dns-hetzner-webhook
      tag: v0.7.0
    env:
      - name: HETZNER_API_KEY
        valueFrom:
          secretKeyRef:
            name: hetzner-credentials
            key: api-key
    livenessProbe:
      httpGet:
        path: /health
        port: http-wh-metrics
      initialDelaySeconds: 10
      timeoutSeconds: 5
    readinessProbe:
      httpGet:
        path: /ready
        port: http-wh-metrics
      initialDelaySeconds: 10
      timeoutSeconds: 5

extraArgs:
  - "--txt-prefix=reg-%{record_type}-"

And then:

# install external-dns with helm
helm install external-dns-hetzner external-dns/external-dns -f external-dns-hetzner-values.yaml --version 0.15.0 -n external-dns

Using the Bitnami chart

Skip this step if you already have the Bitnami repository added:

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

Update your helm chart repositories:

helm repo update

You can then create the helm values file, for example external-dns-hetzner-values.yaml:

provider: webhook
policy: sync
extraArgs:
  webhook-provider-url: http://localhost:8888
  txt-prefix: "reg-%{record_type}-"

sidecars:
  - name: hetzner-webhook
    image: ghcr.io/mconfalonieri/external-dns-hetzner-webhook:v0.7.0
    ports:
      - containerPort: 8888
        name: webhook
      - containerPort: 8080
        name: http-wh-metrics
    livenessProbe:
      httpGet:
        path: /health
        port: http-wh-metrics
      initialDelaySeconds: 10
      timeoutSeconds: 5
    readinessProbe:
      httpGet:
        path: /ready
        port: http-wh-metrics
      initialDelaySeconds: 10
      timeoutSeconds: 5
    env:
      - name: HETZNER_API_KEY
        valueFrom:
          secretKeyRef:
            name: hetzner-credentials
            key: api-key

And then:

# install external-dns with helm
helm install external-dns-hetzner bitnami/external-dns -f external-dns-hetzner-values.yaml -n external-dns

Upgrading from previous versions

0.6.x to 0.7.x

The configuration for previous versions are still compatible, but consider that some warnings will be emitted if HEALTH_HOST and HEALTH_PORT are set. The changes to be aware of are:

Environment variables

The following environment variables can be used for configuring the application.

Hetzner DNS API calls configuration

These variables control the behavior of the webhook when interacting with Hetzner DNS API.

VariableDescriptionNotes
HETZNER_API_KEYHetzner API tokenMandatory
BATCH_SIZENumber of zones per callDefault: 100, max: 100
DEFAULT_TTLDefault record TTLDefault: 7200

Test and debug

These environment variables are useful for testing and debugging purposes.

VariableDescriptionNotes
DRY_RUNIf set, changes won't be appliedDefault: false
HETZNER_DEBUGEnables debugging messagesDefault: false

Socket configuration

These variables control the sockets that this application listens to.

VariableDescriptionNotes
WEBHOOK_HOSTWebhook hostname or IP addressDefault: localhost
WEBHOOK_PORTWebhook portDefault: 8888
METRICS_HOSTMetrics hostnameDefault: 0.0.0.0
METRICS_PORTMetrics portDefault: 8080
READ_TIMEOUTSockets' read timeout in msDefault: 60000
WRITE_TIMEOUTSockets' write timeout in msDefault: 60000

Please notice that the following variables were deprecated:

VariableDescription
HEALTH_HOSTMetrics hostname (deprecated)
HEALTH_PORTMetrics port (deprecated)

Domain filtering

Additional environment variables for domain filtering. When used, this webhook will be able to work only on domains matching the filter.

Environment variableDescription
DOMAIN_FILTERFiltered domains
EXCLUDE_DOMAIN_FILTERExcluded domains
REGEXP_DOMAIN_FILTERRegex for filtered domains
REGEXP_DOMAIN_FILTER_EXCLUSIONRegex for excluded domains

If the REGEXP_DOMAIN_FILTER is set, the following variables will be used to build the filter:

otherwise, the filter will be built using:

Endpoints

This process exposes several endpoints, that will be available through these sockets:

Socket nameSocket address
WebhookWEBHOOK_HOST:WEBHOOK_PORT
MetricsMETRICS_HOST:METRICS_PORT

The environment variables controlling the socket addresses are not meant to be changed, under normal circumstances, for the reasons explained in Tweaking the configuration. The endpoints expected by ExternalDNS are marked with *.

Webhook socket

All these endpoints are required by ExternalDNS.

EndpointPurpose
/Initialization and DomainFilter negotiations
/recordGet and apply records
/adjustendpointsAdjust endpoints before submission

Metrics socket

ExternalDNS doesn't have functional requirements for this endpoint, but some of them are recommended. In this table those endpoints are marked with *.

Endpoint*Purpose
/healthImplements the liveness probe
/readyImplements the readiness probe
/healthz*Implements a combined liveness and readiness probe
/metrics*Exposes the available metrics

Please check the Exposed metrics section for more information.

Tweaking the configuration

While tweaking the configuration, there are some points to take into consideration:

Exposed metrics

The following metrics related to the API calls towards Hetzner are available for scraping.

NameTypeLabelsDescription
successful_api_calls_totalCounteractionThe number of successful Hetzner API calls
failed_api_calls_totalCounteractionThe number of Hetzner API calls that returned an error
filtered_out_zonesGaugenoneThe number of zones excluded by the domain filter
skipped_recordsGaugezoneThe number of skipped records per domain
api_delay_histHistogramactionHistogram of the delay (ms) when calling the Hetzner API

The label action can assume one of the following values, depending on the Hetzner API endpoint called:

The label zone can assume one of the zone names as its value.

Please notice that in some cases an update request from ExternalDNS will be transformed into a delete_record and subsequent create_record calls by this webhook.

Development

The basic development tasks are provided by make. Run make help to see the available targets.

Credits

This Webhook was forked and modified from the IONOS Webhook to work with Hetzner. It also contains huge parts from DrBu7cher's Hetzner provider.

Contributors

NameContribution
DerQuelocal CNAME fix
sschaeffnerbuild configuration for arm64