如何使用已有磁盘作为GKE集群的K8s Persistent Volume
2021 年 12 月 17 日更新。 管理用于实现有状态集解决方案的存储是与管理计算实例不同的问题。 🎿 0a。引擎盖下是什么 “only one lost ski”没有表情符号,所以作者将在文章的这个_theoretical_部分使用一个通用图标。 ☃️ 在 Kubernetes 术语中,PersistentVolume子系统为用户和管理员提供了一个 API,它从如何使用存储中提取了存储如何
2021 年 12 月 17 日更新。
管理用于实现有状态集解决方案的存储是与管理计算实例不同的问题。
🎿 0a。引擎盖下是什么
“only one lost ski”没有表情符号,所以作者将在文章的这个_theoretical_部分使用一个通用图标。 ☃️
在 Kubernetes 术语中,PersistentVolume
子系统为用户和管理员提供了一个 API,它从如何使用存储中提取了存储如何提供的详细信息。为此,K8s 团队引入了两个 API 资源:PersistentVolume
和PersistentVolumeClaim
。
PersistentVolume
(PV) 是集群中的一块存储,由管理员配置或使用Storage Classes动态配置。它是集群中的资源,就像节点是集群资源一样。 PV 是与 Volumes 类似的卷插件,但其生命周期独立于使用 PV 的任何单个 pod。此 API 对象捕获存储实现的详细信息,无论是 NFS、iSCSI 还是特定于云提供商的存储系统。从 K8s 版本 1.11bPersistentVolume
s 甚至可以将配置为可扩展。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--Jtu-XBrd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev -to-uploads.s3.amazonaws.com/uploads/articles/fu8i88mxc22sy6kbikhn.png)
PersistentVolumeClaim
(PVC) 是用户的存储请求。它类似于 pod。 Pod 消耗节点资源,PVC 消耗 PV 资源。
让我们看看 3(三)种方法来使 PV + PVC 对彼此牢固地绑定在一起。
🎿 I. 卷名:是的,我们再次需要对 GKE 进行 hack
而最简单的大约是volumeName
!
有些情况 当您的 GKE 环境中已经有一个永久磁盘(比如命名为pd-name
),并且,让我们想象一下,显然您想严格使用这个磁盘并且不想创建一个新磁盘。
下面的清单文件描述了您的集群可以使用的相应PersistentVolume
和PersistentVolumeClaim
。
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-demo
spec:
storageClassName: ""
capacity:
storage: 50G
accessModes:
- ReadWriteOnce
gcePersistentDisk:
pdName: pd-name
fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-claim-demo
spec:
storageClassName: ""
volumeName: pv-demo
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50G
进入全屏模式 退出全屏模式
⚠️ 注意:必须将""
指定为storageClassName
,这样就不会使用默认存储类。
现在您可以使用上述的kubectl apply -f existing-pd.yaml
命令来创建PersistentVolume
和PersistentVolumeClaim
。
Pod 通过将声明用作卷来访问存储。 Claims 必须与使用该声明的 pod 存在于同一命名空间中。 集群在 pod 的命名空间中找到该声明并使用它来获取支持该声明的PersistentVolume
。然后将卷挂载到主机和 Pod 中。
在集群中存在PersistentVolume
和PersistentVolumeClaim
之后,您可以通过指定容器的volumeMounts.mountPath
和volumeMounts.name
的值来授予 Pod 的容器对卷的访问权限,如下例所示:
kind: Pod
apiVersion: v1
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: pv-claim-demo
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
进入全屏模式 退出全屏模式
这样,当您将此清单应用到集群时,就会创建 Pod,并且task-pv-container
容器可以访问其/usr/share/nginx/html/
目录中的卷。
🎿 0b。手续很重要!我们必须知道我们想做什么
在 GKE 中,要让容器访问您预先存在的永久性磁盘,您需要来执行以下:
-
将现有永久磁盘配置为
PersistentVolume
。 -
将
PersistentVolume
绑定到PersistentVolumeClaim
。 -
让 Pod 中的容器访问
PersistentVolume
。
您可能已经猜到了,有几种方法可以将PersistentVolumeClaim
绑定到特定的PersistentVolume
。例如,以下 YAML 清单创建新的PersistentVolume
和PersistentVolumeClaim
,然后使用claimRef
将声明绑定到卷(见下文),这确保了PersistentVolume
只能绑定到PersistentVolumeClaim
。
☑️ 声明将无限期保持不受约束_如果不存在匹配卷_。当匹配的数量可用时,索赔将受到约束。例如,配置有许多 50Gi PV 的集群不会匹配请求 100Gi 的 PVC。 PVC 可以在 100Gi PV 添加到集群时进行绑定。
☑️ 如果您确切知道希望PersistentVolumeClaim
绑定到哪个PersistentVolume
,则可以使用volumeName
字段在 PVC 中指定 PV。此方法_skips_正常的匹配和绑定过程。 PVC 将只能绑定到与volumeName
中指定的同名的 PV。如果存在具有volumeName
且为Available
的 PV,则 PV 和 PVC 将被绑定_无论 PV 是否满足 PVC 的标签选择器,访问模式和资源请求。
要将PersistentVolume
绑定到PersistentVolumeClaim
,两个资源的storageClassName
以及容量accessModes
和volumeMode
必须匹配。
⚠️ 再次请注意,storageClassName
可以省略,但必须指定""
以防止 Kubernetes 使用默认的StorageClass
。
storageClassName
不需要引用现有的 StorageClass 对象。如果您只需要将声明绑定到卷,则可以使用任何您想要的名称。但是,如果您需要 StorageClass 配置的额外功能,例如调整卷大小,则storageClassName
必须引用现有的 StorageClass object。
🎿 二。轮盘赌还是扑克?魔术声明参考
重要的是要了解应用程序开发人员可以为 Pod 和PersistentVolumeClaim
对象创建清单,而无需了解应用程序将在其上运行的基础架构的任何信息。同样,集群管理员可以预先配置一组不同大小的存储卷,而无需对将使用它们的应用程序了解太多。您可能会在下面看到有关此过程内部结构的一些示意图。
Kubernetes可以操作不同的网络文件系统,当然不仅仅是 NFS。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--coVvTTym--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https:// dev-to-uploads.s3.amazonaws.com/uploads/articles/z1oc30m5dgye12o1e4ix.png)
您可能还希望您的集群管理员_“保留”卷_仅用于您的声明,以便其他人的声明可以在您的声明之前绑定到它。在这种情况下,管理员可以使用claimRef
字段指定 PV 中的 PVC。
apiVersion: "v1"
kind: "PersistentVolumeClaim"
metadata:
name: "claim1"
spec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: "1Gi"
volumeName: "pv0001"
进入全屏模式 退出全屏模式
PV 只能绑定到claimRef
中指定的具有相同名称和命名空间的 PVC。PVC 的访问模式和资源请求仍然必须满足才能绑定 PV 和 PVC,尽管标签选择器被忽略.具有claimRef
示例的持久卷对象定义如下所示:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0001
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
nfs:
path: /tmp
server: 172.17.0.2
persistentVolumeReclaimPolicy: Recycle
claimRef:
name: claim1
namespace: default
进入全屏模式 退出全屏模式
在你的 PVC 中指定volumeName
不会阻止不同的 PVC 在你之前绑定到指定的 PV。在 PV 为Available
之前,您的索赔将保持为Pending
。
☑️ 应该记住,在 PV 中指定claimRef
不会阻止_指定的 PVC 被绑定到不同的 PV! PVC 可以按照正常的绑定过程自由选择另一个 PV 进行绑定。因此,为避免_这些情况并_确保_您的声明被绑定_您想要的卷,您必须_确保_指定_volumeName
和claimRef
。
您可以通过检查Bound
PV 和 PVC 对的pv.kubernetes.io/bound-by-controller:
注释来判断您的volumeName
和/或claimRef
设置影响了匹配和绑定过程。您自己设置volumeName
和/或claimRef
的 PV 和 PVC 将没有此类注释,但普通 PV 和 PVC 会将其设置为“yes
”。有关这种情况,请参阅 GitLab 的文章。
当 PV 将其claimRef
设置为某个 PVC 名称和命名空间,并根据 Retain 或 Recycle 回收策略进行回收时,即使 PVC 或整个命名空间不再存在,它的claimRef
仍将设置为相同的 PVC 名称和命名空间。
⚠️ 设置claimRef
s 的能力是所述用例的临时解决方法。限制谁可以声明某个卷的长期解决方案正在开发中。集群管理员应该首先考虑配置选择器标签卷绑定,然后再代表用户设置claimRef
s。
🎿 三。选择器和标签,或者等等,我都提前写好了!
因此,有一种更优雅的方法可以通过selector
和label
属性将持久卷声明 (PVC) 绑定到持久卷 (PV)。通过实施选择器和标签,普通用户可以通过集群管理员定义的标识符来定位预置存储。
为什么需要它?在静态配置存储的情况下,寻求持久存储的开发人员需要知道 PV 的一些识别属性才能部署和绑定 PVC。这产生了几个有问题的情况。普通用户可能必须联系集群管理员来部署 PVC 或提供 PV 值。单独的 PV 属性_不传达存储卷的预期用途,也不提供可以对卷进行分组的方法_。
选择器和标签属性可用于_从用户那里抽象出 PV 详细信息_,同时为集群管理员提供一种通过描述性和可定制标签识别卷的方法。通过 selector-label 绑定方法,用户_只需要知道管理员定义了哪些标签。让我们看一下带标签的持久卷示例:
apiVersion: v1
kind: PersistentVolume
metadata:
name: gluster-volume
labels:
storage-tier: gold
aws-availability-zone: us-east-1
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteMany
glusterfs:
endpoints: glusterfs-cluster
path: myVol1
readOnly: false
persistentVolumeReclaimPolicy: Retain
进入全屏模式 退出全屏模式
使用 labels 来识别卷之间共享的公共属性或特征。在本例中,我们将Gluster卷定义为具有名为storage-tier
的自定义属性(键),并分配了值gold
。索赔将能够选择具有storage-tier=gold
的 PV 来匹配此 PV。
作为下一步,我们需要编写一个声明,一个带有选择器的持久卷声明。带有 selector 节的声明(参见下面的示例)尝试匹配现有的、未声明的和非预绑定的 PV。 PVC 选择器的存在_忽略_一个 PV 的_容量。但是,matching 标准中仍然_考虑了accessModes
。
⚠️ 重要的是要注意声明必须匹配其选择器节中包含的所有键值对。如果没有 PV 与声明匹配,则 PVC 将保持未绑定 (Pending
)。随后可以创建 PV,并且声明将自动_检查标签匹配_。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gluster-claim
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
selector:
matchLabels:
storage-tier: gold
aws-availability-zone: us-east-1
进入全屏模式 退出全屏模式
🎿 四。如果我们不想产生无用的实体怎么办?
现实生活中常常有惊喜。如果您无法从使用 PersistentVolume 的 Pod 中恢复数据,或者您正在寻找安全删除 Pod 而又不影响存储在 PV 中的存储的方法,该怎么办?
[](https://res.cloudinary.com/practicaldev/image/fetch/s--bOeEXV7H--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev -to-uploads.s3.amazonaws.com/uploads/articles/42ihjq5oe6y19k0qkkxg.png)
⚠️ 确保 PersistentVolumeReclaimPolicy
设置为到Retain
。对于动态配置的 PersistentVolume,默认回收策略是Delete
。这意味着当用户删除相应的 PersistentVolumeClaim 时,会自动删除动态配置的卷。这种自动行为_如果卷包含宝贵的数据_可能是不合适的。
如果ReclaimPolicy
当前设置为Delete
,这是 GKE 中用于 pod 的常见逻辑(查看 YAML 中的spec.persistentVolumeReclaimPolicy: Delete
),您可以通过发出命令来修补 PV:
kubectl patch pv <your-pv-name> -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'
进入全屏模式 退出全屏模式
接下来,继续删除正在使用该 PV 的资源。删除 PVC/Pod 保留后,PV 的STATUS
将变为Released
。
在 Released 状态下,编辑 PV 并删除spec.claimRef
块:
apiVersion: v1
kind: PersistentVolume
...
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 20Gi
claimRef:
...
进入全屏模式 退出全屏模式
删除spec.claimRef
块后,PersistentVolume 将可用。您将能够继续重新添加涉及我们上面讨论的 PV 的应用程序。
如何检查我们所做的一切
kubectl get pv
和kubectl get pvc
命令可用于查看为应用程序定义的PersistentVolume
和PersistentVolumeClaim
。如果STATUS
是Bound
,则应用程序_do have_访问必要的存储。kubectl describe pv
命令可用于查看有关应用程序使用的持久卷的详细信息。
kubectl describe pv
命令用于查看应用程序使用的 Persistent Volume 的详细信息。一个示例(感谢IBM)如下所示:
# kubectl describe pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
powerai-vision-data 40Gi RWX Retain Bound default/powerai-vision-data-pvc 48d
[root@dlf01 ~]# /opt/powerai-vision/bin/kubectl.sh describe pv
Name: powerai-vision-data
Labels: assign-to=powerai-vision-data
type=local
Annotations: pv.kubernetes.io/bound-by-controller=yes
StorageClass:
Status: Bound
Claim: default/powerai-vision-data-pvc
Reclaim Policy: Retain
Access Modes: RWX
Capacity: 40Gi
Message:
Source:
Type: HostPath (bare host directory volume)
Path: /opt/powerai-vision/volume/
Events: <none>
进入全屏模式 退出全屏模式
kubectl describe pvc
命令用于查看有关应用程序的 Persistent Volume Claim 的详细信息。
# kubectl describe pvc
Name: powerai-vision-data-pvc
Namespace: default
StorageClass:
Status: Bound
Volume: powerai-vision-data
Labels: app=powerai-vision
chart=ibm-powerai-vision-prod-1.1.0
heritage=Tiller
release=vision
Annotations: pv.kubernetes.io/bind-completed=yes
pv.kubernetes.io/bound-by-controller=yes
Capacity: 40Gi
Access Modes: RWX
Events: <none>
进入全屏模式 退出全屏模式
上述输出分别显示了有关应用程序使用的持久卷声明的更多详细信息。Volume
部分引用底层 Persistent Volume,如果已成功分配给应用程序,则STATUS
应该是Bound
。事件部分将显示持久卷声明是否存在问题。
此外,作者对 Utku Özdemir 的pv-migrate
感到非常兴奋,这是一个 CLI 工具/kubectl
插件,可以轻松地将一个 KubernetesPersistentVolume[Claim]
的内容迁移到另一个。
可以在此处找到(感谢 DevOpsCube 团队)具有持久卷的 GKE Pod 的 YAML 示例。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--_mKk2VTs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev -to-uploads.s3.amazonaws.com/uploads/articles/z9enban60vm0rz0b3gao.jpeg)
来源:RedHat、loft.sh、K8s 文档、GitLab、GitHub、Letsdoclod.com,作者 Erick Gubi
📖 Marko Lukša 的“Kubernetes In Action”,ISBN9781617293726
更多推荐
所有评论(0)