Einführung
Anwendungen benötigen häufig Werte, die nicht direkt in einem Container-Image oder einem einfachen Manifest hinterlegt werden sollten, wie etwa Passwörter, Token oder Datenbank-Zugangsdaten. Kubernetes Secrets speichern diese Art von sensiblen Konfigurationsdaten als separates Objekt und ermöglichen es Pods, diese beim Start zu beziehen.
In diesem Lab erstellen Sie ein Secret, untersuchen sorgfältig dessen kodierte Daten, verknüpfen es mit einem Anwendungs-Pod, aktualisieren das Secret und erstellen den Pod neu, damit die Anwendung die neuen Werte einliest. Dieses Lab konzentriert sich auf den grundlegenden Workflow von Secrets. In späteren Labs werden detailliertere Methoden zur Einbindung von Umgebungsvariablen und dateibasierten Konfigurations-Mounts behandelt.
Einen Namespace für Secret-Übungen vorbereiten
In diesem Schritt bereiten Sie einen sauberen Namespace für die Arbeit mit Secrets vor.
Beginnen Sie im Verzeichnis /home/labex/project. Sie werden in diesem Verzeichnis ein Pod-Manifest erstellen.
mkdir -p /home/labex/project
cd /home/labex/project
Überprüfen Sie, ob der Kubernetes API-Server erreichbar ist. Falls die VM gerade erst gestartet wurde und der Node noch nicht bereit ist, warten Sie einige Sekunden und führen Sie den Befehl erneut aus.
kubectl get nodes --request-timeout=5s
Die erwartete Ausgabe sieht in etwa so aus:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Warten Sie, bis der Cluster-Networking-Pod bereit ist, bevor Sie Anwendungsobjekte erstellen.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Erwartete Ausgabe:
pod/calico-node-... condition met
Erstellen Sie einen Namespace namens ckad-prep-secrets:
kubectl create namespace ckad-prep-secrets
Setzen Sie diesen Namespace als aktuellen Kontext-Namespace:
kubectl config set-context --current --namespace=ckad-prep-secrets
Bestätigen Sie den aktuellen Namespace:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
Erwartete Ausgabe:
ckad-prep-secrets
Ein Secret erstellen und untersuchen
In diesem Schritt erstellen Sie ein Secret, das Datenbank-Verbindungseinstellungen für eine kleine Anwendung speichert.
Der Befehl kubectl create secret generic erstellt ein sogenanntes "Opaque" Secret. generic bedeutet, dass Kubernetes den Schlüsseln keine spezielle, vordefinierte Bedeutung zuweist. Jedes --from-literal Flag fügt dem Secret ein Schlüssel-Wert-Paar hinzu.
kubectl create secret generic db-credentials \
--from-literal=DB_USER=orders-app \
--from-literal=DB_PASSWORD=dev-password-123 \
--from-literal=DB_NAME=orders
Erwartete Ausgabe:
secret/db-credentials created
Untersuchen Sie die Zusammenfassung des Secrets:
kubectl get secret db-credentials
Erwartete Ausgabe:
NAME TYPE DATA AGE
db-credentials Opaque 3 ...
Lassen Sie sich das Secret als YAML anzeigen. Kubernetes speichert die Werte unter data als base64-kodierte Strings, daher sollten Sie das ursprüngliche Passwort in dieser Ausgabe nicht im Klartext sehen.
kubectl get secret db-credentials -o yaml
Die erwartete Ausgabe enthält:
data:
DB_NAME: b3JkZXJz
DB_PASSWORD: ...
DB_USER: b3JkZXJzLWFwcA==
type: Opaque
Base64-Kodierung ist keine Verschlüsselung. Jeder, der das Secret-Objekt lesen kann, kann dessen Werte dekodieren. Dekodieren Sie hier nur den Benutzernamen, um zu sehen, wie die Darstellung funktioniert, ohne das Passwort preiszugeben.
kubectl get secret db-credentials -o 'jsonpath={.data.DB_USER}' | base64 --decode; echo
Erwartete Ausgabe:
orders-app
Einen Pod mit dem Secret konfigurieren
In diesem Schritt starten Sie einen Pod, der das Secret als Umgebungsvariablen einliest.
Das Feld envFrom.secretRef importiert alle Schlüssel aus einem Secret in die Umgebung des Containers. Dies ähnelt dem ConfigMap-Muster aus dem vorherigen Lab, jedoch stammen die Werte hier aus einem Secret-Objekt. Der Befehl in diesem Pod gibt den Benutzernamen und den Datenbanknamen aus und bestätigt lediglich, dass ein Passwort geladen wurde. Das Passwort selbst wird nicht ausgegeben.
Erstellen Sie secret-reader-pod.yaml:
cat > secret-reader-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: secret-reader
labels:
app: secret-reader
spec:
terminationGracePeriodSeconds: 0
containers:
- name: reader
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo user=${DB_USER}; echo database=${DB_NAME}; if [ -n "${DB_PASSWORD}" ]; then echo password-loaded; fi; sleep 3600'
envFrom:
- secretRef:
name: db-credentials
EOF
Wenden Sie das Pod-Manifest an:
kubectl apply -f secret-reader-pod.yaml
Erwartete Ausgabe:
pod/secret-reader created
Warten Sie, bis der Pod bereit ist:
kubectl wait --for=condition=Ready pod/secret-reader --timeout=120s
Erwartete Ausgabe:
pod/secret-reader condition met
Lesen Sie die Logs des Pods. Die Anwendung bestätigt, dass die Secret-Werte verfügbar waren, aber der Passwortwert wird nicht angezeigt.
kubectl logs secret-reader -c reader
Erwartete Ausgabe:
user=orders-app
database=orders
password-loaded
Das Secret aktualisieren und den Pod neu erstellen
In diesem Schritt aktualisieren Sie das Secret und erstellen den Pod neu, damit der Container die neuen Werte erhält.
Eine Container-Umgebung wird beim Start des Containers festgelegt. Wenn ein Secret als Umgebungsvariable verwendet wird, bewirkt eine Aktualisierung des Secret-Objekts keine Änderung der Umgebung innerhalb eines bereits laufenden Containers. Starten Sie einen neuen Pod, wenn die Anwendung die aktualisierten Secret-Werte einlesen muss.
Patchen Sie das Secret mit einem neuen Anwendungsbenutzer und Passwort:
kubectl patch secret db-credentials --type merge --patch '{"stringData":{"DB_USER":"orders-worker","DB_PASSWORD":"rotated-password-456","DB_NAME":"orders"}}'
Erwartete Ausgabe:
secret/db-credentials patched
Bestätigen Sie den aktualisierten Benutzernamen, indem Sie nur DB_USER dekodieren:
kubectl get secret db-credentials -o 'jsonpath={.data.DB_USER}' | base64 --decode; echo
Erwartete Ausgabe:
orders-worker
Löschen Sie den alten Pod:
kubectl delete pod secret-reader
Die erwartete Ausgabe enthält:
pod "secret-reader" deleted
Erstellen Sie den Pod aus demselben Manifest neu und warten Sie, bis er bereit ist:
kubectl apply -f secret-reader-pod.yaml
kubectl wait --for=condition=Ready pod/secret-reader --timeout=120s
Erwartete Ausgabe:
pod/secret-reader created
pod/secret-reader condition met
Lesen Sie die Logs erneut. Der neue Pod sieht nun den aktualisierten Benutzer aus dem Secret und vermeidet weiterhin die Ausgabe des Passworts im Klartext.
kubectl logs secret-reader -c reader
Erwartete Ausgabe:
user=orders-worker
database=orders
password-loaded
Zusammenfassung
Sie haben ein Kubernetes Secret erstellt, dessen kodierte Daten untersucht, einen nicht-sensiblen Schlüssel dekodiert, um die Darstellung zu verstehen, das Secret mit einem Anwendungs-Pod verknüpft und den Pod nach der Aktualisierung des Secrets neu erstellt. Zudem haben Sie eine wichtige Vorgehensweise für sensible Konfigurationen geübt: Überprüfen Sie, ob die Anwendung das Passwort erhalten hat, ohne den Passwortwert selbst in die Logs zu schreiben.


