3 Commits

Author SHA1 Message Date
unkinben 01e73c3a21 Pull bind CRDs from operator repo instead of vendoring
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline failed
References the CRD bundle from the bind-operator repo by a stable raw URL
so the CRDs never drift from the operator, matching how other apps import
upstream manifests.

- replace the nine vendored crds/*.yaml with a single remote resource:
  git.unkin.net/unkin/bind-operator raw config/crd/install.yaml at v0.1.1
- bump the operator image to v0.1.1 so the running operator and its CRDs
  come from the same tag
2026-07-03 18:56:48 +10:00
unkinben c57b115400 Make external-dns tier authoritative (drop dynamic mode)
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
The dynamic cluster mode was removed from the operator; RFC2136 update
capability is a per-zone property, not a cluster role. The external-dns
tier is an authoritative cluster whose zones set dynamicUpdate.

- switch binddns-externaldns BindCluster to mode authoritative
- regenerate bindcluster schema (enum: authoritative, resolver)
2026-07-03 18:36:04 +10:00
unkinben d11c2900de Deploy bind-operator and three BIND DNS tiers
Adds the bind-operator and the three BindClusters that replace the
Puppet-managed BIND estate (authoritative / resolver / external-dns).

- add apps/base/bind-system: 9 CRDs, operator Deployment, RBAC (ns bind-system)
- add apps/base/binddns-auth: authoritative BindCluster + catalog zone + TSIG key
- add apps/base/binddns-resolver: recursive-resolver BindCluster with forwarders
- add apps/base/binddns-externaldns: dynamic (RFC2136) BindCluster + TSIG key
- add au-syd1 overlays for all four apps
- register the four apps in the platform ApplicationSet
- add binddns-* namespaces to the platform AppProject destinations
- add schemas/bind.unkin.net/*.json so kubeconform validates the new CRs

DNS Services are LoadBalancer via PureLB. TSIG key material is generated by
the operator into Secrets at runtime (no plain Secrets in git).
2026-07-03 17:48:45 +10:00
25 changed files with 78 additions and 316 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ spec:
mountPath: /combined-certs
containers:
- name: api
image: git.unkin.net/unkin/artifactapi:v3.7.4
image: git.unkin.net/unkin/artifactapi:v3.7.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8000
+1 -1
View File
@@ -22,7 +22,7 @@ spec:
automountServiceAccountToken: true
containers:
- name: ui
image: git.unkin.net/unkin/artifactapi-ui:v3.7.4
image: git.unkin.net/unkin/artifactapi-ui:v3.7.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
@@ -1,204 +0,0 @@
# Authoritative zones migrated from puppet-prod
# (profiles::dns::master::zones in hieradata/roles/infra/dns/master.yaml).
# type primary, static (puppet dynamic:false); TTL 600 as in the puppet zone header.
# Record data is populated by PuppetDB exported resources upstream, so it is
# NOT in this repo — migrate it into these zones (AXFR from the current masters,
# or DNSRecord CRs) as a follow-up. The zones start with SOA+NS only.
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: unkin-net
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: unkin.net
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: main-unkin-net
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: main.unkin.net
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 13-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 13.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 14-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 14.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 15-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 15.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 16-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 16.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 17-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 17.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 19-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 19.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 20-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 20.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 21-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 21.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 22-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 22.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 23-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 23.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 24-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 24.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 25-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 25.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 26-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 26.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 27-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 27.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 28-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 28.18.198.in-addr.arpa
type: primary
defaultTTL: 600
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 29-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-authoritative
zoneName: 29.18.198.in-addr.arpa
type: primary
defaultTTL: 600
@@ -1,39 +0,0 @@
---
# external-dns tier (replaces the 3x Puppet external-dns servers). An ordinary
# authoritative cluster; external-dns writes to its zones via RFC2136 because
# those BindZones set dynamicUpdate (allow-update { key externaldns-key; }).
apiVersion: bind.unkin.net/v1alpha1
kind: BindCluster
metadata:
name: bind-externaldns
namespace: bind-internal
spec:
mode: authoritative
replicas: 3
storageClassName: cephrbd-fast-delete
storageSize: 1Gi
service:
type: LoadBalancer
annotations:
purelb.io/service-group: common
purelb.io/addresses: 198.18.200.8
external-dns.alpha.kubernetes.io/hostname: bind-externaldns.k8s.syd1.au.unkin.net
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: "1"
memory: 512Mi
---
# Catalog zone so the dynamic zones replicate onto the cluster's secondaries
# (external-dns writes to the primary; secondaries IXFR the result).
apiVersion: bind.unkin.net/v1alpha1
kind: BindCatalogZone
metadata:
name: bind-externaldns-catalog
namespace: bind-internal
spec:
clusterRef: bind-externaldns
zoneName: catalog.externaldns.internal
transferKeyRef: externaldns-key
@@ -1,34 +0,0 @@
# k8s external-dns zones migrated from puppet-prod
# (externaldns::k8s_zones in hieradata/roles/infra/dns/externaldns.yaml).
# Primary + dynamicUpdate: the Kubernetes external-dns controller writes
# records here via RFC2136 authenticated with externaldns-key.
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: k8s-syd1-au-unkin-net
namespace: bind-internal
spec:
clusterRef: bind-externaldns
zoneName: k8s.syd1.au.unkin.net
type: primary
defaultTTL: 600
dynamicUpdate: true
updateKeyRef: externaldns-key
allowTransfer:
- key externaldns-key
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: 200-18-198-in-addr-arpa
namespace: bind-internal
spec:
clusterRef: bind-externaldns
zoneName: 200.18.198.in-addr.arpa
type: primary
defaultTTL: 600
dynamicUpdate: true
updateKeyRef: externaldns-key
allowTransfer:
- key externaldns-key
@@ -1,9 +0,0 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- authoritative
- resolvers
- externaldns
+1 -1
View File
@@ -21,7 +21,7 @@ spec:
runAsNonRoot: true
containers:
- name: operator
image: git.unkin.net/unkin/bind-operator:v0.1.3
image: git.unkin.net/unkin/bind-operator:v0.1.1
args:
- --metrics-bind-address=:8080
- --health-probe-bind-address=:8081
+1 -1
View File
@@ -6,6 +6,6 @@ resources:
- namespace.yaml
# CRDs are pulled from the bind-operator repo at the matching tag rather than
# vendored here, so they never drift from the operator.
- https://git.unkin.net/unkin/bind-operator/raw/tag/v0.1.3/config/crd/install.yaml
- https://git.unkin.net/unkin/bind-operator/raw/tag/v0.1.1/config/crd/install.yaml
- rbac.yaml
- deployment.yaml
@@ -4,8 +4,8 @@
apiVersion: bind.unkin.net/v1alpha1
kind: BindCluster
metadata:
name: bind-authoritative
namespace: bind-internal
name: auth
namespace: binddns-auth
spec:
mode: authoritative
replicas: 3
@@ -15,8 +15,7 @@ spec:
type: LoadBalancer
annotations:
purelb.io/service-group: common
purelb.io/addresses: 198.18.200.6
external-dns.alpha.kubernetes.io/hostname: bind-authoritative.k8s.syd1.au.unkin.net
external-dns.alpha.kubernetes.io/hostname: ns-auth.k8s.syd1.au.unkin.net
resources:
requests:
cpu: 100m
@@ -29,9 +28,9 @@ spec:
apiVersion: bind.unkin.net/v1alpha1
kind: BindCatalogZone
metadata:
name: bind-authoritative-catalog
namespace: bind-internal
name: auth-catalog
namespace: binddns-auth
spec:
clusterRef: bind-authoritative
clusterRef: auth
zoneName: catalog.internal
transferKeyRef: transfer-key
@@ -3,6 +3,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- cluster.yaml
- namespace.yaml
- tsigkey.yaml
- zones.yaml
- cluster.yaml
@@ -2,4 +2,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: bind-internal
name: binddns-auth
@@ -5,7 +5,6 @@ apiVersion: bind.unkin.net/v1alpha1
kind: BindTSIGKey
metadata:
name: transfer-key
namespace: bind-internal
namespace: binddns-auth
spec:
clusterRef: bind-authoritative
algorithm: hmac-sha256
@@ -0,0 +1,26 @@
---
# external-dns tier (replaces the 3x Puppet external-dns servers). An ordinary
# authoritative cluster; external-dns writes to its zones via RFC2136 because
# those BindZones set dynamicUpdate (allow-update { key externaldns-key; }).
apiVersion: bind.unkin.net/v1alpha1
kind: BindCluster
metadata:
name: externaldns
namespace: binddns-externaldns
spec:
mode: authoritative
replicas: 3
storageClassName: cephrbd-fast-delete
storageSize: 1Gi
service:
type: LoadBalancer
annotations:
purelb.io/service-group: dmz
external-dns.alpha.kubernetes.io/hostname: ns-ext.k8s.syd1.au.unkin.net
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: "1"
memory: 512Mi
@@ -3,6 +3,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- cluster.yaml
- namespace.yaml
- tsigkey.yaml
- zones.yaml
- cluster.yaml
@@ -0,0 +1,5 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: binddns-externaldns
@@ -5,7 +5,6 @@ apiVersion: bind.unkin.net/v1alpha1
kind: BindTSIGKey
metadata:
name: externaldns-key
namespace: bind-internal
namespace: binddns-externaldns
spec:
clusterRef: bind-externaldns
algorithm: hmac-sha256
@@ -4,8 +4,8 @@
apiVersion: bind.unkin.net/v1alpha1
kind: BindCluster
metadata:
name: bind-resolvers
namespace: bind-internal
name: resolver
namespace: binddns-resolver
spec:
mode: resolver
replicas: 3
@@ -15,8 +15,7 @@ spec:
type: LoadBalancer
annotations:
purelb.io/service-group: common
purelb.io/addresses: 198.18.200.7
external-dns.alpha.kubernetes.io/hostname: bind-resolvers.k8s.syd1.au.unkin.net
external-dns.alpha.kubernetes.io/hostname: resolver.k8s.syd1.au.unkin.net
forwarders:
- 1.1.1.1
- 9.9.9.9
@@ -3,4 +3,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- cluster.yaml
@@ -0,0 +1,5 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: binddns-resolver
@@ -3,4 +3,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../base/bind-internal
- ../../../base/binddns-auth
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../base/binddns-externaldns
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../base/binddns-resolver
+3 -1
View File
@@ -13,7 +13,9 @@ spec:
- path: apps/overlays/*/authentik
- path: apps/overlays/*/artifactapi
- path: apps/overlays/*/bind-system
- path: apps/overlays/*/bind-internal
- path: apps/overlays/*/binddns-auth
- path: apps/overlays/*/binddns-resolver
- path: apps/overlays/*/binddns-externaldns
- path: apps/overlays/*/age-api
- path: apps/overlays/*/cattle-system
- path: apps/overlays/*/cert-manager
+5 -1
View File
@@ -21,7 +21,11 @@ spec:
server: https://kubernetes.default.svc
- namespace: 'authentik'
server: https://kubernetes.default.svc
- namespace: 'bind-internal'
- namespace: 'binddns-auth'
server: https://kubernetes.default.svc
- namespace: 'binddns-resolver'
server: https://kubernetes.default.svc
- namespace: 'binddns-externaldns'
server: https://kubernetes.default.svc
- namespace: 'cert-manager'
server: https://kubernetes.default.svc
@@ -24,9 +24,6 @@
],
"type": "string"
},
"clusterRef": {
"type": "string"
},
"importExisting": {
"type": "boolean"
},