Вопрос или проблема
Я сейчас изучаю Kubernetes и осваиваю его, настраивая кластер Microk8s на тестовых машинах, которые у меня есть. Я хотел бы быть облачно-независимым с вычислительными ресурсами в кластере, поэтому у меня есть простые тестовые ВМ или что-то, что не связано ни с одним облачным провайдером. Тем не менее, для простоты я решил использовать облачные сервисы только для хранения, так как hostpath был отличным для тестирования, но я понял, что его не следует использовать в производственной среде, поэтому я пробую что-то более реальное.
В качестве старта я выбрал Azure Blob Storage дляProvision storage в моем тестовом кластере. Я использовал blob-csi-driver
, чтобы подключиться к Azure Blob Storage и настроить для него класс хранения. Я успешно создал PVC и получил статус “Bound”. Однако, когда я пытаюсь использовать этот PVC в поде, он не удается с следующими ошибками в событиях пода: причина FailedMount
с сообщением об ошибке MountVolume.MountDevice failed for volume [...] timeout waiting for mount
и directory is already mounted
.
Я не понимаю, как директория могла быть уже смонтирована, так как я использую свежий кластер Microk8s каждый раз, когда я тестирую это, и PVC создается и связывается успешно именно для этого пода, который я пытаюсь создать.
Есть ли что-то, что я упускаю в настройке, которую я сделал?
Ниже приведены все шаги, которые я предпринял, чтобы настроить кластер, CSI драйвер, класс хранения, PVC и под для справки и воспроизводимости:
- Настройка кластера Microk8s:
# - Отключить своп и файрвол
# - Установить Microk8s
sudo snap install microk8s --classic
# - Между тестами сбросить Microk8s
sudo microk8s reset
# - Включить базовые дополнения
sudo microk8s enable dns
sudo microk8s enable ingress
# - Настроить разрешения пользователя для доступа к Microk8s и Kubectl и т. д.
- Настройка CSI драйвера для Azure Blob Storage:
# - Убедиться, что мастер-узел имеет необходимую метку 'control-plane'
# В Microk8s, мастер-узел, вероятно, не имеет этой конкретной метки
kubectl get nodes --selector="node-role.kubernetes.io/control-plane"
kubectl label node my-vm-hostname node-role.kubernetes.io/control-plane=""
# - Установить blob-csi-driver
# Создать для развертывания на управляющей плоскости с 1 репликой (в настоящее время только один узел в кластере для тестирования этого)
helm upgrade --install \
blob-csi-driver \
blob-csi-driver \
--repo https://raw.githubusercontent.com/kubernetes-sigs/blob-csi-driver/master/charts \
--namespace blob-csi-driver \
--create-namespace \
--version v1.25.0 \
--set node.enableBlobfuseProxy='true' \
--set controller.replicas="1" \
--set controller.runOnControlPlane="true"
# - Посмотреть созданные ресурсы и дождаться их готовности
kubectl get -n blob-csi-driver all
Созданные ресурсы, как и ожидалось:
NAME READY STATUS RESTARTS AGE
pod/csi-blob-controller-5d589dbc77-qvqln 4/4 Running 0 42s
pod/csi-blob-node-6t6g7 4/4 Running 0 42s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/csi-blob-node 1 1 1 1 1 kubernetes.io/os=linux 42s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/csi-blob-controller 1/1 1 1 42s
NAME DESIRED CURRENT READY AGE
replicaset.apps/csi-blob-controller-5d589dbc77 1 1 1 42s
- Создание класса хранения для Azure Blob Storage:
# - Создать пространство имен для конфигурации класса хранения
kubectl create namespace blob-storage-class
kubectl config set-context --current --namespace=blob-storage-class
# - Создать секрет для учетной записи Azure Blob Storage
kubectl create secret generic azure-secret \
--type=Opaque \
--from-literal azurestorageaccountname="azurestorageaccountname" \
--from-literal azurestorageaccountkey='azurestorageaccountkey'
# - Создать класс хранения (без пространств имен)
# Рассмотреть класс хранения как дефолтный для его использования в PVC
kubectl apply -f - <<EOF
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: blob-storage-class
annotations:
"storageclass.kubernetes.io/is-default-class": "true"
provisioner: blob.csi.azure.com
allowVolumeExpansion: true
volumeBindingMode: Immediate # WaitForFirstConsumer
parameters:
csi.storage.k8s.io/provisioner-secret-name: azure-secret
csi.storage.k8s.io/provisioner-secret-namespace: blob-storage-class
csi.storage.k8s.io/node-stage-secret-name: azure-secret
csi.storage.k8s.io/node-stage-secret-namespace: blob-storage-class
EOF
# - Посмотреть созданные ресурсы
kubectl get all,secret,sc
Созданные ресурсы, как и ожидалось:
NAME TYPE DATA AGE
secret/azure-secret Opaque 2 42s
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
storageclass.storage.k8s.io/blob-storage-class (default) blob.csi.azure.com Delete Immediate true 42s
- Создание тестового приложения с PVC, использующим класс хранения.
Сначала создадим PVC:
# - Создать пространство имен для тестового приложения
kubectl create namespace test-app
kubectl config set-context --current --namespace=test-app
# - Создать PVC, используя класс хранения
kubectl apply -f - <<EOF
---
# Запрос на постоянный объем
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
EOF
# - Посмотреть созданный PVC
kubectl get all,pvc
Все работает нормально до сих пор. PVC создан и успешно связан:
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/test-pvc Bound pvc-3c6c062d-9194-40ad-980c-c5677234205e 1Gi RWO blob-storage-class <unset> 42s
Также хранилище успешно создано и отображается в портале Azure, названном в честь PVC.
Затем создадим остальную часть тестового приложения, используя PVC:
# Все еще в пространстве имен 'test-app'
# - Создать развертывание, сервис и ingress
kubectl apply -f - <<EOF
---
# Развертывание
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-deployment
labels:
app: test-deployment
spec:
replicas: 1
selector:
matchLabels:
app: test-deployment
template:
metadata:
labels:
app: test-deployment
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
volumeMounts:
- name: test-volume
mountPath: /usr/share/nginx/html
volumes:
- name: test-volume
persistentVolumeClaim:
claimName: test-pvc
---
# Сервис
apiVersion: v1
kind: Service
metadata:
name: test-deployment
spec:
selector:
app: test-deployment
ports:
- protocol: TCP
port: 80
targetPort: 80
---
# Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
rules:
- host: test-app.localhost
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: test-deployment
port:
number: 80
EOF
# - Посмотреть созданные ресурсы
kubectl get all,ingress,pvc
Под застрял в состоянии ContainerCreating
:
NAME READY STATUS RESTARTS AGE
pod/test-deployment-65c7b4c555-sxzd6 0/1 ContainerCreating 0 42s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/test-deployment ClusterIP 10.152.183.148 <none> 80/TCP 42s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/test-deployment 0/1 1 0 42s
NAME DESIRED CURRENT READY AGE
replicaset.apps/test-deployment-65c7b4c555 1 1 0 42s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
persistentvolumeclaim/test-pvc Bound pvc-3c6c062d-9194-40ad-980c-c5677234205e 1Gi RWO blob-storage-class <unset> 69s
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/test-ingress public test-app.localhost 127.0.0.1 80, 443 42s
Под терпит неудачу с следующими событиями (переформатировано для удобства чтения):
kubectl describe -n test-app pod test-deployment-65c7b4c555-sxzd6
События:
Тип Причина Возраст От Сообщение
---- ------ ---- ---- -------
Normal Запланировано 2м17с default-scheduler
Успешно назначен test-app/test-deployment-65c7b4c555-sxzd6 на my-vm-hostname
Предупреждение Неудача монтирования 76с kubelet
MountVolume.MountDevice failed for volume "pvc-3c6c062d-9194-40ad-980c-c5677234205e" : rpc error:
code = Unknown desc = failed to wait for mount: timeout waiting for mount
/var/snap/microk8s/common/var/lib/kubelet/plugins/kubernetes.io/csi/blob.csi.azure.com/[hash]/globalmount
Предупреждение Неудача монтирования 11с (x7 на 75с) kubelet
MountVolume.MountDevice failed for volume "pvc-3c6c062d-9194-40ad-980c-c5677234205e" : rpc error:
code = Internal desc = Mount failed with error: rpc error:
code = Unknown desc = exit status 1 Error: directory is already mounted
, output:
Пожалуйста, обратитесь к http://aka.ms/blobmounterror для возможных причин и решений для ошибок монтирования.
Конечно, тестирование ingress не работает, так как под не работает.
curl -H "Host: test-app.localhost" http://localhost
<html>
<head><title>503 Сервис временно недоступен</title></head>
<body>
<center><h1>503 Сервис временно недоступен</h1></center>
<hr><center>nginx</center>
</body>
</html>
И, спустя некоторое время, под все еще застрял в состоянии ContainerCreating
, с той же ошибкой в событиях:
kubectl describe -n test-app pod test-deployment-65c7b4c555-sxzd6
Под терпит неудачу с следующими событиями (переформатировано для удобства чтения):
```bash
kubectl describe -n test-app pod test-deployment-65c7b4c555-sxzd6
События:
Тип Причина Возраст От Сообщение
---- ------ ---- ---- -------
Предупреждение Неудача монтирования 2м (x16 на 20м) kubelet
MountVolume.MountDevice failed for volume "pvc-3c6c062d-9194-40ad-980c-c5677234205e" : rpc error:
code = Internal desc = Mount failed with error: rpc error:
code = Unknown desc = exit status 1 Error: directory is already mounted
, output:
Пожалуйста, обратитесь к http://aka.ms/blobmounterror для возможных причин и решений для ошибок монтирования.
Я не уверен, что я упускаю здесь. Я не понимаю ошибку или что могло бы ее вызвать. Я пытался повторить настройку несколько раз и на двух разных машинах с разными ОС, но возникает одна и та же проблема.
Буду очень признателен за любую помощь или направление, так как мне действительно хотелось бы понять и извлечь уроки из этого.
Любой альтернативный (лучший?) подход, который я мог бы предпринять, также будет приветствоваться.
Заранее спасибо!
Ответ или решение
Причины ошибки FailedMount на PVC из Azure Blob Storage в Microk8s и их решение
Кстати, хорошие новости! Вы уже на верном пути, создавая кластер Microk8s и тестируя его с использованием Azure Blob Storage для более реалистичной конфигурации хранения. Давайте подробно разберем возникшую проблему с ошибкой FailedMount
.
Понимание проблемы
В вашем случае, под не может успешно смонтировать Persistent Volume Claim (PVC) из-за ошибок, связанных с монтированием. Наиболее распространенные ошибки, которые вы упомянули:
MountVolume.MountDevice failed for volume [...] timeout waiting for mount
directory is already mounted
Эти ошибки указывают на несколько потенциальных проблем, включая неправильную конфигурацию или конфликты ресурсов. Особенно сообщения о том, что «каталог уже смонтирован», могут указывать на то, что при создании PVC или пода произошел конфликт.
Потенциальные причины и рекомендации
-
Конфликты в монтировании:
- Проверка существующих монтирований: Возможно, что ваш PVC уже используется в другом поде или монтировании. Используйте команду
kubectl get pods --all-namespaces
для проверки статуса всех подов, чтобы удостовериться, что PVC не используется. - Сброс ресурсов: Если у вас есть возможность, полностью очистите кластер Microk8s с помощью
sudo microk8s.reset
, а затем попробуйте заново создать PVC и связанные с ним ресурсы.
- Проверка существующих монтирований: Возможно, что ваш PVC уже используется в другом поде или монтировании. Используйте команду
-
Неправильная конфигурация CSI драйвера:
- Убедитесь, что все зависимости CSI драйвера правильно установлены. Вы использовали команду Helm для установки, но стоит проверить логи, чтобы удостовериться, что драйвер работает корректно.
- Используйте команду
kubectl logs -n blob-csi-driver <имя-pod>
, чтобы просмотреть логи подов CSI драйвера. Ошибки могут подсказать, где проблема.
-
Проблемы с сетевым взаимодействием:
- Если ваш кластер Microk8s работает в окружении с ограничениями сети или брандмауэром, это может повлиять на возможность подключения к Azure Blob Storage.
-
Параметры конфигурации хранения:
- Проверьте параметры, указанные в классе хранения и секрете. Убедитесь, что все данные (имя хранилища, ключи и т.д.) правильные. Иногда небольшие ошибки в конфигурации могут привести к столь же многим ошибкам.
-
Границы ресурсов:
- Изучите, нет ли у вашего кластера ограничений на ресурсы. Конфликтующие лимиты могут вызывать проблемы при монтировании.
-
Доменные имена и маршрутизация:
- Также убедитесь, что ваша конфигурация Ingress корректна, особенно если вы используете локальный хост и виртуальные хосты.
Альтернативные подходы
Если проблема не решается, вы можете рассмотреть следующие альтернативные подходы:
- Использование Local Path: Если ваша цель — локальное развертывание для тестирования, возможно, имеет смысл рассмотреть использование локального пути хранения (Local Path Storage). Это уменьшит зависимость от облачного провайдера.
- Другие облачные решения: Вы также можете рассмотреть использование других облачных хранилищ или специфичных для Kubernetes решений, таких как Azure Files, которые могут предложить более надежный способ управления хранилищем.
Заключение
Проблемы с монтированием PVC в вашем Microk8s кластере могут быть связаны с несколькими моментами — от конфликта ресурсов до ошибок в настройках. Проанализируйте этапы, которые мы обсудили, и попробуйте решить проблему шаг за шагом. Если у вас будут возникать дополнительные вопросы в процессе, не стесняйтесь обращаться за поддержкой. Удачи вам в дальнейшем изучении Kubernetes!