如何在Kubernetes中重新附加已发布的PersistentVolume

时间:2019-05-29 21:01:16

标签: kubernetes statefulset

这是我的总体目标:

  • 正在运行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

作为k8的新手,我删除了PVC,并“重新创建”了相同的PVC:

kubectl delete pvc some-pvc
kubectl apply -f persistent-volume-claims/

由于statefulset默认情况下设置为persistentVolumeReclaimPolicy,因此Delete用新的PV旋转备份并删除了旧的PV。

我将新的PV persistentVolumeReclaimPolicy设置为Retain,以确保不会自动删除数据。。我意识到:我不确定如何回收该PV。早些时候,为了解决“卷附件”错误,我删除了PVC,该PVC只会使用已有的设置创建另一个新的PV,现在我将数据保留在Released PV中。

我的主要问题是:

  • 这听起来是否很适合我的目标?

  • 我应该考虑将claimRef添加到动态创建的PV中,然后使用该ClaimRef重新创建新的PVC,如此处所述:Can a PVC be bound to a specific PV?

  • 我应该尝试获取新鲜的statefulset PVC来实际使用旧的PV吗?

  • 尝试将旧的PV重新连接到正确的节点是否有意义,我该怎么做?

1 个答案:

答案 0 :(得分:0)

如果您想使用StatefulSet具有可扩展性,则您的存储也应支持此功能,有两种方法可以解决此问题:

  • 如果do-block-storage存储类支持ReadWriteMany,则将所有Pod的数据放在单个卷中。

  • 每个吊舱使用不同的音量,将volumeClaimTemplate添加到您的StatefulSet.spec, 那么k8s会自动创建类似some-pvc-{statefulset_name}-{idx}的PVC:

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

更新

StatefulSet副本必须mongodb replication一起部署,然后StatefulSet中的每个吊舱将具有相同的数据存储。

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