【问题标题】:How to pre-populate a ReadOnlyMany Persistent Volume如何预填充 ReadOnlyMany 持久卷
【发布时间】:2020-01-05 07:45:33
【问题描述】:

我正在尝试在 GKE 中创建一个使用多个副本的部署。我有一些我希望在每个 pod 中都可用的静态数据。此数据不会更新,无需写入。

我决定使用带有对应 PVC 和 ReadOnlyMany 存储类的 PV。问题是,我不知道如何将我的数据实际传输到卷 - 因为它是只读的。我尝试使用

gcloud compute scp /local/path instance:/remote/path

当然,我得到一个权限错误。然后我尝试通过控制台创建一个新的 PV。我将它附加到一个虚拟机

gcloud compute instances attach disk

安装并格式化磁盘,传输我的数据,卸载磁盘,将其与 VM 分离,最后在the documentation 之后创建了一个 PVC。我将存储类更改为 ReadOnlyMany,唯一的区别。

但是,当我尝试将我的部署扩展到多个副本时,我收到一条错误消息,指出磁盘已附加到另一个节点。

那么,我如何创建要在 ReadOnlyMany 中使用的卷并用数据填充磁盘?或者有没有更好的方法,因为不需要写?

提前致谢

【问题讨论】:

    标签: kubernetes google-kubernetes-engine persistent-storage


    【解决方案1】:

    你好尼古拉斯,

    您采用的方法在很大程度上取决于您的用例。

    当您将分布式文件系统用作 CEPH、GlusterFS 或 GCP Cloud Filestore 或将远程文件系统用作 NFS 时,您所采用的方法非常常见。

    当使用分布式FS或远程FS时,方法是:

    1.- 创建一个将 AccessMode 设置为 RWO 并将 Reclaim Policy 设置为 RETAIN 的 PV。

    2.- 创建 PVC

    3.- 将 PVC 连接到 POD

    4.- 通过 POD 将数据传输到卷。

    5.- 删除 pod、pvc 和 pv。

    6.- 创建一个新 PV,AccessMode 设置为 ROX,Reclaim Policy 设置为 RETAIN,以便为每个要附加数据的部署或 POD。这不适用于 POD 副本数大于 1 的情况,因为 pod 将附加相同的 PV。

    7.- 为每个 PV 创建一个 PVC。 PV 和 PVC 的关系是 1 : 1 8.- 将 PVC 附加到您要使用的每个 POD 或部署。

    您的问题似乎是您试图将同一个 PV 附加到多个 PVC,这是不允许的,关系 PVC PV 是一对一的。

    关于您的其他问题是否有更好的方法,这在很大程度上取决于您的用例。 Google Cloud Platform 提供了许多存储选项 [1]。例如,如果您使用对象,则可以使用 Google Cloud Storage [2] 而不是 Persistent Disks。

    [1]https://cloud.google.com/kubernetes-engine/docs/concepts/storage-overview

    [2]https://cloud.google.com/filestore/docs/accessing-fileshares

    【讨论】:

      【解决方案2】:

      为我工作。在 Pod 模板中使用持久卷声明时是否指定了 readOnly: true

      volumes:
      - name: my-volume
        persistentVolumeClaim:
          claimName: my-readonly-pvc
          readOnly: true
      

      在此处查看详细信息 https://cloud.google.com/kubernetes-engine/docs/how-to/persistent-volumes/readonlymany-disks

      【讨论】:

        【解决方案3】:

        我们可以稍微简化一下整个过程。在 GKE 上,您实际上不需要基于 GCE Persistent Disk 手动创建PV。您只需定义正确的PVC,如下所示:

        kind: PersistentVolumeClaim
        apiVersion: v1
        metadata:
          name: webserver-content-claim
        spec:
          accessModes: [ReadOnlyMany]
          resources:
            requests:
              storage: 5Gi
        

        请记住,您不能在PVC 中定义访问模式,以设置任何特定的约束。您基本上所做的只是请求支持此特定访问模式的存储。请注意,它采用列表的形式,这意味着您可以提供许多您希望PV 支持的不同访问模式。我在this 回答中更详细地解释了它。但这里的重点是通过在PVC 定义中设置ReadOnlyMany 访问模式,您只请求支持这种访问类型的卷,但这并不意味着它不支持其他模式。强>

        如果您没有按照@Ievgen Goichuk 在他的回答中建议的那样在Pod 模板的volumes 部分指定readOnly: true,则默认情况下它以rw 模式安装。由于 GCE Persistent Disk 不支持ReadWriteMany 访问模式,因此该卷不能被其他Pods 挂载,一旦它已经以rw 模式挂载一个,则调度到不同的nodes Pod,安排在一个特定的node。通过这个Podrw 模式挂载它是可能的,因为GCE Persistent Disk 还支持ReadWriteOnce 访问模式,根据the official docsmenas “卷可以挂载为单节点读写”。这就是为什么在其他节点上调度的Pods 无法挂载它的原因。

        但让我们继续讨论实际的解决方案。

        创建上述PVC 后,您会看到相应的PV 也已创建(kubectl get pv),其STATUSBound

        现在我们只需要在开始以ReadOnlyMany 访问模式使用它之前以某种方式预先填充它。我将分享最适合我的方法。

        如果您已将数据上传到您的一个 Compute Engine 实例,形成了工作程序节点的 node-pool,则可以跳过下一步。

        我假设您已在本地计算机上安装了 gcloud

        gcloud compute scp /local/path instance:/remote/path
        

        是实现这一目标的正确方法。 @Nikolaos Paschos,如果您收到 permission denied 错误,这可能意味着您所反对的 /remote/path 是一些受限目录,您作为非 root 用户无权访问。如果您尝试从本地文件系统复制某些内容,您将看到此错误,例如到远程机器上的/etc 目录。最安全的方法是将文件复制到您有权访问的主目录:

        gcloud compute scp --recurse /home/<username>/data/* <instance-name>:~ --zone <zone-name>
        

        如果您想从源目录复制所有文件和目录及其内容,请使用--recurse 选项。

        一旦我们的数据上传到我们的工作节点之一,我们需要将其复制到我们新创建的PersistentVolume。它可以通过几种不同的方式完成。

        我决定使用一个临时的Podlocal 音量。

        为了使我们的数据(已存在于 GKE 工作节点之一上)也可用于我们的临时Pod,让我们创建以下内容:

        storage-class-local.yaml:

        apiVersion: storage.k8s.io/v1
        kind: StorageClass
        metadata:
          name: local-storage
        provisioner: kubernetes.io/no-provisioner
        volumeBindingMode: WaitForFirstConsumer
        

        pv-local.yaml:

        apiVersion: v1
        kind: PersistentVolume
        metadata:
          name: local-pv
        spec:
          capacity:
            storage: 10Gi
          volumeMode: Filesystem
          accessModes:
          - ReadWriteOnce
          persistentVolumeReclaimPolicy: Delete
          storageClassName: local-storage
          local:
            path: /home/<username>
          nodeAffinity:
            required:
              nodeSelectorTerms:
              - matchExpressions:
                - key: kubernetes.io/hostname
                  operator: In
                  values:
                  - <gke-node-name>
        

        pvc-local.yaml:

        apiVersion: v1
        kind: PersistentVolumeClaim
        metadata:
          name: myclaim
        spec:
          accessModes:
            - ReadWriteOnce
          volumeMode: Filesystem
          resources:
            requests:
              storage: 10Gi
          storageClassName: local-storage
        

        在下一步中,让我们创建我们的临时Pod,这将使我们能够将我们的数据从node复制到Pod作为本地卷,到PV基于GCE永久磁盘。它的定义可能如下:

        apiVersion: v1
        kind: Pod
        metadata:
          name: mypod
        spec:
          containers:
            - name: myfrontend
              image: nginx
              volumeMounts:
              - mountPath: "/mnt/source"
                name: local-volume
              - mountPath: "/mnt/destination"
                name: gce-pd-volume
          volumes:
            - name: local-volume
              persistentVolumeClaim:
                claimName: myclaim
            - name: gce-pd-volume
              persistentVolumeClaim:
                claimName: webserver-content-claim
        

        Pod 启动并运行时,我们可以通过以下方式附加到它:

        kubectl exec -ti mypod -- /bin/bash
        

        然后复制我们的文件:

        cp -a /mnt/source/* /mnt/destination/
        

        现在我们可以删除我们的临时 pod、本地 pv 和 pvc。我们的PersistentVolume 已经预先填充了数据,可以在ro 模式下挂载。

        为了测试它,我们可以运行以下Deployment

        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: nginx-deployment
          labels:
            app: nginx
        spec:
          replicas: 3
          selector:
            matchLabels:
              app: nginx
          template:
            metadata:
              labels:
                app: nginx
            spec:
              containers:
              - name: nginx
                image: nginx:1.14.2
                ports:
                - containerPort: 80
                volumeMounts:
                - mountPath: "/usr/share/nginx/html"
                  name: webserver-content
              volumes:
              - name: webserver-content
                persistentVolumeClaim:
                  claimName: webserver-content-claim
                  readOnly: true ### don't forget about setting this option
        

        【讨论】:

        • 有趣的是,我不知道`您只请求支持这种访问类型的卷,但这并不意味着它不支持其他模式。`。话虽如此,你的回答是有道理的。不过,这似乎很奇怪,从某种意义上说,使用这样一个有用的功能相当耗时且复杂。更奇怪的是官方文档中没有任何示例。无论如何,谢谢,我最终建立了自己的 NFS 服务器。
        猜你喜欢
        • 2020-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-31
        • 1970-01-01
        • 2020-11-08
        • 2022-06-15
        • 1970-01-01
        相关资源
        最近更新 更多