После обновления узла Kubernetes, Pod с запущенным gunicorn не может создать сокет-файл.

Вопрос или проблема

Я недавно завершил работу 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

Так как образ контейнера не изменился, причиной проблемы должно быть что-то из следующих вариантов:

  1. Обновление Bottlerocket с 1.14.2 до 1.32.0? (Я не заметил ничего очевидного в CHANGELOG)
  2. или обновление containerd с 1.6.20 до 1.7.24?
  3. или обновление 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 необходимо рассмотреть несколько потенциальных причин и решений. Давайте разберём ситуацию пошагово.

Теория

  1. Обновление ОС Bottlerocket: Bottlerocket OS обновился с версии 1.14.2 до 1.32.0. Обновления операционной системы могут включать изменения в системной безопасности, которые затрагивают работу служб, особенно в части управления файлами и каталогами. Одним из факторов могут быть изменения в настройках SELinux или AppArmor, которые могли быть внедрены в более новые версии ОС. Эти изменения могут предотвратить создание или доступ к файлам сокетов, если безопасность настроена таким образом, чтобы ограничить права сервиса в контейнере.

  2. Обновление контейнерного рантайма containerd: Версия containerd обновилась с 1.6.20 до 1.7.24. Хотя это и менее вероятно, containerd также может влиять на создание и доступ к файловым сокетам. Например, изменения в управлении пространствами или в организационных структурах могут повлиять на поведение контейнеров при работе с файловыми системами.

  3. Обновление версии Kubernetes: Версия Kubernetes поднялась с v1.27.3 до v1.31.4. Изменения в Kubernetes могут повлиять на поведение подов, особенно если были внесены изменения в механизм управления разрешениями или пространство имен, которое используют контейнеры для работы с файловыми системами.

Пример

Возьмем ваш сценарий:

  • Обновился узел Kubernetes, на котором располагается приложение Gunicorn.
  • Абсолютно та же контейнерная среда продолжает использоваться, что указывает на то, что изменения в самой среде не коснулись приложений напрямую, а проблема заключается в инфраструктуре.
  • Логи показывают, что Gunicorn пытается подключиться к сокету, но не может создать его, повторно пытаясь это сделать каждые секунду.

Применение

  1. Проверьте SELinux/AppArmor: Убедитесь, что изменения SELinux или AppArmor, которые могли произойти, не запрещают созданию сокета. Вы можете временно отключить эти сервисы для тестирования:

    setenforce 0  # для SELinux
    sudo aa-teardown # для AppArmor, если используется

    После отключения перезапустите под и проверьте, создается ли сокет.

  2. Проверка прав на /sock: Несмотря на то, что права выглядят корректно (drwxrwxrwx), необходимо убедиться, что это актуально для всех компонентов, которые имеют доступ к этому общему каталогу. Попробуйте выполнить стандартный тест на запись в этот каталог из контейнера:

    k exec -it <pod-name> -- touch /sock/testfile
  3. Системные логи для диагностики: Проверьте системные логи Bottlerocket и контейнерные логи Kubernetes на предмет наличия сообщений об ошибках, связанных с доступом к файловой системе. Это может дать подсказки относительно ограничения на уровне ядра.

  4. Перепроверка конфигураций Nginx: Убедитесь, что изменения конфигурации Nginx, используемого вместе с Gunicorn, не влияют на доступ к сокету. Все изменения конфигурации в свежих версиях Nginx или вашего использующегося образа могут отразиться на путях и доступности сокета.

  5. Дополнительная проверка version compatibility: Некоторые изменения в компонентах Kubernetes или containerd могли изменить совместимость API или версий протоколов. Убедитесь, что версия Gunicorn и его конфигурации совместимы с обновленной инфраструктурой, возможно, потребуется обновить их.

Следуя этим рекомендациям, вы сможете определить и исправить проблему. Если ни одно решение не работает, можно обратиться к детальным логам контейнера и системными журналами для более детального анализа. Если проблема не разрешается, возможно, стоит рассмотреть обращение в поддержку Bottlerocket или прямое обсуждение проблемы с командой разработчиков, чтобы выяснить возможные изменения, которые могли вызвать проблему.

Оцените материал
Добавить комментарий

Капча загружается...