Skip to content

ExternalDNS ​

ExternalDNS holder postene i dine Frostmoln Administrert DNS-soner synkronisert med Kubernetes-ressursene Ingress, Service og Gateway API — fra hvilken som helst Kubernetes-klynge. Når du eksponerer en arbeidslast, opprettes, oppdateres og ryddes vertsnavnets poster opp automatisk; du redigerer aldri DNS for hånd.

Frostmoln leverer en webhook-leverandør som kjører som en sidecar i external-dns-poden og oversetter ExternalDNS' planer til kall mot Frostmolns DNS-API.

Forutsetninger ​

  • En Frostmoln DNS-sone for domenet du vil ha poster i — se Administrert DNS for å opprette en.
  • En legitimasjon for webhooken, en av:
  • Utgående HTTPS fra arbeidsnodene dine til registry.k8s.io og registry.sweden.frostmoln.cloud. Oppstrøms ExternalDNS-kontrollerbildet hentes fra registry.k8s.io og Frostmolns webhook-bilde fra registry.sweden.frostmoln.cloud når poden starter. Filtrerer du utgående trafikk per vertsnavn, er det ikke nok å tillate registry.k8s.io: hentingen omdirigeres til skybaserte lagringssteder på andre domener. Uten dette blir kontrollercontaineren stående i ImagePullBackOff, og plattformen kan ikke varsle deg — tilgjengeligheten hører til ditt VPC, ikke til oss.

Slik fungerer det ​

  • Poster — webhooken lister tenantens soner og postsett og returnerer dem til ExternalDNS som endepunkter (ett postsett = ett (navn, type) med alle verdiene).
  • Anvend — opprettelser og oppdateringer går gjennom DNS-API-ets idempotente upsert på samlingsnivå; slettinger løses opp via postsettets stabile ID.
  • Domenefilter — som standard henter webhooken tenantens sonenavn ved oppstart og administrerer bare disse. Opprett en ny sone → start poden på nytt slik at den plukkes opp (eller angi DOMAIN_FILTER eksplisitt).
  • Eierskap — bruk ExternalDNS' standard TXT-register (--registry=txt med --txt-owner-id=<klynge-id>) slik at en post bare endres av klyngen som opprettet den. TXT-postsett går uendret gjennom API-et.

Installer ​

På Frostmoln Administrert Kubernetes er ExternalDNS med Frostmoln-webhooken et klyngetillegg med ett klikk. Velg external-dns når du oppretter klyngen, eller legg det til i en klynge som allerede kjører (portalen → klyngens fane Tillegg, fm kubernetes cluster add-addons, eller settet addons i API-et/Terraform-ressursen), så installerer plattformen alt for deg — navnerommet external-dns, RBAC, ExternalDNS-kontrolleren og Frostmoln-webhook-sidecaren, med --txt-owner-id allerede satt til klyngens id og FROSTMOLN_TENANT_ID satt til klyngens tenant. Webhook-bildet leveres av plattformen og hentes fra registry.sweden.frostmoln.cloud (se forutsetningene). Du bygger eller refererer aldri til det selv.

Det eneste steget som gjenstår for deg er legitimasjonen: en Workload Identity-binding (anbefalt) eller en API-nøkkel-Secret. Inntil en av dem finnes, avslutter webhook-containeren på tilleggsversjon v0.22.0-4 med no credential og startes på nytt (CrashLoopBackOff). På tidligere versjoner venter den i CreateContainerConfigError. Opprett DNS-sonen din først (eller start external-dns-Deploymenten på nytt etter at du har opprettet den).

Tilleggsversjonene v0.22.0-1 og v0.22.0-2: flytt låsingen til v0.22.0-3

