配置 Pod 以使用持久卷进行存储

此页面向您展示如何配置 Pod 使用 PersistentVolumeClaim 进行存储。以下是该过程的总结

  1. 您作为集群管理员,创建由物理存储支持的 PersistentVolume。您不将该卷与任何 Pod 关联。

  2. 您现在担任开发人员/集群用户的角色,创建一个会自动绑定到合适的 PersistentVolume 的 PersistentVolumeClaim。

  3. 您创建一个 Pod,该 Pod 使用上述 PersistentVolumeClaim 进行存储。

开始之前

  • 您需要有一个只有一个节点的 Kubernetes 集群,并且必须配置 kubectl 命令行工具与您的集群通信。如果您还没有单节点集群,可以使用 Minikube 创建一个。

  • 熟悉持久卷中的内容。

在您的节点上创建一个 index.html 文件

打开一个 shell 连接到集群中的单个节点。如何打开 shell 取决于您如何设置集群。例如,如果您使用的是 Minikube,可以通过输入 minikube ssh 来打开连接到节点的 shell。

在节点的 shell 中,创建一个 /mnt/data 目录

# This assumes that your Node uses "sudo" to run commands
# as the superuser
sudo mkdir /mnt/data

/mnt/data 目录中,创建一个 index.html 文件

# This again assumes that your Node uses "sudo" to run commands
# as the superuser
sudo sh -c "echo 'Hello from Kubernetes storage' > /mnt/data/index.html"

测试 index.html 文件是否存在

cat /mnt/data/index.html

输出应为

Hello from Kubernetes storage

您现在可以关闭与节点的 shell 连接。

创建一个 PersistentVolume

在本练习中,您将创建一个 _hostPath_ PersistentVolume。Kubernetes 支持在单节点集群上进行开发和测试使用 hostPath。hostPath PersistentVolume 使用节点上的文件或目录来模拟网络连接的存储。

在生产集群中,您不会使用 hostPath。相反,集群管理员将配置网络资源,例如 Google Compute Engine 持久磁盘、NFS 共享或 Amazon Elastic Block Store 卷。集群管理员还可以使用 StorageClasses 来设置动态配置

以下是 hostPath PersistentVolume 的配置文件

apiVersion: v1
kind: PersistentVolume
metadata:
  name: task-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

配置文件指定该卷位于集群节点的 /mnt/data。该配置还指定了 10 吉比字节的大小和 ReadWriteOnce 的访问模式,这意味着该卷可以由单个节点以读写方式挂载。它为 PersistentVolume 定义了StorageClass 名称 manual,它将用于将 PersistentVolumeClaim 请求绑定到此 PersistentVolume。

创建 PersistentVolume

kubectl apply -f https://k8s.io/examples/pods/storage/pv-volume.yaml

查看有关 PersistentVolume 的信息

kubectl get pv task-pv-volume

输出显示 PersistentVolume 的 STATUSAvailable。这意味着它尚未绑定到 PersistentVolumeClaim。

NAME             CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE
task-pv-volume   10Gi       RWO           Retain          Available             manual                   4s

创建 PersistentVolumeClaim

下一步是创建一个 PersistentVolumeClaim。Pod 使用 PersistentVolumeClaim 来请求物理存储。在本练习中,您将创建一个 PersistentVolumeClaim,该请求至少需要 3 吉比字节的卷,并且每次最多为一个节点提供读写访问。

以下是 PersistentVolumeClaim 的配置文件

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: task-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

创建 PersistentVolumeClaim

kubectl apply -f https://k8s.io/examples/pods/storage/pv-claim.yaml

创建 PersistentVolumeClaim 后,Kubernetes 控制平面会查找满足该声明要求的 PersistentVolume。如果控制平面找到具有相同 StorageClass 的合适 PersistentVolume,则会将该声明绑定到该卷。

再次查看 PersistentVolume

kubectl get pv task-pv-volume

