Skip to content

Bruk Frostmoln Hemmeligheter med External Secrets Operator (ESO) ​

External Secrets Operator (ESO) synkroniserer hemmeligheter fra et eksternt lager til native Kubernetes-Secret-objekter. Den generiske webhook-leverandøren kan lese fra hvilket som helst HTTP-API — inkludert Frostmoln Hemmeligheter — slik at du kan holde hemmelighetene dine administrert i Frostmoln og la ESO speile dem inn i klyngene dine, uten kode på ESO-siden og uten en egen leverandør.

Dette fungerer på Frostmoln administrert Kubernetes, der plattformen installerer ESO for deg som et klyngetillegg, og på hvilken som helst annen Kubernetes-klynge med internettutgang som du kjører selv — egen eller on-prem — fordi ESO når den offentlige API-kanten (api.frostmoln.cloud) over HTTPS.

Hva dette gjør ​

Du lagrer en hemmelighet i Frostmoln én gang. Ved hvert oppdateringsintervall kaller ESO Frostmolns oppslags-endepunkt, leser verdien og skriver den inn i et Kubernetes-Secret som arbeidslastene dine bruker som vanlig (miljøvariabel eller montert fil). Når du roterer verdien i Frostmoln, plukker ESO opp den nye verdien ved neste oppdatering.

Forutsetninger ​

  • ESO installert i klyngen.
    • Frostmoln administrert Kubernetes: velg klyngetillegget External Secrets Operator (external-secrets) når du oppretter klyngen, eller legg det til i en klynge som kjører. Ikke installer diagrammet selv. Se På Frostmoln administrert Kubernetes.
    • Alle andre klynger: installer standarddiagrammet —
      bash
      helm repo add external-secrets https://charts.external-secrets.io
      helm install external-secrets external-secrets/external-secrets \
        -n external-secrets --create-namespace --set installCRDs=true
  • En Frostmoln-API-nøkkel. Opprett en under Konto → API-nøkler i portalen (eller med fm account api-key create --name eso --scopes secrets:read). På Frostmoln administrert Kubernetes bruker du i stedet Arbeidslastidentitet.
  • Tenant-ID-en din — fra fm auth whoami eller portalen.

Begrens API-nøkkelen til hemmeligheter

Når du oppretter nøkkelen, gi den kun scope-tilgangen secrets:read. Frostmoln håndhever API-nøkkelens scope-tilganger på serversiden, så en nøkkel uten secrets:read avvises (403) av Secrets-tjenesten ved forespørselen — å begrense nøkkelen begrenser altså på ekte hva den kan gjøre, ikke bare som en anbefaling. Behandle nøkkelen som sensitiv; ESO lagrer den i et Kubernetes-Secret.

På Frostmoln administrert Kubernetes ​

Plattformen installerer ESO for deg, i navnerommet external-secrets. Når det kjører, autentiserer du det med Arbeidslastidentitet — uten API-nøkkel — eller med en API-nøkkel som i trinn 1–3 nedenfor.

Legg det til når du oppretter klyngen, eller senere ​

  • Når du oppretter en klynge — velg External Secrets Operator i portalens opprettingsskjema, gi --addons external-secrets til fm kubernetes cluster create, eller ta med external-secrets i addons på frostmoln_kubernetes_cluster. Klyngen rapporteres først som kjører; ESO tas i bruk noen minutter senere, når arbeidsnodene har koblet seg til, og tillegget vises som Tas i bruk frem til da.
  • I en klynge som kjører —
    • Portalen — klyngens fane Tillegg.
    • fm CLI —
      bash
      fm kubernetes cluster add-addons <cluster-id> --addons external-secrets
    • Terraform — legg external-secrets til i addons og kjør apply på nytt; oppdateringen legger tillegget til i klyngen som kjører, uten å erstatte den.

Når du først angir addons i Terraform, må nøkkelen bli stående der: et tillegg som er lagt til fra portalen eller med fm, og som ikke står i addons, fjernes ved neste apply.