I de to versjonene spør webhooken API-et om hjemmetenanten til brukeren som opprettet nøkkelen, og administrerer den tenantens soner. Hvis nøkkelen ble opprettet i en annen tenant — klyngens, når brukeren din tilhører mer enn én — avslutter webhooken ved oppstart med 403 TENANT_ACCESS_DENIED, og poden blir stående i CrashLoopBackOff. Fra v0.22.0-3 setter plattformen webhookens tenant til klyngens egen. Begge de eldre versjonene er merket som utfasede. Flytt en eksisterende klynge med fm kubernetes cluster pin-addons <cluster-id> --version external-dns=v0.22.0-3, portalens fane Tillegg, eller addon_versions i Terraform — se Kubernetes → Tilleggsversjoner.

Legg det til ved opprettelse, eller senere

Tillegget kan velges når klyngen opprettes og legges til i en klynge som allerede kjører. Å legge det til i etterkant skjer ikke umiddelbart: tillegget starter sin egen synkronisering og installeres vanligvis i løpet av noen minutter; kan ikke den synkroniseringen startes, skjer det først ved plattformens neste synkronisering, inntil en time. Klyngens tilleggsliste viser det nye valget så snart det er akseptert — det er valget du har gjort, ikke et bevis på at objektene allerede er på klyngen.

Å fjerne det er en egen, navngitt handling. I API-et og i Terraform sender du alltid hele det ønskede settet med tillegg, ikke bare den nye nøkkelen — og et sett som rett og slett utelater external-dns, blir avvist, fordi en forespørsel bygget på et utdatert bilde av klyngen ellers ville fjernet et tillegg du aldri mente å røre. Navngi i stedet det du fjerner: knappen Fjern i portalen, fm kubernetes cluster remove-addons, eller feltet remove i forespørselen til API-et. I Terraform anvendes en fjernet nøkkel i addons nå på stedet i stedet for å erstatte klyngen.

Noen klynger som ble opprettet før denne muligheten kom, kan ikke ta imot nye tillegg i det hele tatt; API-et sier fra når du prøver, og da er eneste vei å opprette klyngen på nytt med tillegget valgt. ExternalDNS med Frostmoln-webhooken er foreløpig tilgjengelig kun på Frostmoln Administrert Kubernetes.

Administrert Kubernetes: aktiver tillegget ​

På Frostmoln Administrert Kubernetes er den enkleste veien klyngetillegget external-dns: velg det når klyngen opprettes, eller legg det til i en klynge som allerede kjører (portalen → klyngens fane Tillegg, fm kubernetes cluster add-addons, eller settet addons i API-et/Terraform-ressursen), så installerer plattformen alt i denne veiledningen — navnerommet external-dns, RBAC og Deploymenten, med --txt-owner-id allerede satt til klyngens id.

Det eneste manuelle steget er legitimasjonen. Se Autentiser med Workload Identity (anbefalt) eller Lagre en API-nøkkel.

Legges til i etterkant, og kan fjernes

Tillegget kan også legges til i en klynge som allerede kjører, og starter da sin egen synkronisering og installeres vanligvis i løpet av noen minutter; kan ikke den synkroniseringen startes, skjer det først ved plattformens neste synkronisering, inntil en time. Det kan fjernes på samme måte — fra fanen Tillegg i portalen, med fm kubernetes cluster remove-addons, eller ved å fjerne nøkkelen. En klynge som ble opprettet før den enkelte muligheten kom, kan ikke ta imot det, eller ikke fjerne det, og sier fra når du prøver; opprett den klyngen på nytt, eller bruk manifestet under Distribuer selv.

En fjerning lar DNS-oppføringene dine bli igjen. ExternalDNS eier oppføringene det opprettet, og å fjerne kontrolleren sletter dem ikke — ingenting vil håndtere dem etterpå. Hvis du senere sletter en lastbalanserer en slik oppføring peker på, går adressen tilbake til puljen og kan tildeles noen andre mens oppføringen din fortsatt peker dit. Å velge tillegget igjen i samme klynge gjør at det tar tilbake sine egne oppføringer og fortsetter å håndtere dem.

Med Workload Identity sletter du tilleggets binding (eller kjører terraform destroy på den) for å tilbakekalle tilgangen. Ingen nøkkel blir liggende igjen.

