Kubernetes Pod Предупреждение: 1 узел (ы) столкнулся с конфликтом узлов тома
Я пытаюсь настроить кластер kubernetes. У меня есть классы Persistent Volomue, Persistent Volume Claim и Storage, все они настроены и работают, но когда я хочу создать модуль из развертывания, модуль создается, но он зависает в состоянии ожидания. После описания я получаю только это предупреждение "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: {}
18 ответов
Ошибка "конфликт сродства узла тома" возникает, когда постоянный том утверждает, что используемый модуль запланирован в разных зонах, а не в одной зоне, и поэтому фактический модуль не может быть запланирован, поскольку он не может подключиться к тому из другая зона. Чтобы проверить это, вы можете увидеть детали всех постоянных томов. Чтобы проверить это, сначала получите ваши PVC:
$ kubectl get pvc -n <namespace>
Затем получите сведения о постоянных томах (не утверждения о томах)
$ kubectl get pv
Найдите PV, которые соответствуют вашим PVC и опишите их
$ kubectl describe pv <pv1> <pv2>
Вы можете проверить Source.VolumeID для каждого из PV, скорее всего, это будут разные зоны доступности, поэтому ваш модуль выдаст ошибку привязки. Чтобы исправить это, создайте класс хранения для отдельной зоны и используйте этот класс хранения в своем 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
0. Если вы не нашли решение в других ответах...
В нашем случае ошибка произошла в кластере AWS EKS, только что подготовленном с помощью Pulumi (см. полный исходный код здесь ). Эта ошибка сводила меня с ума, так как я ничего не менял, просто создал, как описано в документации Buildpacks Tekton:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: buildpacks-source-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Mi
Я больше ничего не менял в конфигурации EKS по умолчанию, а также ничего не добавлял/не менял (на самом деле я даже не знал, как это сделать). Поскольку настройка EKS по умолчанию, кажется, полагается на 2 узла, я получил ошибку:
0/2 nodes are available: 2 node(s) had volume node affinity conflict.
Прочитав ответ Сонака Роя, я впервые понял, что делать, но не знал, как это сделать . Итак, для заинтересованных людей вот все мои шаги по устранению ошибки :
1. Проверьте метки узлов EKS.
Как описано в разделе
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.internal
имеет
failure-domain.beta.kubernetes.io/region
определяется как
eu-central-1
и аз с до .
А другой узел определяет az :
$ 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. Проверьте
topology.kubernetes.io
поле
Теперь мы должны проверить автоматически предоставленный после того, как мы вручную применили наш файл . Использовать
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
в az, из-за чего наши поды жалуются, что не находят своего тома — ведь они находятся в совершенно другом az!
3. Добавить в
Как указано в документации Kubernetes, одним из решений проблемы является добавление конфигурации в файл . Если вы уже подготовили кластер EKS, как я, вам нужно получить уже определенный с помощью
kubectl get storageclasses gp2 -o yaml
Сохраните его в файл с именем и добавьте раздел, соответствующий вашему узлу.
failure-domain.beta.kubernetes.io
такие ярлыки:
allowedTopologies:
- matchLabelExpressions:
- key: failure-domain.beta.kubernetes.io/zone
values:
- eu-central-1a
- eu-central-1b
The
allowedTopologies
конфигурация определяет, что
failure-domain.beta.kubernetes.io/zone
принадлежащий
PersistentVolume
должен быть либо в
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
Примените расширенную конфигурацию к своему кластеру EKS с помощью
kubectl apply -f storage-class.yml
4. Удалите, добавьте к нему и повторно примените его
Чтобы все снова заработало, нам нужно удалить первый.
Чтобы сопоставить с нашим ранее определить
StorageClass
нам нужно добавить
storageClassName: gp2
к определению PersistendVolumeClaim в нашем
pvc.yml
:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: buildpacks-source-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Mi
storageClassName: gp2
Наконец, повторно примените
PersistentVolumeClaim
с
kubectl apply -f pvc.yml
. Это должно устранить ошибку.
Есть несколько вещей, которые могут вызвать эту ошибку:
Узел не помечен правильно. У меня была эта проблема в AWS, когда у моего рабочего узла не было соответствующих меток (хотя у мастера они были), например:
failure-domain.beta.kubernetes.io/region=us-east-2
failure-domain.beta.kubernetes.io/zone=us-east-2c
После исправления узла с метками ошибка "1 узел (ы) имела конфликт сродства узла тома" исчезла, поэтому PV, PVC с модулем были успешно развернуты. Значение этих меток зависит от поставщика облачных услуг. По сути, именно облачный провайдер (с параметром -cloud-provider, определенным в cube-controller, API-server, kubelet) устанавливает эти метки. Если соответствующие метки не установлены, проверьте правильность интеграции с CloudProvider. Я использовал kubeadm, поэтому его сложно установить, но с другими инструментами, например, kops, он работает сразу.
Исходя из определения PV и использования поля nodeAffinity, вы пытаетесь использовать локальный том (см. Ссылку на описание локального тома, официальные документы), а затем убедитесь, что вы установили "Поле NodeAffinity" таким образом (это работало в моем дело на AWS):
nodeAffinity:
required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - my-node # it must be the name of your node(kubectl get nodes)
Так что после создания ресурса и запуска описать его там он будет выглядеть так:
Required Terms:
Term 0: kubernetes.io/hostname in [your node name]
- Определение StorageClass (названное local-storage, которое здесь не публикуется) должно быть создано с VolumeBindingMode, установленным в WaitForFirstConsumer, чтобы локальное хранилище работало должным образом. Обратитесь к примеру здесь, локальное описание класса хранения, официальный документ, чтобы понять причину этого.
В AWS EKS вы также можете столкнуться с этой проблемой, если забудете установить надстройку EKS aws-ebs-csi-driver перед обновлением кластера Kubernetes с версии 1.22 до версии 1.23.
Вы также можете установить дополнение после обновления (хотя и с некоторыми перерывами в обслуживании).
Обязательно ознакомьтесь с часто задаваемыми вопросами по AWS: https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi-migration-faq.html .
"1 узел (ы) имел объем сродство узла конфликт" ошибка создается с помощью планировщика, поскольку он не может планировать свой стручок узла, который согласуется сpersistenvolume.spec.nodeAffinity
в вашем PersistentVolume (PV).
Другими словами, вы говорите в своем PV, что под, использующий этот PV, должен быть запланирован узел с меткой kubernetes.io/cvl-gtv-42.corp.globaltelemetrics.eu = master
, но по какой-то причине это невозможно.
Могут быть разные причины, по которым ваш модуль не может быть назначен на такой узел:
- У пода есть сходства узлов, подов и т. Д., Которые конфликтуют с целевым узлом.
- Целевой узел испорчен
- Целевой узел достиг предельного количества пакетов на узел.
- Нет узла с данной меткой
Место для начала поиска причины - определение узла и модуля.
После некоторого расследования, вызывающего головную боль, необходимо проверить несколько вещей:
Лазурь:
- В вашем кластере выбрано более одной зоны? (зона 1, 2, 3)
- У вашего класса хранения по умолчанию есть правильный поставщик хранилища?(ZRS Zone-Redundant-Storage)
Если не:
- измените класс хранения, чтобы использовать правильный поставщик
- создать резервную копию данных PV
- остановить развертывание, использующее PVC (установить для реплик значение 0)
- удалите PVC и убедитесь, что соответствующий PV удален.
- повторно применить yaml конфигурации PVC (без ссылки на старое имя класса хранения)
- запустите развертывание, использующее PVC (установите для реплик значение 1)
- вручную импортировать резервные данные
Пример класса хранилища для AKS:
allowVolumeExpansion: true
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: zone-redundant-storage
parameters:
skuname: StandardSSD_ZRS
provisioner: disk.csi.azure.com
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
ГКЭ:
- В вашем кластере выбрано более одной зоны? (Зона А, В, С)
- Есть ли в вашем классе хранения по умолчанию параметр типа репликации? (тип репликации: региональный-PD)
Если не:
- измените класс хранения, чтобы использовать правильные параметры
- создать резервную копию данных PV
- остановить развертывание, использующее PVC (установить для реплик значение 0)
- удалите PVC и убедитесь, что соответствующий PV удален.
- повторно применить yaml конфигурации PVC (без ссылки на старое имя класса хранения)
- запустите развертывание, использующее PVC (установите для реплик значение 1)
- вручную импортировать резервные данные
Пример класса хранилища для GKE:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: standard-regional-pd-storage
provisioner: pd.csi.storage.gke.io
parameters:
type: pd-standard
replication-type: regional-pd
volumeBindingMode: WaitForFirstConsumer
После этого PV будет иметь избыточность в выбранных зонах, что позволит модулю получать доступ к PV с других узлов в разных зонах.
У меня это произошло на GKE после обновления до k8s v1.25. В моем случае ничего из вышеперечисленного не сработало, поэтому я решил клонировать том, чтобы не потерять данные.
Этот пост побудил меня включить CSI-драйвер постоянного диска Compute Engine , который после включения решил мою проблему.
Отличный ответ Сонака Роя. У меня был такой же случай, когда PV создавался в другой зоне по сравнению с узлом, который должен был его использовать. Решение, которое я применил, было основано на ответе Сонака, только в моем случае было достаточно указать класс хранилища без списка "allowedTopologies", например:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: cloud-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
type: gp2
volumeBindingMode: WaitForFirstConsumer
Убедитесь, что узел kubernetes имеет требуемую метку. Вы можете проверить метки узлов, используя:
Один из узлов должен показать вам имя постоянного тома , с которым связан ваш модуль .
Этапы проверки:
- Опишите ваш постоянный том:
kubectl describe pv postgres-br-proxy-pv-0
Выход:
...
Node Affinity:
Required Terms:
Term 0: postgres-br-proxy in [postgres-br-proxy-pv-0]
...
- Показать метки узлов:
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
Если вы не получаете постоянную метку тома на узле , который использует ваш модуль, модуль не будет запланирован.
В моем случае основная причина заключалась в том, что постоянный том находится в us-west-2c, а новые рабочие узлы перезапускаются в us-west-2a и us-west-2b. Решение состоит в том, чтобы либо иметь больше рабочих узлов, чтобы они находились в большем количестве зон, либо удалить / расширить привязку узлов для приложения, чтобы большее количество рабочих узлов соответствовало требованиям для привязки к постоянному тому.
Другой случай от GCP GKE. Предположим, вы используете региональный кластер и создали два PVC. Оба были созданы в разных зонах (вы не заметили).
На следующем шаге вы пытаетесь запустить модуль, в котором оба PVC будут установлены в один модуль. Вы должны запланировать этот модуль для определенного узла в определенной зоне, но поскольку ваши тома находятся в разных зонах, 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
Следующий простой модуль:
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, потому что тома находятся в разных зонах.
Почти та же проблема, описанная здесь... https://github.com/kubernetes/kubernetes/issues/61620
"Если вы используете локальные тома, и узел выходит из строя, ваш модуль не может быть перенесен на другой узел. Он должен быть запланирован на тот же узел. Это предостережение об использовании локального хранилища, ваш модуль навсегда привязан к одному конкретному узел."
Скорее всего, вы просто сократили количество узлов в кластере кубернетов, и некоторые «регионы» больше не доступны ...
Кое-что стоит упомянуть ... если ваш модуль будет находиться в другой зоне, чем постоянный том, тогда:
- время доступа к вашему диску значительно снизится (ваше локальное постоянное хранилище больше не является локальным - даже с гипербыстрыми оптоволоконными соединениями Amazon / Google он все еще проходит через центры обработки данных)
- вы будете платить за «межрегиональную сеть» (в вашем счете AWS это что-то, что входит в «EC2-other», и только после детализации счета Aws вы можете это заметить)
В моем случае я работал сDocker Desktop
наWindows
, и мой пример использовал толькоdocker-desktop
значение как имя узла. поэтому настройка очень важна.
я добавилminikube
поскольку я использовал один узел. их может быть больше, если будут добавлены дополнительные узлы, напримерminikube-m02
.
spec:
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- minikube
kubectl get node
должно быть достаточно, чтобы указать имена узлов.
Одной из причин этого является то, что у вас есть определение, подобное приведенному ниже (Kafka Zookeeper в этом примере), которое использует несколько pvc для одного контейнера. Если они попадут на разные узлы, вы получите что-то вроде следующего:
..volume node affinity conflict
. Решение здесь состоит в том, чтобы использовать одно определение ПВХ и использовать
subPath
на
volumeMount
.
Проблема
...
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"
Другая причина возникновения этой ошибки — наличие нескольких узлов, использующих taints. В некоторых выпусках компонент DaemonSet драйвера EBS CSI по умолчанию не допускает всех испорченных данных; если вы пытаетесь запланировать Pod на узел с taint и из-за этого taint он не имеет
Я запускал кластер k8s на AWS. В моем случае PV описывался как
│ Node Affinity: │
│ Required Terms: │
│ Term 0: topology.kubernetes.io/zone in [ap-southeast-1a] │
│ topology.kubernetes.io/region in [ap-southeast-1]
Но когда я добавил
topology.ebs.csi.aws.com/zone=ap-southeast-1a
topology.ebs.csi.aws.com/region=ap-southeast-1
как метки к моему узлу, контейнер начал создаваться. Должен работать для вас, если вы работаете на AWS.
Мой случай был posthog (самообслуживание)
В моем случае я просто удалил