现在输出显示 STATUSBound

NAME             CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM                   STORAGECLASS   REASON    AGE
task-pv-volume   10Gi       RWO           Retain          Bound     default/task-pv-claim   manual                   2m

查看 PersistentVolumeClaim

kubectl get pvc task-pv-claim

输出显示 PersistentVolumeClaim 已绑定到您的 PersistentVolume task-pv-volume

NAME            STATUS    VOLUME           CAPACITY   ACCESSMODES   STORAGECLASS   AGE
task-pv-claim   Bound     task-pv-volume   10Gi       RWO           manual         30s

创建一个 Pod

下一步是创建一个使用您的 PersistentVolumeClaim 作为卷的 Pod。

以下是 Pod 的配置文件

apiVersion: v1
kind: Pod
metadata:
  name: task-pv-pod
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
        claimName: task-pv-claim
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage


请注意,Pod 的配置文件指定了一个 PersistentVolumeClaim,但未指定 PersistentVolume。从 Pod 的角度来看,该声明是一个卷。

创建 Pod

kubectl apply -f https://k8s.io/examples/pods/storage/pv-pod.yaml

验证 Pod 中的容器是否正在运行;

kubectl get pod task-pv-pod

获取连接到 Pod 中正在运行的容器的 shell

kubectl exec -it task-pv-pod -- /bin/bash

在您的 shell 中,验证 nginx 是否正在从 hostPath 卷提供 index.html 文件

# Be sure to run these 3 commands inside the root shell that comes from
# running "kubectl exec" in the previous step
apt update
apt install curl
curl https://127.0.0.1/

输出显示您写入 hostPath 卷上的 index.html 文件的文本

Hello from Kubernetes storage

如果您看到该消息,则说明您已成功配置 Pod 以使用 PersistentVolumeClaim 中的存储。

清理

删除 Pod、PersistentVolumeClaim 和 PersistentVolume

kubectl delete pod task-pv-pod
kubectl delete pvc task-pv-claim
kubectl delete pv task-pv-volume

如果您还没有打开与集群中节点的 shell 连接,请以您之前的方式打开一个新的 shell。

在您的节点的 shell 中,删除您创建的文件和目录

# This assumes that your Node uses "sudo" to run commands
# as the superuser
sudo rm /mnt/data/index.html
sudo rmdir /mnt/data

您现在可以关闭与节点的 shell 连接。

在两个地方挂载相同的持久卷


apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  containers:
    - name: test
      image: nginx
      volumeMounts:
        # a mount for site-data
        - name: config
          mountPath: /usr/share/nginx/html
          subPath: html
        # another mount for nginx config
        - name: config
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
  volumes:
    - name: config
      persistentVolumeClaim:
        claimName: test-nfs-claim

您可以在 nginx 容器上执行 2 次卷挂载

  • 用于静态网站的 /usr/share/nginx/html
  • 用于默认配置的 /etc/nginx/nginx.conf

访问控制

使用组 ID (GID) 配置的存储仅允许使用相同 GID 的 Pod 写入。不匹配或缺少 GID 会导致权限被拒绝错误。为了减少与用户协调的需要,管理员可以使用 GID 注释 PersistentVolume。然后,该 GID 会自动添加到使用该 PersistentVolume 的任何 Pod。

如下使用 pv.beta.kubernetes.io/gid 注释

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
  annotations:
    pv.beta.kubernetes.io/gid: "1234"

当 Pod 使用带有 GID 注释的 PersistentVolume 时,带注释的 GID 将以与 Pod 的安全上下文中指定的 GID 相同的方式应用于 Pod 中的所有容器。每个 GID,无论是源自 PersistentVolume 注释还是 Pod 的规范,都将应用于每个容器中运行的第一个进程。

下一步

参考

上次修改时间:太平洋标准时间 2023 年 10 月 10 日 早上 7:55:将 ReadWriteOncePod 升级为 GA (c07ce392e4)