Använd Frostmoln Hemligheter med External Secrets Operator (ESO)
External Secrets Operator (ESO) synkroniserar hemligheter från ett externt lager till inbyggda Kubernetes-Secret-objekt. Dess generiska webhook-leverantör kan läsa från vilket HTTP-API som helst — inklusive Frostmoln Hemligheter — så du kan behålla dina hemligheter hanterade i Frostmoln och låta ESO spegla dem in i dina kluster, utan kod på ESO-sidan och utan någon egen leverantör.
Detta fungerar på Frostmolns hanterade Kubernetes, där plattformen installerar ESO åt dig som ett klustertillägg, och på vilket annat Kubernetes-kluster som helst med internetutgång som du kör själv — eget eller on-prem — eftersom ESO når det publika API-kantskiktet (api.frostmoln.cloud) över HTTPS.
Vad detta gör
Du lagrar en hemlighet i Frostmoln en gång. Vid varje uppdateringsintervall anropar ESO Frostmolns uppslags-endpoint, läser värdet och skriver in det i ett Kubernetes-Secret som dina arbetsbelastningar använder som vanligt (miljövariabel eller monterad fil). När du roterar värdet i Frostmoln plockar ESO upp det nya värdet vid nästa uppdatering.
Förutsättningar
- ESO installerat i klustret.
- Frostmoln hanterad Kubernetes: välj klustertillägget External Secrets Operator (
external-secrets) när du skapar klustret, eller lägg till det i ett kluster som körs. Installera inte diagrammet själv. Se På Frostmolns hanterade Kubernetes. - Alla andra kluster: installera det ordinarie diagrammet —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
- Frostmoln hanterad Kubernetes: välj klustertillägget External Secrets Operator (
- En Frostmoln-API-nyckel. Skapa en under Konto → API-nycklar i portalen (eller med
fm account api-key create --name eso --scopes secrets:read). På Frostmolns hanterade Kubernetes använder du i stället arbetsbelastningsidentitet. - Ditt tenant-ID — från
fm auth whoamieller portalen.
Begränsa API-nyckeln till hemligheter
När du skapar nyckeln, ge den endast scope-behörigheten secrets:read. Frostmoln tillämpar API-nyckelns scope-behörigheter på serversidan, så en nyckel utan secrets:read avvisas (403) av Secrets-tjänsten vid anropet — att begränsa nyckeln begränsar alltså på riktigt vad den kan göra, inte bara som en rekommendation. Behandla nyckeln som känslig; ESO lagrar den i ett Kubernetes-Secret.
På Frostmolns hanterade Kubernetes
Plattformen installerar ESO åt dig, i namnrymden external-secrets. När det väl körs autentiserar du det med arbetsbelastningsidentitet — utan API-nyckel — eller med en API-nyckel enligt steg 1–3 nedan.
Lägg till det när du skapar klustret, eller senare
- När du skapar ett kluster — välj External Secrets Operator i portalens formulär för att skapa kluster, ange
--addons external-secretstillfm kubernetes cluster create, eller ta medexternal-secretsiaddonspåfrostmoln_kubernetes_cluster. Klustret rapporteras först som körs; ESO tillämpas några minuter senare, när arbetsnoderna har anslutit, och tillägget visas som Tillämpas fram till dess. - I ett kluster som körs —
- Portalen — klustrets flik Tillägg.
- fm CLI —bash
fm kubernetes cluster add-addons <cluster-id> --addons external-secrets - Terraform — lägg till
external-secretsiaddonsoch kör apply igen; uppdateringen lägger till tillägget i det körande klustret utan att klustret ersätts.
När du väl anger addons i Terraform ska nyckeln stå kvar där: ett tillägg som lagts till från portalen eller med fm och som inte finns i din addons tas bort vid nästa apply.
Att lägga till det i ett kluster som körs träder inte i kraft direkt: tillägget startar en egen synkronisering och ESO når klustret 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. På ett kluster vars styrplan är äldre än tillägget godtas tillägget, men ESO installeras aldrig; skapa ett nytt kluster för att använda det.
Dina noder behöver utgående HTTPS till ghcr.io
ESO:s styrenhetsavbildning, ghcr.io/external-secrets/external-secrets, hämtas över klustrets egen utgående HTTPS när podden startar. Den är inte förinstallerad på dina noder. Om du filtrerar utgående trafik per värdnamn, tillåt både ghcr.io och pkg-containers.githubusercontent.com, eftersom ghcr.io omdirigerar hämtningen dit. ESO behöver dessutom utgående HTTPS till api.frostmoln.cloud för att läsa dina hemligheter. Plattformen kontrollerar inget av detta; se Skapa ett kluster.
Autentisera med arbetsbelastningsidentitet (rekommenderas)
Med arbetsbelastningsidentitet läser ESO en kortlivad token som plattformen håller i ett Secret åt dig, så det finns ingen API-nyckel att skapa, lagra eller rotera. Du behöver:
- Båda tilläggen i klustret: External Secrets Operator och Workload Identity.
- En bindning med
secrets:readför ett tjänstekonto i den namnrymd därSecretStorefinns:bashfm kubernetes workload-identity binding create \ --cluster <cluster-id> --namespace default --service-account eso \ --scope secrets:read - Det tjänstekontot, annoterat så att token hålls i ett Secret med namnet
frostmoln-token:yamlapiVersion: v1 kind: ServiceAccount metadata: name: eso namespace: default annotations: frostmoln.cloud/workload-identity-secret: frostmoln-token
Secret bär redan etiketten external-secrets.io/type: webhook, så hoppa över steg 1. I steg 2 använder du i stället den här SecretStore — samma URL, med token som bearer-header:
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: tokenSteg 3 är oförändrat. Hur Secret hålls uppdaterat, och när det tas bort: Uppgift i ett Secret.
Skillnader mot ett ESO du installerat själv
Du kan inte se ESO:s poddar eller loggar.
external-secretsär en skyddad plattformsnamnrymd: din kubeconfig kan varken läsa eller skriva något i den, såkubectl -n external-secrets get podsochkubectl logsdär avvisas. Läs i stället status och händelser för dina egna objekt, medkubectl -n <namespace> describe externalsecret <name>ochkubectl -n <namespace> describe secretstore <name>.Bara namnrymdsbundna resurser.
SecretStoreochExternalSecretfinns.ClusterSecretStore,ClusterExternalSecretochPushSecretär inte aktiverade.ESO kan läsa alla
Secreti klustret. Precis som ordinarie ESO har tilläggets styrenhet läsbehörighet tillSecret-objekt i hela klustret, även i dina namnrymder. Plattformen begränsar vad den får skriva, inte vad den får läsa.Tjänstekontotokens avvisas avsiktligt. ESO får inte skriva
Secret-objekt i plattformens namnrymder. I alla namnrymder får det inte skapa eller uppdatera ettSecretav typenkubernetes.io/service-account-token, eller ett som bär annoteringenkubernetes.io/service-account.name, och det får inte begära tokens för plattformens tjänstekonton. EttExternalSecretvars mål skulle bli ett sådantSecret— viatarget.templateeller medcreationPolicy: Mergein i ett befintligt — misslyckas med att synkronisera, och felet ikubectl describe externalsecretinnehåller:textthe external-secrets add-on may not create or update a service-account token SecretTa bort ditt eget ESO först, i den här ordningen:
- Medan ditt eget ESO fortfarande körs, radera eller frikoppla varje
ExternalSecretenligt Ta bort tillägget. - Avinstallera ditt ESO.
- Radera dess CRD:er.
Följ ordningen. Att radera en CRD raderar alla
ExternalSecretav den typen, och medcreationPolicy: Owneräven derasSecret; utan någon styrenhet som tar bort deras finalizers fastnar CRD:n iTerminating, och tillägget kan inte installera sina egna. CRD:er du lämnar kvar tas över som de är, inklusive fält du lagt till.- Medan ditt eget ESO fortfarande körs, radera eller frikoppla varje
Ta bort tillägget
Att ta bort tillägget lämnar också namnrymden external-secrets kvar. Den förblir reserverad för plattformen, så din kubeconfig kan fortfarande inte använda den, och lägger du till tillägget igen återanvänds den.
Hantera varje ExternalSecret INNAN du tar bort tillägget
ESO lägger till en städ-finalizer på varje ExternalSecret. När tillägget tas bort raderas ESO:s styrenhet och dess webhooks, men CRD:erna blir kvar, och utan styrenheten finns inget som tar bort finalizern. Ett ExternalSecret som finns kvar i klustret kan då inte raderas, och inte heller en namnrymd som innehåller ett.
Lista
ExternalSecret-objekten i varje namnrymd. En lista över alla namnrymder avvisas, så kör den en gång per namnrymd:bashkubectl -n <namespace> get externalsecretsFör varje
ExternalSecretvarsSecretdu vill behålla, gör allt detta i ordning. Vänta inte på att ESO släpper ägarskapet vid en synkronisering: det sker bara vid en lyckad synkronisering, och en misslyckad hämtning, ett tomt resultat medRetaineller vissa uppdateringsinställningar hoppar över det.<target>är detSecretsom anges ispec.target.name, ellerExternalSecret-objektets eget namn om fältet inte är satt.- Sätt
creationPolicy: Orphanförst; medOwnerlägger ESO tillbaka ägarreferensen vid nästa synkronisering:bashkubectl -n <namespace> patch externalsecret <name> \ --type=merge -p '{"spec":{"target":{"creationPolicy":"Orphan"}}}' - Kontrollera om
Secretfortfarande har en ägarreferens:bashkubectl -n <namespace> get secret <target> -o jsonpath='{.metadata.ownerReferences}' - Bara om det skrev ut något, ta bort den och kör sedan steg 2.2 igen tills inget skrivs ut. Ett
422(Unprocessable Entity) från patchen är inget fel:Secrethar ingen ägarreferens att ta bort och är redan säkert.bashkubectl -n <namespace> patch secret <target> \ --type=json -p '[{"op":"remove","path":"/metadata/ownerReferences"}]' - Radera
ExternalSecret;Secretblir kvar:bashkubectl -n <namespace> delete externalsecret <name>
- Sätt
För varje
ExternalSecretvarsSecretdu inte behöver, raderaExternalSecretmedan ESO fortfarande körs. Med standardvärdetcreationPolicy: Ownerraderas dess synkadeSecretmed det, och allt som fortfarande använder detSecretslutar fungera: poddar som refererar till det misslyckas nästa gång de startar, och används det som pull-secret för avbildningar kan nya noder inte längre hämta avbildningen.Först därefter tar du bort tillägget — från fliken Tillägg, med
fm kubernetes cluster remove-addons <cluster-id> --addons external-secrets, eller genom att ta bort nyckeln uraddonsi Terraform.
Om du redan har tagit bort tillägget
Att ta bort finalizern kan radera det synkade Secret-objektet
Med standardvärdet creationPolicy: Owner ägs det synkade Secret av sitt ExternalSecret. När finalizern är borta och ExternalSecret har raderats raderar Kubernetes skräpinsamling även Secret — också med deletionPolicy: Retain.
För varje kvarvarande ExternalSecret:
- Om själva namnrymden håller på att raderas kan du inte behålla
Secret: varjeSecreti den raderas också, oavsett ägarreferenser. Återskapa det på annat ställe från Frostmoln Hemligheter. Annars, för att behålla dessSecret, kontrollera först om det finns en ägarreferens och ta i så fall bort den (steg 2.2 och 2.3 ovan). - Ta bort finalizern:bash
kubectl -n <namespace> patch externalsecret <name> \ --type=merge -p '{"metadata":{"finalizers":null}}' - Om
ExternalSecretinte redan håller på att raderas, radera det.
På Frostmolns kluster är det bara ExternalSecret som har den här finalizern, eftersom PushSecret och ClusterExternalSecret inte är aktiverade.
Steg 1 — Lagra API-nyckeln som ett märkt Secret
API-nyckel: andra kluster än Frostmolns hanterade Kubernetes
Steg 1 och 2 använder en API-nyckel. På Frostmolns hanterade Kubernetes använder du i stället arbetsbelastningsidentitet.
ESO:s webhook-leverantör läser API-nyckeln från ett Kubernetes-Secret. Secret måste bära etiketten external-secrets.io/type: webhook — webhook-leverantören vägrar att läsa ett omärkt Secret.
Spara nyckeln i en lokal fil som bara innehåller nyckeln, utan avslutande radbrytning. Skapa Secret från filen, märk det och radera sedan filen:
kubectl -n default create secret generic frostmoln-api-key --from-file=apikey=./apikey
# KRÄVS — webhook-leverantören ignorerar ett omärkt Secret
kubectl -n default label secret frostmoln-api-key external-secrets.io/type=webhook
rm ./apikeyAnvänd kubectl create, inte kubectl apply med ett manifest: apply sparar hela manifestet, nyckeln inräknad, i klartext i Secret-objektets annotering kubectl.kubernetes.io/last-applied-configuration. Checka inte in nyckeln i git. Endast SecretStore- och ExternalSecret-manifesten nedan är säkra att versionshantera.
Håll nyckeln i en egen namnrymd
En SecretStore läser API-nyckelns Secret från sin egen namnrymd, så nyckeln, lagret och de ExternalSecret som använder det delar namnrymd. Nyckeln kan läsa varje hemlighet i din tenant, och det kan även alla som kan läsa Secrets i den namnrymden. Använd en dedikerad namnrymd för dem och håll dess RBAC snäv. Exemplen på den här sidan använder default.
Steg 2 — Skapa SecretStore
SecretStore pekar ESO mot Frostmolns uppslags-endpoint. Använd CRD-gruppen external-secrets.io/v1 (inte den äldre v1beta1). Ersätt <TENANT_ID> med ditt tenant-ID.
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-hemlighet-KARTA: <secrets-postnamn>.<datanyckel>.
# {{ .apikey }} renderar hela kartan och API:et returnerar 401 — använd nyckeln .apikey.
X-API-Key: '{{ .apikey.apikey }}'
result:
jsonPath: '$.secretValue'
secrets:
- name: apikey
secretRef:
name: frostmoln-api-key
key: apikey{{ .remoteRef.key }} i URL:en fylls i per ExternalSecret med Frostmolns hemlighetsnamn (Steg 3), så en SecretStore betjänar alla dina hemligheter.
Steg 3 — Skapa en ExternalSecret
Varje ExternalSecret mappar en Frostmoln-hemlighet till ett Kubernetes-Secret. remoteRef.key är Frostmolns hemlighetsnamn; target.name är det Kubernetes-Secret som ESO skapar och håller synkroniserat.
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 # nyckeln inuti det synkade Kubernetes-Secret
remoteRef: { key: my-secret-name } # Frostmolns hemlighetsnamnESO skapar Secret my-secret-synced med en value-nyckel som håller det hämtade hemlighetsvärdet. Montera det eller referera till det från din Pod som vilket annat Secret som helst.
Uppdateringsintervall
refreshInterval styr hur ofta ESO hämtar på nytt. Ett kort intervall sprider rotationer snabbare men gör fler API-anrop; ett längre är lättare. Välj per hemlighet utifrån hur snabbt en rotation måste nå dina arbetsbelastningar — en minut eller några minuter är typiskt.
Låsa en specifik version
Frostmoln-hemligheter är versionshanterade. För att låsa en version, lägg till &version=N i SecretStore-URL:en (skapa en andra SecretStore för den låsta hemligheten):
url: 'https://api.frostmoln.cloud/api/v1/tenants/<TENANT_ID>/secrets/lookup?name={{ .remoteRef.key }}&version=2'Utan &version läser ESO alltid den senaste versionen.
Att ta bort en hemlighet är felsäkert
Om du kör fm secrets delete på en hemlighet som ESO synkroniserar börjar uppslaget returnera ett fel (hemligheten går in i väntande borttagning). ESO:s uppdatering misslyckas (SecretSyncedError) och behåller det senast synkade Kubernetes-Secret oförändrat — det tömmer det inte. Dina arbetsbelastningar fortsätter köra på det senast kända fungerande värdet.
Återställ för att återuppta synkronisering
Medan hemligheten är borttagen kan ESO inte uppdatera den och värdet i ditt kluster blir inaktuellt. Kör fm secrets recover <name> inom återställningsfönstret för att återställa det; ESO återupptar då synkroniseringen vid nästa intervall. Om återställningsfönstret passerar och hemligheten tas bort permanent fortsätter uppslaget att misslyckas — återskapa hemligheten för att återuppta.
Felsökning
Kontrollera ExternalSecret-statusen med kubectl describe externalsecret <name>.
secret does not contain needed label— API-nyckelnsSecretsaknar etikettenexternal-secrets.io/type: webhook(Steg 1).401/ obehörig — headermallen är fel. Den måste vara{{ .apikey.apikey }}(<secrets-postnamn>.<datanyckel>);{{ .apikey }}renderar hela kartan och API:et avvisar den. Kontrollera även nyckelvärdet och att nyckeln inte har gått ut.- Arbetsbelastningsidentitet:
Secretfrostmoln-tokendyker inte upp — kontrollera att tillägget Workload Identity finns i klustret, att tjänstekontot bär annoteringen och har en bindning, och att inget Secret med det namnet fanns sedan tidigare: tillägget skriver aldrig över ett Secret som det inte själv skapat. could not get secret data from provider— hemlighetsnamnet eller tenant-ID:t är fel, eller så är hemligheten borttagen / under väntande borttagning. Verifiera att namnet finns:fm secrets get <name>.- Inget synkroniseras alls — kontrollera att
SecretStoreanvänderexternal-secrets.io/v1, intev1beta1. På ett kluster du kör själv, bekräfta att ESO körs (kubectl -n external-secrets get pods). På Frostmolns hanterade Kubernetes kan du inte lista de poddarna: bekräfta att tillägget finns på klustret (fm kubernetes cluster addons <cluster-id>eller fliken Tillägg), att det lades till för mer än några minuter sedan (om plattformen meddelade att den inte kunde starta synkroniseringen, räkna med längre tid: vanligtvis högst en timme, mer under plattformsunderhåll) och att dina noder nårghcr.ioochpkg-containers.githubusercontent.com.