diff --git a/docs/ttl.md b/docs/ttl.md index 35295e90b..57a262aab 100644 --- a/docs/ttl.md +++ b/docs/ttl.md @@ -28,6 +28,7 @@ Providers - [ ] InMemory - [x] Linode - [x] TransIP +- [x] RFC2136 PRs welcome! diff --git a/docs/tutorials/rfc2136.md b/docs/tutorials/rfc2136.md index 154a836d0..3fa790ca6 100644 --- a/docs/tutorials/rfc2136.md +++ b/docs/tutorials/rfc2136.md @@ -1,69 +1,255 @@ # Configuring RFC2136 provider +This tutorial describes how to use the RFC2136 with either BIND or Windows DNS. ## Using with BIND +To use external-dns with BIND: generate/procure a key, configure DNS and add a +deployment of external-dns. + ### Server credentials: -- RFC2136 was developed for and tested with [BIND](https://www.isc.org/downloads/bind/) DNS server. This documentation assumes that you already have a configured and working server. If you don't, please check BIND documents or tutorials. -- So you should obtain from your administrator a TSIG key. It will look like: +- RFC2136 was developed for and tested with +[BIND](https://www.isc.org/downloads/bind/) DNS server. This documentation +assumes that you already have a configured and working server. If you don't, +please check BIND documents or tutorials. +- If your DNS is provided for you, ask for a TSIG key authorized to update and +transfer the zone you wish to update. The key will look something like below. +Skip the next steps wrt BIND setup. ```text key "externaldns-key" { algorithm hmac-sha256; - secret "XXXXXXXXXXXXXXXXXXXXXX=="; + secret "96Ah/a2g0/nLeFGK+d/0tzQcccf9hCEIy34PoXX2Qg8="; }; ``` -- **Warning!** Bind server configuration should enable this key for AFXR zone transfer. `external-dns` uses it for listing DNS records. +- If you are your own DNS administrator create a TSIG key. Use +`tsig-keygen -a hmac-sha256 externaldns` or on older distributions +`dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST externaldns`. You will end up with +a key printed to standard out like above (or in the case of dnssec-keygen in a +file called `Kexternaldns......key`). +### BIND Configuration: +If you do not administer your own DNS, skip to RFC provider configuration + +- Edit your named.conf file (or appropriate included file) and add/change the +following. + - Make sure You are listening on the right interfaces. At least whatever + interface external-dns will be communicating over and the interface that + faces the internet. + - Add the key that you generated/was given to you above. Copy paste the four + lines that you got (not the same as the example key) into your file. + - Create a zone for kubernetes. If you already have a zone, skip to the next + step. (I put the zone in it's own subdirectory because named, + which shouldn't be running as root, needs to create a journal file and the + default zone directory isn't writeable by named). + ```text + zone "k8s.example.org" { + type master; + file "/etc/bind/pri/k8s/k8s.zone"; + }; + ``` + - Add your key to both transfer and update. For instance with our previous + zone. + ```text + zone "k8s.example.org" { + type master; + file "/etc/bind/pri/k8s/k8s.zone"; + allow-transfer { + key "externaldns-key"; + }; + update-policy { + grant externaldns-key zonesub ANY; + }; + }; + ``` + - Create a zone file (k8s.zone): + ```text + $TTL 60 ; 1 minute + k8s.example.org IN SOA k8s.example.org. root.k8s.example.org. ( + 16 ; serial + 60 ; refresh (1 minute) + 60 ; retry (1 minute) + 60 ; expire (1 minute) + 60 ; minimum (1 minute) + ) + NS ns.k8s.example.org. + ns A 123.456.789.012 + ``` + - Reload (or restart) named + + +### Using external-dns +To use external-dns add an ingress or a LoadBalancer service with a host that +is part of the domain-filter. For example both of the following would produce +A records. ```text -# cat /etc/named.conf -... -include "/etc/rndc.key"; - -controls { - inet 123.123.123.123 port 953 allow { 10.x.y.151; } keys { "externaldns-key"; }; -}; -options { - include "/etc/named/options.conf"; -}; - -include "/etc/named/zones.conf"; -... - -# cat /etc/named/options.conf -... -dnssec-enable yes; -dnssec-validation yes; -... - -# cat /etc/named/zones.conf -... -zone "example.com" { - type master; - file "/var/named/dynamic/db.example.com"; - update-policy { - grant externaldns-key zonesub ANY; - }; -}; -... +apiVersion: v1 +kind: Service +metadata: + name: nginx + annotations: + external-dns.alpha.kubernetes.io/hostname: svc.example.org +spec: + type: LoadBalancer + ports: + - port: 80 + targetPort: 80 + selector: + app: nginx +--- +apiVersion: networking.k8s.io/v1beta1 +kind: Ingress +metadata: + name: my-ingress +spec: + rules: + - host: ingress.example.org + http: + paths: + - path: / + backend: + serviceName: my-service + servicePort: 8000 ``` +There are other annotation that can affect the generation of DNS records like +external-dns.alpha.kubernetes.io/ttl. These are beyond the scope of this +tutorial and are covered elsewhere in the docs. + +### Test with external-dns installed on local machine (optional) +You may install external-dns and test on a local machine by running: +```external-dns --txt-owner-id k8s --provider rfc2136 --rfc2136-host=192.168.0.1 --rfc2136-port=53 --rfc2136-zone=k8s.example.org --rfc2136-tsig-secret=96Ah/a2g0/nLeFGK+d/0tzQcccf9hCEIy34PoXX2Qg8= --rfc2136-tsig-secret-alg=hmac-sha256 --rfc2136-tsig-keyname=externaldns-key --rfc2136-tsig-axfr --source ingress --once --domain-filter=k8s.example.org --dry-run``` +- host should be the IP of your master DNS server. +- tsig-secret should be changed to match your secret. +- tsig-keyname needs to match the keyname you used (if you changed it). +- domain-filter can be used as shown to filter the domains you wish to update. ### RFC2136 provider configuration: -- Example fragment of real configuration of ExternalDNS service pod. +In order to use external-dns with your cluster you need to add a deployment +with access to your ingress and service resources. The following are two +example manifests with and without RBAC respectively. +- With RBAC: ```text -... +apiVersion: v1 +kind: Namespace +metadata: + name: external-dns + labels: + name: external-dns +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: external-dns + namespace: external-dns +rules: +- apiGroups: + - "" + resources: + - services + verbs: + - get + - watch + - list +- apiGroups: + - extensions + resources: + - ingresses + verbs: + - get + - list + - watch +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: external-dns + namespace: external-dns +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: external-dns-viewer + namespace: external-dns +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: external-dns +subjects: +- kind: ServiceAccount + name: external-dns + namespace: external-dns +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: external-dns + namespace: external-dns +spec: + selector: + matchLabels: + app: external-dns + template: + metadata: + labels: + app: external-dns + spec: + serviceAccountName: external-dns + containers: + - name: external-dns + image: registry.opensource.zalan.do/teapot/external-dns:v0.5.17 + args: + - --txt-owner-id=k8s - --provider=rfc2136 - - --rfc2136-host=123.123.123.123 + - --rfc2136-host=192.168.0.1 - --rfc2136-port=53 - - --rfc2136-zone=your-domain.com - - --rfc2136-tsig-secret=${rfc2136_tsig_secret} + - --rfc2136-zone=k8s.example.org + - --rfc2136-tsig-secret=96Ah/a2g0/nLeFGK+d/0tzQcccf9hCEIy34PoXX2Qg8= - --rfc2136-tsig-secret-alg=hmac-sha256 - --rfc2136-tsig-keyname=externaldns-key - --rfc2136-tsig-axfr -... + - --source=ingress + - --domain-filter=k8s.example.org ``` -- `--rfc2136-tsig-secret` - environment variable containing actual secret value from TSIG key. Something like `XXXXXXXXXXXXXXXXXXXXXX==`. -- `--rfc2136-tsig-keyname` - this is a string parameter with the key name in the Kubernetes secret. It **must match** with key name on the DNS server. In this example it is `externaldns-key`. - -## Using with Microsoft DNS + +- Without RBAC: +```text +apiVersion: v1 +kind: Namespace +metadata: + name: external-dns + labels: + name: external-dns +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: external-dns + namespace: external-dns +spec: + selector: + matchLabels: + app: external-dns + template: + metadata: + labels: + app: external-dns + spec: + containers: + - name: external-dns + image: registry.opensource.zalan.do/teapot/external-dns:v0.5.17 + args: + - --txt-owner-id=k8s + - --provider=rfc2136 + - --rfc2136-host=192.168.0.1 + - --rfc2136-port=53 + - --rfc2136-zone=k8s.example.org + - --rfc2136-tsig-secret=96Ah/a2g0/nLeFGK+d/0tzQcccf9hCEIy34PoXX2Qg8= + - --rfc2136-tsig-secret-alg=hmac-sha256 + - --rfc2136-tsig-keyname=externaldns-key + - --rfc2136-tsig-axfr + - --source=ingress + - --domain-filter=k8s.example.org +``` + +## Microsoft DNS While `external-dns` was not developed or tested against Microsoft DNS, it can be configured to work against it. YMMV.