Volumes
Ziel
In diesem Projekt geht es um Volumes und Mount-Punkten. Sie werden:
- Volumes erstellen und inspizieren
- Dateien aus ConfigMaps und Secrets mounten
Hilfsmittel
- Versuchen Sie, die unten stehenden Aufgaben mit Hilfe der Folien und des Cheatsheets eigenständig zu lösen.
- Sollten Sie dabei Probleme haben, finden Sie bei jeder Aufgabe einen ausklappbaren Block, in dem der Lösungsweg beschrieben wird.
Aufgabe 1: emptyDir Volumes
- Hier finden Sie die offizielle Dokumentation für emptyDir-Volumes
- Erstellen Sie eine Datei
emptydir.yaml
, die einen Pod mit dem Namenvolume-emptydir
beschreibt. - Die Pod-Spezifikation sollte ein Volume des Typs
emptyDir
mit dem Namencache
enthalten. - Mounten Sie das Volume in der Container-Spezifikation unter dem Pfad
/cache
.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: Pod
metadata:
name: volume-emptydir
spec:
volumes:
- name: cache
emptyDir: {}
containers:
- name: web
image: nginx
volumeMounts:
- mountPath: /cache
name: cache
- Wenden Sie den Pod mit
kubectl apply
an.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f emptydir.yaml
- Schauen Sie sich den Pod mit
kubectl describe
an.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl describe pod volume-emptydir
Name: volume-emptydir
(...)
Containers:
web:
(...)
Mounts:
/cache from cache (rw)
(...)
Volumes:
cache:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
- Überprüfen Sie die Mounts innerhalb des Pod-Containers indem Sie
df
im Pod ausführen.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl exec -it volume-emptydir -- df --exclude-type=tmpfs
Filesystem 1K-blocks Used Available Use% Mounted on
overlay 619139212 8908236 584839800 2% /
/dev/sda1 619139212 8908236 584839800 2% /cache
Aufgabe 2: hostpath Volumes
- Hier finden Sie die offizielle Dokumentation für hostPath-Volumes
-
Erstellen Sie eine Datei
hostpath.yaml
, die einen Pod mit dem Namenvolume-hostpath
beschreibt. -
Die Pod-Spezifikation sollte ein Volume des Typs
hostPath
mit dem Namendata
enthalten. - Mounten Sie das Volume in der Container-Spezifikation unter dem Pfad
/data
.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: Pod
metadata:
name: volume-hostpath
labels:
exercise: volumes
spec:
volumes:
- name: data
hostPath:
path: /data
type: DirectoryOrCreate
containers:
- name: web
image: nginx
volumeMounts:
- mountPath: /data
name: data
- Wenden Sie den Pod mit
kubectl apply
an.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f hostpath.yaml
- Schauen Sie sich den Pod mit
kubectl describe
an.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl describe pod volume-hostpath
Name: volume-hostpath
(...)
Containers:
web:
(...)
Mounts:
/data from data (rw)
(...)
Volumes:
data:
Type: HostPath (bare host directory volume)
Path: /data
HostPathType: DirectoryOrCreate
- Überprüfen Sie die Mounts innerhalb des Pod-Containers.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl exec -it volume-hostpath -- df --exclude-type=tmpfs
Filesystem 1K-blocks Used Available Use% Mounted on
overlay 619139212 9021932 584726104 2% /
/dev/sda1 619139212 9021928 584726108 2% /data
- Verwenden Sie
kubectl exec
, um eine Datei innerhalb von/data
desvolume-hostpath
Pods zu erstellen
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl exec -it volume-hostpath -- sh -c "echo '# here we go' > /data/foo"
- Sehen Sie sich den
volume-hostpath
-Pod an, um herauszufinden, auf welchem Node er ausgerollt wurde
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pod volume-hostpath -o wide
- Löschen Sie den Pod
volume-hostpath
mitkubectl delete
.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl delete -f hostpath.yaml
- Starten Sie den Pod erneut an mit
kubectl apply
.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f hostpath.yaml
- Prüfen Sie, ob der Pod auf demselben Node erstellt wurde.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pod volume-hostpath -o wide
- Prüfen Sie, ob die Datei im Pod noch existiert.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Wenn der Node derselbe ist wie zuvor, sollte die Testdatei in Ihrem neuen Pod zu finden sein
kubectl exec -it volume-hostpath -- cat /data/foo
# here we go
- Wenn der Node NICHT derselbe ist wie zuvor, sollte die Testdatei in Ihrem neuen Pod nicht zu finden sein
kubectl exec -it volume-hostpath -- cat /data/foo
cat: /data/foo: No such file or directory
command terminated with exit code 1
Hinweis
- Daten in hostPath-Mounts werden auf einem bestimmten Knoten gespeichert
- Pods können auf jedem verfügbaren Clusterknoten erstellt werden.
- Wenn Sie mehr als einen Knoten haben, wird die Verwendung von hostPath für die Persistenz von Dateien während des Pod-Lebenszyklus unzuverlässig.
Hinweis: Pod auf einem Node erzwingen
---
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
nodeName: <node-name>
# Beispiel:
# nodeName: code-0-worker-cf4jc-6txcb
# Verfügbare Node-Namen erhalten Sie mit "kubectl get nodes"
volumes:
[...]
containers:
[...]
Pods lassen sich explizit auf Nodes verteilen. Dies kann zu Testzwecken nützlich sein, sorgt aber auch dafür, dass der Node nicht mehr so einfach austauschbar ist und Pods nicht gestartet werden können, wenn dieser Node nicht verfügbar ist.
Aufgabe 3: ConfigMap-Mount
- Erstellen Sie eine Datei
configmap-mount.yaml
, die eine ConfigMap namensmy-mount
enthält. - Die ConfigMap-Daten sollten einen Schlüssel
index.html
mit dem folgenden Wert enthalten:<html><body>Hooray!</body></html>
- Alternativ können Sie mit einer KI Ihrer Wahl einen anderen HTML-Inhalt erstellen
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: ConfigMap
metadata:
name: my-mount
labels:
exercise: mount
data:
index.html: |
<html><body>Hooray!</body></html>
- Wenden Sie die ConfigMap mit
kubectl apply
an
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f configmap-mount.yaml
- Lassen Sie sich die Configmap mit
kubectl get
als YAML ausgeben
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get configmap my-mount -o yaml
apiVersion: v1
data:
index.html: |
<html><body>Hooray!</body></html>
kind: ConfigMap
(...)
- Schauen Sie sich das Kapitel "Using ConfigMaps as files from a pod" an
- Erstellen Sie einen Pod namens
web
inpod-web-mount.yaml
unter Verwendung des Imagesnginx
(ähnlich wie in den Übungen zuvor) - Fügen Sie dem Pod ein Volume hinzu, das auf die ConfigMap
my-mount
zeigt. - Mappen Sie das Volume auf den Mountpfad
/usr/share/nginx/html
.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: Pod
metadata:
name: web-mount
labels:
exercise: mount
spec:
volumes:
- name: html-files
configMap:
name: my-mount
containers:
- name: web
image: nginx:stable-alpine
volumeMounts:
- mountPath: /usr/share/nginx/html
name: html-files
- Wenden Sie es mit
kubectl apply
an.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f pod-web-mount.yaml
- Schauen Sie sich den Pod mit
kubectl describe
an.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl describe pod web-mount
(...)
Containers:
env:
(...)
Mounts:
/usr/share/nginx/html from html-files (rw)
(...)
Volumes:
html-files:
Type: ConfigMap (a volume populated by a ConfigMap)
Name: my-mount
Optional: false
(...)
- Verwenden Sie
kubectl exec
, um sich mit dem Podweb-mount
zu verbinden - Führen Sie
df -a
im Pod aus, um den Einhängepunkt/usr/share/nginx/html
zu sehen - Führen Sie
ls -l /usr/share/nginx/html
in der Gruppe aus, um die gemounteten Dateien zu sehen - Führen Sie
curl -s localhost
in der Gruppe aus, um die Antwort des Webservers zu prüfen
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl exec -it web-mount -- df -a
/dev/sda1 619139212 8467828 585280208 1% /usr/share/nginx/html
- Dateien auflisten:
kubectl exec -it web-mount -- ls -l /usr/share/nginx/html
total 0
lrwxrwxrwx 1 root root 17 Feb 28 10:14 index.html -> ..data/index.html
- Mit curl die Antwort des Webservers prüfen:
kubectl exec -it web-mount -- curl -s localhost
<html><body>Hooray!</body></html>
Aufgabe 4: Mount Secret (Optional)
Wenn Sie Dateien mounten wollen, die sicherheitskritische Daten enthalten, verwenden Sie besser ein Secret statt einer ConfigMap. Das Einbinden eines Secrets in einen Pod funktioniert im Grunde genauso wie das Einbinden einer ConfigMap.
- Erstellen Sie eine Datei
secret-mount.yaml
, die die Beschreibung für ein Secret mit dem Namenmy-secret-mount
enthält. - Die Secret-Daten sollten zwei Schlüssel enthalten:
secret.txt
mit dem Wert "abracadabra"passphrase.txt
mit dem Wert "open sesame".
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: Secret
metadata:
name: my-secret-mount
labels:
exercise: mount
type: Opaque
stringData:
secrets.txt: "abracadabra"
passphrase.txt: "open sesame"
- Deployen Sie das Secret mit
kubectl apply
.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f secret-mount.yaml
- Lassen Sie sich das Secret als YAML ausgeben
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get secret my-secret-mount -o yaml
apiVersion: v1
data:
passphrase.txt: b3BlbiBzZXNhbWU=
secrets.txt: YWJyYWNhZGFicmE=
kind: Secret
(...)
- Erstellen Sie einen neuen Pod mit einem Volume, das auf das Secret
my-secret-mount
zeigt und alle Daten aus dem Secret in den Mountpfad/secrets
mounted.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: Pod
metadata:
name: secret-mount
labels:
exercise: mount
spec:
volumes:
- name: secret-files
secret:
secretName: my-secret-mount
containers:
- name: web
image: nginx:stable-alpine
volumeMounts:
- mountPath: /secrets
name: secret-files
- Deployen:
kubectl apply -f pod-secret-mount.yaml
- Schauen Sie sich den Pod mit
kubectl describe
an.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl describe pod secret-mount
(...)
Containers:
web:
(...)
Mounts:
/secrets from secret-files (rw)
Volumes:
secret-files:
Type: Secret (a volume populated by a Secret)
SecretName: my-secret-mount
Optional: false
(...)
- Verbinden Sie sich mit dem Pod
secret-mount
und überprüfen Sie die gemounteten Dateien.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
- Mount-Files anzeigen:
kubectl exec -it secret-mount -- ls -l /secrets
total 0
lrwxrwxrwx 1 root root 21 Feb 28 11:18 passphrase.txt -> ..data/passphrase.txt
lrwxrwxrwx 1 root root 18 Feb 28 11:18 secrets.txt -> ..data/secrets.txt
- Inhalt der Dateien anzeigen:
kubectl exec -it secret-mount -- cat /secrets/passphrase.txt
open sesame
kubectl exec -it secret-mount -- cat /secrets/secrets.txt
abracadabra
Aufgabe 5: PersistentVolume und PersistentVolumeClaim
Aufgabe 5.1: PersistentVolume erstellen
- Erstellen Sie eine PersistentVolume YAML-Datei
pv.yaml
und definieren Sie ein PersistentVolume, das einenhostPath
-Volumen-Typ verwendet und eine Kapazität von 5Gi angibt.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
apiVersion: v1
kind: PersistentVolume
metadata:
name: dummy-pv
labels:
storage: dummy
spec:
capacity:
storage: 5Gi
storageClassName: ""
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
hostPath:
path: /data/pv/dummy
type: DirectoryOrCreate
- Deployen Sie das PersistentVolume mit
kubectl apply
.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f pv.yaml
- Überprüfen Sie, ob das PersistentVolume erfolgreich erstellt wurde
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pv
kubectl describe pv dummy-pv
Aufgabe 5.2: PersistentVolumeClaim definieren
- Erstellen Sie eine PersistentVolumeClaim YAML-Datei
pvc.yaml
und definieren Sie einen PersistentVolumeClaim mit einer Kapazität von 5Gi.
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dummy-pvc
spec:
volumeName: dummy-pv
storageClassName: ""
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 5Gi
- Deployen Sie den PersistentVolumeClaim
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f pvc.yaml
- Überprüfen Sie, ob der PersistentVolumeClaim erfolgreich erstellt wurde
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pvc
kubectl describe pvc dummy-pvc
Aufgabe 5.3: Pod mit PersistentVolumeClaim erstellen
-
Erstellen Sie eine Pod YAML-Datei
storage-demo.yaml
und definieren Sie einen Pod:- der den
dummy-pvc
PersistentVolumeClaim verwendet und - ein Volume "data" an das Verzeichnis
/usr/share/nginx/html
mountet. - Verwenden Sie dieses Beispiel als Ausgangspunkt:
--- apiVersion: v1 kind: Pod metadata: name: storage-demo labels: exercise: storage spec: containers: - name: nginx image: nginx
- der den
-
Wenden Sie das Pod-Manifest an
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
apiVersion: v1
kind: Pod
metadata:
name: storage-demo
labels:
exercise: storage
spec:
volumes:
- name: pvc-volume
persistentVolumeClaim:
claimName: dummy-pvc
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: pvc-volume
kubectl apply -f storage-demo.yaml
- Führen Sie
kubectl describe
aus, um die Ereignisse des Pods zu überprüfen und zu sehen, ob das Volume erfolgreich gemountet wurde - Führen Sie
kubectl exec
aus, um eine Datei in das gemountete Volume zu schreiben
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl exec -it storage-demo -- /bin/sh -c 'echo "Hello from Kubernetes" > /usr/share/nginx/html/index.html'
- Löschen Sie den Pod und erstellen Sie einen neuen Pod mit demselben PersistentVolumeClaim
- Führen Sie
kubectl exec
aus, um den Inhalt des gemounteten Volumes zu überprüfen
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl exec -it storage-demo -- /bin/sh -c 'cat /usr/share/nginx/html/index.html'
- Löschen Sie den Pod und den PersistentVolumeClaim
Aufgabe 6: PersistentVolumeClaim mit CSI Plugin
In der vorherigen Aufgabe haben wir ein PV und PVC händisch angelegt. Über CSI-Plugins und StorageClasses können PVs auch automatisch erzeugt werden.
Aufgabe 6.1: PersistentVolumeClaim erstellen
- Lassen Sie sich alle PersistentVolumes und PersistentVolumeClaims anzeigen
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pv,pvc
- Lassen Sie sich alle verfügbaren StorageClasses anzeigen
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get stor<TAB>
kubectl get storageclasses.storage.k8s.io
- Erstellen Sie ein PVC, das die StorageClass
hcloud-volumes
verwendet. Die StorageClass sollte der Default sein und muss deshalb nicht explizit angegeben werden
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: hetzner-pvc
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 5Gi
kubectl apply -f <pvc.yml>
- Lassen Sie sich Details zum erstellten PVC anzeigen
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl describe persistentvolumeclaims hetzner-pvc
Name: hetzner-pvc
Namespace: default
StorageClass: hcloud-volumes
Status: Pending
Volume:
Labels: <none>
Annotations: <none>
Finalizers: [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode: Filesystem
Used By: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal WaitForFirstConsumer 3s (x4 over 46s) persistentvolume-controller waiting for first consumer to be created before binding
Der PVC ist erstellt. Das dazugehörige PersistentVolume wird aber erst erstellt, sobald das PVC verwendet wird.
Aufgabe 6.2: PersistentVolumeClaim verwenden
- Starten Sie einen Pod, der das PVC verwendet
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
apiVersion: v1
kind: Pod
metadata:
name: hetzner-storage-demo
labels:
exercise: storage
spec:
volumes:
- name: pvc-volume
persistentVolumeClaim:
claimName: hetzner-pvc
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: pvc-volume
- Lassen Sie sich alle PersistentVolumes und PersistentVolumeClaims anzeigen
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl get pv,pvc
- Sie sollten das erstellte PersistentVolume sehen.
Cleanup
- Löschen Sie alle Objekte, die Sie erstellt haben.
- Beobachten Sie, wie sie mit
watch kubectl get all
verschwinden.