如何在 Kubernetes 中重新挂载已释放的 PersistentVolume

6
这是我的总体目标:
  • 运行一个MongoDB

  • 在Pod失败/更新等情况下持久保存数据

我采取的方法:
  • K8S提供者:Digital Ocean

  • 节点:3个

  • 创建PVC

  • 创建无头服务

  • 创建StatefulSet

下面是配置的简化版本:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: some-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: do-block-storage
---
apiVersion: v1
kind: Service
metadata:
  name: some-headless-service
  labels:
    app: my-app
spec:
  ports:
  - port: 27017
    name: my-app-database
  clusterIP: None
  selector:
    app: my-app
    tier: database
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-app-database
  labels:
    app: my-app
    tier: database
spec:
  serviceName: some-headless-service
  replicas: 1
  selector:
    matchLabels:
      app: my-app
      tier: database
  template:
    metadata:
      labels:
        app: my-app
        tier: database
    spec:
      containers:
      - name: my-app-database
        image: mongo:latest
        volumeMounts:
        - name: some-volume
          mountPath: /data
        ports:
        - containerPort: 27017
          name: my-app-database
      volumes:
      - name: some-volume
        persistentVolumeClaim:
          claimName: some-pvc

这个命令可以如预期地工作。我可以将副本数降至0:

kubectl scale —replicas=0 statefulset/my-app-database

再次将其启动:

kubectl scale —replicas=1 statefulset/my-app-database

数据将得以保存。

但是有一次,当我在增加和减少有状态集的规模时,遇到了以下错误:

Volume is already exclusively attached to one node and can't be attached to another

由于对k8s不太了解,我删除了PVC并“重新创建”相同的内容:

kubectl delete pvc some-pvc
kubectl apply -f persistent-volume-claims/
statefulset使用新的持久卷(PV),由于persistentVolumeReclaimPolicy默认设置为Delete,旧的PV被删除了。我将新的PV的persistentVolumeReclaimPolicy设置为Retain,以确保数据不会被自动删除。但是,如果需要重新获取该PV,我不确定如何操作。之前,为了解决“卷附件”错误,我删除了PVC,这将根据我的设置创建一个新的PV,现在我的数据在那个Released PV中。我的主要问题是:这是否是实现目标的正确方法?我是否应该尝试添加一个claimRef到动态创建的PV中,并使用该claimRef重新创建一个新的PVC,如此处所述:Can a PVC be bound to a specific PV??我是否应该尝试让新的statefulset使用旧的PV?如果我想要尝试重新连接旧的PV并将其附加到正确的节点上,这是否有意义?如果有,我该如何操作?
1个回答

1
如果您想要使用可扩展的StatefulSet,那么您的存储也应该支持此功能。有两种处理方法:
  • 如果do-block-storage存储类支持ReadWriteMany,那么将所有pod的数据放在单个卷中。

  • 每个pod使用不同的卷,在您的StatefulSet.spec中添加volumeClaimTemplate,然后k8s会自动创建PVC,例如some-pvc-{statefulset_name}-{idx}

spec:
  volumeClaimTemplates:
  - metadata:
      name: some-pvc
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 5Gi
      storageClassName: do-block-storage

更新:

StatefulSet 副本必须mongodb复制一起部署,然后 StatefulSet 中的每个 pod 都将具有相同的数据存储。

因此,当容器运行 mongod 命令时,必须添加选项 --replSet={name}。当所有 pod 启动时,执行命令 rs.initiate() 来告诉 mongodb 如何处理数据复制。当您扩展或缩小 StatefulSet 时,请执行命令 rs.add()rs.remove() 来告诉 mongodb 成员已更改。


目前,DigitalOcean的do-block-storage StorageClass仅支持ReadWriteOnce(20190530)。我需要阅读更多关于通过volumeClaimTemplates使用不同卷的信息,对我来说,让MongoDB集合分布在不同的卷上很困惑,但是StatefulSet及其所有副本将把它视为一个源..这是它的工作方式吗? - Jason Awbrey
“Replicas” 仅向每个 pod 发出服务“负载均衡”请求,因此它与数据复制不同。要进行数据复制,您应该使用 mongodb 复制。有关更多详细信息,请参见 更新 - menya
如何重新连接太阳能电池板?这似乎没有回答主要问题。 - collimarco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接