Med en API-nøkkel beholdes også navnerommet external-dns og frostmoln-dns-hemmeligheten din. Hemmeligheten inneholder en Frostmoln-API-nøkkel, og å slette hemmeligheten tilbakekaller ikke nøkkelen. Gjør dette i denne rekkefølgen:

  1. Hvis noe annet bruker den samme nøkkelen, gi det først en egen nøkkel.

  2. Tilbakekall denne nøkkelen. Bare brukeren som opprettet den, kan gjøre det: under Innstillinger → API-nøkler i portalen, eller med fm account api-key list og fm account api-key revoke. Alle nøkler begynner med fmk_, så sammenlign nøkkelens første 12 tegn med det listede nøkkelprefikset. Les dem fra hemmeligheten:

    bash
    kubectl -n external-dns get secret frostmoln-dns -o jsonpath='{.data.api-key}' | base64 -d | cut -c1-12
  3. Slett hemmeligheten først etter det — plattformen viser aldri hele nøkkelen igjen, så les prefikset før hemmeligheten er borte.

Hvis ExternalDNS ikke er fjernet ennå, logger det autentiseringsfeil etter tilbakekallingen til det er borte; ikke legg en ny nøkkel i denne hemmeligheten for å få dem til å stoppe. For å velge tillegget igjen senere oppretter du en ny nøkkel og hemmelighet.

Bytte ut en klynge: ta over postene dens ​

ExternalDNS endrer bare poster der TXT-eierskapsposten angir dens egen klynge-id. En ny klynge får en ny id, så den oppdaterer ikke poster som en tidligere klynge har publisert, heller ikke under de samme navnene. Loggen viser All records are already up to date mens navnet fortsatt peker på den gamle klyngens adresse. Det skjer når du sletter en klynge og oppretter en ny, og det er også slik en blue/green-flytting mellom klynger oppfører seg.

For å overlate et navn til den nye klyngen skriver du om eieren i TXT-posten når du bytter over:

  1. Finn den nye klyngens id med fm kubernetes cluster list.

  2. List sonens TXT-poster med fm dns record list <zone-id> --type TXT -o json. ExternalDNS navngir hver av dem etter posten den eier, med posttypen foran, så a-www.example.com eier A-posten www.example.com. Verdien inneholder external-dns/owner=<gammel klynge-id>.

  3. Kopier verdien nøyaktig, og bytt bare id-en etter external-dns/owner=:

    bash
    fm dns record update <zone-id> <txt-record-id> --value '<verdien med den nye klynge-id-en>'

Innen ett minutt behandler den nye klyngens ExternalDNS posten som sin egen og peker den mot den nye adressen. Kjører den gamle klyngen fortsatt, slutter den å styre navnet fra samme øyeblikk.

Skriv om alle eierskapspostene for et navn før du går videre til det neste. Det finnes én per posttype (A, AAAA, CNAME), og et navn der en eierskapspost fortsatt har den gamle id-en, styres ikke av noen av klyngene. Et jokertegn *.example.com eies av a-*.example.com. Det virker ikke for et navn i sonens apex, fordi eierskapsposten da ville havne utenfor sonen.

Ikke gjenbruk den gamle id-en i den nye klyngens --txt-owner-id i stedet. I det administrerte tillegget settes verdien av plattformen, og to kjørende klynger som deler én eier-id, sletter hverandres poster.

Autentiser med Workload Identity (anbefalt) ​

Fra tilleggsversjon v0.22.0-4 autentiserer webhooken med Workload Identity. Plattformen oppretter et kortlivd, soneavgrenset token for den og fornyer det omtrent hver time. Det finnes ingen API-nøkkel å opprette, lagre i en Secret, rotere eller tilbakekalle, og ingenting havner i Terraform-tilstanden din. Tilleggets tjenestekonto (external-dns i navnerommet external-dns) er allerede påmeldt, så du trenger bare å gi det tilgang.

