Kubernetes 在 StatefulSet 和 3 个 PersistentVolumes 方面的问题
Kubernetes trouble with StatefulSet and 3 PersistentVolumes
我正在创建一个有 3 个副本的 StatefulSet based on this yaml。我希望 3 个 pods 中的每一个都连接到不同的 PersistentVolume。
对于持久卷,我使用了 3 个如下所示的对象,只是更改了名称 (pvvolume, pvvolume2, pvvolume3):
kind: PersistentVolume
apiVersion: v1
metadata:
name: pvvolume
labels:
type: local
spec:
storageClassName: standard
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/nfs"
claimRef:
kind: PersistentVolumeClaim
namespace: default
name: mongo-persistent-storage-mongo-0
StatefulSet 中的 3 个 pods 中的第一个似乎可以毫无问题地创建。
第二次失败,错误为 pod has unbound PersistentVolumeClaims
Back-off restarting failed container
。
然而,如果我转到显示 PersistentVolumeClaims 的选项卡,则创建的第二个似乎已成功。
如果成功了,为什么 pod 认为它失败了?
I want each of the 3 pods to connect to a different PersistentVolume.
要使其正常工作,您需要:
- provisioner(在您发布的 link 中有示例如何在 aws、azure、googlecloud 和 minicube 上设置 provisioner)或
- 可以多次挂载的卷(例如 nfs 卷)。但是请注意,在这种情况下,您所有的 pods read/write 都放在同一个文件夹中,当它们不打算同时 lock/write 相同的数据时,这可能会导致问题。通常的用例是 pods 保存到的上传文件夹,稍后用于只读和此类用例。 SQL 另一方面,数据库(例如 mysql)并不意味着写入此类共享文件夹。
您正在使用 hostPath(指向 /nfs)并将其设置为 ReadWriteOnce(只有一个人可以使用),而不是声明清单中提到的任一要求。您还使用 'standard' 作为存储 class 并且在 url 中您给出了快速和慢速的存储,因此您可能也创建了存储 class。
The second fails with the error pod has unbound PersistentVolumeClaims
Back-off restarting failed container
- 这是因为第一个 pod 已经取得了它的声明(读写一次,主机路径),如果没有设置适当的配置器或访问,第二个 pod 不能重复使用相同的声明。
If it was successful why does the pod think it failed?
- 所有 PVC 都已成功绑定到随附的 PV。但是你永远不会将第二个和第三个 PVC 绑定到第二个或第三个 pods。您正在重试第二个 pod 的第一个声明,并且第一个声明已经在 ReadWriteOnce 模式下绑定(到第一个 pod)并且不能绑定到第二个 pod 并且您收到错误...
建议的方法
由于您引用 /nfs 作为您的主机路径,可以安全地假设您正在使用某种 NFS 支持的文件系统,因此这里有一个替代设置,可以让您将动态配置的持久卷挂载到nfs 到有状态集中的任意数量 pods
备注:
- 这仅回答了假设 nfs 共享 pods 跨状态复制挂载持久卷的原始问题。
- 对于数据库等动态数据,NFS 并不是真正可取的。通常的用例是上传文件夹或中等 logging/backing 上传文件夹。数据库(sql 或没有 sql)通常是 nfs 的禁忌。
- 对于 mission/time 关键应用程序,您可能需要 time/stresstest 在生产中采用这种方法之前仔细考虑,因为 k8s 和外部 pv 都在中间添加了一些 layers/latency 。尽管对于某些应用程序这可能就足够了,但请注意。
- 您对动态创建的 pv 名称的控制有限(k8s 为新创建的 pv 添加后缀,并在被告知这样做时重用可用的旧名称),但 k8s 将在 pod 终止并首先分配后保留它们可用于新 pod,因此您不会松动 state/data。不过,这是您可以通过政策控制的事情。
步骤:
要使其正常工作,您首先需要从此处安装 nfs provisioner:
- https://github.com/kubernetes-incubator/external-storage/tree/master/nfs。请注意,安装并不复杂,但有一些步骤您必须采取谨慎的方法(权限、设置 nfs 共享等),因此它不仅仅是即发即弃的部署。花点时间正确安装 nfs provisioner。正确设置后,您可以继续使用下面建议的清单:
存储class清单:
kind: StorageClass
apiVersion: storage.k8s.io/v1beta1
metadata:
name: sc-nfs-persistent-volume
# if you changed this during provisioner installation, update also here
provisioner: example.com/nfs
状态集(仅重要摘录):
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: ss-my-app
spec:
replicas: 3
...
selector:
matchLabels:
app: my-app
tier: my-mongo-db
...
template:
metadata:
labels:
app: my-app
tier: my-mongo-db
spec:
...
containers:
- image: ...
...
volumeMounts:
- name: persistent-storage-mount
mountPath: /wherever/on/container/you/want/it/mounted
...
...
volumeClaimTemplates:
- metadata:
name: persistent-storage-mount
spec:
storageClassName: sc-nfs-persistent-volume
accessModes: [ ReadWriteOnce ]
resources:
requests:
storage: 10Gi
...
我正在创建一个有 3 个副本的 StatefulSet based on this yaml。我希望 3 个 pods 中的每一个都连接到不同的 PersistentVolume。
对于持久卷,我使用了 3 个如下所示的对象,只是更改了名称 (pvvolume, pvvolume2, pvvolume3):
kind: PersistentVolume
apiVersion: v1
metadata:
name: pvvolume
labels:
type: local
spec:
storageClassName: standard
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/nfs"
claimRef:
kind: PersistentVolumeClaim
namespace: default
name: mongo-persistent-storage-mongo-0
StatefulSet 中的 3 个 pods 中的第一个似乎可以毫无问题地创建。
第二次失败,错误为 pod has unbound PersistentVolumeClaims
Back-off restarting failed container
。
然而,如果我转到显示 PersistentVolumeClaims 的选项卡,则创建的第二个似乎已成功。
如果成功了,为什么 pod 认为它失败了?
I want each of the 3 pods to connect to a different PersistentVolume.
要使其正常工作,您需要:
- provisioner(在您发布的 link 中有示例如何在 aws、azure、googlecloud 和 minicube 上设置 provisioner)或
- 可以多次挂载的卷(例如 nfs 卷)。但是请注意,在这种情况下,您所有的 pods read/write 都放在同一个文件夹中,当它们不打算同时 lock/write 相同的数据时,这可能会导致问题。通常的用例是 pods 保存到的上传文件夹,稍后用于只读和此类用例。 SQL 另一方面,数据库(例如 mysql)并不意味着写入此类共享文件夹。
您正在使用 hostPath(指向 /nfs)并将其设置为 ReadWriteOnce(只有一个人可以使用),而不是声明清单中提到的任一要求。您还使用 'standard' 作为存储 class 并且在 url 中您给出了快速和慢速的存储,因此您可能也创建了存储 class。
The second fails with the error pod has unbound PersistentVolumeClaims Back-off restarting failed container
- 这是因为第一个 pod 已经取得了它的声明(读写一次,主机路径),如果没有设置适当的配置器或访问,第二个 pod 不能重复使用相同的声明。
If it was successful why does the pod think it failed?
- 所有 PVC 都已成功绑定到随附的 PV。但是你永远不会将第二个和第三个 PVC 绑定到第二个或第三个 pods。您正在重试第二个 pod 的第一个声明,并且第一个声明已经在 ReadWriteOnce 模式下绑定(到第一个 pod)并且不能绑定到第二个 pod 并且您收到错误...
建议的方法
由于您引用 /nfs 作为您的主机路径,可以安全地假设您正在使用某种 NFS 支持的文件系统,因此这里有一个替代设置,可以让您将动态配置的持久卷挂载到nfs 到有状态集中的任意数量 pods
备注:
- 这仅回答了假设 nfs 共享 pods 跨状态复制挂载持久卷的原始问题。
- 对于数据库等动态数据,NFS 并不是真正可取的。通常的用例是上传文件夹或中等 logging/backing 上传文件夹。数据库(sql 或没有 sql)通常是 nfs 的禁忌。
- 对于 mission/time 关键应用程序,您可能需要 time/stresstest 在生产中采用这种方法之前仔细考虑,因为 k8s 和外部 pv 都在中间添加了一些 layers/latency 。尽管对于某些应用程序这可能就足够了,但请注意。
- 您对动态创建的 pv 名称的控制有限(k8s 为新创建的 pv 添加后缀,并在被告知这样做时重用可用的旧名称),但 k8s 将在 pod 终止并首先分配后保留它们可用于新 pod,因此您不会松动 state/data。不过,这是您可以通过政策控制的事情。
步骤:
要使其正常工作,您首先需要从此处安装 nfs provisioner:
- https://github.com/kubernetes-incubator/external-storage/tree/master/nfs。请注意,安装并不复杂,但有一些步骤您必须采取谨慎的方法(权限、设置 nfs 共享等),因此它不仅仅是即发即弃的部署。花点时间正确安装 nfs provisioner。正确设置后,您可以继续使用下面建议的清单:
存储class清单:
kind: StorageClass apiVersion: storage.k8s.io/v1beta1 metadata: name: sc-nfs-persistent-volume # if you changed this during provisioner installation, update also here provisioner: example.com/nfs
状态集(仅重要摘录):
apiVersion: apps/v1 kind: StatefulSet metadata: name: ss-my-app spec: replicas: 3 ... selector: matchLabels: app: my-app tier: my-mongo-db ... template: metadata: labels: app: my-app tier: my-mongo-db spec: ... containers: - image: ... ... volumeMounts: - name: persistent-storage-mount mountPath: /wherever/on/container/you/want/it/mounted ... ... volumeClaimTemplates: - metadata: name: persistent-storage-mount spec: storageClassName: sc-nfs-persistent-volume accessModes: [ ReadWriteOnce ] resources: requests: storage: 10Gi ...