asd*_*gav 4 google-cloud-platform kubernetes google-kubernetes-engine persistent-volumes persistent-volume-claims
我有一个三节点 GCE 集群和一个带有三个副本的单 pod GKE 部署。我像这样创建了 PV 和 PVC:
# Create a persistent volume for web content
apiVersion: v1
kind: PersistentVolume
metadata:
name: nginx-content
labels:
type: local
spec:
capacity:
storage: 5Gi
accessModes:
- ReadOnlyMany
hostPath:
path: "/usr/share/nginx/html"
--
# Request a persistent volume for web content
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-content-claim
annotations:
volume.alpha.kubernetes.io/storage-class: default
spec:
accessModes: [ReadOnlyMany]
resources:
requests:
storage: 5Gi
Run Code Online (Sandbox Code Playgroud)
它们在容器规范中被引用,如下所示:
spec:
containers:
- image: launcher.gcr.io/google/nginx1
name: nginx-container
volumeMounts:
- name: nginx-content
mountPath: /usr/share/nginx/html
ports:
- containerPort: 80
volumes:
- name: nginx-content
persistentVolumeClaim:
claimName: nginx-content-claim
Run Code Online (Sandbox Code Playgroud)
尽管我将卷创建为 ReadOnlyMany,但在任何给定时间只有一个 pod 可以挂载该卷。其余的给出“错误 400:RESOURCE_IN_USE_BY_ANOTHER_RESOURCE”。我怎样才能让所有三个副本从同一卷读取相同的 Web 内容?
mar*_*rio 15
首先,我想指出您的配置中的一个基本差异。请注意,当您PersistentVolumeClaim在示例中使用定义时,您根本不使用您nginx-content PersistentVolume的。您可以通过运行轻松验证它:
kubectl get pv
Run Code Online (Sandbox Code Playgroud)
在您的GKE 集群上。您会注意到,除了您手动创建的nginx-content PV,还有另一个是根据PVC您应用的自动配置的。
请注意,在您的PersistentVolumeClaim定义中,您明确引用了default与您手动创建的PV. 实际上即使你完全省略注释:
annotations:
volume.alpha.kubernetes.io/storage-class: default
Run Code Online (Sandbox Code Playgroud)
它将以完全相同的方式工作,即default无论如何都会使用存储类。在GKE上使用默认存储类意味着GCE Persistent Disk将用作您的卷配置器。您可以在此处阅读更多相关信息:
诸如 gcePersistentDisk 之类的卷实现是通过 StorageClass 资源配置的。GKE 会为您创建一个默认的 StorageClass,它使用标准的永久性磁盘类型 (ext4)。当 PersistentVolumeClaim 未指定 StorageClassName 时,将使用默认 StorageClass。您可以将提供的默认 StorageClass 替换为您自己的。
但是让我们继续解决您面临的问题。
首先,我想强调您不必使用任何类似 NFS 的文件系统来实现您的目标。
如果您需要PersistentVolume在ReadOnlyMany模式下可用,GCE Persistent Disk是完全满足您要求的完美解决方案。
它可以ro由许多人Pods同时以模式挂载,更重要的是许多人Pods在不同的GKE 上安排nodes。此外,它的配置非常简单,并且可以在GKE 上开箱即用。
如果你想在ReadWriteMany模式下使用你的存储,我同意像 NFS 这样的东西可能是唯一的解决方案,因为GCE Persistent Disk不提供这种功能。
让我们仔细看看如何配置它。
我们需要从定义我们的PVC. 这一步实际上已经由你自己完成了,但你在进一步的步骤中有点迷失了。让我解释一下它是如何工作的。
以下配置是正确的(正如我提到的annotations部分可以省略):
# Request a persistent volume for web content
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-content-claim
spec:
accessModes: [ReadOnlyMany]
resources:
requests:
storage: 5Gi
Run Code Online (Sandbox Code Playgroud)
但是,我想对此添加一项重要评论。你说:
尽管我将卷创建为 ReadOnlyMany,但在任何给定时间只有一个 pod 可以挂载该卷。
好吧,实际上你没有。我知道这看起来有点棘手,有点令人惊讶,但这并不是定义accessModes真正起作用的方式。事实上,这是一个被广泛误解的概念。首先,您不能PVC在某种意义上定义访问模式,即在那里放置您想要的约束。支持的访问模式是特定存储类型的固有特性。它们已经由存储提供者定义。
您在PVC定义中实际做的是请求PV支持特定访问模式或访问模式的 。请注意,它采用列表形式,这意味着您可以提供许多您希望PV支持的不同访问模式。
基本上就像说:“嘿!存储提供商!给我一个支持ReadOnlyMany模式的卷。” 您要求以这种方式获得满足您要求的存储。但是请记住,您可以得到的比您要求的更多。这也是我们在GCP 中要求PV支持ReadOnlyMany模式时的场景。它为我们创建了一个满足我们在部分中列出的要求但它也支持模式。虽然我们没有要求支持. 所以基本上这就是它的工作方式。PersistentVolumeaccessModesReadWriteOnceReadWriteOnceReadOnlyMany
您PV是由 GCP 自动提供的,以响应您的PVC支持这两个accessModes,如果您没有明确指定Pod或Deployment定义要以只读模式安装它,默认情况下它以读写模式安装。
您可以通过附加到Pod能够成功安装的来轻松验证它PersistentVolume:
kubectl exec -ti pod-name -- /bin/bash
Run Code Online (Sandbox Code Playgroud)
并试图在挂载的文件系统上写一些东西。
你得到的错误信息:
"Error 400: RESOURCE_IN_USE_BY_ANOTHER_RESOURCE"
Run Code Online (Sandbox Code Playgroud)
关注具体GCE永久磁盘已经装入一个GKE node的ReadWriteOnce模式,它不能被其他安装node在其上的其余部分Pods进行调度。
如果您希望它以ReadOnlyMany模式安装,则需要Deployment通过在模板规范下readOnly: true的volumes部分中添加语句来在定义中明确指定它,Pod's如下所示:
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: nginx-content
volumes:
- name: nginx-content
persistentVolumeClaim:
claimName: nginx-content-claim
readOnly: true
Run Code Online (Sandbox Code Playgroud)
但是请记住,为了能够在readOnly模式下挂载它,首先我们需要用数据预先填充这样的卷。否则,您将看到另一条错误消息,指出无法以只读模式安装未格式化的卷。
最简单的方法是创建一个单一的Pod,它仅用于将已经上传到我们的GKE 节点之一的数据复制到我们的目的地PV。
请注意,PersistentVolume可以通过许多不同的方式使用数据进行预填充。您可以Pod只安装在PersistentVolume您将在您的文件中使用的文件,Deployment并使用curl或wget从某个外部位置获取您的数据,并将其直接保存在您的目的地PV。由你决定。
在我的例子我展示了如何使用额外做局部容积,使我们能够安装到我们的Pod一个directory,partition或者disk(在我的例子中,我使用目录/var/tmp/test位于我的GKE节点之一)我们kubernetes节点之一可用。它比hostPath我们不必关心将此类调度Pod到包含数据的特定节点更灵活的解决方案。特定节点关联规则已在特定节点上定义PersistentVolume并Pod自动调度。
要创建它,我们需要 3 件事:
StorageClass:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
Run Code Online (Sandbox Code Playgroud)
PersistentVolume 定义:
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /var/tmp/test
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- <gke-node-name>
Run Code Online (Sandbox Code Playgroud)
最后PersistentVolumeClaim:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 10Gi
storageClassName: local-storage
Run Code Online (Sandbox Code Playgroud)
然后我们可以创建我们的临时文件Pod,它仅用于将数据从我们的GKE 节点复制到我们的GCE 永久磁盘。
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: myfrontend
image: nginx
volumeMounts:
- mountPath: "/mnt/source"
name: mypd
- mountPath: "/mnt/destination"
name: nginx-content
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim
- name: nginx-content
persistentVolumeClaim:
claimName: nginx-content-claim
Run Code Online (Sandbox Code Playgroud)
您可以在上面看到的路径并不重要。这样做的任务Pod只是让我们将数据复制到目的地PV。最终我们PV将安装在完全不同的路径上。
一旦Pod被创建和这两个卷都成功安装,我们可以通过运行附加到它:
kubectl exec -ti my-pod -- /bin/bash
Run Code Online (Sandbox Code Playgroud)
随着Pod简单的运行:
cp /mnt/source/* /mnt/destination/
Run Code Online (Sandbox Code Playgroud)
就这样。现在我们可以exit删除我们的临时文件Pod:
kubectl delete pod mypod
Run Code Online (Sandbox Code Playgroud)
一旦它消失了,我们就可以应用我们的,Deployment并且我们PersistentVolume最终可以readOnly通过Pods位于各种GKE 节点上的所有节点以模式挂载:
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: nginx-content
volumes:
- name: nginx-content
persistentVolumeClaim:
claimName: nginx-content-claim
readOnly: true
Run Code Online (Sandbox Code Playgroud)
顺便提一句。如果您认为您Pods将只在一个特定节点上调度这一事实,那么您可以完全放弃使用GCE Persistent Disk并切换到上述本地卷。通过这种方式,您Pods不仅可以读取它,还可以同时写入它。唯一需要注意的是,所有这些Pods都将在单个节点上运行。
| 归档时间: |
|
| 查看次数: |
10509 次 |
| 最近记录: |