86

我尝试设置 Kubernetes 集群。我已经设置并运行了 Persistent Volume、Persistent Volume Claim 和 Storage 类,但是当我想从部署中创建 pod 时,pod 已创建但它挂在 Pending 状态。描述后,我只收到此警告“1 个节点有卷节点关联冲突。” 有人可以告诉我我的卷配置中缺少什么吗?

apiVersion: v1
kind: PersistentVolume
metadata:
  creationTimestamp: null
  labels:
    io.kompose.service: mariadb-pv0
  name: mariadb-pv0
spec:
  volumeMode: Filesystem
  storageClassName: local-storage
  local:
    path: "/home/gtcontainer/applications/data/db/mariadb"
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 2Gi
  claimRef:
    namespace: default
    name: mariadb-claim0
  nodeAffinity:
    required:
      nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/cvl-gtv-42.corp.globaltelemetrics.eu
            operator: In
            values:
            - master

status: {}
4

11 回答 11

127

当持久卷声称 Pod 正在使用的被调度在不同的区域而不是一个区域时,会发生错误“卷节点关联冲突”,因此实际的 Pod 无法被调度,因为它无法连接到卷另一个区域。要检查这一点,您可以查看所有持久卷的详细信息。要检查这一点,首先获取您的 PVC:

$ kubectl get pvc -n <namespace>

然后获取持久卷的详细信息(不是卷声明)

$  kubectl get pv

找到与您的 PVC 对应的 PV 并描述它们

$  kubectl describe pv <pv1> <pv2>

您可以检查每个 PV 的 Source.VolumeID,它们很可能是不同的可用区,因此您的 pod 会给出关联错误。要解决此问题,请为单个区域创建一个存储类并在您的 PVC 中使用该存储类。

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: region1storageclass
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
  encrypted: "true" # if encryption required
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
  - key: failure-domain.beta.kubernetes.io/zone
    values:
    - eu-west-2b # this is the availability zone, will depend on your cloud provider
    # multi-az can be added, but that defeats the purpose in our scenario
于 2019-04-04T11:28:44.877 回答
15

有几件事可能导致此错误:

  1. 节点未正确标记。当我的工作节点没有像这样的适当标签(尽管主节点有)时,我在 AWS 上遇到了这个问题:

    failure-domain.beta.kubernetes.io/region=us-east-2

    failure-domain.beta.kubernetes.io/zone=us-east-2c

    给节点打了标签后,“1 node(s) has volume node affinity conflict”的错误消失了,所以PV、PVC和pod部署成功。这些标签的值是特定于云提供商的。基本上,设置这些标签是云提供商的工作(在 cube-controller、API-server、kubelet 中定义了 --cloud-provider 选项)。如果未设置适当的标签,请检查您的 CloudProvider 集成是否正确。我使用了 kubeadm,因此设置起来很麻烦,但是使用其他工具,例如 kops,它可以立即工作。

  2. 根据您的 PV 定义和 nodeAffinity 字段的使用,您正在尝试使用本地卷,(在此处阅读本地卷描述链接,官方文档),然后确保您像这样设置“NodeAffinity 字段”(它在我的AWS 案例):

    节点亲和性:

         required:
          nodeSelectorTerms:
           - matchExpressions:
             - key: kubernetes.io/hostname
               operator: In
               values:
               - my-node  # it must be the name of your node(kubectl get nodes)
    

因此,在创建资源并在其上运行 describe 后,它将显示如下:

         Required Terms:  
                    Term 0:  kubernetes.io/hostname in [your node name]
  1. StorageClass 定义(命名为local-storage,这里不贴)必须在volumeBindingMode 设置为WaitForFirstConsumer 的情况下创建本地存储才能正常工作。参考这里的示例存储类本地描述,官方文档了解其背后的原因。
于 2019-02-04T13:22:01.490 回答
8

1 个节点有卷节点关联冲突”错误是由调度程序创建的,因为它无法将您的 pod 调度到符合persistenvolume.spec.nodeAffinity您的 PersistentVolume (PV) 中的字段的节点。

