Kubernetes在使用StatefulSet和3 PersistentVolumes时出现问题

时间:2018-05-08 15:45:39

标签: kubernetes kubernetes-pvc

我正在创建一个有3个副本的StatefulSet based on this yaml。我希望3个pod中的每一个都连接到不同的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个pod中的第一个似乎没有问题。

第二个失败,错误为pod has unbound PersistentVolumeClaims Back-off restarting failed container

enter image description here

然而,如果我转到显示PersistentVolumeClaims的标签,那么创建的第二个似乎已经成功。

enter image description here

如果成功,为什么pod认为它失败了?

1 个答案:

答案 0 :(得分:1)

  

我希望3个pod中的每一个都连接到不同的PersistentVolume。

  • 为了使其正常工作,您需要:

    • 供应商(在您发布的链接中有关于如何在aws,azure,googlecloud和minicube上设置供应商的示例)或
    • 可以多次安装的卷(例如nfs卷)。但请注意,在这种情况下,所有pod都会读取/写入同一文件夹,这可能会导致问题,因为它们并不意味着同时锁定/写入相同的数据。通常的用例是pod正在保存的上传文件夹,以后用于只读和这样的用例。另一方面,SQL数据库(例如mysql)并不打算写入这样的共享文件夹。
  • 而不是声明清单中提到的任何要求,而是使用hostPath(指向/ nfs)并将其设置为ReadWriteOnce(只有一个可以使用它)。你也使用'标准'作为存储类,在你给出的url中有快速和慢速的,所以你可能也创建了你的存储类。

  

第二个失败,错误pod具有未绑定的PersistentVolumeClaims   退回重启失败的容器

  • 这是因为第一个pod已经接受了它的声明(读取一次写入,主机路径),如果没有设置适当的配置器或访问权限,则第二个pod不能重复使用相同的设备。
  

如果成功,为什么pod认为它失败了?

  • 所有PVC成功地与伴随的PV结合。但是你永远不会将第二和第三PVC限制在第二或第三个豆荚。您正在重试第二个pod上的第一个声明,并且第一个声明已经在ReadWriteOnce模式下绑定(到第一个pod)并且也不能绑定到第二个pod并且您收到错误...

建议的方法

由于您将/ nfs作为主机路径引用,因此可以安全地假设您正在使用某种NFS支持的文件系统,因此这里有一个备用设置可以让您通过nfs将动态配置的持久卷挂载到尽可能多的有状态的豆荚

注意:

  • 这只回答了假设nfs共享在有状态集复制pod中挂载持久卷的原始问题。
  • NFS不适用于动态数据,例如数据库。通常的用例是上传文件夹或中等日志记录/备份文件夹。对于nfs,数据库(sql或no sql)通常是禁止的。
  • 对于任务/时间关键应用程序,您可能需要在生产此方法之前仔细计时/压力测试,因为k8s和外部pv都会在其间添加一些层/延迟。虽然对于某些应用来说这可能就足够了,但要注意它。
  • 你对动态创建的pv的名称控制有限(k8s为新创建的后缀添加了后缀,如果被告知这样做,则重用可用的旧名称),但k8s将在pod终止后保留它们并分配第一个可用于新的pod,所以你不会松动状态/数据。这是您可以通过策略控制的。

步骤:

  • 为此,您首先需要从此处安装nfs provisioner:

  • 存储类清单:

    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
      ...