diff --git a/README.md b/README.md index 949ac4c53..72722d0a4 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ The following tutorials are provided: * [Cloudflare](docs/tutorials/cloudflare.md) * [CoreDNS](docs/tutorials/coredns.md) * [DigitalOcean](docs/tutorials/digitalocean.md) +* [Hetzner](docs/tutorials/hetzner.md) * [DNSimple](docs/tutorials/dnsimple.md) * [Dyn](docs/tutorials/dyn.md) * [Exoscale](docs/tutorials/exoscale.md) diff --git a/docs/tutorials/hetzner.md b/docs/tutorials/hetzner.md new file mode 100644 index 000000000..e40f1af83 --- /dev/null +++ b/docs/tutorials/hetzner.md @@ -0,0 +1,191 @@ +# Setting up ExternalDNS for Services on Hetzner DNS + +This tutorial describes how to setup ExternalDNS for usage within a Kubernetes cluster using Hetzner DNS. + +Make sure to use **>=0.7.2** version of ExternalDNS for this tutorial. + +## Creating a Hetzner DNS zone + +If you want to learn about how to use Hetzner's DNS service read the following tutorial series: + +[An Introduction to Managing DNS](https://wiki.hetzner.de/index.php/DNS_Overview), and [Add a new DNS zone](https://wiki.hetzner.de/index.php/Getting_started). + +Create a new DNS zone where you want to create your records in. Let's use `example.com` as an example here. + +## Creating Hetzner Credentials + +Generate a new personal token by going to [the API settings](https://dns.hetzner.com/settings/api-token) or follow [Generating an API access token](https://wiki.hetzner.de/index.php/API_access_token) if you need more information. Give the token a name and choose read and write access. The token needs to be passed to ExternalDNS so make a note of it for later use. + +The environment variable `HETZNER_TOKEN` will be needed to run ExternalDNS with Hetzner. + +## Deploy ExternalDNS + +Connect your `kubectl` client to the cluster you want to test ExternalDNS with. +Then apply one of the following manifests file to deploy ExternalDNS. + +### Manifest (for clusters without RBAC enabled) +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: external-dns +spec: + replicas: 1 + selector: + matchLabels: + app: external-dns + strategy: + type: Recreate + template: + metadata: + labels: + app: external-dns + spec: + containers: + - name: external-dns + image: registry.opensource.zalan.do/teapot/external-dns:latest + args: + - --source=service # ingress is also possible + - --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above. + - --provider=hetznerYOUR_HETZNER_DNS_API_KEY + env: + - name: HETZNER_TOKEN + value: "YOUR_HETZNER_DNS_API_KEY" +``` + +### Manifest (for clusters with RBAC enabled) +```yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: external-dns +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: external-dns +rules: +- apiGroups: [""] + resources: ["services","endpoints","pods"] + verbs: ["get","watch","list"] +- apiGroups: ["extensions"] + resources: ["ingresses"] + verbs: ["get","watch","list"] +- apiGroups: [""] + resources: ["nodes"] + verbs: ["list"] +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: external-dns-viewer +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: external-dns +subjects: +- kind: ServiceAccount + name: external-dns + namespace: default +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: external-dns +spec: + replicas: 1 + selector: + matchLabels: + app: external-dns + strategy: + type: Recreate + template: + metadata: + labels: + app: external-dns + spec: + serviceAccountName: external-dns + containers: + - name: external-dns + image: registry.opensource.zalan.do/teapot/external-dns:latest + args: + - --source=service # ingress is also possible + - --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above. + - --provider=hetzner + env: + - name: HETZNER_TOKEN + value: "YOUR_HETZNER_DNS_API_KEY" +``` + + +## Deploying an Nginx Service + +Create a service file called 'nginx.yaml' with the following contents: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx +spec: + replicas: 1 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - image: nginx + name: nginx + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx + annotations: + external-dns.alpha.kubernetes.io/hostname: my-app.example.com +spec: + selector: + app: nginx + type: LoadBalancer + ports: + - protocol: TCP + port: 80 + targetPort: 80 +``` + +Note the annotation on the service; use the same hostname as the Hetzner DNS zone created above. + +ExternalDNS uses this annotation to determine what services should be registered with DNS. Removing the annotation will cause ExternalDNS to remove the corresponding DNS records. + +Create the deployment and service: + +```console +$ kubectl create -f nginx.yaml +``` + +Depending where you run your service it can take a little while for your cloud provider to create an external IP for the service. + +Once the service has an external IP assigned, ExternalDNS will notice the new service IP address and synchronize the Hetzner DNS records. + +## Verifying Hetzner DNS records + +Check your [Hetzner DNS UI](https://dns.hetzner.com/) to view the records for your Hetzner DNS zone. + +Click on the zone for the one created above if a different domain was used. + +This should show the external IP address of the service as the A record for your domain. + +## Cleanup + +Now that we have verified that ExternalDNS will automatically manage Hetzner DNS records, we can delete the tutorial's example: + +``` +$ kubectl delete service -f nginx.yaml +$ kubectl delete service -f externaldns.yaml +```