Du trenger:

  1. Tillegget Workload Identity i samme klynge. Se Workload Identity → Trinn 1.
  2. Tillegget external-dns i versjon v0.22.0-4 eller nyere. Flytt låsingen på en eksisterende klynge med fm kubernetes cluster pin-addons <cluster-id> --version external-dns=v0.22.0-4, portalens fane Tillegg, eller addon_versions i Terraform.
  3. En binding for external-dns/external-dns med en tilgangspolicy som lar den liste soner, og lese, oppdatere og slette på sonene den håndterer. Å opprette eller endre en oppføring regnes som en oppdatering av sonen som eier den, og å slette en oppføring regnes som en sletting på den sonen. Avgrens den regelen til sonens id:
hcl
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 tillater også å slette sonen

Oppføringer har ennå ingen egen rettighet, så rettigheten external-dns trenger for å fjerne en oppføring lar også den legitimasjonen slette hele sonen den er avgrenset til. Hold regelen avgrenset til sonene external-dns håndterer. Uten delete publiserer external-dns oppføringer, men kan aldri fjerne dem: en oppføring for en slettet Service blir liggende i DNS og peker på en adresse som kan bli gjenbrukt, og webhooken logger 403 ... does not permit network:dns-zones:delete hvert minutt.

Med fm-CLI-en oppretter du bindingen uten rettigheter og knytter til den samme policyen:

bash
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 tillegget Workload Identity og bindingen er på plass, trenger du ikke gjøre noe mer. Legitimasjonen kobles bare inn i en pod når poden opprettes, så en pod som ble opprettet før tillegget Workload Identity kjørte, får den ikke. Det gjelder også klynger der begge tilleggene ble valgt samtidig. Fra workload-identity v0.3.0-1 starter tillegget selv en slik pod på nytt innen et par minutter, og den kommer tilbake med legitimasjonen. På en eldre versjon av workload-identity fortsetter poden å bruke API-nøkkelen eller, uten en, startes på nytt med workload identity is not injected. Flytt klyngen til den nyere versjonen:

bash
fm kubernetes cluster pin-addons <cluster-id> --version workload-identity=v0.3.0-1

Webhooken logger hvilken legitimasjon den bruker:

bash
kubectl -n external-dns logs deploy/external-dns -c frostmoln-webhook | grep authenticating
# ... "authenticating with the workload-identity credential"

Workload Identity går foran en API-nøkkel

Hver forespørsel bruker Workload Identity-tokenet når det finnes, og faller tilbake på API-nøkkelen i frostmoln-dns bare når det ikke finnes noe. Det skjer for eksempel når tillegget Workload Identity er installert, men det ikke finnes noen binding for external-dns. Dermed kan du migrere uten nedetid: legg til bindingen, sjekk logglinjen ovenfor, og tilbakekall deretter nøkkelen og slett Secreten. Hvis en binding slettes, utløper det siste tokenet innen omtrent en time. Deretter mislykkes webhookens forespørsler med 401 til en binding finnes igjen. Nøkkelen brukes ikke som reserve mens det utløpte tokenet fortsatt ligger på disk.

Lagre en API-nøkkel (reserve) ​

Bruk en API-nøkkel der Workload Identity ikke er tilgjengelig: i en klynge uten tillegget Workload Identity, på tilleggsversjoner før v0.22.0-4, eller når du selv distribuerer manifestet nedenfor. Legg tenant-API-nøkkelen i en Secret som webhooken kan lese:

bash
kubectl create namespace external-dns   # hopp over hvis tillegget allerede har opprettet det
kubectl create secret generic frostmoln-dns \
  --namespace external-dns \
  --from-literal=api-key=fmk_...

Distribuer ​

På Administrert Kubernetes med tillegget aktivert kan du hoppe over dette avsnittet — bare Secreten ovenfor trengs.