换句话说,您在 PV 中说必须将使用此 PV 的 pod 调度到标签为 的节点kubernetes.io/cvl-gtv-42.corp.globaltelemetrics.eu = master,但由于某种原因这是不可能的。

无法将您的 pod 调度到这样的节点可能有多种原因:

  • Pod 有与目标节点冲突的节点亲和性、Pod 亲和性等
  • 目标节点被污染
  • 目标节点已达到其“每个节点的最大 pods”限制
  • 不存在具有给定标签的节点

开始寻找原因的地方是节点和pod的定义。

于 2019-06-18T22:36:03.933 回答
6

索纳克·罗伊(Sownak Roy)的出色回答。与应该使用它的节点相比,我在不同的区域中创建了相同的 PV。我应用的解决方案仅基于 Sownak 的回答,仅在我的情况下,指定没有“allowedTopologies”列表的存储类就足够了,如下所示:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: cloud-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
volumeBindingMode: WaitForFirstConsumer
于 2020-05-07T09:34:09.650 回答
4

与 GCP GKE 不同的情况。假设您使用的是区域集群并且您创建了两个 PVC。两者都是在不同的区域创建的(您没有注意到)。

在下一步中,您将尝试运行将两个 PVC 都安装到同一个 pod 的 pod。您必须将该 pod 安排到特定区域中的特定节点,但由于您的卷位于不同的区域,k8s 将无法安排该操作,您将收到以下问题。

例如 - 区域集群(不同区域中的节点)上的两个简单 PVC:

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: disk-a
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: disk-b
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

下一个简单的 pod:

apiVersion: v1
kind: Pod
metadata:
  name: debug
spec:
  containers:
    - name: debug
      image: pnowy/docker-tools:latest
      command: [ "sleep" ]
      args: [ "infinity" ]
      volumeMounts:
        - name: disk-a
          mountPath: /disk-a
        - name: disk-b
          mountPath: /disk-b
  volumes:
    - name: disk-a
      persistentVolumeClaim:
        claimName: disk-a
    - name: disk-b
      persistentVolumeClaim:
        claimName: disk-b

最后,由于卷位于不同的区域,k8s 可能无法调度 pod。

于 2020-04-17T16:58:06.147 回答
3

就我而言,根本原因是持久卷位于 us-west-2c 中,而新的工作节点重新启动到 us-west-2a 和 us-west-2b 中。解决方案是要么拥有更多工作节点,因此它们位于更多区域中,要么删除/扩大应用程序的节点亲和性,以便更多工作节点有资格绑定到持久卷。

于 2019-12-03T00:11:26.697 回答
3

0.如果您在其他答案中没有找到解决方案...

在我们的案例中,错误发生在新配置了 Pulumi 的 AWS EKS 集群上(请参阅此处的完整源代码)。这个错误让我发疯了,因为我没有改变任何东西,只是PersistentVolumeClaim 按照 Buildpacks Tekton docs 中的描述创建了一个:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: buildpacks-source-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi

我没有从默认的 EKS 配置中更改任何其他内容,也没有添加/更改任何PersistentVolumeStorageClass(实际上我什至不知道该怎么做)。由于默认的 EKS 设置似乎依赖于 2 个节点,因此出现错误:

0/2 nodes are available: 2 node(s) had volume node affinity conflict.

通读Sownak Roy 的回答,我得到了第一个胶水该怎么做 - 但不知道该怎么做。因此,对于这里感兴趣的人来说,这是我解决错误的所有步骤

1.检查EKS节点failure-domain.beta.kubernetes.io标签

Statefull applications 本文中的部分所述,在其他 AWS 可用区中将两个节点预置为持久卷 (PV),它是通过应用PersistendVolumeClaim上述内容创建的。

要检查这一点,您需要查看/描述您的节点kubectl get nodes

$ kubectl get nodes
NAME                                             STATUS   ROLES    AGE     VERSION
ip-172-31-10-186.eu-central-1.compute.internal   Ready    <none>   2d16h   v1.21.5-eks-bc4871b
ip-172-31-20-83.eu-central-1.compute.internal    Ready    <none>   2d16h   v1.21.5-eks-bc4871b

