Storage
В данном практическом занятии рассмотрим работу с постоянным хранилищем посредством ресурсов PersistentVolume, PersistentVolumeClaim и StorageClass.
Persistent Volume
Создадим ресурс PersistentVolume
, который будет использовать файловую систему хоста, на котором он
будет расположен.
$ k apply -f - << EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-volume
spec:
storageClassName: manual
capacity:
storage: 100Mi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
EOF
В данном примере в параметрах указано:
storageClassName: manual
- имя StorageClass, указано явно для будущего связывания с pvccapacity.storage
- размер томаaccessModes
- режим подключения тома к подамhostPath.path
- путь на ноде, по которому будут храниться данные
После создания можно увидеть его состояние:
$ k get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-volume 100Mi RWO Retain Available manual 12s
Также из вывода видно, что reclaim policy задано как Retain
, означающая, что после удаления pv
данные в нем не будут удалены. А также status - Available
, означающий, что том готов к подключению.
Persistent Volume Claim
Теперь необходимо создать ресурс PersistentVolumeClaim
, который можно рассматривать как запрос на
том с определенными характеристиками(размер, параметры доступа, тип хранилища и т.д.), который можно
использовать непосредственно в поде.
$ k apply -f - << EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Mi
EOF
После создания можно увидеть состояние pvc:
$ k get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pv-claim Bound pv-volume 100Mi RWO manual 2s
Можно заметить интересную особенность: при создании pvc мы указали требуемый нам размер - 50Mi, при этом параметр capacity - 100Mi. Дело в том, что при создании pvc ищется любой подходящий по параметрам pv, в том числе большего размера. Если теперь посмотреть список pv, то мы увидим, что он теперь связан с созданным pvc:
$ k get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-volume 100Mi RWO Retain Bound default/pv-claim manual 21m
PVC in Pod
Теперь созданный pvc можно использовать в параметре spec.volumes
пода:
$ k apply -f - << EOF
apiVersion: v1
kind: Pod
metadata:
name: pv-pod
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: pv-storage
volumes:
- name: pv-storage
persistentVolumeClaim:
claimName: pv-claim
EOF
После создания можно создать файл в нашем pv выполнив команду внутри контейнера:
$ k exec -it pv-pod -- /bin/sh -c 'echo "hello" > /usr/share/nginx/html/index.html'
Далее можно убедиться, что файл корректно создан обратившись к nginx либо через port-forward
, либо с
использованием Service
и Ingress
. Также можно воспользоваться специальным сабресурсом /proxy
у пода,
сделав запрос через api kubernetes:
$ k get --raw /api/v1/namespaces/default/pods/pv-pod/proxy
hello
Создадим еще один под, который также будет использовать данный pvc:
$ k apply -f - << EOF
apiVersion: v1
kind: Pod
metadata:
name: pv-pod-new
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: pv-storage
volumes:
- name: pv-storage
persistentVolumeClaim:
claimName: pv-claim
EOF
После его запуска также сделаем запрос к nginx:
$ k get po
NAME READY STATUS RESTARTS AGE
pv-pod 1/1 Running 0 11m
pv-pod-new 1/1 Running 0 10s
$ k get --raw /api/v1/namespaces/default/pods/pv-pod-new/proxy
hello
Как видно, под запустился и также смонтировал данный том не смотря на режим ReadWriteOnce
. Это связано
с тем, что режим ReadWriteOnce
позволяет монтировать pv, если поды находятся на одной ноде. Если
требуется запретить данную возможность, то существует режим ReadWriteOncePod
.
Также можем удалить созданные нами ресурсы и убедиться, что данные остались на ноде согласно политике
Retain
:
$ k delete pvc --all
persistentvolumeclaim "pv-claim" deleted
$ k delete pv --all
persistentvolume "pv-volume" deleted
$ k delete po --all
pod "pv-pod" deleted
pod "pv-pod-new" deleted
$ docker exec -it kind-control-plane /bin/sh -c 'cat /mnt/data/index.html'
hello
Storage Class
В kind при создании кластера также устанавливается local-path-provisioner
, который позволяет
динамически нарезать pv на нодах. Для их использования создается StorageClass:
$ k get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 14d
Так как данный Storage Class используется по умолчанию, то можно создавать pvc без указания параметра
storageClassName
. Таким образом нам достаточно создать pvc и под, а pv создастся автоматически:
$ k apply -f - << EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-claim-sc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 150Mi
---
apiVersion: v1
kind: Pod
metadata:
name: pv-pod-sc
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: pv-storage
volumes:
- name: pv-storage
persistentVolumeClaim:
claimName: pv-claim-sc
EOF
$ k get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-828145c8-2e48-4046-b96f-d3cadbece5d8 150Mi RWO Delete Bound default/pv-claim-sc standard 28s
$ k get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
pv-claim-sc Bound pvc-828145c8-2e48-4046-b96f-d3cadbece5d8 150Mi RWO standard 36s
$ k get po
NAME READY STATUS RESTARTS AGE
pv-pod-sc 1/1 Running 0 38s