Як організувати доступ до файлової системи хосту для Persistent Volume в Kind
Кубернетіс вже перестає бути чимось таким, з чим працюють лише інженери платформи. Все більше і більше застосунків загортаються в контейнери та запускаються в контейнерних середовищах. Що робити, якщо з певних причин у вас немає доступу до хмарної платформи, але треба вести розробку застосунку, який працюватиме в хмарі? Ви можете скористатись Kind для локального розгортання Кубернетіс.
Kind — це інструмент для запуску локальних кластерів Kubernetes з використанням «вузлів» контейнерів Docker. В першу чергу kind був розроблений для тестування самого Kubernetes, але може бути використаний для локальної розробки або CI.
Для запуску Kind вам знадобиться docker, podman або інший рушій для роботи з контейнерами. Ви можете звернутись до Швидкого початку роботи з Kind на офіційному сайті.
Створення кластера
Отже, ми маємо встановлений Kind та середовище для роботи з контейнерами, kubectl
— інструмент командного рядка для виконання маніпуляцій з кластером.
Для створення локального кластера скористаємось командою kind create cluster
.
Ви завжди можете отримати потрібну довідку, скориставшись командою виду kind [command] --help
.
Ми створили свій локальний кластер з іменем kind-kind
. Це стандартне імʼя, яке використовує kind, якщо параметр -n назва
або --name назва
не вказано.
Крім використання ключів для kind
ми можемо використати маніфест для створення кластера з потрібними нам параметрами.
cat <<EOF > kind-config.yaml kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 name: my-super-cluster nodes: - role: control-plane - role: worker extraMounts: - hostPath: /path/to/local/data containerPath: /data # - role: worker # - role: worker # extraMounts: # - hostPath: /path/to/local/data/dump # containerPath: /data/dump # - hostPath: /path/to/local/data/diff # containerPath: /data/diff
☝️ тут ми можемо зазначити кількість потрібних вузлів, їх роль та, головне, в нашому випадку, — шлях у локальній файловій системі, який ми будемо монтувати у вузли нашого кластера та використовувати як систему зберігання для наших Постійних Томів (Persistent Volumes). Див Extra Mounts в документації Kind.
Застосуємо нашу конфігурацію для створення кластера
kind create cluster --config kind-config.yaml Creating cluster "kind" ... ✓ Ensuring node image (kindest/node:v1.32.2) 🖼 ✓ Preparing nodes 📦 ✓ Writing configuration 📜 ✓ Starting control-plane 🕹️ ✓ Installing CNI 🔌 ✓ Installing StorageClass 💾 Set kubectl context to "kind-my-super-cluster" You can now use your cluster with: kubectl cluster-info --context kind-my-super-cluster Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
Перевіримо, що файлову систему хосту змонтовано у вузол worker нашого кластера.
docker container inspect osm-cluster-worker \ | jq '[{"Name": .[0].Name, "BindMounts": ( .[] | .Mounts[] | select(.Type == "bind") )}]'
І бачимо, що все ОК, файлову систему змонтовано.
[ { "Name": "/my-super-cluster-worker", "BindMounts": { "Type": "bind", "Source": "/host_mnt/path/to/local/data", "Destination": "/data", "Mode": "", "RW": true, "Propagation": "rprivate" } }, { "Name": "/my-super-cluster-worker", "BindMounts": { "Type": "bind", "Source": "/lib/modules", "Destination": "/lib/modules", "Mode": "ro", "RW": false, "Propagation": "rprivate" } } ]
Створення PersistentVolume та PersistentVolumeClaim
Створимо маніфест для Постійного Тому:
apiVersion: v1 kind: PersistentVolume metadata: name: my-super-cluster-pv spec: capacity: storage: 100Gi accessModes: - ReadWriteOnce volumeMode: Filesystem hostPath: path: "/data" storageClassName: my-storageclass
А також створимо Заявку PersistentVolumeClaim, яку будемо використовувати для монтування Постійного Тому в робочі навантаження.
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-super-cluster-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 100Gi storageClassName: my-storageclass
Тепер найголовніше 🥁, потрібно створити StorageClass, який дозволить нам явно повʼязати Заявку PVC з Постійним Томом PV.
Примітка: зверніть увагу, що kind створює стандартний StorageClass під час створення кластера. Однак цей StorageClass не задовольняє наші вимоги, маючи
reclaimPolicy:Delete
.
kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 80m
Це означає, що вміст нашого Постійного Тому буде очищатись після його розмонтування з пода, а це не те, що нам треба.
Створимо наш StorageClass в кластері.
kubectl apply -f - <<EOF apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: my-storageclass provisioner: rancher.io/local-path parameters: nodePath: /data reclaimPolicy: Retain volumeBindingMode: WaitForFirstConsumer EOF storageclass.storage.k8s.io/my-storageclass created
Перевіримо наш StorageClass.
kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE my-storageclass rancher.io/local-path Retain WaitForFirstConsumer false 5m27s standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 91m
І зробимо його типовим, на всяк випадок:
kubectl patch storageclass my-storageclass -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
А StorageClass standard
навпаки зробимо звичайним.
kubectl patch storageclass standard -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"false"}}}'
Переглянемо поточні відомості про StorageClass:
kubectl get storageclass NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE my-storageclass (default) rancher.io/local-path Retain WaitForFirstConsumer false 12m standard rancher.io/local-path Delete WaitForFirstConsumer false 98m
Використання PersistentVolumeClaim в поді
Застосуємо маніфести PV та PVC в кластері.
kubectl apply -f pv.yaml -f pvc.yaml
Створимо под, який використовує Заявку на постійний том для зберігання даних.
kubectl apply -f - <<EOF apiVersion: v1 kind: Pod metadata: name: debug-pod spec: containers: - name: debug-container image: busybox:latest command: ["sh", "-c", "sleep 3600"] volumeMounts: - mountPath: "/data" name: my-super-cluster volumes: - name: my-super-cluster persistentVolumeClaim: claimName: my-super-cluster-pvc EOF
Перевіримо, що Заявка PVC має привʼязку до PV та використовується в нашому тестовому поді.
kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE my-super-cluster-pv 100Gi RWO Retain Bound default/my-super-cluster-pvc my-storageclass <unset> 9m20s kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE my-super-cluster-pvc Bound my-super-cluster-pv 100Gi RWO my-storageclass <unset> 8m48s
Зверніть увагу, що статус PV та PVC має значення Bound
, що означає, що Заявку було успішно звʼязано з Постійним Томом.
kubectl describe pod Name: debug-pod Namespace: default Priority: 0 Service Account: default Node: kind-control-plane/172.20.0.4 Start Time: Fri, 04 Apr 2025 18:17:09 +0300 Labels: <none> Annotations: <none> Status: Running IP: 10.244.0.5 IPs: IP: 10.244.0.5 Containers: debug-container: Container ID: containerd://d030a6edfc13c314853f22efc505990bbbb8e3954ed1c9887b9c7b3be575a0be Image: busybox:latest Image ID: docker.io/library/busybox@sha256:37f7b378a29ceb4c551b1b5582e27747b855bbfaa73fa11914fe0df028dc581f Port: <none> Host Port: <none> Command: sh -c sleep 3600 State: Running Started: Fri, 04 Apr 2025 18:17:13 +0300 Ready: True Restart Count: 0 Environment: <none> Mounts: /data from my-super-cluster (rw) /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-5wdzj (ro) Conditions: Type Status PodReadyToStartContainers True Initialized True Ready True ContainersReady True PodScheduled True Volumes: my-super-cluster: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: my-super-cluster-pvc ReadOnly: false kube-api-access-5wdzj: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 8m36s default-scheduler Successfully assigned default/debug-pod to kind-control-plane Normal Pulling 8m36s kubelet Pulling image "busybox:latest" Normal Pulled 8m32s kubelet Successfully pulled image "busybox:latest" in 3.395s (3.395s including waiting). Image size: 1855985 bytes. Normal Created 8m32s kubelet Created container: debug-container Normal Started 8m32s kubelet Started container debug-container
Наш под було успішно створено і він працює.
Отримаємо доступ до термінала в нашому поді та перевіримо, що том змонтований у нашій файловій системі і все працює належним чином.
kubectl exec -it debug-pod -- sh / # ls -l / | grep data drwxr-xr-x 2 root root 4096 Apr 4 15:17 data / # touch /data/somefile.txt / # ls -l /data total 0 -rw-r--r-- 1 root root 0 Apr 4 15:31 somefile.txt / # / # exit
Тепер перегляньте файлову систему хосту, змонтовану у вузол worker нашого кластера і ви побачите там тільки що створений файл somefile.txt
.
Підсумки
Ми створили Заявку на використання Постійного Тому в робочому навантажені, яка використовує Клас Зберігання (StorageClass) для звʼязування Заявки з Томом. Постійний том використовує систему зберігання наявну на вузлі нашого кластера. Система зберігання вузла кластера базується на файловій системі хосту, на якому розгорнуто наш кластер.
У такий спосіб ми можемо надійно зберігати та повторно використовувати дані, розміщені в Постійному Томі в робочих навантаження нашого кластера, які за своєю природою мають обмежений життєвий цикл. Окрім цього ми також можемо передавати в наші робочі навантаження попередньо створені дані з нашого хосту та використовувати їх в подах.
Очищення
Для очищення (вилучення) кластера скористайтесь наступною командою.
kind delete cluster --name kind-my-super-cluster Deleting cluster "kind-my-super-cluster" ...
Зачекайте, допоки Kind видалить кластер. За потреби видаліть створені файли у файловій системі хосту.
P.S.: Я також підтримую переклад документації Kubernetes і OpenTelemetry українською. Якщо хочете допомогти з перекладом та долучитися до проєкту — переходьте за посиланням. До речі, українська версія документацій Helm та Istio вже доступна на офіційних сайтах проєктів.
5 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів