external-dns/docs/advanced/ptr-records.md
Seena Fallah 736a2d58ae
feat!: generalize PTR record support from rfc2136 to all providers (#6232)
* feat(metrics): add source wrapper metrics for invalid and deduplicated endpoints

Add GaugeVecMetric.Reset() to clear stale label combinations between cycles.

Introduce invalidEndpoints and deduplicatedEndpoints gauge vectors in the
source wrappers package, partitioned by record_type and source_type. The
dedup source wrapper now tracks rejected (invalid) and de-duplicated
endpoints per collection cycle.

Update the metrics documentation and bump the known metrics count.

Signed-off-by: Seena Fallah <seenafallah@gmail.com>

* feat(source): add PTR source wrapper for automatic reverse DNS

Implement ptrSource, a source wrapper that generates PTR endpoints from
A/AAAA records. The wrapper supports:

- Global default via WithCreatePTR (maps to --create-ptr flag)
- Per-endpoint override via record-type provider-specific property
- Grouping multiple hostnames sharing an IP into a single PTR endpoint
- Skipping wildcard DNS names

Add WithPTRSupported and WithCreatePTR options to the wrapper Config
and wire the PTR wrapper into the WrapSources chain when PTR is in
managed-record-types.

Signed-off-by: Seena Fallah <seenafallah@gmail.com>

* feat(config): add --create-ptr flag and deprecate --rfc2136-create-ptr

Add the generic --create-ptr boolean flag to Config, enabling automatic
PTR record creation for any provider. Add IsPTRSupported() helper that
checks whether PTR is included in --managed-record-types.

Add validation: --create-ptr (or legacy --rfc2136-create-ptr) now
requires PTR in --managed-record-types, preventing misconfiguration.

Mark --rfc2136-create-ptr as deprecated in the flag description.

Signed-off-by: Seena Fallah <seenafallah@gmail.com>

* refactor(rfc2136): remove inline PTR logic in favor of PTR source wrapper

Remove the createPTR field, AddReverseRecord, RemoveReverseRecord, and
GenerateReverseRecord methods from the rfc2136 provider. PTR record
generation is now handled generically by the PTR source wrapper before
records reach the provider.

Update the PTR creation test to supply pre-generated PTR endpoints
(simulating what the source wrapper produces) instead of relying on
the provider to create them internally.

Signed-off-by: Seena Fallah <seenafallah@gmail.com>

* feat(controller): wire PTR source wrapper into buildSource

Pass the top-level Config to buildSource so it can read IsPTRSupported()
and the CreatePTR / RFC2136CreatePTR flags. When PTR is in
managed-record-types, the PTR source wrapper is installed in the
wrapper chain with the combined create-ptr default.

Signed-off-by: Seena Fallah <seenafallah@gmail.com>

* chore(pdns): remove stale comment and fix whitespace

Remove an outdated comment about a single-target-per-tuple assumption
that no longer applies.

Signed-off-by: Seena Fallah <seenafallah@gmail.com>

* docs: add PTR records documentation and update existing guides

Add docs/advanced/ptr-records.md covering the --create-ptr flag,
per-resource annotation overrides, prerequisites, and usage examples.

Update:
- annotations.md: document record-type annotation
- flags.md: add --create-ptr, mark --rfc2136-create-ptr as deprecated
- tutorials/rfc2136.md: point to generic --create-ptr flag
- contributing/source-wrappers.md: add PTR wrapper to the chain
- mkdocs.yml: add PTR Records navigation entry

Signed-off-by: Seena Fallah <seenafallah@gmail.com>

* feat(rfc2136)!: remove rfc2136-create-ptr in favor of create-ptr

Signed-off-by: Seena Fallah <seenafallah@gmail.com>

---------

Signed-off-by: Seena Fallah <seenafallah@gmail.com>
2026-03-30 13:36:16 +05:30

4.1 KiB

Automatic PTR (Reverse DNS) Records

To automatically create PTR records for your A/AAAA endpoints, use the --create-ptr flag. This feature works with any provider that has authority over reverse DNS zones (e.g. in-addr.arpa for IPv4 or ip6.arpa for IPv6).

Flag and annotation

The --create-ptr flag is a boolean (default: false) that sets the global default for PTR record creation. The external-dns.alpha.kubernetes.io/record-type annotation on a resource overrides this default, following the standard configuration precedence:

Flag Annotation Result
true (absent) PTR record created
true "" (empty) PTR record not created (annotation opts out)
false (absent) PTR record not created
false "ptr" PTR record created (annotation opts in)

Prerequisites

The underlying DNS provider must have authority over the relevant reverse DNS zones. Include the reverse zone in --domain-filter so that ExternalDNS knows it is allowed to manage records there.

PTR must also be included in --managed-record-types so the planner considers PTR records during sync:

  --create-ptr \
  --managed-record-types=A \
  --managed-record-types=AAAA \
  --managed-record-types=CNAME \
  --managed-record-types=PTR \
  --domain-filter=example.com \
  --domain-filter=49.168.192.in-addr.arpa

Usage

Global PTR creation

With --create-ptr enabled, every A/AAAA record managed by ExternalDNS automatically gets a corresponding PTR record. Individual resources can opt out by setting the annotation to an empty value.

external-dns \
  --provider=pdns \
  --create-ptr \
  --domain-filter=example.com \
  --domain-filter=49.168.192.in-addr.arpa

Per-resource PTR creation

Without --create-ptr, only resources annotated with external-dns.alpha.kubernetes.io/record-type: "ptr" produce PTR records.

apiVersion: v1
kind: Service
metadata:
  name: web
  annotations:
    external-dns.alpha.kubernetes.io/hostname: web.example.com
    external-dns.alpha.kubernetes.io/record-type: "ptr"
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: web

If the Service receives the external IP 192.168.49.2, ExternalDNS creates both web.example.com → 192.168.49.2 (A) and 2.49.168.192.in-addr.arpa → web.example.com (PTR).

Resources without the annotation are not affected.

DNSEndpoint CRD

The DNSEndpoint CRD source does not process Kubernetes resource annotations. To enable PTR for individual CRD endpoints, set the record-type property directly in spec.endpoints[].providerSpecific:

apiVersion: externaldns.k8s.io/v1alpha1
kind: DNSEndpoint
metadata:
  name: web
spec:
  endpoints:
  - dnsName: web.example.com
    recordType: A
    targets:
    - 192.168.49.2
    providerSpecific:
    - name: record-type
      value: ptr

When --create-ptr is enabled globally, PTR records are generated for all A/AAAA endpoints regardless of source, including DNSEndpoint.

Behaviour details

  • Wildcard records (e.g. *.example.com) are skipped — a PTR pointing to a wildcard hostname is not meaningful.
  • When multiple A/AAAA records point to the same IP address, their hostnames are grouped into a single ExternalDNS endpoint. In DNS this produces multiple PTR resource records in the same RRSet (one per hostname), which is valid per RFC 1035. For example, if both a.example.com and b.example.com resolve to 192.168.49.2, a dig -x 192.168.49.2 will return two PTR answers. Note that not all providers may handle multi-target PTR records correctly — verify with your provider if this applies to your setup.
  • PTR records whose forward hostname does not match --domain-filter are automatically cleaned up.
  • PTR records are tracked by the TXT registry like any other record type, so ownership is preserved across restarts.