在单节点Kubernetes集群中,尝试操作PV和PVC
你好。
我是Class Act基础设施事业部的大塚。
上次,我学习了在Docker上创建卷以及将其挂载到容器的方法,并尝试了实际操作。下面是具体内容。
这次我想在Kubernetes上做类似于上面提到的事情。
我认为Kubernetes的优点在于可以在多节点上部署和管理Pod(容器),但是如果直接在多节点上操作可能会让人头脑混乱,所以我打算先在单节点的k8s集群上尝试一下,之后再逐步在多节点的k8s集群环境中进行操作。
环境
在Ubuntu 22.04上启动虚拟机。
正在安装microk8s并创建Kubernetes环境。
root@ansible-tower:~# kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ansible-tower Ready <none> 23h v1.26.4 192.168.2.35 <none> Ubuntu 22.04.2 LTS 5.15.0-71-generic containerd://1.6.15
用语 –
视频
持久卷(PV)是集群存储的一部分,由管理员或动态分配使用存储类来进行管理。它与节点一样是集群资源的一部分。PV是类似于卷的插件,但与使用PV的独立Pod具有不同的生命周期。
聚氯乙烯
持久卷索取(PVC)是由用户请求的存储资源。它类似于Pod。Pod消耗节点资源,而PVC消耗PV资源。Pod可以请求特定级别的CPU和内存资源。索取可以以特定的大小和访问模式(例如,ReadWriteOnce、ReadOnlyMany、ReadWriteMany)进行挂载。
我对此的理解是,在物理卷(PV)中创建一个大容量的存储空间,然后可以使用逻辑卷(PVC)来分割并利用它。我的理解如下:
验证:尝试使用spec.persistentVolumeReclaimPolicy设置为”Delete”部署和使用PV和PVC。
首先,我们将准备PV。
这次准备的yaml文件如下所示。
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-vol
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: my-vol-class
hostPath:
path: /tmp/k8s-vol
type: DirectoryOrCreate
我将简略地写下在yaml文件中所写的细节。
参考:Kubernetes: ReadWriteOnceとReadWriteOncePodの動作検証spec:persistentVolumeReclaimPolicy:DeletePVCが削除されるとPVも削除するような挙動にする。このほかにRetainなどもある。
参考:Kubernetes: ReadWriteOnceとReadWriteOncePodの動作検証spec.hostpath.path:/tmp/k8s-vol作成するPVをノードのどのディレクトリに作成するかを指定している。今回のyamlでは/tmp/k8s-vol配下に作ることになる。spec.hostpath.type:DirectoryOrCreatespec.hostpath.pathで指定したディレクトリが存在しない場合作成する
参考:KubernetesでHostPathを使う
我会部署它。
看起来已经完成了。
root@ansible-tower:~/yaml# kubectl create -f my-vol.yaml
persistentvolume/my-vol created
root@ansible-tower:~/yaml# kubectl get pv -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
my-vol 5Gi RWO Delete Available my-vol-class 6s Filesystem
对于PV和后续提到的PVC,可以像pod一样进行描述。
以下是其结果。您可以在这里确认您在yaml中的写法。
root@ansible-tower:~/yaml# kubectl describe pv my-vol
Name: my-vol
Labels: <none>
Annotations: <none>
Finalizers: [kubernetes.io/pv-protection]
StorageClass: my-vol-class
Status: Available
Claim:
Reclaim Policy: Delete
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 5Gi
Node Affinity: <none>
Message:
Source:
Type: HostPath (bare host directory volume)
Path: /tmp/k8s-vol
HostPathType: DirectoryOrCreate
Events: <none>
在这个时间点,/tmp目录下没有被创建的节点。
root@ansible-tower:~/yaml# ls /tmp/
snap-private-tmp systemd-private-e9093ba59c54473c8be00fd9efae24cd-systemd-resolved.service-8TljcD ubuntu-advantage
systemd-private-e9093ba59c54473c8be00fd9efae24cd-ModemManager.service-YQKnnw systemd-private-e9093ba59c54473c8be00fd9efae24cd-systemd-timesyncd.service-NfUEnV
systemd-private-e9093ba59c54473c8be00fd9efae24cd-systemd-logind.service-VAqu3p systemd-private-e9093ba59c54473c8be00fd9efae24cd-upower.service-oEMHBO
PVC将会被创建。
我们准备的yaml文件如下。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc01-my-vol
spec:
resources:
requests:
storage: 5Gi
accessModes:
- ReadWriteOnce
storageClassName: my-vol-class
根据yaml配置文件进行部署。
如果PVC的状态为Bound,则表示PV和PVC已经成功关联。
root@ansible-tower:~/yaml# kubectl create -f pvc01-my-vol.yaml
persistentvolumeclaim/pvc01-my-vol created
root@ansible-tower:~/yaml# kubectl get pv,pvc -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/my-vol 5Gi RWO Delete Bound default/pvc01-my-vol my-vol-class 13s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol Bound my-vol 5Gi RWO my-vol-class 46s Filesystem
我会查看PVC的描述以获得更多详细信息。
root@ansible-tower:~/yaml# kubectl describe pvc pvc01-my-vol
Name: pvc01-my-vol
Namespace: default
StorageClass: my-vol-class
Status: Bound
Volume: my-vol
Labels: <none>
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 5Gi
Access Modes: RWO
VolumeMode: Filesystem
Used By: <none>
创建一个名为PostgreSQL的Pod,并将PVC挂载到/var/lib/postgresql/data目录下。
准备以下的YAML文件。
apiVersion: v1
kind: Pod
metadata:
name: postgres01
spec:
containers:
- name: postgres01
image: postgres:latest
env:
- name: POSTGRES_PASSWORD
value: "postgres"
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: pvc01-my-vol
volumes:
- name: pvc01-my-vol
persistentVolumeClaim:
claimName: pvc01-my-vol
我要部署pod。
root@ansible-tower:~/yaml# kubectl create -f vol-postgresql01.yaml
pod/postgres01 created
root@ansible-tower:~/yaml# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
postgres01 1/1 Running 0 108s 10.1.108.9 ansible-tower <none> <none>
我会尝试查看Pod的详细信息,根据以下的输出,它似乎已经成功挂载了。
root@ansible-tower:~/yaml# kubectl describe pod postgres01
~中略~
Volumes:
pvc01-my-vol:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: pvc01-my-vol
ReadOnly: false
在此时创建了/tmp/k8s-vol。
以下是实际确认的日志。自动创建了名为k8s-vol的目录,其下可以确认到PostgreSQL的数据存在于/tmp目录中。
root@ansible-tower:/# cd /tmp
root@ansible-tower:/tmp# ls
k8s-vol systemd-private-7b30335e5c3847888ee14c9d4ae96fea-ModemManager.service-9JtOcV systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-resolved.service-y1Y1GA
snap-private-tmp systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-logind.service-f83oWV systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-timesyncd.service-Mr4GTU
root@ansible-tower:/tmp/k8s-vol# ls
base pg_commit_ts pg_hba.conf pg_logical pg_notify pg_serial pg_stat pg_subtrans pg_twophase pg_wal postgresql.auto.conf postmaster.opts
global pg_dynshmem pg_ident.conf pg_multixact pg_replslot pg_snapshots pg_stat_tmp pg_tblspc PG_VERSION pg_xact postgresql.conf postmaster.pid
我会在已部署的pod中进行确认。
/tmp/k8s-vol/的内容和之前一样。
root@ansible-tower:~# kubectl get pod
NAME READY STATUS RESTARTS AGE
postgres01 1/1 Running 0 7h13m
root@ansible-tower:~# kubectl exec -it postgres01 -- /bin/bash
root@postgres01:/# cd /var/lib/postgresql/data
root@postgres01:/var/lib/postgresql/data# ls
base pg_commit_ts pg_hba.conf pg_logical pg_notify pg_serial pg_stat pg_subtrans pg_twophase pg_wal postgresql.auto.conf postmaster.opts
global pg_dynshmem pg_ident.conf pg_multixact pg_replslot pg_snapshots pg_stat_tmp pg_tblspc PG_VERSION pg_xact postgresql.conf postmaster.pid
我在pod侧创建数据,并确认节点侧是否能够看到。在pod中创建一个名为text.txt的空文件。
root@postgres01:/var/lib/postgresql/data# touch test.txt
root@postgres01:/var/lib/postgresql/data# ls -ltr test.txt
-rw-r--r-- 1 root root 0 May 10 21:15 test.txt
我会在节点端进行确认。看起来没什么问题。
root@ansible-tower:~# cd /tmp/k8s-vol/
root@ansible-tower:/tmp/k8s-vol# ls -ltr test.txt
-rw-r--r-- 1 root root 0 May 10 21:15 test.txt
首先,我们将删除装有PVC的Pod,以确认能否再利用。
root@ansible-tower:~# kubectl delete pod postgres01
root@ansible-tower:~# kubectl get pod,pv,pvc -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/my-vol 5Gi RWO Delete Bound default/pvc01-my-vol my-vol-class 7h31m Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol Bound my-vol 5Gi RWO my-vol-class 7h31m Filesystem
root@ansible-tower:~# ls /tmp/k8s-vol/
base pg_commit_ts pg_hba.conf pg_logical pg_notify pg_serial pg_stat pg_subtrans pg_twophase pg_wal postgresql.auto.conf postmaster.opts test.txt
global pg_dynshmem pg_ident.conf pg_multixact pg_replslot pg_snapshots pg_stat_tmp pg_tblspc PG_VERSION pg_xact postgresql.conf postmaster.pid
使用相同的 ymal 重新部署 pod。
root@ansible-tower:~/yaml# kubectl get pod,pv,pvc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/postgres01 1/1 Running 0 21s 10.1.108.10 ansible-tower <none> <none>
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/my-vol 5Gi RWO Delete Bound default/pvc01-my-vol my-vol-class 7h33m Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol Bound my-vol 5Gi RWO my-vol-class 7h33m Filesystem
我会检查重新部署的pod中的/var/lib/postgresql/data文件夹,并确认是否存在text.txt。
从下面的日志中,我可以看出它是可以重新使用的。
root@ansible-tower:~/yaml# kubectl exec -it postgres01 -- /bin/bash
root@postgres01:/# cd /var/lib/postgresql/data/
root@postgres01:/var/lib/postgresql/data# ls
base pg_commit_ts pg_hba.conf pg_logical pg_notify pg_serial pg_stat pg_subtrans pg_twophase pg_wal postgresql.auto.conf postmaster.opts test.txt
global pg_dynshmem pg_ident.conf pg_multixact pg_replslot pg_snapshots pg_stat_tmp pg_tblspc PG_VERSION pg_xact postgresql.conf postmaster.pid
删除pod和PVC。由于在创建PV时指定了Delete操作,所以应当同时删除PVC时也会删除PV。
从get命令没有任何输出来看,可以确认PVC和PV已经被同时删除。
root@ansible-tower:~# kubectl delete pod postgres0
persistentvolumeclaim "pvc01-my-vol" deleted
root@ansible-tower:~# kubectl get pod,pv,pvc
No resources found
/tmp文件夹下的内容也被删除了。
root@ansible-tower:~# cd /tmp
root@ansible-tower:/tmp# ls
snap-private-tmp systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-resolved.service-y1Y1GA
systemd-private-7b30335e5c3847888ee14c9d4ae96fea-fwupd.service-Srke4w systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-timesyncd.service-Mr4GTU
systemd-private-7b30335e5c3847888ee14c9d4ae96fea-ModemManager.service-9JtOcV systemd-private-7b30335e5c3847888ee14c9d4ae96fea-upower.service-LLEENP
systemd-private-7b30335e5c3847888ee14c9d4ae96fea-systemd-logind.service-f83oWV
验证:尝试使用”保留”作为spec.persistentVolumeReclaimPolicy在PV和PVC的部署以及使用。
以下是PV的yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-vol-retain
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: my-vol-retain-class
hostPath:
path: /tmp/my-vol-retain
type: DirectoryOrCreate
进行部署
root@ansible-tower:~/yaml# kubectl create -f my-vol-retain.yaml
persistentvolume/my-vol-retain created
root@ansible-tower:~/yaml# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
my-vol-retain 5Gi RWO Retain Available my-vol-retain-class 6s
PVC的yaml如下所示
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc01-my-vol-retain
spec:
resources:
requests:
storage: 5Gi
accessModes:
- ReadWriteOnce
storageClassName: my-vol-retain-class
部署
root@ansible-tower:~/yaml# kubectl create -f pvc01-my-vol-retain.yaml
persistentvolumeclaim/pvc01-my-vol-retain created
root@ansible-tower:~/yaml# kubectl get pv,pvc -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/my-vol-retain 5Gi RWO Retain Bound default/pvc01-my-vol-retain my-vol-retain-class 68s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol-retain Bound my-vol-retain 5Gi RWO my-vol-retain-class 10s Filesystem
pod的yaml内容如下
apiVersion: v1
kind: Pod
metadata:
name: postgres01
spec:
containers:
- name: postgres01
image: postgres:latest
env:
- name: POSTGRES_PASSWORD
value: "postgres"
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: pvc01-my-vol-retain
volumes:
- name: pvc01-my-vol-retain
persistentVolumeClaim:
claimName: pvc01-my-vol-retain
部署中
root@ansible-tower:~/yaml# kubectl create -f vol-retain-postgresql01.yaml
pod/postgres01 created
root@ansible-tower:~/yaml# kubectl get pod,pv,pvc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/postgres01 1/1 Running 0 24s 10.1.108.11 ansible-tower <none> <none>
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/my-vol-retain 5Gi RWO Retain Bound default/pvc01-my-vol-retain my-vol-retain-class 5m12s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol-retain Bound my-vol-retain 5Gi RWO my-vol-retain-class 4m14s Filesystem
在pod中创建一个名为test.txt的文件,并将其放置在/var/lib/postgresql/data目录下。
root@ansible-tower:~/yaml# kubectl exec -it postgres01 -- /bin/bash
root@postgres01:/# cd /var/lib/postgresql/data/
root@postgres01:/var/lib/postgresql/data# touch test.txt
root@postgres01:/var/lib/postgresql/data# ls
base pg_commit_ts pg_hba.conf pg_logical pg_notify pg_serial pg_stat pg_subtrans pg_twophase pg_wal postgresql.auto.conf postmaster.opts test.txt
global pg_dynshmem pg_ident.conf pg_multixact pg_replslot pg_snapshots pg_stat_tmp pg_tblspc PG_VERSION pg_xact postgresql.conf postmaster.pid
确认主机上的/tmp/my-vol-retain目录中存在数据。
root@ansible-tower:~# cd /tmp/my-vol-retain/
root@ansible-tower:/tmp/my-vol-retain# ls
base pg_commit_ts pg_hba.conf pg_logical pg_notify pg_serial pg_stat pg_subtrans pg_twophase pg_wal postgresql.auto.conf postmaster.opts test.txt
global pg_dynshmem pg_ident.conf pg_multixact pg_replslot pg_snapshots pg_stat_tmp pg_tblspc PG_VERSION pg_xact postgresql.conf postmaster.pid
我们将确认即使删除了pod和PVC,它们也不会自动删除。
root@ansible-tower:~/yaml# kubectl get pod,pv,pvc -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/postgres01 1/1 Running 0 3m22s 10.1.108.11 ansible-tower <none> <none>
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/my-vol-retain 5Gi RWO Retain Bound default/pvc01-my-vol-retain my-vol-retain-class 8m10s Filesystem
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
persistentvolumeclaim/pvc01-my-vol-retain Bound my-vol-retain 5Gi RWO my-vol-retain-class 7m12s Filesystem
root@ansible-tower:~/yaml# kubectl delete pod postgres01
pod "postgres01" deleted
root@ansible-tower:~/yaml# kubectl delete pvc pvc01-my-vol-retain
可以确认还有剩余光伏电量,并且从主机上也确认还留有数据。
root@ansible-tower:~/yaml# kubectl get pod,pv,pvc -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
persistentvolume/my-vol-retain 5Gi RWO Retain Released default/pvc01-my-vol-retain my-vol-retain-class 25m Filesystem
root@ansible-tower:~/yaml# cd /tmp/my-vol-retain/
root@ansible-tower:/tmp/my-vol-retain# ls
base pg_commit_ts pg_hba.conf pg_logical pg_notify pg_serial pg_stat pg_subtrans pg_twophase pg_wal postgresql.auto.conf postmaster.opts test.txt
global pg_dynshmem pg_ident.conf pg_multixact pg_replslot pg_snapshots pg_stat_tmp pg_tblspc PG_VERSION pg_xact postgresql.conf postmaster.pid
要再利用这个可能需要花一点功夫呢。
1. 删除 PersistentVolume。删除 PV 后,与外部基础设施(如 AWS EBS、GCE PD、Azure Disk、Cinder 等)关联的存储组件仍然存在。
2. 手动清理与存储组件相关的数据。
3. 如果要手动删除相关存储组件或者希望重新使用相同的存储组件,则需创建新的 PersistentVolume 定义与其一起使用。