Вопрос или проблема
Я недавно завершил работу Kubernetes Pod, на котором работал gunicorn, и теперь, когда он находится на более новом узле, он не запускается.
Когда он работал, журналы запуска выглядели так:
$ k logs pph-similarity-5f9b5d7d88-4k6nt app
[2025-02-07 09:00:48 +0000] [1] [INFO] Starting gunicorn 19.7.0
[2025-02-07 09:00:48 +0000] [1] [INFO] Listening at: unix:/sock/gunicorn.sock (1)
[2025-02-07 09:00:48 +0000] [1] [INFO] Using worker: sync
[2025-02-07 09:00:48 +0000] [9] [INFO] Booting worker with pid: 9
[2025-02-07 09:00:48 +0000] [11] [INFO] Booting worker with pid: 11
Узел, на котором работал gunicorn, использовал Bottlerocket OS 1.14.2 и containerd 1.6.20:
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-10-56-47-176.ec2.internal Ready <none> 585d v1.27.3-eks-6f07bbc 10.56.47.176 <none> Bottlerocket OS 1.14.2 (aws-k8s-1.27) 5.15.117 containerd://1.6.20+bottlerocket
Теперь он не работает, журналы следующие:
$ k logs pph-similarity-7f95fcf997-xfbbf app
[2025-02-19 13:13:28 +0000] [1] [INFO] Starting gunicorn 19.7.0
[2025-02-19 13:13:28 +0000] [1] [ERROR] Retrying in 1 second.
[2025-02-19 13:13:29 +0000] [1] [ERROR] Retrying in 1 second.
[2025-02-19 13:13:30 +0000] [1] [ERROR] Retrying in 1 second.
[2025-02-19 13:13:31 +0000] [1] [ERROR] Retrying in 1 second.
[2025-02-19 13:13:32 +0000] [1] [ERROR] Retrying in 1 second.
[2025-02-19 13:13:33 +0000] [1] [ERROR] Can't connect to /sock/gunicorn.sock
Gunicorn не может создать файл сокета.
Более новый узел на 2 года современнее и использует Bottlerocket OS 1.32.0
и containerd 1.7.24
:
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-10-56-45-144.ec2.internal Ready <none> 59m v1.31.4-eks-0f56d01 10.56.45.144 <none> Bottlerocket OS 1.32.0 (aws-k8s-1.31) 6.1.124 containerd://1.7.24+bottlerocket
Так как образ контейнера не изменился, причиной проблемы должно быть что-то из следующих вариантов:
- Обновление Bottlerocket с
1.14.2
до1.32.0
? (Я не заметил ничего очевидного в CHANGELOG) - или обновление containerd с
1.6.20
до1.7.24
? - или обновление Kubernetes-демона на узле с
v1.27.3
доv1.31.4
?
Я предполагаю, что проблема может быть связана с SELinux или AppArmor?
Дополнительная информация о моей точной настройке (на случай, если она будет полезной)
Образ контейнера, который запускается в Pod, создается с помощью Dockerfile:
cat Dockerfile
FROM python:3.6.6-slim
RUN mkdir -p /app
WORKDIR /app
COPY requirements.txt .
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
COPY . .
ENV FLASK_APP=manage.py
CMD ["gunicorn", "--reload", "-c", "config/gunicorn.conf", "manage:app"]
Это конфигурация gunicorn:
$ cat config/gunicorn.conf
import multiprocessing
bind = "unix:/sock/gunicorn.sock"
workers = 2
timeout = 120
Манифест развертывания Kubernetes также важен, потому что файл сокета помещается в папку, которая создается через emptyDir
configmap. Вот этот фрагмент:
...
containers:
- name: app
image: blahblah/similarity:v294
readinessProbe:
exec:
command:
- flask
- --version
volumeMounts:
- name: app-socket
mountPath: /sock
- name: nginx
image: blahblah/nginx_base
readinessProbe:
httpGet:
path: /nginx_ready
port: 80
initialDelaySeconds: 1
periodSeconds: 10
ports:
- containerPort: 80
volumeMounts:
- name: app-socket
mountPath: /sock
- name: nginx-config-volume
mountPath: /etc/nginx/conf.d/
volumes:
# Для связи приложения similarity с nginx
- name: app-socket
emptyDir: {}
- name: nginx-config-volume
configMap:
name: pph-similarity-nginx-config
Разрешения для папки /sock
в порядке:
k exec -it pph-similarity-5db4fd8d8d-4dzxt -c nginx -- ls -ld /sock
drwxrwxrwx 2 root root 6 Feb 25 15:09 /sock
Ответ или решение
При появлении проблемы с невозможностью создания сокетного файла Gunicorn после обновления узла Kubernetes необходимо рассмотреть несколько потенциальных причин и решений. Давайте разберём ситуацию пошагово.
Теория
-
Обновление ОС Bottlerocket: Bottlerocket OS обновился с версии 1.14.2 до 1.32.0. Обновления операционной системы могут включать изменения в системной безопасности, которые затрагивают работу служб, особенно в части управления файлами и каталогами. Одним из факторов могут быть изменения в настройках SELinux или AppArmor, которые могли быть внедрены в более новые версии ОС. Эти изменения могут предотвратить создание или доступ к файлам сокетов, если безопасность настроена таким образом, чтобы ограничить права сервиса в контейнере.
-
Обновление контейнерного рантайма containerd: Версия containerd обновилась с 1.6.20 до 1.7.24. Хотя это и менее вероятно, containerd также может влиять на создание и доступ к файловым сокетам. Например, изменения в управлении пространствами или в организационных структурах могут повлиять на поведение контейнеров при работе с файловыми системами.
-
Обновление версии Kubernetes: Версия Kubernetes поднялась с v1.27.3 до v1.31.4. Изменения в Kubernetes могут повлиять на поведение подов, особенно если были внесены изменения в механизм управления разрешениями или пространство имен, которое используют контейнеры для работы с файловыми системами.
Пример
Возьмем ваш сценарий:
- Обновился узел Kubernetes, на котором располагается приложение Gunicorn.
- Абсолютно та же контейнерная среда продолжает использоваться, что указывает на то, что изменения в самой среде не коснулись приложений напрямую, а проблема заключается в инфраструктуре.
- Логи показывают, что Gunicorn пытается подключиться к сокету, но не может создать его, повторно пытаясь это сделать каждые секунду.
Применение
-
Проверьте SELinux/AppArmor: Убедитесь, что изменения SELinux или AppArmor, которые могли произойти, не запрещают созданию сокета. Вы можете временно отключить эти сервисы для тестирования:
setenforce 0 # для SELinux sudo aa-teardown # для AppArmor, если используется
После отключения перезапустите под и проверьте, создается ли сокет.
-
Проверка прав на /sock: Несмотря на то, что права выглядят корректно (
drwxrwxrwx
), необходимо убедиться, что это актуально для всех компонентов, которые имеют доступ к этому общему каталогу. Попробуйте выполнить стандартный тест на запись в этот каталог из контейнера:k exec -it <pod-name> -- touch /sock/testfile
-
Системные логи для диагностики: Проверьте системные логи Bottlerocket и контейнерные логи Kubernetes на предмет наличия сообщений об ошибках, связанных с доступом к файловой системе. Это может дать подсказки относительно ограничения на уровне ядра.
-
Перепроверка конфигураций Nginx: Убедитесь, что изменения конфигурации Nginx, используемого вместе с Gunicorn, не влияют на доступ к сокету. Все изменения конфигурации в свежих версиях Nginx или вашего использующегося образа могут отразиться на путях и доступности сокета.
-
Дополнительная проверка version compatibility: Некоторые изменения в компонентах Kubernetes или containerd могли изменить совместимость API или версий протоколов. Убедитесь, что версия Gunicorn и его конфигурации совместимы с обновленной инфраструктурой, возможно, потребуется обновить их.
Следуя этим рекомендациям, вы сможете определить и исправить проблему. Если ни одно решение не работает, можно обратиться к детальным логам контейнера и системными журналами для более детального анализа. Если проблема не разрешается, возможно, стоит рассмотреть обращение в поддержку Bottlerocket или прямое обсуждение проблемы с командой разработчиков, чтобы выяснить возможные изменения, которые могли вызвать проблему.