然后看看Label使用的部分kubectl describe node <node-name>

$ kubectl describe node ip-172-77-88-99.eu-central-1.compute.internal
Name:               ip-172-77-88-99.eu-central-1.compute.internal
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/instance-type=t2.medium
                    beta.kubernetes.io/os=linux
                    failure-domain.beta.kubernetes.io/region=eu-central-1
                    failure-domain.beta.kubernetes.io/zone=eu-central-1b
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=ip-172-77-88-99.eu-central-1.compute.internal
                    kubernetes.io/os=linux
                    node.kubernetes.io/instance-type=t2.medium
                    topology.kubernetes.io/region=eu-central-1
                    topology.kubernetes.io/zone=eu-central-1b
Annotations:        node.alpha.kubernetes.io/ttl: 0
...

在我的情况下,节点ip-172-77-88-99.eu-central-1.compute.internalfailure-domain.beta.kubernetes.io/region定义为eu-central-1和 az 与failure-domain.beta.kubernetes.io/zoneto eu-central-1b

另一个节点定义failure-domain.beta.kubernetes.io/zoneaz eu-central-1a

$ kubectl describe nodes ip-172-31-10-186.eu-central-1.compute.internal
Name:               ip-172-31-10-186.eu-central-1.compute.internal
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/instance-type=t2.medium
                    beta.kubernetes.io/os=linux
                    failure-domain.beta.kubernetes.io/region=eu-central-1
                    failure-domain.beta.kubernetes.io/zone=eu-central-1a
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=ip-172-31-10-186.eu-central-1.compute.internal
                    kubernetes.io/os=linux
                    node.kubernetes.io/instance-type=t2.medium
                    topology.kubernetes.io/region=eu-central-1
                    topology.kubernetes.io/zone=eu-central-1a
Annotations:        node.alpha.kubernetes.io/ttl: 0
...

2.检查PersistentVolume字段topology.kubernetes.io

现在我们应该PersistentVolume在手动应用我们的PersistentVolumeClaim. 使用kubectl get pv

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                           STORAGECLASS   REASON   AGE
pvc-93650993-6154-4bd0-bd1c-6260e7df49d3   1Gi        RWO            Delete           Bound    default/buildpacks-source-pvc   gp2                     21d

其次是kubectl describe pv <pv-name>

$ kubectl describe pv pvc-93650993-6154-4bd0-bd1c-6260e7df49d3
Name:              pvc-93650993-6154-4bd0-bd1c-6260e7df49d3
Labels:            topology.kubernetes.io/region=eu-central-1
                   topology.kubernetes.io/zone=eu-central-1c
Annotations:       kubernetes.io/createdby: aws-ebs-dynamic-provisioner
...

PersistentVolume配置了topology.kubernetes.io/zoneaz中的标签eu-central-1c这使我们的 Pod 抱怨找不到它们的卷 - 因为它们位于完全不同的 az 中!

3. 添加allowedTopologiesStorageClass

Kubernetes 文档中所述,该问题的一种解决方案是将allowedTopologies配置添加到StorageClass. 如果您已经像我一样配置了 EKS 集群,则需要检索您已经定义StorageClass

kubectl get storageclasses gp2 -o yaml

将其保存到一个名为的文件中storage-class.yml,并添加一个allowedTopologies与您的节点failure-domain.beta.kubernetes.io标签匹配的部分,如下所示:

allowedTopologies:
- matchLabelExpressions:
  - key: failure-domain.beta.kubernetes.io/zone
    values:
    - eu-central-1a
    - eu-central-1b

allowedTopologies配置定义的必须是 infailure-domain.beta.kubernetes.io/zone或- not !PersistentVolumeeu-central-1aeu-central-1beu-central-1c

完整的storage-class.yml样子是这样的:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gp2
parameters:
  fsType: ext4
  type: gp2
