sigs.k8s.io/external-dns@v0.14.1/docs/faq.md (about) 1 # Frequently asked questions 2 3 ### How is ExternalDNS useful to me? 4 5 You've probably created many deployments. Typically, you expose your deployment to the Internet by creating a Service with `type=LoadBalancer`. Depending on your environment, this usually assigns a random publicly available endpoint to your service that you can access from anywhere in the world. On Google Kubernetes Engine, this is a public IP address: 6 7 ```console 8 $ kubectl get svc 9 NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE 10 nginx 10.3.249.226 35.187.104.85 80:32281/TCP 1m 11 ``` 12 13 But dealing with IPs for service discovery isn't nice, so you register this IP with your DNS provider under a better name—most likely, one that corresponds to your service name. If the IP changes, you update the DNS record accordingly. 14 15 Those times are over! ExternalDNS takes care of that last step for you by keeping your DNS records synchronized with your external entry points. 16 17 ExternalDNS' usefulness also becomes clear when you use Ingresses to allow external traffic into your cluster. Via Ingress, you can tell Kubernetes to route traffic to different services based on certain HTTP request attributes, e.g. the Host header: 18 19 ```console 20 $ kubectl get ing 21 NAME HOSTS ADDRESS PORTS AGE 22 entrypoint frontend.example.org,backend.example.org 35.186.250.78 80 1m 23 ``` 24 25 But there's nothing that actually makes clients resolve those hostnames to the Ingress' IP address. Again, you normally have to register each entry with your DNS provider. Only if you're lucky can you use a wildcard, like in the example above. 26 27 ExternalDNS can solve this for you as well. 28 29 ### Which DNS providers are supported? 30 31 Please check the [provider status table](https://github.com/kubernetes-sigs/external-dns#status-of-providers) for the list of supported providers and their status. 32 33 As stated in the README, we are currently looking for stable maintainers for those providers, to ensure that bugfixes and new features will be available for all of those. 34 35 ### Which Kubernetes objects are supported? 36 37 Services exposed via `type=LoadBalancer`, `type=ExternalName`, `type=NodePort`, and for the hostnames defined in Ingress objects as well as [headless hostPort](tutorials/hostport.md) services. 38 39 ### How do I specify a DNS name for my Kubernetes objects? 40 41 There are three sources of information for ExternalDNS to decide on DNS name. ExternalDNS will pick one in order as listed below: 42 43 1. For ingress objects ExternalDNS will create a DNS record based on the hosts specified for the ingress object, as well as the `external-dns.alpha.kubernetes.io/hostname` annotation. For services ExternalDNS will look for the annotation `external-dns.alpha.kubernetes.io/hostname` on the service and use the loadbalancer IP, it also will look for the annotation `external-dns.alpha.kubernetes.io/internal-hostname` on the service and use the service IP. 44 - For ingresses, you can optionally force ExternalDNS to create records based on _either_ the hosts specified or the `external-dns.alpha.kubernetes.io/hostname` annotation. This behavior is controlled by 45 setting the `external-dns.alpha.kubernetes.io/ingress-hostname-source` annotation on that ingress to either `defined-hosts-only` or `annotation-only`. 46 47 2. If compatibility mode is enabled (e.g. `--compatibility={mate,molecule}` flag), External DNS will parse annotations used by Zalando/Mate, wearemolecule/route53-kubernetes. Compatibility mode with Kops DNS Controller is planned to be added in the future. 48 49 3. If `--fqdn-template` flag is specified, e.g. `--fqdn-template={{.Name}}.my-org.com`, ExternalDNS will use service/ingress specifications for the provided template to generate DNS name. 50 51 ### Can I specify multiple global FQDN templates? 52 53 Yes, you can. Pass in a comma separated list to `--fqdn-template`. Beaware this will double (triple, etc) the amount of DNS entries based on how many services, ingresses and so on you have and will get you faster towards the API request limit of your DNS provider. 54 55 ### Which Service and Ingress controllers are supported? 56 57 Regarding Services, we'll support the OSI Layer 4 load balancers that Kubernetes creates on AWS and Google Kubernetes Engine, and possibly other clusters running on Google Compute Engine. 58 59 Regarding Ingress, we'll support: 60 * Google's Ingress Controller on GKE that integrates with their Layer 7 load balancers (GLBC) 61 * nginx-ingress-controller v0.9.x with a fronting Service 62 * Zalando's [AWS Ingress controller](https://github.com/zalando-incubator/kube-ingress-aws-controller), based on AWS ALBs and [Skipper](https://github.com/zalando/skipper) 63 * [Traefik](https://github.com/containous/traefik) 64 * version 1.7, when [`kubernetes.ingressEndpoint`](https://docs.traefik.io/v1.7/configuration/backends/kubernetes/#ingressendpoint) is configured (`kubernetes.ingressEndpoint.useDefaultPublishedService` in the [Helm chart](https://github.com/helm/charts/tree/HEAD/stable/traefik#configuration)) 65 * versions \>=2.0, when [`providers.kubernetesIngress.ingressEndpoint`](https://doc.traefik.io/traefik/providers/kubernetes-ingress/#ingressendpoint) is configured (`providers.kubernetesIngress.publishedService.enabled` is set to `true` in the [new Helm chart](https://github.com/traefik/traefik-helm-chart)) 66 67 ### Are other Ingress Controllers supported? 68 69 For Ingress objects, ExternalDNS will attempt to discover the target hostname of the relevant Ingress Controller automatically. If you are using an Ingress Controller that is not listed above you may have issues with ExternalDNS not discovering Endpoints and consequently not creating any DNS records. As a workaround, it is possible to force create an Endpoint by manually specifying a target host/IP for the records to be created by setting the annotation `external-dns.alpha.kubernetes.io/target` in the Ingress object. 70 71 Another reason you may want to override the ingress hostname or IP address is if you have an external mechanism for handling failover across ingress endpoints. Possible scenarios for this would include using [keepalived-vip](https://github.com/kubernetes/contrib/tree/HEAD/keepalived-vip) to manage failover faster than DNS TTLs might expire. 72 73 Note that if you set the target to a hostname, then a CNAME record will be created. In this case, the hostname specified in the Ingress object's annotation must already exist. (i.e. you have a Service resource for your Ingress Controller with the `external-dns.alpha.kubernetes.io/hostname` annotation set to the same value.) 74 75 ### What about other projects similar to ExternalDNS? 76 77 ExternalDNS is a joint effort to unify different projects accomplishing the same goals, namely: 78 79 * Kops' [DNS Controller](https://github.com/kubernetes/kops/tree/HEAD/dns-controller) 80 * Zalando's [Mate](https://github.com/linki/mate) 81 * Molecule Software's [route53-kubernetes](https://github.com/wearemolecule/route53-kubernetes) 82 83 We strive to make the migration from these implementations a smooth experience. This means that, for some time, we'll support their annotation semantics in ExternalDNS and allow both implementations to run side-by-side. This enables you to migrate incrementally and slowly phase out the other implementation. 84 85 ### How does it work with other implementations and legacy records? 86 87 ExternalDNS will allow you to opt into any Services and Ingresses that you want it to consider, by an annotation. This way, it can co-exist with other implementations running in the same cluster if they also support this pattern. However, we'll most likely declare ExternalDNS to be the default implementation. This means that ExternalDNS will consider Services and Ingresses that don't specifically declare which controller they want to be processed by; this is similar to the `ingress.class` annotation on GKE. 88 89 ### I'm afraid you will mess up my DNS records! 90 91 Since v0.3, ExternalDNS can be configured to use an ownership registry. When this option is enabled, ExternalDNS will keep track of which records it has control over, and will never modify any records over which it doesn't have control. This is a fundamental requirement to operate ExternalDNS safely when there might be other actors creating DNS records in the same target space. 92 93 For now ExternalDNS uses TXT records to label owned records, and there might be other alternatives coming in the future releases. 94 95 ### Does anyone use ExternalDNS in production? 96 97 Yes, multiple companies are using ExternalDNS in production. Zalando, as an example, has been using it in production since its v0.3 release, mostly using the AWS provider. 98 99 ### How can we start using ExternalDNS? 100 101 Check out the following descriptive tutorials on how to run ExternalDNS in [GKE](tutorials/gke.md) and [AWS](tutorials/aws.md) or any other supported provider. 102 103 ### Why is ExternalDNS only adding a single IP address in Route 53 on AWS when using the `nginx-ingress-controller`? How do I get it to use the FQDN of the ELB assigned to my `nginx-ingress-controller` Service instead? 104 105 By default the `nginx-ingress-controller` assigns a single IP address to an Ingress resource when it's created. ExternalDNS uses what's assigned to the Ingress resource, so it too will use this single IP address when adding the record in Route 53. 106 107 In most AWS deployments, you'll instead want the Route 53 entry to be the FQDN of the ELB that is assigned to the `nginx-ingress-controller` Service. To accomplish this, when you create the `nginx-ingress-controller` Deployment, you need to provide the `--publish-service` option to the `/nginx-ingress-controller` executable under `args`. Once this is deployed new Ingress resources will get the ELB's FQDN and ExternalDNS will use the same when creating records in Route 53. 108 109 According to the `nginx-ingress-controller` [docs](https://kubernetes.github.io/ingress-nginx/) the value you need to provide `--publish-service` is: 110 111 > Service fronting the ingress controllers. Takes the form namespace/name. The controller will set the endpoint records on the ingress objects to reflect those on the service. 112 113 For example if your `nginx-ingress-controller` Service's name is `nginx-ingress-controller-svc` and it's in the `default` namespace the start of your resource YAML might look like the following. Note the second to last line. 114 115 ``` 116 apiVersion: apps/v1 117 kind: Deployment 118 metadata: 119 name: nginx-ingress-controller 120 spec: 121 replicas: 1 122 selector: 123 matchLabels: 124 app: nginx-ingress 125 template: 126 metadata: 127 labels: 128 app: nginx-ingress 129 spec: 130 hostNetwork: false 131 containers: 132 - name: nginx-ingress-controller 133 image: "gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.11" 134 imagePullPolicy: "IfNotPresent" 135 args: 136 - /nginx-ingress-controller 137 - --default-backend-service={your-backend-service} 138 - --publish-service=default/nginx-ingress-controller-svc 139 - --configmap={your-configmap} 140 ``` 141 142 ### I have a Service/Ingress but it's ignored by ExternalDNS. Why? 143 144 ExternalDNS can be configured to only use Services or Ingresses as source. In case Services or Ingresses seem to be ignored in your setup, consider checking how the flag `--source` was configured when deployed. For reference, see the issue https://github.com/kubernetes-sigs/external-dns/issues/267. 145 146 ### I'm using an ELB with TXT registry but the CNAME record clashes with the TXT record. How to avoid this? 147 148 CNAMEs cannot co-exist with other records, therefore you can use the `--txt-prefix` flag which makes sure to create a TXT record with a name following the pattern `prefix.<CNAME record>`. For reference, see the issue https://github.com/kubernetes-sigs/external-dns/issues/262. 149 150 ### Can I force ExternalDNS to create CNAME records for ELB/ALB? 151 152 The default logic is: when a target looks like an ELB/ALB, ExternalDNS will create ALIAS records for it. 153 Under certain circumstances you want to force ExternalDNS to create CNAME records instead. If you want to do that, start ExternalDNS with the `--aws-prefer-cname` flag. 154 155 Why should I want to force ExternalDNS to create CNAME records for ELB/ALB? Some motivations of users were: 156 157 > "Our hosted zones records are synchronized with our enterprise DNS. The record type ALIAS is an AWS proprietary record type and AWS allows you to set a DNS record directly on AWS resources. Since this is not a DNS RfC standard and therefore can not be transferred and created in our enterprise DNS. So we need to force CNAME creation instead." 158 159 or 160 161 > "In case of ALIAS if we do nslookup with domain name, it will return only IPs of ELB. So it is always difficult for us to locate ELB in AWS console to which domain is pointing. If we configure it with CNAME it will return exact ELB CNAME, which is more helpful.!" 162 163 ### Which permissions do I need when running ExternalDNS on a GCE or GKE node. 164 165 You need to add either https://www.googleapis.com/auth/ndev.clouddns.readwrite or https://www.googleapis.com/auth/cloud-platform on your instance group's scope. 166 167 ### What metrics can I get from ExternalDNS and what do they mean? 168 169 ExternalDNS exposes 2 types of metrics: Sources and Registry errors. 170 171 `Source`s are mostly Kubernetes API objects. Examples of `source` errors may be connection errors to the Kubernetes API server itself or missing RBAC permissions. It can also stem from incompatible configuration in the objects itself like invalid characters, processing a broken fqdnTemplate, etc. 172 173 `Registry` errors are mostly Provider errors, unless there's some coding flaw in the registry package. Provider errors often arise due to accessing their APIs due to network or missing cloud-provider permissions when reading records. When applying a changeset, errors will arise if the changeset applied is incompatible with the current state. 174 175 In case of an increased error count, you could correlate them with the `http_request_duration_seconds{handler="instrumented_http"}` metric which should show increased numbers for status codes 4xx (permissions, configuration, invalid changeset) or 5xx (apiserver down). 176 177 You can use the host label in the metric to figure out if the request was against the Kubernetes API server (Source errors) or the DNS provider API (Registry/Provider errors). 178 179 Here is the full list of available metrics provided by ExternalDNS: 180 181 | Name | Description | Type | 182 | -------------------------------------------------------- | ------------------------------------------------------------------ | ------- | 183 | external_dns_controller_last_sync_timestamp_seconds | Timestamp of last successful sync with the DNS provider | Gauge | 184 | external_dns_controller_last_reconcile_timestamp_seconds | Timestamp of last attempted sync with the DNS provider | Gauge | 185 | external_dns_registry_endpoints_total | Number of Endpoints in all sources | Gauge | 186 | external_dns_registry_errors_total | Number of Registry errors | Counter | 187 | external_dns_source_endpoints_total | Number of Endpoints in the registry | Gauge | 188 | external_dns_source_errors_total | Number of Source errors | Counter | 189 | external_dns_controller_verified_aaaa_records | Number of DNS AAAA-records that exists both in source and registry | Gauge | 190 | external_dns_controller_verified_a_records | Number of DNS A-records that exists both in source and registry | Gauge | 191 | external_dns_registry_aaaa_records | Number of AAAA records in registry | Gauge | 192 | external_dns_registry_a_records | Number of A records in registry | Gauge | 193 | external_dns_source_aaaa_records | Number of AAAA records in source | Gauge | 194 | external_dns_source_a_records | Number of A records in source | Gauge | 195 196 197 If you're using the webhook provider, the following additional metrics will be provided: 198 199 | Name | Description | Type | 200 | ------------------------------------------------------------ | ------------------------------------------------------ | ------- | 201 | external_dns_webhook_provider_records_errors_total | Number of errors with the /records method | Gauge | 202 | external_dns_webhook_provider_records_requests_total | Number of requests made to the /records method | Gauge | 203 | external_dns_webhook_provider_applychanges_errors_total | Number of errors with the /applychanges method | Gauge | 204 | external_dns_webhook_provider_applychanges_requests_total | Number of requests made to the /applychanges method | Gauge | 205 | external_dns_webhook_provider_adjustendpoints_errors_total | Number of errors with the /adjustendpoints method | Gauge | 206 | external_dns_webhook_provider_adjustendpoints_requests_total | Number of requests made to the /adjustendpoints method | Gauge | 207 208 209 ### How can I run ExternalDNS under a specific GCP Service Account, e.g. to access DNS records in other projects? 210 211 Have a look at https://github.com/linki/mate/blob/v0.6.2/examples/google/README.md#permissions 212 213 ### How do I configure multiple Sources via environment variables? (also applies to domain filters) 214 215 Separate the individual values via a line break. The equivalent of `--source=service --source=ingress` would be `service\ningress`. However, it can be tricky do define that depending on your environment. The following examples work (zsh): 216 217 Via docker: 218 219 ```console 220 $ docker run \ 221 -e EXTERNAL_DNS_SOURCE=$'service\ningress' \ 222 -e EXTERNAL_DNS_PROVIDER=google \ 223 -e EXTERNAL_DNS_DOMAIN_FILTER=$'foo.com\nbar.com' \ 224 registry.k8s.io/external-dns/external-dns:v0.14.0 225 time="2017-08-08T14:10:26Z" level=info msg="config: &{APIServerURL: KubeConfig: Sources:[service ingress] Namespace: ... 226 ``` 227 228 229 Locally: 230 231 ```console 232 $ export EXTERNAL_DNS_SOURCE=$'service\ningress' 233 $ external-dns --provider=google 234 INFO[0000] config: &{APIServerURL: KubeConfig: Sources:[service ingress] Namespace: ... 235 ``` 236 237 ``` 238 $ EXTERNAL_DNS_SOURCE=$'service\ningress' external-dns --provider=google 239 INFO[0000] config: &{APIServerURL: KubeConfig: Sources:[service ingress] Namespace: ... 240 ``` 241 242 In a Kubernetes manifest: 243 244 ```yaml 245 spec: 246 containers: 247 - name: external-dns 248 args: 249 - --provider=google 250 env: 251 - name: EXTERNAL_DNS_SOURCE 252 value: "service\ningress" 253 ``` 254 255 Or preferably: 256 257 ```yaml 258 spec: 259 containers: 260 - name: external-dns 261 args: 262 - --provider=google 263 env: 264 - name: EXTERNAL_DNS_SOURCE 265 value: |- 266 service 267 ingress 268 ``` 269 270 271 ### Running an internal and external dns service 272 273 Sometimes you need to run an internal and an external dns service. 274 The internal one should provision hostnames used on the internal network (perhaps inside a VPC), and the external one to expose DNS to the internet. 275 276 To do this with ExternalDNS you can use the `--ingress-class` flag to specifically tie an instance of ExternalDNS to an instance of a ingress controller. 277 Let's assume you have two ingress controllers, `internal` and `external`. 278 You can then start two ExternalDNS providers, one with `--ingress-class=internal` and one with `--ingress-class=external`. 279 280 If you need to search for multiple ingress classes, you can specify the flag multiple times, like so: 281 `--ingress-class=internal --ingress-class=external`. 282 283 The `--ingress-class` flag will check both the `spec.ingressClassName` field and the deprecated `kubernetes.io/ingress.class` annotation. 284 The `spec.ingressClassName` tasks precedence over the annotation if both are supplied. 285 286 **Backward compatibility** 287 288 The previous `--annotation-filter` flag can still be used to restrict which objects ExternalDNS considers; for example, `--annotation-filter=kubernetes.io/ingress.class in (public,dmz)`. 289 290 However, beware when using annotation filters with multiple sources, e.g. `--source=service --source=ingress`, since `--annotation-filter` will filter every given source object. 291 If you need to use annotation filters against a specific source you have to run a separated external dns service containing only the wanted `--source` and `--annotation-filter`. 292 293 Note: the `--ingress-class` flag cannot be used at the same time as the `--annotation-filter=kubernetes.io/ingress.class in (...)` flag; if you do this an error will be raised. 294 295 **Performance considerations** 296 297 Filtering based on ingress class name or annotations means that the external-dns controller will receive all resources of that kind and then filter on the client-side. 298 In larger clusters with many resources which change frequently this can cause performance issues. 299 If only some resources need to be managed by an instance of external-dns then label filtering can be used instead of ingress class filtering (or legacy annotation filtering). 300 This means that only those resources which match the selector specified in `--label-filter` will be passed to the controller. 301 302 ### How do I specify that I want the DNS record to point to either the Node's public or private IP when it has both? 303 304 If your Nodes have both public and private IP addresses, you might want to write DNS records with one or the other. 305 For example, you may want to write a DNS record in a private zone that resolves to your Nodes' private IPs so that traffic never leaves your private network. 306 307 To accomplish this, set this annotation on your service: `external-dns.alpha.kubernetes.io/access=private` 308 Conversely, to force the public IP: `external-dns.alpha.kubernetes.io/access=public` 309 310 If this annotation is not set, and the node has both public and private IP addresses, then the public IP will be used by default. 311 312 Some loadbalancer implementations assign multiple IP addresses as external addresses. You can filter the generated targets by their networks 313 using `--target-net-filter=10.0.0.0/8` or `--exclude-target-net=10.0.0.0/8`. 314 315 ### Can external-dns manage(add/remove) records in a hosted zone which is setup in different AWS account? 316 317 Yes, give it the correct cross-account/assume-role permissions and use the `--aws-assume-role` flag https://github.com/kubernetes-sigs/external-dns/pull/524#issue-181256561 318 319 ### How do I provide multiple values to the annotation `external-dns.alpha.kubernetes.io/hostname`? 320 321 Separate them by `,`. 322 323 324 ### Are there official Docker images provided? 325 326 When we tag a new release, we push a container image to the Kubernetes projects official container registry with the following name: 327 328 ``` 329 registry.k8s.io/external-dns/external-dns 330 ``` 331 332 As tags, you use the external-dns release of choice(i.e. `v0.7.6`). A `latest` tag is not provided in the container registry. 333 334 If you wish to build your own image, you can use the provided [.ko.yaml](../.ko.yaml) as a starting point. 335 336 ### Which architectures are supported? 337 338 From `v0.7.5` on we support `amd64`, `arm32v7` and `arm64v8`. This means that you can run ExternalDNS on a Kubernetes cluster backed by Rasperry Pis or on ARM instances in the cloud as well as more traditional machines backed by `amd64` compatible CPUs. 339 340 ### Which operating systems are supported? 341 342 At the time of writing we only support GNU/linux and we have no plans of supporting Windows or other operating systems. 343 344 ### Why am I seeing time out errors even though I have connectivity to my cluster? 345 346 If you're seeing an error such as this: 347 ``` 348 FATA[0060] failed to sync cache: timed out waiting for the condition 349 ``` 350 351 You may not have the correct permissions required to query all the necessary resources in your kubernetes cluster. Specifically, you may be running in a `namespace` that you don't have these permissions in. By default, commands are run against the `default` namespace. Try changing this to your particular namespace to see if that fixes the issue.