问题描述
我有一个运行良好的 statefulset,并且 stateful set 有 ReadWriteMany PVC。我需要与另一个 statefulset 共享这个 PVC。
基本上我有一个 backendService,它是一个有 2 个副本的 statefulset,所以它定义了一个 volumeClaimTemplate - 因此它有 2 个卷 service-data-service-0 和 service-data-service-1 例如。
在另一个 statefulset 中 - 它有自己的数据量,但我需要共享来自另一个 statefulset 的数据量。
存在一对一映射 - 这意味着需要将下级服务中序号为 0 的卷添加到 pod0,对于序号为 1 的卷到 pod1 也是如此。
我不太清楚我是如何做到这一点的。部署很容易,因为从技术上讲,您有 2 个部署..所以每个部署都可以严格发送到正确的 service-data-service-XX(其中 XX 是较低服务器的序号,即 0,1 等)
volumes:
- name: lnd2-data-volume
persistentVolumeClaim:
# This volumes section is in the higher service but shares a data volume
# with the lower service
claimName: service-data-service-{{ "SOME TEMPLATE HERE to give me either 0 or 1 for the current POD ordinal number }}
有什么想法吗?
解决方法
要查看 TLDR 版本,请转到下面的解决方案。
您想要实现的目标在今天的 Statefulset (STS) 中无法实现。
声明由于 StatefulSet 控制器的设计需要有一个唯一的标识符,以便映射到它们对应的 Pod,并且不能在不同的 StatefulSet 应用程序之间重复使用。
因此,无论您在 Volumes 中指定什么声明名称作为 StatefulSet 定义中的 Pod 模板的一部分(例如 claimName=service-data-service-0
),它总是会被 StatefulSet 控制器覆盖,使用以下命名方案由它控制的每个 Pod :
PVC name = claim.Name + set.Name + ordinal number
哪里:
claim.Name
- 在 volumeClaimTemplates 中与“volumeMount”匹配的 STS PodTemplateSpec 列表中声明
set.Name
- StatefulSet 名称
ordinal
- Pod 的(副本 - 1)
我的观察:
STS 可以使用现有的 PVC(ReadWriteMany 模式),只有当您第一次在集群中引入 StatefulSet 时(=它还没有被其他工作负载拥有)。
例如,像这样的 STS:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: peb
spec:
...
volumeClaimTemplates:
- metadata:
name: fileserver-claim
spec:
accessModes: [ "ReadWriteMany" ]
storageClassName: ""
resources:
requests:
storage: 1Gi
会消耗现有的 PVC:
fileserver-claim-peb-0
在 API 服务器日志中看到伴随事件:
PVC 'fileserver-claim-peb-0' 已经存在
并且因为不能有任何不同的同名 STS(Pod 'peb-0' 在集群中是唯一的,就像它的 claimName),你的选择就在这里。
解决方案:
手动预配置一对 PV,它们使用相同的关联存储资产(例如,支持 RWX 访问模式的基于 NFS 的卷),并且在您的 STS 中的 PVC 列表中按名称 (volumeName) 引用现有的未绑定 PV,例如:
...
volumeClaimTemplates:
- metadata:
name: datadir
spec:
accessModes:
- "ReadWriteOnce"
volumeName: fileserver-claim-peb
resources:
requests:
storage: 1Gi
我认为这是在不同 StatefulSet 之间共享相同数据存储的方法。