provisioner: kubernetes.io/aws-ebs
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowedTopologies:
- matchLabelExpressions:
  - key: failure-domain.beta.kubernetes.io/zone
    values:
    - eu-central-1a
    - eu-central-1b

将增强StorageClass配置应用到您的 EKS 集群

kubectl apply -f storage-class.yml

4.删除PersistentVolumeClaim,添加storageClassName: gp2并重新应用

为了让事情重新开始,我们需要删除第PersistentVolumeClaim一个。

要将 映射PersistentVolumeClaim到我们之前的定义StorageClass,我们需要storageClassName: gp2在 PersistendVolumeClaim 定义中添加pvc.yml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: buildpacks-source-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi
  storageClassName: gp2

最后重新应用PersistentVolumeClaimwith kubectl apply -f pvc.yml。这应该可以解决错误。

于 2022-01-20T08:32:36.153 回答
2
  1. 确保 Kubernetes 节点具有所需的标签。您可以使用以下方法验证节点标签:
kubectl get nodes --show-labels

其中一个 kubernetes 节点应该向您显示持久卷的名称/标签,并且您的 pod 应该安排在同一个节点上

  1. 确保请求PersistentVolumeClaim的大小与PersistentVolume. 如果大小不匹配,请更正或删除旧的resources.requests.storage并创建一个具有正确大小的新。PersistentVolumeClaimPersistentVolume

验证步骤:

  1. 描述您的持久卷:
kubectl describe pv postgres-br-proxy-pv-0

输出:

...
Node Affinity:
  Required Terms:
    Term 0:        postgres-br-proxy in [postgres-br-proxy-pv-0]
...
  1. 显示节点标签:
kubectl get nodes --show-labels

输出:

NAME    STATUS   ROLES    AGE   VERSION   LABELS
node3   Ready    <none>   19d   v1.17.6   postgres-br-proxy=postgres-br-proxy-pv-0

如果您没有在您的 pod 正在使用的节点上获得持久卷标,则不会安排该 pod。

于 2021-11-22T16:28:34.180 回答
1

这里描述的几乎相同的问题...... https://github.com/kubernetes/kubernetes/issues/61620

“如果您使用本地卷,并且节点崩溃,您的 Pod 无法重新调度到不同的节点。它必须被调度到同一个节点。这是使用本地存储的警告,您的 Pod 将永远绑定到一个特定的节点。”

于 2018-09-19T05:05:42.447 回答
0

很可能您只是减少了 kubernetes 集群中的节点数量,并且某些“区域”不再可用......

值得一提的是......如果您的 pod 与持久卷位于不同的区域,那么:

  • 您的磁盘访问时间将显着下降(您的本地持久存储不再是本地的 - 即使使用亚马逊/谷歌的光纤超快速链接,它仍然是跨数据中心的流量)
  • 您将为“跨区域网络”付费(在您的 AWS 账单上,它是进入“EC2-other”的内容,只有在深入了解 Aws 账单后您才能发现)
于 2021-01-06T23:13:08.363 回答
0

一个原因是当你有一个像下面这样的定义(在这个例子中是 Kafka Zookeeper),它为一个容器使用多个 pvcs。如果它们落在不同的节点上,您将得到如下内容:..volume node affinity conflict. 这里的解决方案是使用一个 pvc 定义并subPathvolumeMount.

问题

      ...
      volumeMounts:
        - mountPath: /data
          name: kafka-zoo-data
        - mountPath: /datalog
          name: kafka-zoo-datalog
  restartPolicy: Always
  volumes:
    - name: kafka-zoo-data
      persistentVolumeClaim:
        claimName: "zookeeper-data"
    - name: kafka-zoo-datalog
      persistentVolumeClaim:
        claimName: "zookeeper-datalog"

解决

      ...
      volumeMounts:
        - mountPath: /data
          subPath: data
          name: kafka-zoo-data
        - mountPath: /datalog
          subPath: datalog
          name: kafka-zoo-data
  restartPolicy: Always
  volumes:
    - name: kafka-zoo-data
      persistentVolumeClaim:
        claimName: "zookeeper-data"
于 2022-02-25T19:41:31.800 回答