This reference documents the user-facing API — the resources platform users
create and read to manage DNS. The operator serves them under the API
group/version dns.networking.miloapis.com/v1alpha1. Generated CRDs live in
config/crd/bases; runnable samples live in
config/samples.
| Resource | Scope | Purpose |
|---|---|---|
DNSZoneClass |
Cluster | Selects backend and nameserver policy |
DNSZone |
Namespaced | A single authoritative domain |
DNSRecordSet |
Namespaced | Records of one type, for one or more owner names |
DNSZoneDiscovery |
Namespaced | One-shot snapshot of live records |
Cluster-scoped policy, analogous to a StorageClass. Every DNSZone references
a class, which determines the backend and how the operator assigns authoritative
nameservers.
| Field | Type | Description |
|---|---|---|
spec.controllerName |
string | Backend selector (e.g. powerdns). The downstream agent only acts on zones whose class it implements. |
spec.nameServerPolicy.mode |
string | Nameserver assignment mode. Static is currently supported. |
spec.nameServerPolicy.static.servers |
[]string | Authoritative nameservers advertised for zones using this class. |
spec.defaults.defaultTTL |
int64 | Optional default TTL applied to zones. |
status.conditions |
[]Condition | Accepted, Programmed. |
apiVersion: dns.networking.miloapis.com/v1alpha1
kind: DNSZoneClass
metadata:
name: powerdns
spec:
controllerName: powerdns
nameServerPolicy:
mode: Static
static:
servers: ["ns1.example.net.", "ns2.example.net."]Namespaced. Models a single domain.
| Field | Type | Description |
|---|---|---|
spec.domainName |
string | Required FQDN (e.g. example.com). Immutable once set. |
spec.dnsZoneClassName |
string | Reference to a DNSZoneClass. |
status.nameservers |
[]string | Authoritative nameservers, derived from the class policy. |
status.recordCount |
int | Number of record sets in the zone. |
status.conditions |
[]Condition | Accepted, Programmed. |
status.domainRef |
object | Link to the owning Domain, exposing its name and assigned nameservers, when present. |
apiVersion: dns.networking.miloapis.com/v1alpha1
kind: DNSZone
metadata:
name: example-com
namespace: default
spec:
domainName: example.com
dnsZoneClassName: powerdnsNamespaced. Models records of one record type within a zone, across one or more
owner names. Each entry in spec.records sets one owner name and carries exactly
one typed field matching spec.recordType; the backend groups entries that share
an owner name into a single RRset.
| Field | Type | Description |
|---|---|---|
spec.dnsZoneRef |
LocalObjectReference | The DNSZone in the same namespace. |
spec.recordType |
string | One of A, AAAA, ALIAS, CNAME, TXT, MX, SRV, CAA, NS, SOA, PTR, TLSA, HTTPS, SVCB. |
spec.records[].name |
string | Owner name; @ for the zone apex. |
spec.records[].ttl |
int64 | Optional per-owner TTL. |
spec.records[].<type> |
object | Typed record content for the entry. Each typed field's content is a single value (e.g. a.content: "192.0.2.10"); other types use their own fields (mx.preference/mx.exchange, srv.*, soa.*). |
status.conditions |
[]Condition | Accepted, Programmed. |
status.recordSets[] |
[]object | Per-owner-name realized status, including per-record Programmed. |
Each entry holds a single value. To give one owner name several addresses, add one entry per value; the backend groups them into one RRset:
apiVersion: dns.networking.miloapis.com/v1alpha1
kind: DNSRecordSet
metadata:
name: www-a
namespace: default
spec:
dnsZoneRef:
name: example-com
recordType: A
records:
- name: www
a:
content: "192.0.2.10"
ttl: 300
- name: www
a:
content: "192.0.2.11"
ttl: 300When several DNSRecordSet resources target the same zone, owner name, and
record type, the agent programs a single owner, chosen by oldest creation
timestamp and then by name. Each losing claim gets Programmed=False with
reason NotOwner on its own entry in status.recordSets[], so a record set
that holds other names keeps reporting on those normally.
Claims are compared by owner name as written, while the backend keys its record set on the qualified name. Two spellings of one name can therefore each win their own contest and then overwrite each other. See Record Ownership for the full rules, including the intended handling of case and the apex, and Conditions and Reasons for which reasons clear on their own.
Namespaced, write-once. Snapshots a zone's live records via DNS queries; performs no backend writes. Useful for onboarding or verifying an existing domain.
| Field | Type | Description |
|---|---|---|
spec.dnsZoneRef |
LocalObjectReference | The DNSZone to snapshot. |
status.conditions |
[]Condition | Accepted, Discovered. |
status.recordSets[] |
[]object | Discovered records, grouped by record type. |
Every DNS resource reports status through standard Kubernetes conditions:
| Condition | Meaning |
|---|---|
Accepted |
The resource is valid and its dependencies are satisfied. |
Programmed |
The backend has realized the desired state. |
Discovered |
(DNSZoneDiscovery only) The live-record snapshot completed. |
Common reasons include Pending, Programmed, DNSZoneInUse (domain already
claimed by another zone), NotOwner (a conflicting record set owns the name),
and PDNSError (the backend rejected the change). See
Replication Model for how the operator
synthesizes conditions across clusters.
On a DNSRecordSet, Programmed aggregates the per-record conditions in
status.recordSets[], and distinguishes a record set that is still converging
from one that cannot proceed:
Aggregate Programmed |
Meaning |
|---|---|
True / Programmed |
Every record is realized in the backend. |
False / Pending |
One or more records have not been programmed yet; no record has reported a cause. |
False / a per-record reason |
At least one record cannot be programmed until something changes. The reason is that record's own reason and the message names the record and the cause. |
When several records are blocked for different reasons, the aggregate reports
the reason of the first blocked record in record-name order and lists every
blocked record in its message. A caller can therefore treat any reason other
than Pending as needing attention, without reading status.recordSets[].
Note
This reference covers the user-facing API. The DNSOperator object that
configures the operator binary is deployment configuration, not part of the
served API — see Deployment Topology → Operator
Configuration.