Å legge det til i en klynge som kjører, trer ikke i kraft umiddelbart: tillegget starter sin egen synkronisering, og ESO når klyngen vanligvis i løpet av noen minutter; kan ikke den synkroniseringen startes, skjer det først ved plattformens neste synkronisering, inntil en time. På en klynge der kontrollplanet er eldre enn tillegget, blir tillegget godtatt, men ESO installeres aldri; opprett en ny klynge for å bruke det.

Nodene dine trenger utgående HTTPS til ghcr.io

ESOs kontrollerbilde, ghcr.io/external-secrets/external-secrets, hentes over klyngens egen utgående HTTPS når poden starter. Det er ikke forhåndslastet på nodene dine. Filtrerer du utgående trafikk per vertsnavn, må du tillate bådeghcr.io og pkg-containers.githubusercontent.com, fordi ghcr.io omdirigerer hentingen dit. ESO trenger i tillegg utgående HTTPS til api.frostmoln.cloud for å lese hemmelighetene dine. Plattformen sjekker ingen av delene; se Opprette en klynge.

Autentiser med Arbeidslastidentitet (anbefalt) ​

Med Arbeidslastidentitet leser ESO et kortlivd token som plattformen holder i et Secret for deg, så det finnes ingen API-nøkkel å opprette, lagre eller rotere. Du trenger:

  • Begge tilleggene på klyngen: External Secrets Operator og Workload Identity.
  • En binding med secrets:read for en tjenestekonto i navnerommet der SecretStore ligger:
    bash
    fm kubernetes workload-identity binding create \
      --cluster <cluster-id> --namespace default --service-account eso \
      --scope secrets:read
  • Den tjenestekontoen, annotert slik at tokenet holdes i et Secret som heter frostmoln-token:
    yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: eso
      namespace: default
      annotations:
        frostmoln.cloud/workload-identity-secret: frostmoln-token

Secret-et har allerede etiketten external-secrets.io/type: webhook, så hopp over Trinn 1. I Trinn 2 bruker du i stedet denne SecretStore — samme URL, med tokenet som en bearer-header:

yaml
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: frostmoln
  namespace: default
spec:
  provider:
    webhook:
      url: 'https://api.frostmoln.cloud/api/v1/tenants/<TENANT_ID>/secrets/lookup?name={{ .remoteRef.key }}'
      headers:
        Authorization: 'Bearer {{ .auth.token }}'
      result:
        jsonPath: '$.secretValue'
      secrets:
        - name: auth
          secretRef:
            name: frostmoln-token
            key: token

Trinn 3 er uendret. Hvordan Secret-et holdes, og når det fjernes: Legitimasjon i et Secret.

Forskjeller fra en ESO du installerer selv ​

  • Du kan ikke se ESOs poder eller logger. external-secrets er et beskyttet plattformnavnerom: kubeconfig-en din kan verken lese eller skrive noe i det, så kubectl -n external-secrets get pods og kubectl logs der avvises. Les i stedet status og hendelser for dine egne objekter, med kubectl -n <namespace> describe externalsecret <name> og kubectl -n <namespace> describe secretstore <name>.

  • Bare navneromsbundne ressurser. SecretStore og ExternalSecret er tilgjengelige. ClusterSecretStore, ClusterExternalSecret og PushSecret er ikke aktivert.

  • ESO kan lese alle Secrets i klyngen. I likhet med standard-ESO har tilleggets kontroller lesetilgang til Secrets i hele klyngen, også i dine navnerom. Plattformen begrenser hva den får skrive, ikke hva den får lese.

  • Tjenestekonto-tokens avvises med vilje. ESO får ikke skrive Secrets i plattformens navnerom. I alle navnerom får den ikke opprette eller oppdatere en Secret av typen kubernetes.io/service-account-token, eller en som har annotasjonen kubernetes.io/service-account.name, og den får ikke be om tokens for plattformens tjenestekontoer. En ExternalSecret der målet ville bli en slik Secret — via target.template eller med creationPolicy: Merge inn i en eksisterende — klarer ikke å synkronisere, og feilen i kubectl describe externalsecret inneholder:

    text
    the external-secrets add-on may not create or update a service-account token Secret
  • Fjern din egen ESO først, i denne rekkefølgen:

    1. Mens din egen ESO fortsatt kjører, slett eller frikoble hver ExternalSecret som beskrevet i Fjerne tillegget.
    2. Avinstaller ESO-en din.
    3. Slett CRD-ene.

    Hold rekkefølgen. Å slette en CRD sletter alle ExternalSecret av den typen, og med creationPolicy: Owner også Secretene deres; uten en kontroller som fjerner finalizerne, blir CRD-en hengende i Terminating, og tillegget kan ikke installere sine egne. CRD-er du lar stå, overtas slik de er, inkludert felter du har lagt til.

