· Kubernetes · 8 Min. Lesezeit
Schluss mit ewigen kubeconfigs: kurzlebige Cluster-Logins mit Pinniped
Statische kubeconfig-Dateien mit langlebigen Tokens laufen nie ab. Pinniped hängt den Cluster-Login an den zentralen Identity-Provider und stellt nur kurzlebige Credentials aus. Einrichtung von Supervisor, Concierge und CLI in v0.47.0, mit Prüfbefehl nach jedem Schritt.

Der unscheinbarste Dauerläufer im Kubernetes-Alltag ist die kubeconfig-Datei. Enthält sie ein statisches Token, läuft sie nicht von selbst ab, und sie ist beliebig kopierbar. Wer das Team verlässt, dessen Zugang bleibt bestehen.
Pinniped setzt genau hier an. Die Anmeldung läuft über den zentralen Identity-Provider, und der Cluster sieht nur noch eine Credential mit sehr kurzer Lebensdauer. Dieser Beitrag zeigt die Einrichtung in Version v0.47.0, erschienen am 8. Juli 2026, mit einem Prüfbefehl nach jedem Schritt.
Wann sich der Aufwand lohnt
Pinniped ist kein Werkzeug für einen einzelnen Cluster mit drei Administratoren. Es lohnt sich, wenn mehrere Cluster von denselben Personen bedient werden und ein Identity-Provider existiert, an dem Ein- und Austritte gepflegt werden.
Pinniped macht ausschließlich Authentifizierung. Wer was darf, bleibt Sache von Kubernetes-RBAC. Pinniped liefert Benutzername und Gruppen, die Rechtevergabe passiert über Role- und ClusterRoleBindings.
Die zwei Strategien des Concierge
Entscheiden Sie vor der Installation, wie der Concierge die Credential erzeugt. Die Architektur-Dokumentation beschreibt zwei Wege.
| Kriterium | Kube-Cluster-Signing-Certificate | Impersonation Proxy |
|---|---|---|
| Signatur der Credential | Signing-Key des Kubernetes-API-Servers | eigener Pinniped-Key |
| Weg zum API-Server | direkt | über einen Proxy mit Identität und Gruppen des Nutzers |
| Voraussetzung | eigener Pod auf dem Node des kube-controller-manager | läuft auf jedem Cluster |
| Typische Umgebung | selbst betrieben, etwa kubeadm, kind, TKG | Managed Services wie EKS, GKE, AKS |
--anonymous-auth=false | nicht möglich, siehe Stolperstein 3 | zulässig |
Die Übersicht der unterstützten Cluster nennt die Details je Distribution.
Voraussetzungen
Beide Komponenten brauchen Linux-Nodes mit amd64 oder arm64:
kubectl get nodes -o custom-columns=NAME:.metadata.name,ARCH:.status.nodeInfo.architectureDer Supervisor braucht zusätzlich HTTPS-Ingress oder LoadBalancer, denn der Browser des Nutzers muss ihn erreichen. Hier läuft er auf einem Management-Cluster und der Concierge auf dem Workload-Cluster, denn ein Supervisor bedient viele Concierge.
Schritt 1: Die CLI installieren
Die CLI ist ein kubectl-Plugin. Unter macOS und Linux geht der Weg über brew install vmware/pinniped/pinniped-cli, für Linux auf amd64 über den direkten Dreisatz:
curl -Lso pinniped https://get.pinniped.dev/v0.47.0/pinniped-cli-linux-amd64 && chmod +x pinniped && sudo mv pinniped /usr/local/bin/pinnipedPrüfung: pinniped version muss die Version ausgeben. Sonst liegt die Binärdatei nicht im PATH oder ist nicht ausführbar.
Schritt 2: Den Concierge im Workload-Cluster installieren
Erst die CustomResourceDefinitions, dann die übrigen Ressourcen:
kubectl apply -f https://get.pinniped.dev/v0.47.0/install-pinniped-concierge-crds.yaml
kubectl apply -f https://get.pinniped.dev/v0.47.0/install-pinniped-concierge-resources.yamlPrüfung:
kubectl get pods -n pinniped-concierge
kubectl get credentialissuer -o yamlIm status.strategies des CredentialIssuer steht, welche der beiden Strategien Erfolg meldet. Diese Antwort kommt aus dem Cluster statt aus einer Vermutung.
Schritt 3: Den Supervisor installieren und erreichbar machen
Der Supervisor kommt mit einem einzigen Manifest:
kubectl apply -f https://get.pinniped.dev/v0.47.0/install-pinniped-supervisor.yamlEinen von außen erreichbaren Service legen die Manifeste nicht an. Sie brauchen einen eigenen auf targetPort 8443, die Supervisor-Konfiguration nennt diese Form:
apiVersion: v1
kind: Service
metadata:
name: pinniped-supervisor-loadbalancer
namespace: pinniped-supervisor
spec:
type: LoadBalancer
selector:
app: pinniped-supervisor
ports:
- protocol: TCP
port: 443
targetPort: 8443Den mitgelieferten Service pinniped-supervisor-api auf Port 10250 fassen Sie nicht an, er dient einem anderen Zweck.
Prüfung: Pods kontrollieren, die vergebene Adresse auslesen und im DNS auf supervisor.lab.rz.jabi-it.de zeigen lassen.
kubectl get pods -n pinniped-supervisor
kubectl get service pinniped-supervisor-loadbalancer \
-o jsonpath="{.status.loadBalancer.ingress[*].ip}" -n pinniped-supervisorWeil der Supervisor die Authentifizierung aller angeschlossenen Cluster kontrolliert, muss der Zugriff auf seine Interna abgesichert werden. Das ist Stolperstein 1.
Schritt 4: Die FederationDomain anlegen
Die FederationDomain trägt Issuer, TLS-Secret und die Liste der Identity-Provider. Zuerst das Zertifikat als Secret vom Typ kubernetes.io/tls:
kubectl create secret tls supervisor-tls-cert -n pinniped-supervisor \
--cert tls.crt --key tls.keyDann die Ressource selbst:
apiVersion: config.supervisor.pinniped.dev/v1alpha1
kind: FederationDomain
metadata:
name: rz-federation-domain
namespace: pinniped-supervisor
spec:
issuer: https://supervisor.lab.rz.jabi-it.de/produktion
tls:
secretName: supervisor-tls-cert
identityProviders: []Im Issuer ist ein beliebiger Pfad erlaubt, ein Hostname kann so mehrere Issuer tragen. Notieren Sie den Wert wörtlich, er taucht in Schritt 6 unverändert wieder auf.
Prüfung: Der OIDC-Discovery-Endpunkt muss ohne -k antworten, das Zertifikat also von einer bekannten CA stammen.
curl https://supervisor.lab.rz.jabi-it.de/produktion/.well-known/openid-configurationSchritt 5: Den Identity-Provider anbinden
Zuerst die Client-Zugangsdaten als Secret vom Typ secrets.pinniped.dev/oidc-client:
kubectl create secret generic idp-client-credentials -n pinniped-supervisor \
--type secrets.pinniped.dev/oidc-client \
--from-literal=clientID=0oa2fbhcnq1eGZUiG5d7 \
--from-literal=clientSecret="$IDP_CLIENT_SECRET"Dann der Provider:
apiVersion: idp.supervisor.pinniped.dev/v1alpha1
kind: OIDCIdentityProvider
metadata:
name: zentraler-idp
namespace: pinniped-supervisor
spec:
issuer: https://idp.lab.rz.jabi-it.de
authorizationConfig:
additionalScopes: [groups, email, offline_access]
claims:
username: email
groups: groups
client:
secretName: idp-client-credentialsOhne den Scope groups bekommen Sie keine Gruppenzuordnung, und ohne Gruppen wird die RBAC-Vergabe zur Einzelfallarbeit. Beim Provider tragen Sie als Redirect-URI den spec.issuer der FederationDomain mit angehängtem /callback ein.
Prüfung: kubectl describe OIDCIdentityProvider -n pinniped-supervisor zentraler-idp muss phase: Ready zeigen. Sonst ist der Provider nicht erreichbar oder die Zugangsdaten stimmen nicht. Bei Keycloak ist die Client-Anlage dieselbe Arbeit wie im Beitrag ArgoCD an Keycloak hängen.
Schritt 6: Concierge und Supervisor verbinden
Der JWTAuthenticator im Workload-Cluster ist das Bindeglied. Die Doku zur JWT-Konfiguration verlangt wörtlich, dass sein issuer exakt dem issuer der FederationDomain entspricht.
apiVersion: authentication.concierge.pinniped.dev/v1alpha1
kind: JWTAuthenticator
metadata:
name: rz-supervisor-authenticator
spec:
issuer: https://supervisor.lab.rz.jabi-it.de/produktion
audience: workload1-ed9de33c370981f61e9c
tls:
certificateAuthorityData: LS0tLS1CRUdJTiBDRVJUSUZJQ0...0tLQo=Die audience ist frei wählbar, muss aus Sicherheitsgründen aber je Cluster eindeutig sein. Das base64-kodierte certificateAuthorityData brauchen Sie nur, wenn die CA hinter dem FederationDomain-Zertifikat den Concierge-Pods unbekannt ist.
Prüfung: Beide Issuer maschinell vergleichen, nicht mit dem Auge. Die Ausgaben müssen zeichengleich sein, bis hin zu einem Schrägstrich am Ende.
kubectl get federationdomain -n pinniped-supervisor \
-o jsonpath='{.items[*].spec.issuer}' --kubeconfig management-admin.yaml
kubectl get jwtauthenticator \
-o jsonpath='{.items[*].spec.issuer}' --kubeconfig workload-admin.yamlSchritt 7: kubeconfig erzeugen und anmelden
Die Nutzer-kubeconfig entsteht aus einer Admin-kubeconfig des Workload-Clusters:
pinniped get kubeconfig --kubeconfig "$HOME/admin-kubeconfig.yaml" > pinniped-kubeconfig.yamlDiese Datei enthält kein Geheimnis mehr, sie beschreibt nur, wie sich die CLI eine Credential holt. Damit dürfen Sie sie verteilen. Den Login löst ein normaler Aufruf aus:
kubectl get namespaces --kubeconfig "$HOME/pinniped-kubeconfig.yaml"Der erste Aufruf schlägt erwartbar fehl, denn der Nutzer ist authentifiziert, hat aber keine Rechte. Die Autorisierung vergeben Sie über normales RBAC:
kubectl create clusterrolebinding my-user-can-edit \
--clusterrole edit --user entwickler@lab.rz.jabi-it.de
kubectl create clusterrolebinding my-auditors \
--clusterrole view --group auditorsPrüfung: pinniped whoami --kubeconfig pinniped-kubeconfig.yaml zeigt Benutzername und Gruppen so, wie der Cluster sie sieht. Stimmen die Gruppen nicht, liegt der Fehler bei den claims aus Schritt 5 und nicht bei RBAC.
Die Lebensdauern, die Sie kennen müssen
Die Referenz zu Tokens und Credentials nennt konkrete Werte.
| Artefakt | Gültigkeit |
|---|---|
| Client-Zertifikat | 5 Minuten, plus 5 Minuten rückdatiert gegen Clock Skew |
| ID-Token | 2 Minuten |
| Access-Token | 2 Minuten |
| Refresh-Token | 9 Stunden ab der ersten Anmeldung |
| Maximale Sitzungsdauer | 9 Stunden ab der ersten Anmeldung |
Der Nutzer meldet sich also morgens einmal an und arbeitet durch, und was auf dem Laptop liegt, ist nie länger als fünf Minuten gültig. Keiner dieser Werte ist konfigurierbar.
Die folgenreichsten Stolpersteine
1. Nicht-privilegierte Nutzer lesen die Pinniped-Secrets
Symptom: Ein Nutzer ohne Administratorrechte kann Secrets im Namespace pinniped-supervisor lesen.
Ursache: Die Manifeste bringen keine Absicherung gegen Lesezugriffe auf den eigenen Namespace mit. Die Doku fordert diesen Schutz als eigenen Schritt ein.
Prüfung: Die Antwort muss no lauten.
kubectl auth can-i get secrets -n pinniped-supervisor --as entwickler@lab.rz.jabi-it.deLösung: RBAC so setzen, dass Nicht-Administratoren die Secrets in pinniped-concierge und pinniped-supervisor nicht lesen können.
2. Der Login scheitert, obwohl alles Ready meldet
Symptom: Supervisor und Concierge laufen, alle Ressourcen melden Ready, der Login schlägt trotzdem fehl.
Ursache: Der issuer im JWTAuthenticator weicht vom issuer der FederationDomain ab, etwa durch einen abweichenden Pfad oder einen Schrägstrich am Ende.
Prüfung: Die beiden jsonpath-Abfragen aus Schritt 6 gegeneinander stellen.
Lösung: Den Wert wörtlich aus der FederationDomain übernehmen. Die Doku verlangt eine exakte Übereinstimmung, keine sinngemäße.
3. --anonymous-auth=false sperrt alle Nutzer aus
Symptom: Nach dem Setzen von --anonymous-auth=false am API-Server kann sich niemand mehr anmelden.
Ursache: Die TokenCredentialRequest-API des Concierge ist auf anonymen Zugriff angewiesen. Wird der abgeschaltet, bricht der Login-Pfad.
Prüfung: Nach der Änderung pinniped whoami mit der Pinniped-kubeconfig ausführen.
Lösung: --anonymous-auth=false nur auf Clustern setzen, die die Impersonation-Proxy-Strategie verwenden.
Die vollständige Sammlung der Stolpersteine
Diese drei Fälle sind die folgenreichsten, sie sind aber nicht alle. Die vollständige Sammlung aller sechzehn Stolpersteine steht im Beitrag Pinniped: die Stolpersteine bei Supervisor, Concierge und CLI, jeder nach Symptom, Ursache, Prüfung und Lösung geordnet. Dort stehen unter anderem der ungefragt auftauchende LoadBalancer, die geteilte audience, der Registry-Wechsel ab v0.40.0 und der Login für CI/CD-Konten.
Grenzen
Der Entzug wirkt nicht sofort. Identitäts- und Gruppeninformationen werden erst beim Refresh revalidiert. Die Doku beziffert die Veraltung nach einem Refresh auf 2 + 2 + 5 = 9 Minuten. Nach der ersten Anmeldung kommen die 10 Minuten des Authorization Code hinzu, im schlimmsten Fall also 10 + 2 + 2 + 5 = 19 Minuten. Typisch sind laut Doku etwa 5 Minuten. Ein im Identity-Provider deaktivierter Nutzer kommt also noch kurze Zeit an den Cluster. Wer sofortigen Entzug braucht, muss zusätzlich im Cluster eingreifen, etwa über RBAC.
Die Maximalsitzung liegt fest bei 9 Stunden. Verlangen Ihre Vorgaben einen kürzeren Wert, ist das mit Bordmitteln nicht erreichbar.
Service-zu-Service-Authentifizierung ist nicht abgedeckt. Dafür brauchen Sie einen anderen Mechanismus.
Der Supervisor wird zur zentralen Abhängigkeit. Ist er nicht erreichbar, kommt niemand mehr an die angeschlossenen Cluster. Halten Sie einen Notfallzugang außerhalb des Pinniped-Pfads bereit.
Ich halte den Aufwand für gerechtfertigt, sobald es mehr als eine Handvoll Cluster gibt. Der Gewinn ist nicht nur die kurze Lebensdauer, sondern dass der Cluster-Zugang aufhört, ein Sonderfall zu sein. Wer keinen Identity-Provider aufbauen will, fährt mit einem eng geführten Zugangsweg besser, wie im Beitrag Wenn der einzige Zugang die Rancher-Shell ist beschrieben.
Sie wollen den Zugang zu Ihren Systemen an echte Identitäten binden, statt an Schlüssel, die nie ablaufen? Ich baue Zugangswege, die zentral steuerbar sind und mit der Sitzung enden. Mehr unter IT-Sicherheit & ISMS, das Erstgespräch ist unverbindlich.

Alex Jabi
Ich betreue IT, Informationssicherheit und Datenschutz für KMU und Praxen an der Bergstraße und im Odenwald, persönlich, dokumentiert und ohne Cloud-Zwang.
Mehr über mich