Manifestet nedenfor kjører external-dns med Frostmoln-webhooken som en sidecar, pluss ServiceAccount og RBAC som external-dns trenger. Erstatt <klynge-id> med en verdi som er unik for denne klyngen — den stempler TXT-eierskapspostene slik at flere klynger trygt kan dele en sone. Podden deklarerer hele Pod Security-kontrakten restricted (Administrert Kubernetes håndhever den på hele klyngen; den eksplisitte runAsUser er viktig fordi external-dns-bildet oppstrøms kjører som root).

På Administrert Kubernetes er webhook-bildet forhåndslastet på nodene dine, og det ligger i et Frostmoln-internt register klyngen din ikke når — så <webhook-image> er ikke ditt valg. Den må være en referanse som allerede ligger på nodene; enhver annen verdi etterlater sidecaren i ImagePullBackOff. Hent den fra klyngen og lim den inn ordrett:

bash
kubectl get nodes -o json \
  | jq -r '.items[].status.images[]?.names[]?' \
  | grep 'external-dns-frostmoln-webhook:' | sort -u

Mer enn én referanse betyr at nodepoolen din spenner over to nodebildegenerasjoner: bruk den som ligger på hver node, eller rull poolen på nytt så de samsvarer. Ingen utdata i det hele tatt betyr at bildet ikke er listet på en travel node — prøv én node om gangen (kubectl get node <name> -o json), eller kontakt supporten.

yaml
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:

bash
kubectl apply -f external-dns.yaml

Webhook-API-et lytter bare på podens loopback — det er uautentisert etter kontrakt og nekter enhver annen bindingsadresse — og FROSTMOLN_API_URL må være https. Begge håndheves ved oppstart.

Konfigurasjon ​

Tillegget setter fornuftige standardverdier. For å justere webhook-sidecaren, rediger external-dns-Deploymenten og sett disse miljøvariablene:

VariabelStandardBeskrivelse
FROSTMOLN_WORKLOAD_CREDENTIALS_FILEsettes av Workload IdentityTokenfilen for Workload Identity. Injiseres av plattformen; ikke sett den selv
FROSTMOLN_API_KEY—Tenant-API-nøkkel (fmk_...). Ikke nødvendig med Workload Identity
FROSTMOLN_API_KEY_FILE—Les nøkkelen fra en montert fil i stedet, for å holde den ute av pod-env
FROSTMOLN_API_URLhttps://api.frostmoln.cloud/apiBasis-URL for kunde-API-et (må være https)
FROSTMOLN_TENANT_IDutledet fra nøkkelenTenanten hvis soner administreres; sett den til nøkkelens tenant når det ikke er brukerens hjemmetenant
DOMAIN_FILTERdine sonenavnOverstyring av kommaseparert domenefilter
ZONE_CACHE_TTL1mHvor lenge sonekatalogen bufres
DRY_RUNfalseLogg endringene ExternalDNS ville gjort uten å anvende dem

På tillegget fra v0.22.0-3 er FROSTMOLN_TENANT_ID allerede satt til klyngens tenant fra plattformens ConfigMap external-dns-cluster-identity — ikke overstyr den. Uten den faller webhooken tilbake til nøkkelens hjemmetenant.

Merknader og forbehold ​

  • Offentlige soner avviser private mål og loopback-mål. En A/AAAA-post i en offentlig sone må peke på en rutbar adresse — en lastbalanserer eller en offentlig IP, ikke en klyngeintern IP. For interne navn, bruk en privat (vpcId) sone.
  • Deleger sonen før du forventer offentlig oppslag. En sone svarer på internett først når domenet ditt er delegert til navnetjenerne dens — se Administrert DNS → Deleger domenet ditt.
  • Nye soner krever en omstart av webhooken. Domenefilteret hentes én gang ved oppstart, så start external-dns-poden på nytt etter at du oppretter en sone du vil at ExternalDNS skal administrere.
  • TXT-eierskap støttes innebygd — behold --registry=txt med en --txt-owner-id som er unik for hver klynge, slik at flere klynger trygt kan dele en sone. En erstatningsklynge må ta over forgjengerens poster.

Relatert ​