Fjerne tillegget ​

Når tillegget fjernes, blir også navnerommet external-secrets igjen. Det forblir reservert for plattformen, så kubeconfig-en din fortsatt ikke kan bruke det, og legger du til tillegget igjen, gjenbrukes det.

Håndter hver ExternalSecret FØR du fjerner tillegget

ESO legger en opprydnings-finalizer på hver ExternalSecret. Når tillegget fjernes, slettes ESO-kontrolleren og webhookene, men CRD-ene blir igjen, og uten kontrolleren er det ingenting som fjerner finalizeren. En ExternalSecret som fortsatt finnes i klyngen, kan da ikke slettes, og heller ikke et navnerom som inneholder en.

  1. List ExternalSecret-objektene i hvert navnerom. En liste over alle navnerom avvises, så kjør den én gang per navnerom:

    bash
    kubectl -n <namespace> get externalsecrets
  2. For hver ExternalSecret der du vil beholde Secreten, gjør alt dette i rekkefølge. Ikke vent på at ESO gir fra seg eierskapet ved en synkronisering: det skjer bare ved en vellykket synkronisering, og en mislykket henting, et tomt resultat med Retain eller visse oppfriskningsinnstillinger hopper over det. <target> er Secreten som er angitt i spec.target.name, eller navnet på selve ExternalSecret-en hvis feltet ikke er satt.

    1. Sett creationPolicy: Orphan først; med Owner legger ESO eierreferansen tilbake ved neste synkronisering:
      bash
      kubectl -n <namespace> patch externalsecret <name> \
        --type=merge -p '{"spec":{"target":{"creationPolicy":"Orphan"}}}'
    2. Sjekk om Secreten fortsatt har en eierreferanse:
      bash
      kubectl -n <namespace> get secret <target> -o jsonpath='{.metadata.ownerReferences}'
    3. Bare hvis det skrev ut noe, fjern den, og kjør deretter trinn 2.2 på nytt til ingenting skrives ut. En 422 (Unprocessable Entity) fra patchen er ikke en feil: Secreten har ingen eierreferanse å fjerne og er allerede trygg.
      bash
      kubectl -n <namespace> patch secret <target> \
        --type=json -p '[{"op":"remove","path":"/metadata/ownerReferences"}]'
    4. Slett ExternalSecret-en; Secreten blir stående:
      bash
      kubectl -n <namespace> delete externalsecret <name>
  3. For hver ExternalSecret der du ikke trenger Secreten, slett ExternalSecret-en mens ESO fortsatt kjører. Med standardverdien creationPolicy: Owner slettes den synkroniserte Secreten sammen med den, og alt som fortsatt bruker den Secreten, slutter å virke: poder som refererer til den, feiler neste gang de starter, og er det en pull-secret for bilder, kan nye noder ikke lenger hente bildet.

  4. Først da fjerner du tillegget — fra fanen Tillegg, med fm kubernetes cluster remove-addons <cluster-id> --addons external-secrets, eller ved å fjerne nøkkelen fra addons i Terraform.

Hvis du allerede har fjernet tillegget ​

Fjerner du finalizeren, kan den synkroniserte Secreten bli slettet

Med standardverdien creationPolicy: Owner eies den synkroniserte Secreten av sin ExternalSecret. Når finalizeren er borte og ExternalSecret er slettet, sletter Kubernetes' søppelinnsamling (garbage collection) også Secreten — selv med deletionPolicy: Retain.

