1. Фон
В процессе работы программы на последнем проекте я сталкивался с различными проблемами, такими как статус ‘NotReady’ в ‘kubectl get nodes’, зависание ‘kubectl exec’ или внезапная смена состояния Pod на Evicted. В связи с этим я подготовил руководство по реагированию на проблемы в среде KubeEdge, основываясь на реально встреченных четырех типах сбоев.
2. Введение
В отличие от обычного кластера на базе Kubernetes, в KubeEdge между облаком и узлами на краю существует дополнительный CloudCore ↔ EdgeCore туннель. Благодаря этому, даже в условиях нестабильной сети на местах можно управлять узлами на краю, но это также делает причины сбоев ещё более сложными.
3. Типы сбоев
|
Тип сбоя 1 |
Неудача ‘kubectl exec’ — "unexpected EOF" |
|---|
(1) Симптомы
$ kubectl exec -it my-app-6jf2m -n iot-edge -- /bin/bash
error: Internal error occurred: error sending request:
Post "https://192.168.1.3:10351/exec/...": unexpected EOF
Выполнение ‘kubectl exec’ приводит к разрыву соединения, в результате чего ничего не происходит. Хотя другие Pod на том же узле могут показывать статус Running, exec может не работать.
(2) Анализ причин
Для того чтобы ‘kubectl exec’ работал в KubeEdge, необходимо, чтобы была активирована функция EdgeStream. Если эта функция отключена, туннель exec, соединяющий API Server → CloudCore → EdgeCore, не будет установлен.
Обычный Kubernetes напрямую обращается к API-серверу на 10250 порту kubelet для обработки exec, но у KubeEdge этого пути нет. Без EdgeStream exec, логи и port-forward не работают.
[kubectl exec flow in KubeEdge]
API Server
↓
CloudCore (streamPort: 10003)
↓ ← without this tunnel, unexpected EOF occurs
EdgeCore (edgeStream.server)
↓
컨테이너
(3) Способы решения
Проверка и активация настроек CloudCore:
# cloudcore.yaml
cloudStream:
enable: true
streamPort: 10003
tlsTunnelCAFile: /etc/kubeedge/ca/rootCA.crt
tlsTunnelCertFile: /etc/kubeedge/certs/server.crt
tlsTunnelPrivateKeyFile: /etc/kubeedge/certs/server.key
Проверка и активация настроек EdgeCore:
# edgecore.yaml
edgeStream:
enable: true
handshakeTimeout: 30
readDeadline: 15
server: <CloudCore_IP>:10004
tlsTunnelCAFile: /etc/kubeedge/ca/rootCA.crt
tlsTunnelCertFile: /etc/kubeedge/certs/server.crt
tlsTunnelPrivateKeyFile: /etc/kubeedge/certs/server.key
writeDeadline: 15
После изменения настроек необходимо перезапустить обе стороны:
# On the master node where CloudCore is running
systemctl restart cloudcore.
# On the edge node
systemctl restart edgecore
|
Тип неисправности 2 |
Выталкивание Pod из-за DiskPressure |
|---|
(1) Симптомы
$ kubectl get po -A -o wide | grep <NodeName>
iot-edge chronograf-xxxxx 0/1 Evicted 0 2m
iot-edge influxdb-xxxxx 0/1 Evicted 0 9m
iot-edge my-app-xxxxx 0/1 Evicted 0 14m
Pod, находящиеся на конкретном узле, становятся в состоянии Evicted все сразу. Если не один или два, а все Pod на данном узле были исключены, это может указывать на проблему с ресурсами на уровне узла.
(2) Анализ причин
Eviction — это механизм принудительного завершения Pod, который срабатывает, когда kubelet (в KubeEdge это edgecore) обнаруживает нехватку ресурсов на узле. Причину можно напрямую проверить через ‘kubectl describe node’:
kubectl describe node <NodeName> | grep -A5 "Conditions"
В реальных случаях появлялось сообщение следующего вида:
DiskPressure True ...
Message: The node was low on resource: ephemeral-storage.
Threshold: 37556267476 (~35GB)
Available: 36674584Ki (~34.9GB)
В момент, когда доступное место на диске падает ниже порога, kubelet принудительно вытаскивает Pod с данного узла.
Проверка использования диска
Подключитесь к узлу Edge по SSH и узнайте, где используется диск:
df -h
du -sh /* 2>/dev/null | sort -rh | head -15
В реальных случаях одна из директорий логов конкретного приложения занимала 89% всего диска.
$ du -sh /var/app/logs/*/
166G /var/app/logs/device-001.ASSET/
(3) Решение
Очистка старых логов(Обязательно проверьте необходимость сохранения перед удалением!)
# Delete files older than N days
find /var/app/logs -mtime +7 -type f -delete
Очистка неиспользуемых образов контейнеров
crictl rmi --prune
Перезапуск edgecore для переоценки DiskPressure
systemctl restart edgecore
Очистка и перераспределение Evicted Pod
# On the master node
kubectl get pods -A | grep Evicted | awk '{print "kubectl delete pod " $2 " -n " $1}' | sh
|
Тип ошибки 3 |
Init Container ImagePullBackOff — сбой DNS |
|---|
(1) Симптомы
$ kubectl describe pod my-app-qn6r8 -n iot-edge
Init Containers:
init-snapshot:
State: Waiting
Reason: ImagePullBackOff
Image: registry.company.internal:5000/infra/busybox:latest
Сбой извлечения изображения происходит не в основном контейнере, а в Init Container. Если Init Container терпит неудачу, основной контейнер даже не запускается.
В этом случае, если посмотреть на предыдущее состояние завершения основного контейнера, оно будет следующим:
Last State: Terminated
Reason: Unknown
Exit Code: 255
Код завершения 255 означает, что контейнерная среда выполнения принудительно завершила процесс, что в большинстве случаев является результатом проблем на уровне узла (предыдущий DiskPressure, обрывы сети и т. д.).
(2) Анализ причин — сбой DNS частного реестра
Причины ImagePullBackOff разнообразны, но в IoT-средах с использованием корпоративного частного реестраПроблема с DNSпроисходит особенно часто.
Способ проверки:
# On the edge node
nslookup registry.company.internal
Если появляется DNS SERVFAIL, это означает, что домен не может быть разрешён.
server can't find registry.company.internal: SERVFAIL
(3) Способы решения
Быстрое временное решение — регистрация в /etc/hosts
После проверки IP на другом нормальном узле зарегистрируйте его непосредственно в ‘/etc/hosts’:
# Resolve IP from a healthy node
nslookup registry.company.internal
# Add entry to /etc/hosts on the affected node
echo "<IP> registry.company.internal" >> /etc/hosts
# Test image pull
crictl pull registry.company.internal:5000/infra/busybox:latest
Устранение коренной причины DNS
После временных мер проверьте состояние ‘systemd-resolved’ и перезапустите его:
systemctl status systemd-resolved
systemctl restart systemd-resolved
# Verify DNS resolution is restored
nslookup registry.company.internal
Перезапуск Pod после восстановления DNS
# Force delete and recreate the Pod from the master node
kubectl delete pod my-app-qn6r8 -n iot-edge --force --grace-period=0
# Watch Pod status
kubectl get pod -n iot-edge -w | grep my-app
4. Итоги
- Если ‘kubectl exec’ не работает, это может быть не проблема kubelet, а проблема конфигурации EdgeStream.
- Если Pod массово вытесняются, сначала проверьте использование дискового пространства на узле.
- ImagePullBackOff может указывать не на проблему с образом, а на сбой DNS.
В условиях пограничной среды есть сложности, отличающиеся от дата-центра, такие как нестабильность сетевой связи на месте, ограниченное дисковое пространство и сложное управление несколькими распределенными узлами. Если команды в команде поделятся этим контрольным списком, время реагирования может быть сокращено, независимо от того, кто находится на дежурстве.
Jsia