0. 如果在其他答案中没有找到解决方案...
在我们的情况下,该错误发生在使用 Pulumi 最新提供的 AWS EKS 集群上 (请见完整代码)。这个错误让我感到非常困扰,因为我没有更改任何内容,只是按照 Buildpacks Tekton 文档中描述的方式创建了一个 PersistentVolumeClaim:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: buildpacks-source-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Mi
除了默认的EKS配置之外,我没有更改其他任何内容,也没有添加/更改任何PersistentVolume
或StorageClass
(实际上我甚至不知道如何做)。由于默认的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 可用区提供,并且创建了由我们上面描述的PersistendVolumeClaim
应用程序生成的持久卷(PV)。
为了检查这一点,您需要使用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
接着使用kubectl describe node <node-name>
命令查看Label
部分:
$ 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.internal
的failure-domain.beta.kubernetes.io/region
定义为eu-central-1
,并且将az与failure-domain.beta.kubernetes.io/zone
定义为eu-central-1b
。
而另一个节点则将failure-domain.beta.kubernetes.io/zone
定义为az 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
字段
现在,我们应该检查手动申请PersistentVolumeClaim
后自动分配的PersistentVolume
。使用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
...
使用标签topology.kubernetes.io/zone
在azeu-central-1c
配置了 PersistentVolume
,这导致我们的Pod抱怨找不到它们的卷——因为它们位于完全不同的az!
3. 添加allowedTopologies
到StorageClass
如Kubernetes文档中所述,解决这个问题的一种方法是向StorageClass
添加allowedTopologies
配置。如果您已经像我一样配置了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
配置定义了
PersistentVolume
的
failure-domain.beta.kubernetes.io/zone
必须是
eu-central-1a
或者
eu-central-1b
,而不是
eu-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
,我们需要在pvc.yml
中的PersistendVolumeClaim定义中添加storageClassName: gp2
:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: buildpacks-source-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Mi
storageClassName: gp2
最后使用kubectl apply -f pvc.yml
重新应用PersistentVolumeClaim
,这样应该可以解决错误。