ExternalDNS
ExternalDNS holder posterne i dine Frostmoln Administreret DNS-zoner synkroniseret med Kubernetes-ressourcerne Ingress, Service og Gateway API — fra en hvilken som helst Kubernetes-klynge. Når du eksponerer en arbejdslast, bliver værtsnavnets poster oprettet, opdateret og ryddet op automatisk; du redigerer aldrig DNS i hånden.
Frostmoln leverer en webhook-udbyder, der kører som en sidecar i external-dns-podden og oversætter ExternalDNS' planer til kald mod Frostmolns DNS-API.
Forudsætninger
- En Frostmoln DNS-zone til det domæne, du vil have poster i — se Administreret DNS for at oprette en.
- En legitimationsoplysning til webhooken, en af:
- Workload Identity (anbefalet): ingen nøgle at oprette eller gemme. Se Godkend med Workload Identity.
- En tenant-API-nøgle (
fmk_...), som ejes af en bruger i den tenant. Se Gem en API-nøgle.
- Udgående HTTPS fra dine arbejdsnoder til
registry.k8s.ioogregistry.sweden.frostmoln.cloud. Opstrøms ExternalDNS-controllerens image hentes fraregistry.k8s.ioog Frostmolns webhook-image fraregistry.sweden.frostmoln.cloud, når podden starter. Hvis du filtrerer udgående trafik efter værtsnavn, er det ikke nok at tilladeregistry.k8s.ioalene: den omdirigerer image-hentninger til skybaserede lagringssteder på andre domæner. Uden dette bliver controllerens container stående iImagePullBackOff, og platformen kan ikke advare dig — netværksadgangen hører til dit VPC, ikke til os.
Sådan fungerer det
- Poster — webhooken lister din tenants zoner og postsæt og returnerer dem til ExternalDNS som endepunkter (ét postsæt = ét
(navn, type)med alle sine værdier). - Anvend — oprettelser og opdateringer går gennem DNS-API'ets idempotente upsert på samlingsniveau; sletninger slår postsættet op via dets stabile ID.
- Domænefilter — som standard henter webhooken din tenants zonenavne ved opstart og administrerer kun dem. Opretter du en ny zone → genstart podden, så den bliver taget med (eller angiv
DOMAIN_FILTEReksplicit). - Ejerskab — brug ExternalDNS' TXT-standardregister (
--registry=txtmed--txt-owner-id=<klynge-id>), så en post kun ændres af den klynge, der oprettede den. TXT-postsæt går uændret gennem API'et.
Installer
På Frostmoln Administreret Kubernetes er ExternalDNS med Frostmoln-webhooken en klyngetilføjelse med ét klik. Vælg external-dns, når du opretter klyngen, eller føj den til en klynge, der allerede kører (portalen → klyngens fane Tilføjelser, fm kubernetes cluster add-addons, eller sættet addons på API'et/Terraform-ressourcen), så installerer platformen det hele for dig — navnerummet external-dns, RBAC, ExternalDNS-controlleren og Frostmoln-webhook-sidecaren, med --txt-owner-id allerede sat til din klynges id og FROSTMOLN_TENANT_ID sat til din klynges tenant. Webhook-imaget leveres af platformen og hentes fra registry.sweden.frostmoln.cloud (se forudsætningerne). Du bygger eller refererer aldrig til det selv.
Det eneste trin, der er tilbage til dig, er legitimationsoplysningen: en Workload Identity-binding (anbefalet) eller en API-nøgle-Secret. Indtil en af dem findes, afslutter webhook-containeren på tilføjelsesversion v0.22.0-4 med no credential og genstartes (CrashLoopBackOff). På tidligere versioner venter den i CreateContainerConfigError. Opret din DNS-zone først (eller genstart external-dns-Deploymenten, efter at du har oprettet den).
Tilføjelsesversionerne v0.22.0-1 og v0.22.0-2: flyt låsningen til v0.22.0-3
I de to versioner spørger webhooken API'et om hjemme-tenanten for den bruger, der oprettede nøglen, og administrerer den tenants zoner. Hvis nøglen blev oprettet i en anden tenant — klyngens, når din bruger hører til mere end én — afslutter webhooken ved opstart med 403 TENANT_ACCESS_DENIED, og podden bliver hængende i CrashLoopBackOff. Fra v0.22.0-3 sætter platformen webhookens tenant til klyngens egen. Begge de ældre versioner er markeret som forældede. Flyt en eksisterende klynge med fm kubernetes cluster pin-addons <cluster-id> --version external-dns=v0.22.0-3, portalens fane Tilføjelser, eller addon_versions i Terraform — se Kubernetes → Tilføjelsesversioner.
Føj den til ved oprettelsen, eller senere
Tilføjelsen kan vælges, når klyngen oprettes, og føjes til en klynge, der allerede kører. At føje den til bagefter sker ikke øjeblikkeligt: tilføjelsen starter sin egen synkronisering og installeres typisk inden for få minutter; kan den synkronisering ikke startes, sker det først ved platformens næste synkronisering, op til en time. Klyngens tilføjelsesliste viser dit nye valg, så snart det er accepteret — det er det valg, du har bedt om, ikke et bevis på, at objekterne allerede er på klyngen.
At fjerne den er en separat, navngiven handling. På API'et og i Terraform sender du altid hele det ønskede sæt af tilføjelser, ikke kun den nye nøgle — og et sæt, der ganske enkelt udelader external-dns, afvises, fordi en forespørgsel bygget på et forældet billede af klyngen ellers ville slette en tilføjelse, du aldrig havde til hensigt at røre. Navngiv i stedet det, du fjerner: knappen Fjern i portalen, fm kubernetes cluster remove-addons, eller feltet remove i forespørgslen til API'et. I Terraform anvendes en nøgle, du fjerner fra addons, nu på stedet i stedet for at erstatte klyngen.
Nogle klynger, der blev oprettet, før denne mulighed kom, kan slet ikke modtage nye tilføjelser; API'et siger det til dig, når du prøver, og der er den eneste vej at oprette klyngen på ny med tilføjelsen valgt. ExternalDNS med Frostmoln-webhooken er i øjeblikket kun tilgængelig på Frostmoln Administreret Kubernetes.
Administreret Kubernetes: aktiver tilføjelsen
På Frostmoln Administreret Kubernetes er den nemmeste vej klyngetilføjelsen external-dns: vælg den, når klyngen oprettes, eller føj den til en kørende klynge bagefter (portalen → klyngens fane Tilføjelser, fm kubernetes cluster add-addons, eller sættet addons på API'et/Terraform-ressourcen), så installerer platformen alt i denne vejledning — navnerummet external-dns, RBAC og Deploymenten, med --txt-owner-id allerede sat til klyngens id.
Det eneste manuelle trin er legitimationsoplysningen. Se Godkend med Workload Identity (anbefalet) eller Gem en API-nøgle.
Tilføjet senere, og kan fjernes
Tilføjelsen kan også føjes til en klynge, der allerede kører; tilføjelsen starter da sin egen synkronisering og installeres typisk inden for få minutter. Kan den synkronisering ikke startes, sker det først ved platformens næste synkronisering, op til en time. Den kan fjernes igen på samme måde — fra fanen Tilføjelser i portalen, med fm kubernetes cluster remove-addons, eller ved at fjerne nøglen. En klynge, der blev oprettet, før den enkelte mulighed kom, kan ikke modtage den eller ikke fjerne den, og siger det, når du prøver; opret den klynge på ny, eller anvend manifestet under Distribuer selv.
Fjerner du den, bliver dine DNS-poster liggende. ExternalDNS ejer de poster, den har oprettet, og at slette controlleren sletter dem ikke — ingenting vil administrere dem bagefter. Hvis du senere sletter en lastbalancer, som en af de poster peger på, går adressen tilbage til puljen og kan blive tildelt på ny, mens din post stadig slår op til den. Vælger du tilføjelsen igen på samme klynge, adopterer den sine egne poster på ny og fortsætter med at administrere dem.
Med Workload Identity sletter du tilføjelsens binding (eller kører terraform destroy på den) for at tilbagekalde dens adgang. Der efterlades ingen nøgle.
Med en API-nøgle beholdes navnerummet external-dns og din frostmoln-dns-Secret også. Den Secret indeholder en Frostmoln-API-nøgle, og at slette Secret'en tilbagekalder ikke nøglen. Gør det i denne rækkefølge:
Bruger noget andet den samme nøgle, så giv det først sin egen nøgle.
Tilbagekald denne nøgle. Kun den bruger, der oprettede den, kan gøre det: under Indstillinger → API-nøgler i portalen eller med
fm account api-key listogfm account api-key revoke. Alle nøgler begynder medfmk_, så sammenlign nøglens første 12 tegn med det viste nøglepræfiks. Læs dem fra Secret'en:bashkubectl -n external-dns get secret frostmoln-dns -o jsonpath='{.data.api-key}' | base64 -d | cut -c1-12Slet først derefter Secret'en — platformen viser aldrig hele nøglen igen, så læs præfikset, før Secret'en er væk.
Er ExternalDNS ikke fjernet endnu, logger den godkendelsesfejl efter tilbagekaldelsen, indtil den er væk; læg ikke en ny nøgle i denne Secret for at få dem til at stoppe. Vil du vælge tilføjelsen igen senere, skal du oprette en ny nøgle og Secret.
Udskiftning af en klynge: overtag dens poster
ExternalDNS ændrer kun poster, hvis TXT-ejerskabspost angiver dens egen klynge-id. En ny klynge får et nyt id, så den opdaterer ikke poster, som en tidligere klynge har publiceret, heller ikke under de samme navne. Dens log viser All records are already up to date, mens navnet bliver ved med at pege på den gamle klynges adresse. Det sker, når du sletter en klynge og opretter en ny, og det er også sådan en blue/green-flytning mellem klynger opfører sig.
For at overdrage et navn til den nye klynge skal du omskrive ejeren i dens TXT-post, når du skifter over:
Find den nye klynges id med
fm kubernetes cluster list.List zonens TXT-poster med
fm dns record list <zone-id> --type TXT -o json. ExternalDNS navngiver hver af dem efter den post, den ejer, med posttypen foran, såa-www.example.comejer A-postenwww.example.com. Værdien indeholderexternal-dns/owner=<gammelt klynge-id>.Kopiér værdien nøjagtigt, og udskift kun id'et efter
external-dns/owner=:bashfm dns record update <zone-id> <txt-record-id> --value '<værdien med det nye klynge-id>'
Inden for et minut behandler den nye klynges ExternalDNS posten som sin egen og peger den mod den nye adresse. Kører den gamle klynge stadig, holder den op med at styre navnet fra samme øjeblik.
Omskriv alle ejerskabsposter for et navn, før du går videre til det næste. Der er én pr. posttype (A, AAAA, CNAME), og et navn, hvor en ejerskabspost stadig har det gamle id, styres ikke af nogen af klyngerne. Et jokertegn *.example.com ejes af a-*.example.com. Det virker ikke for et navn i zonens apex, fordi ejerskabsposten så ville ligge uden for zonen.
Genbrug ikke det gamle id i den nye klynges --txt-owner-id i stedet. I den administrerede tilføjelse sættes værdien af platformen, og to kørende klynger, der deler ét ejer-id, sletter hinandens poster.
Godkend med Workload Identity (anbefalet)
Fra tilføjelsesversion v0.22.0-4 godkender webhooken med Workload Identity. Platformen udsteder et kortlivet, zoneafgrænset token til den og fornyer det omkring hver time. Der er ingen API-nøgle at oprette, gemme i en Secret, rotere eller tilbagekalde, og intet havner i din Terraform-tilstand. Tilføjelsens ServiceAccount (external-dns i navnerummet external-dns) er allerede tilmeldt, så du skal kun tildele den adgang.
Du skal bruge:
- Tilføjelsen Workload Identity på samme klynge. Se Workload Identity → Trin 1.
- Tilføjelsen external-dns i version v0.22.0-4 eller nyere. Flyt en eksisterende klynges låsning med
fm kubernetes cluster pin-addons <cluster-id> --version external-dns=v0.22.0-4, portalens fane Tilføjelser elleraddon_versionsi Terraform. - En binding for
external-dns/external-dnsmed en adgangspolitik, der lader den liste zoner, og læse, opdatere og slette på de zoner, den administrerer. At oprette eller ændre en post tæller som en opdatering af den zone, der ejer den, og at slette en post tæller som en sletning på den zone. Afgræns den regel til din zones id:
resource "frostmoln_workload_identity_binding" "external_dns" {
cluster_id = frostmoln_kubernetes_cluster.prod.id
namespace = "external-dns"
service_account = "external-dns"
}
data "frostmoln_iam_policy_document" "external_dns" {
rule {
name = "list-zones"
access = "allow"
operations = ["network:dns-zones:list"]
targets = ["frn:network:*:*:dns-zones/*"]
}
rule {
name = "manage-zone"
access = "allow"
operations = ["network:dns-zones:read", "network:dns-zones:update", "network:dns-zones:delete"]
targets = ["frn:network:*:*:dns-zones/${frostmoln_dns_zone.example.id}"]
}
}
resource "frostmoln_iam_policy" "external_dns" {
name = "external-dns"
document = data.frostmoln_iam_policy_document.external_dns.json
}
resource "frostmoln_iam_policy_attachment" "external_dns" {
policy_id = frostmoln_iam_policy.external_dns.id
attachee_type = "workload_identity"
attachee_id = frostmoln_workload_identity_binding.external_dns.id
}network:dns-zones:delete tillader også at slette zonen
Poster har endnu ingen egen adgang, så den adgang, external-dns skal bruge for at fjerne en post, lader også de legitimationsoplysninger slette hele den zone, de er afgrænset til. Hold reglen afgrænset til de zoner, external-dns administrerer. Uden delete udgiver external-dns poster, men kan aldrig fjerne dem: en post for en slettet Service bliver i DNS og peger på en adresse, der kan blive genbrugt, og webhooken logger 403 ... does not permit network:dns-zones:delete hvert minut.
Med fm-CLI'en opretter du bindingen uden adgange og knytter den samme politik:
fm kubernetes workload-identity binding create \
--cluster <cluster-id> --namespace external-dns --service-account external-dns
fm iam policy create --name external-dns --document @external-dns-policy.json
fm iam policy attach <policy-id> --type workload_identity --id <binding-id>Når tilføjelsen Workload Identity og bindingen er på plads, skal du ikke gøre mere. Legitimationsoplysningen kobles kun ind i en pod, når podden oprettes, så en pod, der blev oprettet, før tilføjelsen Workload Identity kørte, får den ikke. Det gælder også klynger, hvor begge tilføjelser blev valgt samtidig. Fra workload-identity v0.3.0-1 genstarter tilføjelsen selv en sådan pod inden for et par minutter, og den kommer tilbage med legitimationsoplysningen. På en ældre version af workload-identity bliver podden ved med at bruge API-nøglen eller genstartes, uden en nøgle, med workload identity is not injected. Flyt klyngen til den nyere version:
fm kubernetes cluster pin-addons <cluster-id> --version workload-identity=v0.3.0-1Webhooken logger, hvilken legitimationsoplysning den bruger:
kubectl -n external-dns logs deploy/external-dns -c frostmoln-webhook | grep authenticating
# ... "authenticating with the workload-identity credential"Workload Identity går forud for en API-nøgle
Hver forespørgsel bruger Workload Identity-tokenet, når der er et, og falder kun tilbage til API-nøglen i frostmoln-dns, når der ikke er noget. Det sker for eksempel, når tilføjelsen Workload Identity er installeret, men der ikke er nogen binding for external-dns. Derfor kan du migrere uden nedetid: tilføj bindingen, kontrollér loglinjen ovenfor, og tilbagekald derefter nøglen og slet dens Secret. Slettes en binding, udløber dens sidste token inden for omkring en time. Derefter fejler webhookens forespørgsler med 401, indtil der igen findes en binding. Nøglen bruges ikke som reserve, mens det udløbne token stadig ligger på disken.
Gem en API-nøgle (reserve)
Brug en API-nøgle, hvor Workload Identity ikke er tilgængelig: på en klynge uden tilføjelsen Workload Identity, på tilføjelsesversioner før v0.22.0-4, eller når du selv distribuerer manifestet nedenfor. Læg tenant-API-nøglen i en Secret, som webhooken kan læse:
kubectl create namespace external-dns # spring over, hvis tilføjelsen allerede har oprettet det
kubectl create secret generic frostmoln-dns \
--namespace external-dns \
--from-literal=api-key=fmk_...Distribuer
På Administreret Kubernetes med tilføjelsen aktiveret kan du springe dette afsnit over — kun Secreten ovenfor er nødvendig.
Manifestet nedenfor kører external-dns med Frostmoln-webhooken som en sidecar, plus den ServiceAccount og RBAC, som external-dns har brug for. Erstat <cluster-id> med en værdi, der er unik for denne klynge — den stempler TXT-ejerskabsposterne, så flere klynger trygt kan dele en zone. Podden erklærer hele Pod Security-kontrakten restricted (Administreret Kubernetes håndhæver den på tværs af hele klyngen; den eksplicitte runAsUser er vigtig, fordi det opstrøms external-dns-image kører som root).
På Frostmoln Administreret Kubernetes er webhook-imaget forudindlæst på dine noder, og det ligger i et Frostmoln-internt register, som din klynge ikke kan nå — så <webhook-image> er ikke dit valg. Det skal være en reference, der allerede findes på noderne; enhver anden værdi efterlader sidecaren i ImagePullBackOff. Aflæs den fra klyngen, og indsæt den ordret:
kubectl get nodes -o json \
| jq -r '.items[].status.images[]?.names[]?' \
| grep 'external-dns-frostmoln-webhook:' | sort -uMere end én reference betyder, at din node pool spænder over to generationer af node-images: brug den, der findes på hver node, eller rul poolen om, så de passer sammen. Slet ingen output betyder, at imaget ikke er listet på en travl node — prøv én node ad gangen (kubectl get node <name> -o json), eller kontakt supporten.
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
namespace: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: ['']
resources: ['services', 'endpoints', 'pods', 'nodes']
verbs: ['get', 'watch', 'list']
- apiGroups: ['discovery.k8s.io']
resources: ['endpointslices']
verbs: ['get', 'watch', 'list']
- apiGroups: ['extensions', 'networking.k8s.io']
resources: ['ingresses']
verbs: ['get', 'watch', 'list']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: external-dns
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: external-dns
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: external-dns
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
seccompProfile:
type: RuntimeDefault
containers:
- name: external-dns
image: registry.k8s.io/external-dns/external-dns:v0.21.0
args:
- --source=ingress
- --source=service
- --provider=webhook
- --registry=txt
- --txt-owner-id=<cluster-id>
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
- name: frostmoln-webhook
image: <webhook-image>
imagePullPolicy: IfNotPresent
env:
- name: FROSTMOLN_API_KEY
valueFrom:
secretKeyRef:
name: frostmoln-dns
key: api-key
ports:
- containerPort: 8080
name: http
livenessProbe:
httpGet:
path: /healthz
port: http
readinessProbe:
httpGet:
path: /healthz
port: http
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]Anvend det:
kubectl apply -f external-dns.yamlWebhook-API'et lytter kun på poddens loopback — det er uautentificeret efter kontrakt og afviser enhver anden bindingsadresse — og FROSTMOLN_API_URL skal være https. Begge dele håndhæves ved opstart.
Konfiguration
Tilføjelsen sætter fornuftige standardværdier. Vil du justere webhook-sidecaren, så rediger external-dns-Deploymenten og sæt disse miljøvariabler:
| Variabel | Standard | Beskrivelse |
|---|---|---|
FROSTMOLN_WORKLOAD_CREDENTIALS_FILE | sættes af Workload Identity | Tokenfilen for Workload Identity. Injiceres af platformen; sæt den ikke selv |
FROSTMOLN_API_KEY | — | Tenant-API-nøgle (fmk_...). Ikke nødvendig med Workload Identity |
FROSTMOLN_API_KEY_FILE | — | Læs i stedet nøglen fra en monteret fil for at holde den ude af poddens miljø |
FROSTMOLN_API_URL | https://api.frostmoln.cloud/api | Basis-URL for kunde-API'et (skal være https) |
FROSTMOLN_TENANT_ID | udledes af nøglen | Den tenant, hvis zoner administreres; sæt den til nøglens tenant, når det ikke er dens brugers hjemme-tenant |
DOMAIN_FILTER | dine zonenavne | Tilsidesættelse af kommasepareret domænefilter |
ZONE_CACHE_TTL | 1m | Hvor længe zonekataloget caches |
DRY_RUN | false | Log de ændringer, ExternalDNS ville foretage, uden at anvende dem |
På tilføjelsen fra v0.22.0-3 er FROSTMOLN_TENANT_ID allerede sat til klyngens tenant fra platformens ConfigMap external-dns-cluster-identity — tilsidesæt den ikke. Uden den falder webhooken tilbage til nøglens hjemme-tenant.
Bemærkninger og forbehold
- Offentlige zoner afviser private mål og loopback-mål. En A/AAAA-post i en offentlig zone skal pege på en rutebar adresse — en lastbalancer eller en offentlig IP-adresse, ikke en klyngeintern IP-adresse. Brug en privat (
vpcId) zone til interne navne. - Deleger zonen, før du forventer offentligt opslag. En zone svarer først på internettet, når dit domæne er delegeret til dens navneservere — se Administreret DNS → Deleger dit domæne.
- Nye zoner kræver en genstart af webhooken. Domænefilteret hentes én gang ved opstart, så genstart external-dns-podden, når du har oprettet en zone, du vil have ExternalDNS til at administrere.
- TXT-ejerskab understøttes indbygget — behold
--registry=txtmed et--txt-owner-id, der er unikt for hver klynge, så flere klynger trygt kan dele en zone. En afløsende klynge skal overtage forgængerens poster.