For hver gjenværende ExternalSecret:

  1. Hvis selve navnerommet er i ferd med å slettes, kan du ikke beholde Secreten: alle Secrets i det slettes også, uansett eierreferanser. Gjenskap den et annet sted fra Frostmoln Hemmeligheter. Ellers må du, for å beholde Secreten, først sjekke om det finnes en eierreferanse, og i så fall fjerne den (trinn 2.2 og 2.3 over).
  2. Fjern finalizeren:
    bash
    kubectl -n <namespace> patch externalsecret <name> \
      --type=merge -p '{"metadata":{"finalizers":null}}'
  3. Hvis ExternalSecret-en ikke allerede er i ferd med å slettes, slett den.

På Frostmoln-klynger er det bare ExternalSecret som har denne finalizeren, fordi PushSecret og ClusterExternalSecret ikke er aktivert.

Trinn 1 — Lagre API-nøkkelen som et merket Secret ​

API-nøkkel: andre klynger enn Frostmoln administrert Kubernetes

Trinn 1 og 2 bruker en API-nøkkel. På Frostmoln administrert Kubernetes bruker du i stedet Arbeidslastidentitet.

ESOs webhook-leverandør leser API-nøkkelen fra et Kubernetes-Secret. Secret må bære etiketten external-secrets.io/type: webhook — webhook-leverandøren nekter å lese et umerket Secret.

Lagre nøkkelen i en lokal fil som bare inneholder nøkkelen, uten avsluttende linjeskift. Opprett Secret fra filen, merk det, og slett deretter filen:

bash
kubectl -n default create secret generic frostmoln-api-key --from-file=apikey=./apikey
# PÅKREVD — webhook-leverandøren ignorerer et umerket Secret
kubectl -n default label secret frostmoln-api-key external-secrets.io/type=webhook
rm ./apikey

Bruk kubectl create, ikke kubectl apply med et manifest: apply lagrer hele manifestet, inkludert nøkkelen, i klartekst i Secret-ens annotasjon kubectl.kubernetes.io/last-applied-configuration. Ikke sjekk nøkkelen inn i git. Bare SecretStore- og ExternalSecret-manifestene nedenfor er trygge å ha i versjonskontroll.

Hold nøkkelen i et eget navnerom

En SecretStore leser API-nøkkelens Secret fra sitt eget navnerom, så nøkkelen, lageret og ExternalSecret-ene som bruker det, deler navnerom. Nøkkelen kan lese alle hemmeligheter i tenanten din, og det kan også alle som kan lese Secrets i det navnerommet. Bruk et dedikert navnerom til dem, og hold RBAC-en stram. Eksemplene på denne siden bruker default.

Trinn 2 — Opprett SecretStore ​

SecretStore peker ESO mot Frostmolns oppslags-endepunkt. Bruk CRD-gruppen external-secrets.io/v1 (ikke den eldre v1beta1). Erstatt <TENANT_ID> med tenant-ID-en din.

yaml
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: frostmoln
  namespace: default
spec:
  provider:
    webhook:
      url: 'https://api.frostmoln.cloud/api/v1/tenants/<TENANT_ID>/secrets/lookup?name={{ .remoteRef.key }}'
      headers:
        # per-hemmelighet-KART: <secrets-oppføringsnavn>.<datanøkkel>.
        # {{ .apikey }} rendrer hele kartet og API-et returnerer 401 — bruk nøkkelen .apikey.
        X-API-Key: '{{ .apikey.apikey }}'
      result:
        jsonPath: '$.secretValue'
      secrets:
        - name: apikey
          secretRef:
            name: frostmoln-api-key
            key: apikey

{{ .remoteRef.key }} i URL-en fylles inn per ExternalSecret med Frostmolns hemmelighetsnavn (Trinn 3), så én SecretStore betjener alle hemmelighetene dine.

Trinn 3 — Opprett en ExternalSecret ​

Hver ExternalSecret kobler én Frostmoln-hemmelighet til ett Kubernetes-Secret. remoteRef.key er Frostmolns hemmelighetsnavn; target.name er Kubernetes-Secret-et som ESO oppretter og holder synkronisert.

yaml
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: my-secret
  namespace: default
