我们可以稍微简化一下整个过程。在 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。通过这个Pod 以rw 模式挂载它是可能的,因为GCE Persistent Disk 还支持ReadWriteOnce 访问模式,根据the official docsmenas “卷可以挂载为单节点读写”。这就是为什么在其他节点上调度的Pods 无法挂载它的原因。
但让我们继续讨论实际的解决方案。
创建上述PVC 后,您会看到相应的PV 也已创建(kubectl get pv),其STATUS 为Bound。
现在我们只需要在开始以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。它可以通过几种不同的方式完成。
我决定使用一个临时的Pod 和local 音量。
为了使我们的数据(已存在于 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