ExternalDNS
ExternalDNS håller posterna i dina Frostmoln Hanterad DNS-zoner synkroniserade med Kubernetes-resurserna Ingress, Service och Gateway API — från vilket Kubernetes-kluster som helst. När du exponerar en arbetslast skapas, uppdateras och städas värdnamnets poster automatiskt; du redigerar aldrig DNS för hand.
Frostmoln levererar en webhook-leverantör som körs som en sidecar i external-dns-podden och översätter ExternalDNS planer till anrop mot Frostmolns DNS-API.
Förutsättningar
- En Frostmoln DNS-zon för domänen du vill ha poster i — se Hanterad DNS för att skapa en.
- En uppgift för webhooken, något av:
- Workload Identity (rekommenderas): ingen nyckel att skapa eller lagra. Se Autentisera med Workload Identity.
- En tenant-API-nyckel (
fmk_...) som ägs av en användare i den tenanten. Se Lagra en API-nyckel.
- Utgående HTTPS från dina arbetsnoder till
registry.k8s.ioochregistry.sweden.frostmoln.cloud. Uppströms ExternalDNS-styrenhetens avbildning hämtas frånregistry.k8s.iooch Frostmolns webhook-avbildning frånregistry.sweden.frostmoln.cloudnär podden startar. Om du filtrerar utgående trafik per värdnamn räcker det inte att tillåtaregistry.k8s.io: hämtningen omdirigeras till molnbaserade lagringsplatser på andra domäner. Utan detta blir styrenhetens container kvar iImagePullBackOff, och plattformen kan inte varna dig — åtkomsten hör till ditt VPC, inte till oss.
Så fungerar det
- Poster — webhooken listar tenantens zoner och postuppsättningar och returnerar dem till ExternalDNS som ändpunkter (en postuppsättning = ett
(namn, typ)med alla sina värden). - Tillämpa — skapa och uppdatera går genom DNS-API:ets idempotenta upsert på samlingsnivå; borttagningar löses upp via postuppsättningens stabila ID.
- Domänfilter — som standard hämtar webhooken tenantens zonnamn vid start och hanterar bara dessa. Skapa en ny zon → starta om podden så att den plockas upp (eller ange
DOMAIN_FILTERuttryckligen). - Ägarskap — använd ExternalDNS standardregister för TXT (
--registry=txtmed--txt-owner-id=<kluster-id>) så att en post bara ändras av klustret som skapade den. TXT-postuppsättningar går oförändrade genom API:et.
Installera
På Frostmoln Hanterad Kubernetes är ExternalDNS med Frostmoln-webhooken ett klustertillägg med ett klick. Välj external-dns när du skapar klustret, eller lägg till det i ett kluster som redan körs (portalen → klustrets flik Tillägg, fm kubernetes cluster add-addons, eller uppsättningen addons i API:et/Terraform-resursen), så installerar plattformen allt åt dig — namnrymden external-dns, RBAC, ExternalDNS-kontrollern och Frostmoln-webhook-sidecaren, med --txt-owner-id redan satt till klustrets id och FROSTMOLN_TENANT_ID satt till klustrets tenant. Webhook-avbildningen tillhandahålls av plattformen och hämtas från registry.sweden.frostmoln.cloud (se förutsättningarna). Du bygger eller refererar aldrig till den själv.
Det enda steg som återstår för dig är uppgiften: en bindning för Workload Identity (rekommenderas) eller en API-nyckel-Secret. Tills någon av dem finns avslutas webhook-containern i tilläggsversion v0.22.0-4 med no credential och startas om (CrashLoopBackOff). I tidigare versioner väntar den i CreateContainerConfigError. Skapa din DNS-zon först (eller starta om external-dns-Deploymenten efter att du skapat den).
Tilläggsversionerna v0.22.0-1 och v0.22.0-2: flytta låsningen till v0.22.0-3
I de två versionerna frågar webhooken API:et efter hemtenanten för den användare som skapade nyckeln, och hanterar den tenantens zoner. Om nyckeln skapades i en annan tenant — klustrets, när din användare tillhör fler än en — avslutas webhooken vid start med 403 TENANT_ACCESS_DENIED och podden fastnar i CrashLoopBackOff. Från och med v0.22.0-3 sätter plattformen webhookens tenant till klustrets egen. Båda de äldre versionerna är markerade som föråldrade. Flytta ett befintligt kluster med fm kubernetes cluster pin-addons <cluster-id> --version external-dns=v0.22.0-3, portalens flik Tillägg, eller addon_versions i Terraform — se Kubernetes → Tilläggsversioner.
Lägg till vid skapandet eller senare
Tillägget kan väljas när klustret skapas och läggas till i ett kluster som redan körs. Att lägga till det i efterhand sker inte direkt: tillägget startar en egen synkronisering och installeras vanligtvis inom några minuter; om den synkroniseringen inte kan startas sker det vid plattformens nästa synkronisering i stället, upp till en timme. Klustrets tilläggslista visar ditt nya val så snart det har accepterats — det är valet du gjort, inte ett bevis på att objekten redan finns i klustret.
Att ta bort det är en separat, namngiven åtgärd. I API:et och i Terraform skickar du alltid hela den önskade uppsättningen tillägg, inte bara den nya nyckeln — och en uppsättning som helt enkelt utelämnar external-dns nekas, eftersom en begäran byggd på en inaktuell bild av klustret annars skulle ta bort ett tillägg du aldrig menat att röra. Namnge i stället det du tar bort: knappen Ta bort i portalen, fm kubernetes cluster remove-addons, eller fältet remove i begäran till API:et. I Terraform tillämpas en borttagen nyckel i addons nu på plats i stället för att ersätta klustret.
Vissa kluster som skapades innan den här funktionen fanns kan inte ta emot nya tillägg alls; API:et säger till när du försöker, och då är enda vägen att återskapa klustret med tillägget valt. ExternalDNS med Frostmoln-webhooken är för närvarande tillgängligt endast på Frostmoln Hanterad Kubernetes.
Hanterad Kubernetes: aktivera tillägget
På Frostmoln Hanterad Kubernetes är den enklaste vägen klustertillägget external-dns: välj det när klustret skapas, eller lägg till det i ett kluster som redan körs (portalen → klustrets flik Tillägg, fm kubernetes cluster add-addons, eller uppsättningen addons i API:et/Terraform-resursen), så installerar plattformen allt i den här guiden — namnrymden external-dns, RBAC och Deploymenten, med --txt-owner-id redan satt till klustrets id.
Det enda manuella steget är uppgiften. Se Autentisera med Workload Identity (rekommenderas) eller Lagra en API-nyckel.
Läggs till i efterhand, och går att ta bort
Tillägget kan även läggas till i ett kluster som redan körs, och startar då en egen synkronisering och installeras vanligtvis inom några minuter; om den synkroniseringen inte kan startas sker det vid plattformens nästa synkronisering i stället, upp till en timme. Det kan tas bort på samma sätt — från fliken Tillägg i portalen, med fm kubernetes cluster remove-addons, eller genom att ta bort nyckeln. Ett kluster som skapades innan respektive funktion fanns kan inte ta emot det, eller inte ta bort det, och säger ifrån när du försöker; återskapa det klustret, eller tillämpa manifestet under Distribuera själv.
En borttagning lämnar kvar dina DNS-poster. ExternalDNS äger de poster det skapat, och att ta bort kontrollern tar inte bort dem — ingenting kommer att hantera dem efteråt. Om du senare tar bort en lastbalanserare som en sådan post pekar på återgår adressen till poolen och kan tilldelas någon annan medan din post fortfarande pekar dit. Att välja tillägget igen i samma kluster gör att det återtar sina egna poster och fortsätter hantera dem.
Med Workload Identity tar du bort tilläggets bindning (eller kör terraform destroy på den) för att återkalla dess åtkomst. Ingen nyckel lämnas kvar.
Med en API-nyckel behålls också namnrymden external-dns och din frostmoln-dns-hemlighet. Hemligheten innehåller en Frostmoln-API-nyckel, och att ta bort hemligheten återkallar inte nyckeln. Gör så här, i den här ordningen:
Om något annat använder samma nyckel, ge det först en egen nyckel.
Återkalla den här nyckeln. Bara användaren som skapade den kan göra det: under Inställningar → API-nycklar i portalen, eller med
fm account api-key listochfm account api-key revoke. Alla nycklar börjar medfmk_, så jämför nyckelns första 12 tecken med det listade nyckelprefixet. Läs dem ur hemligheten:bashkubectl -n external-dns get secret frostmoln-dns -o jsonpath='{.data.api-key}' | base64 -d | cut -c1-12Ta bort hemligheten först därefter — plattformen visar aldrig hela nyckeln igen, så läs prefixet innan hemligheten är borta.
Om ExternalDNS inte har tagits bort än loggar det autentiseringsfel efter återkallelsen tills det är borta; lägg inte in en ny nyckel i den här hemligheten för att tysta dem. För att välja tillägget igen senare skapar du en ny nyckel och hemlighet.
Ersätta ett kluster: ta över dess poster
ExternalDNS ändrar bara poster vars TXT-ägarpost anger dess eget kluster-id. Ett nytt kluster får ett nytt id, så det uppdaterar inte poster som ett tidigare kluster publicerat, inte ens under samma namn. Loggarna visar All records are already up to date medan namnet fortsätter att peka på det gamla klustrets adress. Det händer när du tar bort ett kluster och skapar ett nytt, och det är också så en blue/green-flytt mellan kluster beter sig.
För att lämna över ett namn till det nya klustret skriver du om ägaren i dess TXT-post när du byter över:
Hämta det nya klustrets id med
fm kubernetes cluster list.Lista zonens TXT-poster med
fm dns record list <zone-id> --type TXT -o json. ExternalDNS döper varje sådan post efter posten den äger, med posttypen först, såa-www.example.comäger A-postenwww.example.com. Värdet innehållerexternal-dns/owner=<gammalt kluster-id>.Kopiera värdet exakt och byt bara id:t efter
external-dns/owner=:bashfm dns record update <zone-id> <txt-record-id> --value '<värdet med det nya kluster-id:t>'
Inom en minut behandlar det nya klustrets ExternalDNS posten som sin egen och pekar den mot den nya adressen. Om det gamla klustret fortfarande kör slutar det hantera namnet från samma ögonblick.
Skriv om alla ägarposter för ett namn innan du går vidare till nästa. Det finns en per posttyp (A, AAAA, CNAME), och ett namn där en ägarpost fortfarande har det gamla id:t hanteras inte av något av klustren. Ett jokertecken *.example.com ägs av a-*.example.com. Det fungerar inte för ett namn i zonens apex, eftersom ägarposten då skulle hamna utanför zonen.
Återanvänd inte det gamla id:t i det nya klustrets --txt-owner-id i stället. I det hanterade tillägget sätts värdet av plattformen, och två körande kluster som delar samma ägar-id tar bort varandras poster.
Autentisera med Workload Identity (rekommenderas)
Från och med tilläggsversion v0.22.0-4 autentiserar webhooken med Workload Identity. Plattformen skapar en kortlivad, zonavgränsad token åt den och förnyar den ungefär varje timme. Det finns ingen API-nyckel att skapa, lagra i en Secret, rotera eller återkalla, och ingenting hamnar i ditt Terraform-tillstånd. Tilläggets tjänstekonto (external-dns i namnrymden external-dns) är redan aktiverat, så du behöver bara bevilja det åtkomst.
Du behöver:
- Tillägget Workload Identity i samma kluster. Se Workload Identity → Steg 1.
- Tillägget external-dns i version v0.22.0-4 eller senare. Flytta ett befintligt klusters låsning med
fm kubernetes cluster pin-addons <cluster-id> --version external-dns=v0.22.0-4, portalens flik Tillägg, elleraddon_versionsi Terraform. - En bindning för
external-dns/external-dnsmed en åtkomstpolicy som låter den lista zoner, och läsa, uppdatera och ta bort på de zoner den hanterar. Att skapa eller ändra en post räknas som en uppdatering av zonen som äger den, och att ta bort en post räknas som en borttagning på den zonen. Avgränsa den regeln till din zons 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 tillåter också att zonen tas bort
Poster har ännu ingen egen behörighet, så behörigheten som external-dns behöver för att ta bort en post låter också den autentiseringsuppgiften ta bort hela zonen den är avgränsad till. Håll regeln avgränsad till de zoner external-dns hanterar. Utan delete publicerar external-dns poster men kan aldrig ta bort dem: en post för en borttagen Service ligger kvar i DNS och pekar på en adress som kan återanvändas, och webhooken loggar 403 ... does not permit network:dns-zones:delete varje minut.
Med CLI:n fm skapar du bindningen utan behörigheter och kopplar samma policy:
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 tillägget Workload Identity och bindningen är på plats behöver du inte göra något mer. Uppgiften kopplas bara in i en pod när podden skapas, så en pod som skapades innan tillägget Workload Identity körde får den inte. Det gäller även kluster där båda tilläggen valdes samtidigt. Från workload-identity v0.3.0-1 startar tillägget själv om en sådan pod inom ett par minuter, och den kommer tillbaka med uppgiften. På en äldre version av workload-identity fortsätter podden att använda API-nyckeln eller, utan en sådan, startas om med workload identity is not injected. Flytta klustret till den nyare versionen:
fm kubernetes cluster pin-addons <cluster-id> --version workload-identity=v0.3.0-1Webhooken loggar vilken uppgift den använder:
kubectl -n external-dns logs deploy/external-dns -c frostmoln-webhook | grep authenticating
# ... "authenticating with the workload-identity credential"Workload Identity går före en API-nyckel
Varje anrop använder Workload Identity-token när en sådan finns, och faller tillbaka på API-nyckeln i frostmoln-dns bara när ingen finns. Det händer till exempel när tillägget Workload Identity är installerat men det inte finns någon bindning för external-dns. Därför kan du migrera utan avbrott: lägg till bindningen, kontrollera loggraden ovan, och återkalla sedan nyckeln och ta bort dess Secret. Om en bindning tas bort går dess sista token ut inom ungefär en timme. Därefter misslyckas webhookens anrop med 401 tills en bindning finns igen. Nyckeln används inte som reserv medan den utgångna token fortfarande ligger på disk.
Lagra en API-nyckel (reserv)
Använd en API-nyckel där Workload Identity inte är tillgängligt: i ett kluster utan tillägget Workload Identity, i tilläggsversioner före v0.22.0-4, eller när du själv distribuerar manifestet nedan. Lägg tenant-API-nyckeln i en Secret som webhooken kan läsa:
kubectl create namespace external-dns # hoppa över om tillägget redan har skapat den
kubectl create secret generic frostmoln-dns \
--namespace external-dns \
--from-literal=api-key=fmk_...Distribuera
På Hanterad Kubernetes med tillägget aktiverat kan du hoppa över det här avsnittet — bara Secreten ovan behövs.
Manifestet nedan kör external-dns med Frostmoln-webhooken som en sidecar, plus ServiceAccount och RBAC som external-dns behöver. Ersätt <kluster-id> med ett värde som är unikt för detta kluster — det stämplar TXT-ägarskapsposterna så att flera kluster tryggt kan dela en zon. Podden deklarerar hela Pod Security-kontraktet restricted (Hanterad Kubernetes upprätthåller det klusterbrett; det explicita runAsUser är viktigt eftersom external-dns-avbildningen uppströms körs som root).
På Hanterad Kubernetes är webhook-avbildningen förinläst på dina noder, och den ligger i ett Frostmoln-internt register som ditt kluster inte når — så <webhook-image> är inte ditt val. Den måste vara en referens som redan finns på noderna; varje annat värde lämnar sidecaren i ImagePullBackOff. Läs av den från klustret och klistra in den ordagrant:
kubectl get nodes -o json \
| jq -r '.items[].status.images[]?.names[]?' \
| grep 'external-dns-frostmoln-webhook:' | sort -uMer än en referens betyder att din nodpool spänner över två nodavbildningsgenerationer: använd den som finns på varje nod, eller rulla om poolen så att de matchar. Ingen utdata alls betyder att avbildningen inte listas på en hårt belastad nod — prova en nod i taget (kubectl get node <name> -o json), eller kontakta 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]Tillämpa det:
kubectl apply -f external-dns.yamlWebhook-API:et lyssnar bara på poddens loopback — det är oautentiserat enligt kontrakt och avvisar varje annan bindningsadress — och FROSTMOLN_API_URL måste vara https. Båda upprätthålls vid start.
Konfiguration
Tillägget sätter förnuftiga standardvärden. För att justera webhook-sidecaren, redigera external-dns-Deploymenten och sätt dessa miljövariabler:
| Variabel | Standard | Beskrivning |
|---|---|---|
FROSTMOLN_WORKLOAD_CREDENTIALS_FILE | sätts av Workload Identity | Tokenfilen för Workload Identity. Injiceras av plattformen; sätt den inte själv |
FROSTMOLN_API_KEY | — | Tenant-API-nyckel (fmk_...). Behövs inte med Workload Identity |
FROSTMOLN_API_KEY_FILE | — | Läs nyckeln från en monterad fil i stället, för att hålla den utanför podens miljö |
FROSTMOLN_API_URL | https://api.frostmoln.cloud/api | Bas-URL för kund-API:et (måste vara https) |
FROSTMOLN_TENANT_ID | härleds från nyckeln | Tenanten vars zoner hanteras; sätt den till nyckelns tenant när det inte är dess användares hemtenant |
DOMAIN_FILTER | dina zonnamn | Åsidosättning av kommaseparerat domänfilter |
ZONE_CACHE_TTL | 1m | Hur länge zonkatalogen cachas |
DRY_RUN | false | Logga ändringarna ExternalDNS skulle göra utan att tillämpa dem |
I tillägget från och med v0.22.0-3 är FROSTMOLN_TENANT_ID redan satt till klustrets tenant från plattformens ConfigMap external-dns-cluster-identity — åsidosätt den inte. Utan den faller webhooken tillbaka på nyckelns hemtenant.
Anmärkningar och förbehåll
- Publika zoner avvisar privata mål och loopback-mål. En A/AAAA-post i en publik zon måste peka på en rutbar adress — en lastbalanserare eller en publik IP, inte en klusterintern IP. För interna namn, använd en privat (
vpcId) zon. - Delegera zonen innan du förväntar dig publik uppslagning. En zon svarar på internet först när din domän är delegerad till dess namnservrar — se Hanterad DNS → Delegera din domän.
- Nya zoner kräver en omstart av webhooken. Domänfiltret hämtas en gång vid start, så starta om external-dns-podden efter att du skapat en zon du vill att ExternalDNS ska hantera.
- TXT-ägarskap stöds inbyggt — behåll
--registry=txtmed ett--txt-owner-idsom är unikt per kluster så att flera kluster tryggt kan dela en zon. Ett ersättande kluster måste ta över föregångarens poster.