sigs.k8s.io/external-dns@v0.14.1/docs/tutorials/pihole.md (about) 1 # Setting up ExternalDNS for Pi-hole 2 3 This tutorial describes how to setup ExternalDNS to sync records with Pi-hole's Custom DNS. 4 Pi-hole has an internal list it checks last when resolving requests. This list can contain any number of arbitrary A or CNAME records. 5 There is a pseudo-API exposed that ExternalDNS is able to use to manage these records. 6 7 __NOTE:__ Your Pi-hole must be running [version 5.9 or newer](https://pi-hole.net/blog/2022/02/12/pi-hole-ftl-v5-14-web-v5-11-and-core-v5-9-released). 8 9 10 ## Deploy ExternalDNS 11 12 You can skip to the [manifest](#externaldns-manifest) if authentication is disabled on your Pi-hole instance or you don't want to use secrets. 13 14 If your Pi-hole server's admin dashboard is protected by a password, you'll likely want to create a secret first containing its value. 15 This is optional since you _do_ retain the option to pass it as a flag with `--pihole-password`. 16 17 You can create the secret with: 18 19 ```bash 20 kubectl create secret generic pihole-password \ 21 --from-literal EXTERNAL_DNS_PIHOLE_PASSWORD=supersecret 22 ``` 23 24 Replacing **"supersecret"** with the actual password to your Pi-hole server. 25 26 ### ExternalDNS Manifest 27 28 Apply the following manifest to deploy ExternalDNS, editing values for your environment accordingly. 29 Be sure to change the namespace in the `ClusterRoleBinding` if you are using a namespace other than **default**. 30 31 ```yaml 32 --- 33 apiVersion: v1 34 kind: ServiceAccount 35 metadata: 36 name: external-dns 37 --- 38 apiVersion: rbac.authorization.k8s.io/v1 39 kind: ClusterRole 40 metadata: 41 name: external-dns 42 rules: 43 - apiGroups: [""] 44 resources: ["services","endpoints","pods"] 45 verbs: ["get","watch","list"] 46 - apiGroups: ["extensions","networking.k8s.io"] 47 resources: ["ingresses"] 48 verbs: ["get","watch","list"] 49 - apiGroups: [""] 50 resources: ["nodes"] 51 verbs: ["list","watch"] 52 --- 53 apiVersion: rbac.authorization.k8s.io/v1 54 kind: ClusterRoleBinding 55 metadata: 56 name: external-dns-viewer 57 roleRef: 58 apiGroup: rbac.authorization.k8s.io 59 kind: ClusterRole 60 name: external-dns 61 subjects: 62 - kind: ServiceAccount 63 name: external-dns 64 namespace: default 65 --- 66 apiVersion: apps/v1 67 kind: Deployment 68 metadata: 69 name: external-dns 70 spec: 71 strategy: 72 type: Recreate 73 selector: 74 matchLabels: 75 app: external-dns 76 template: 77 metadata: 78 labels: 79 app: external-dns 80 spec: 81 serviceAccountName: external-dns 82 containers: 83 - name: external-dns 84 image: registry.k8s.io/external-dns/external-dns:v0.14.0 85 # If authentication is disabled and/or you didn't create 86 # a secret, you can remove this block. 87 envFrom: 88 - secretRef: 89 # Change this if you gave the secret a different name 90 name: pihole-password 91 args: 92 - --source=service 93 - --source=ingress 94 # Pihole only supports A/CNAME records so there is no mechanism to track ownership. 95 # You don't need to set this flag, but if you leave it unset, you will receive warning 96 # logs when ExternalDNS attempts to create TXT records. 97 - --registry=noop 98 # IMPORTANT: If you have records that you manage manually in Pi-hole, set 99 # the policy to upsert-only so they do not get deleted. 100 - --policy=upsert-only 101 - --provider=pihole 102 # Change this to the actual address of your Pi-hole web server 103 - --pihole-server=http://pihole-web.pihole.svc.cluster.local 104 securityContext: 105 fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes token files 106 ``` 107 108 ### Arguments 109 110 - `--pihole-server (env: EXTERNAL_DNS_PIHOLE_SERVER)` - The address of the Pi-hole web server 111 - `--pihole-password (env: EXTERNAL_DNS_PIHOLE_PASSWORD)` - The password to the Pi-hole web server (if enabled) 112 - `--pihole-tls-skip-verify (env: EXTERNAL_DNS_PIHOLE_TLS_SKIP_VERIFY)` - Skip verification of any TLS certificates served by the Pi-hole web server. 113 114 ## Verify ExternalDNS Works 115 116 ### Ingress Example 117 118 Create an Ingress resource. ExternalDNS will use the hostname specified in the Ingress object. 119 120 ```yaml 121 apiVersion: networking.k8s.io/v1 122 kind: Ingress 123 metadata: 124 name: foo 125 spec: 126 ingressClassName: nginx 127 rules: 128 - host: foo.bar.com 129 http: 130 paths: 131 - path: / 132 pathType: Prefix 133 backend: 134 service: 135 name: foo 136 port: 137 number: 80 138 ``` 139 140 ### Service Example 141 142 The below sample application can be used to verify Services work. 143 For services ExternalDNS will look for the annotation `external-dns.alpha.kubernetes.io/hostname` on the service and use the corresponding value. 144 145 ```yaml 146 --- 147 apiVersion: v1 148 kind: Service 149 metadata: 150 name: nginx 151 annotations: 152 external-dns.alpha.kubernetes.io/hostname: nginx.external-dns-test.homelab.com 153 spec: 154 type: LoadBalancer 155 ports: 156 - port: 80 157 name: http 158 targetPort: 80 159 selector: 160 app: nginx 161 --- 162 apiVersion: apps/v1 163 kind: Deployment 164 metadata: 165 name: nginx 166 spec: 167 selector: 168 matchLabels: 169 app: nginx 170 template: 171 metadata: 172 labels: 173 app: nginx 174 spec: 175 containers: 176 - image: nginx 177 name: nginx 178 ports: 179 - containerPort: 80 180 name: http 181 ``` 182 183 You can then query your Pi-hole to see if the record was created. 184 185 _Change `@192.168.100.2` to the actual address of your DNS server_ 186 187 ```bash 188 $ dig +short @192.168.100.2 nginx.external-dns-test.homelab.com 189 190 192.168.100.129 191 ```