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
- Erstellen Sie eine Datei 
emptydir.yaml, die einen Pod mit dem Namenvolume-emptydirbeschreibt. - Die Pod-Spezifikation sollte ein Volume des Typs 
emptyDirmit dem Namencacheenthalten. - 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 applyan. 
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f emptydir.yaml
- Schauen Sie sich den Pod mit 
kubectl describean. 
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 
dfim 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-hostpathbeschreibt. - 
Die Pod-Spezifikation sollte ein Volume des Typs
hostPathmit dem Namendataenthalten. - 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 applyan. 
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f hostpath.yaml
- Schauen Sie sich den Pod mit 
kubectl describean. 
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/datadesvolume-hostpathPods 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-hostpathmitkubectl 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-mountenthält. - Die ConfigMap-Daten sollten einen Schlüssel 
index.htmlmit 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 applyan 
Lösung (Klicken Sie auf den Pfeil, falls Sie nicht weiterkommen)
kubectl apply -f configmap-mount.yaml
- Lassen Sie sich die Configmap mit 
kubectl getals 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 
webinpod-web-mount.yamlunter Verwendung des Imagesnginx(ähnlich wie in den Übungen zuvor) - Fügen Sie dem Pod ein Volume hinzu, das auf die ConfigMap 
my-mountzeigt. - 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 applyan. 
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 describean. 
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-mountzu verbinden - Führen Sie 
df -aim Pod aus, um den Einhängepunkt/usr/share/nginx/htmlzu sehen - Führen Sie 
ls -l /usr/share/nginx/htmlin der Gruppe aus, um die gemounteten Dateien zu sehen - Führen Sie 
curl -s localhostin 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: PersistentVolume und PersistentVolumeClaim
Aufgabe 4.1: PersistentVolume erstellen
- Erstellen Sie eine PersistentVolume YAML-Datei 
pv.yamlund 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 4.2: PersistentVolumeClaim definieren
- Erstellen Sie eine PersistentVolumeClaim YAML-Datei 
pvc.yamlund 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 4.3: Pod mit PersistentVolumeClaim erstellen
- 
Erstellen Sie eine Pod YAML-Datei
storage-demo.yamlund definieren Sie einen Pod:- der den 
dummy-pvcPersistentVolumeClaim verwendet und - ein Volume "data" an das Verzeichnis 
/usr/share/nginx/htmlmountet. - 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 describeaus, um die Ereignisse des Pods zu überprüfen und zu sehen, ob das Volume erfolgreich gemountet wurde - Führen Sie 
kubectl execaus, 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 execaus, 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 5: 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 5.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-volumesverwendet. 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 5.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 allverschwinden.