Введение
Контейнеры имеют записываемую файловую систему, но это хранилище привязано к самому контейнеру. Тома Kubernetes предоставляют подам более удобный способ управления файлами. Некоторые тома являются эфемерными и предназначены для временных данных внутри одного пода. Другие тома являются постоянными (persistent) и позволяют сохранять данные даже после удаления и повторного создания пода.
В этой лабораторной работе вы будете использовать том emptyDir для временных данных пода, а затем создадите PersistentVolumeClaim и подключите его к двум разным подам, чтобы убедиться, что данные сохраняются после замены пода.
Подготовка пространства имен для работы с томами
На этом этапе вы подготовите чистое пространство имен и убедитесь, что в кластере есть все необходимые компоненты для хранения данных.
Начните работу в директории /home/labex/project. В этой директории вы будете создавать манифесты подов и PVC.
mkdir -p /home/labex/project
cd /home/labex/project
Проверьте доступность API-сервера Kubernetes. Если виртуальная машина только что запустилась и узел еще не готов, подождите несколько секунд и повторите команду.
kubectl get nodes --request-timeout=5s
Ожидаемый вывод:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Дождитесь готовности пода сетевого взаимодействия кластера:
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Ожидаемый вывод:
pod/calico-node-... condition met
В этой лабораторной работе позже будет использоваться PersistentVolumeClaim. Убедитесь, что существует стандартный StorageClass standard, а затем дождитесь готовности пода провизионера хранилища minikube.
kubectl get storageclass standard
kubectl wait --namespace kube-system --for=condition=Ready pod/storage-provisioner --timeout=120s
Ожидаемый вывод:
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ...
standard (default) k8s.io/minikube-hostpath Delete Immediate ...
pod/storage-provisioner condition met
Создайте пространство имен с именем ckad-prep-volumes:
kubectl create namespace ckad-prep-volumes
Установите это пространство имен в качестве текущего контекста:
kubectl config set-context --current --namespace=ckad-prep-volumes
Проверьте текущее пространство имен:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
Ожидаемый вывод:
ckad-prep-volumes
Использование emptyDir для временных данных пода
На этом этапе вы создадите под, который использует том emptyDir.
Том emptyDir создается пустым при запуске пода. Контейнеры внутри одного пода могут использовать его как общее пространство для временных файлов, кэша или рабочей директории. Он не предназначен для сохранения данных после удаления пода.
Создайте файл emptydir-pod.yaml:
cat > emptydir-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: scratch-worker
labels:
app: scratch-worker
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: scratch-space
emptyDir: {}
containers:
- name: worker
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo scratch-ready > /scratch/status.txt; sleep 3600'
volumeMounts:
- name: scratch-space
mountPath: /scratch
EOF
Примените манифест:
kubectl apply -f emptydir-pod.yaml
Ожидаемый вывод:
pod/scratch-worker created
Дождитесь готовности пода:
kubectl wait --for=condition=Ready pod/scratch-worker --timeout=120s
Ожидаемый вывод:
pod/scratch-worker condition met
Прочитайте файл из смонтированного тома emptyDir:
kubectl exec scratch-worker -c worker -- cat /scratch/status.txt
Ожидаемый вывод:
scratch-ready
Проверьте тип тома пода. Выражение jsonpath выведет имя тома и подтвердит, что это emptyDir.
kubectl get pod scratch-worker -o 'jsonpath={.spec.volumes[0].name}{" emptyDir\n"}'
Ожидаемый вывод:
scratch-space emptyDir
Запись данных в PersistentVolumeClaim
На этом этапе вы создадите PersistentVolumeClaim (PVC) и подключите его к поду-писателю.
PersistentVolumeClaim — это запрос приложения на предоставление хранилища. В этой лабораторной работе StorageClass standard динамически предоставляет хранилище для этого запроса. Ваш под монтирует этот ресурс в директорию /data и записывает туда файл.
Создайте файл notes-pvc.yaml:
cat > notes-pvc.yaml <<'EOF'
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: notes-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: standard
resources:
requests:
storage: 1Mi
EOF
Примените PVC:
kubectl apply -f notes-pvc.yaml
Ожидаемый вывод:
persistentvolumeclaim/notes-pvc created
Дождитесь, пока статус PVC станет Bound:
kubectl wait --for=jsonpath='{.status.phase}'=Bound pvc/notes-pvc --timeout=120s
Ожидаемый вывод:
persistentvolumeclaim/notes-pvc condition met
Создайте под-писатель, который монтирует этот PVC:
cat > pvc-writer-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: pvc-writer
labels:
app: pvc-writer
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: notes-storage
persistentVolumeClaim:
claimName: notes-pvc
containers:
- name: writer
image: busybox:1.36
command:
- /bin/sh
- -c
- 'echo persistent-note > /data/note.txt; sleep 3600'
volumeMounts:
- name: notes-storage
mountPath: /data
EOF
Примените манифест пода-писателя и дождитесь его готовности:
kubectl apply -f pvc-writer-pod.yaml
kubectl wait --for=condition=Ready pod/pvc-writer --timeout=120s
Ожидаемый вывод:
pod/pvc-writer created
pod/pvc-writer condition met
Прочитайте файл из смонтированного PVC:
kubectl exec pvc-writer -c writer -- cat /data/note.txt
Ожидаемый вывод:
persistent-note
Повторное использование PVC в новом поде
На этом этапе вы удалите под-писатель, создадите новый под-читатель, который монтирует тот же PVC, и убедитесь, что файл по-прежнему доступен.
В этом заключается практическая разница между временными данными пода и постоянным хранилищем. Под-писатель может быть удален, но PVC останется. Новый под может смонтировать тот же ресурс и прочитать данные.
Удалите под-писатель:
kubectl delete pod pvc-writer
Ожидаемый вывод:
pod "pvc-writer" deleted
Создайте под-читатель, который монтирует тот же PVC:
cat > pvc-reader-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: pvc-reader
labels:
app: pvc-reader
spec:
terminationGracePeriodSeconds: 0
volumes:
- name: notes-storage
persistentVolumeClaim:
claimName: notes-pvc
containers:
- name: reader
image: busybox:1.36
command:
- /bin/sh
- -c
- 'cat /data/note.txt; sleep 3600'
volumeMounts:
- name: notes-storage
mountPath: /data
EOF
Примените манифест пода-читателя и дождитесь его готовности:
kubectl apply -f pvc-reader-pod.yaml
kubectl wait --for=condition=Ready pod/pvc-reader --timeout=120s
Ожидаемый вывод:
pod/pvc-reader created
pod/pvc-reader condition met
Прочитайте файл из нового пода:
kubectl exec pvc-reader -c reader -- cat /data/note.txt
Ожидаемый вывод:
persistent-note
Проверьте состояние PVC. Он должен оставаться в статусе Bound, даже несмотря на то, что исходный под-писатель был удален.
kubectl get pvc notes-pvc
Ожидаемый вывод:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
notes-pvc Bound ... 1Mi RWO standard <unset> ...
Резюме
Вы использовали том emptyDir для временных данных пода, создали PVC для постоянного хранения, записали данные через один под, удалили этот под и прочитали те же данные из нового пода, который смонтировал тот же ресурс. Теперь вы знаете, когда использовать эфемерное хранилище для временных данных пода, а когда запрашивать постоянное хранилище для данных, которые должны сохраняться после замены пода.