spec:
  refreshInterval: 1m
  secretStoreRef: { name: frostmoln, kind: SecretStore }
  target: { name: my-secret-synced }
  data:
    - secretKey: value # nøkkelen inne i det synkroniserte Kubernetes-Secret
      remoteRef: { key: my-secret-name } # Frostmolns hemmelighetsnavn

ESO oppretter my-secret-synced-Secret med en value-nøkkel som holder den hentede hemmelighetsverdien. Monter det eller referer til det fra Pod-en din som et hvilket som helst annet Secret.

Oppdateringsintervall ​

refreshInterval styrer hvor ofte ESO henter på nytt. Et kort intervall sprer rotasjoner raskere, men gjør flere API-kall; et lengre er lettere. Velg per hemmelighet ut fra hvor raskt en rotasjon må nå arbeidslastene dine — ett minutt eller noen minutter er typisk.

Lås en bestemt versjon ​

Frostmoln-hemmeligheter er versjonert. For å låse en versjon, legg til &version=N i SecretStore-URL-en (opprett et andre SecretStore for den låste hemmeligheten):

yaml
url: 'https://api.frostmoln.cloud/api/v1/tenants/<TENANT_ID>/secrets/lookup?name={{ .remoteRef.key }}&version=2'

Uten &version leser ESO alltid den nyeste versjonen.

Å slette en hemmelighet er feilsikkert ​

Hvis du kjører fm secrets delete på en hemmelighet som ESO synkroniserer, begynner oppslaget å returnere en feil (hemmeligheten går inn i ventende sletting). ESOs oppdatering mislykkes (SecretSyncedError) og beholder det sist synkroniserte Kubernetes-Secret uendret — det tømmer det ikke. Arbeidslastene dine fortsetter å kjøre på den sist kjente fungerende verdien.

Gjenopprett for å gjenoppta synkronisering

Mens hemmeligheten er slettet, kan ESO ikke oppdatere den, og verdien i klyngen din blir foreldet. Kjør fm secrets recover <name> innenfor gjenopprettingsvinduet for å gjenopprette den; ESO gjenopptar da synkroniseringen ved neste intervall. Hvis gjenopprettingsvinduet passerer og hemmeligheten fjernes permanent, fortsetter oppslaget å mislykkes — opprett hemmeligheten på nytt for å gjenoppta.

Feilsøking ​

Sjekk ExternalSecret-statusen med kubectl describe externalsecret <name>.

  • secret does not contain needed label — API-nøkkelens Secret mangler etiketten external-secrets.io/type: webhook (Trinn 1).
  • 401 / uautorisert — header-malen er feil. Den må være {{ .apikey.apikey }} (<secrets-oppføringsnavn>.<datanøkkel>); {{ .apikey }} rendrer hele kartet og API-et avviser den. Sjekk også nøkkelverdien og at nøkkelen ikke har utløpt.
  • Arbeidslastidentitet: Secret-et frostmoln-token dukker ikke opp — sjekk at tillegget Workload Identity er på klyngen, at tjenestekontoen har annotasjonen og en binding, og at det ikke fantes et Secret med det navnet fra før: tillegget overskriver aldri et Secret det ikke selv har opprettet.
  • could not get secret data from provider — hemmelighetsnavnet eller tenant-ID-en er feil, eller hemmeligheten er slettet / venter på sletting. Bekreft at navnet finnes: fm secrets get <name>.
  • Ingenting synkroniseres i det hele tatt — sjekk at SecretStore bruker external-secrets.io/v1, ikke v1beta1. På en klynge du kjører selv, bekreft at ESO kjører (kubectl -n external-secrets get pods). På Frostmoln administrert Kubernetes kan du ikke liste disse podene: bekreft at tillegget er på klyngen (fm kubernetes cluster addons <cluster-id> eller fanen Tillegg), at det ble lagt til for mer enn noen minutter siden (hvis plattformen meldte at den ikke kunne starte synkroniseringen, regn med lengre tid: vanligvis høyst en time, mer under plattformvedlikehold), og at nodene dine når ghcr.io og pkg-containers.githubusercontent.com.

Relatert ​