Ubuntu 24.04 условие гонки ssh

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

Мне интересно, как работает мой ansible playbook и как ведет себя ssh. С Ubuntu 22 изменили способ запуска ssh-сервиса и, соответственно, его поведение при использовании ListenAdress в /etc/ssh/sshd_config

https://discourse.ubuntu.com/t/sshd-now-uses-socket-based-activation-ubuntu-22-10-and-later/30189

Поэтому я хочу использовать “старое” поведение и создал две задачи в ansible для достижения этой цели – деактивировать ssh.socket и активировать ssh.service.

Но я получил непоследовательное поведение. Я пробовал снова и снова с перестроенными виртуальными машинами на Hetzner, иногда все работает хорошо, иногда меня выкидывает. Мои задачи выглядят так:

- name: ssh | Использовать старое поведение
  when: ansible_distribution_version is version('22.04', '>=')
  block:

  - name: ssh | Отключить службу ssh.socket
    ansible.builtin.systemd_service:
      name: ssh.socket
      state: stopped
      enabled: false

  - name: ssh | Включить службу ssh.service
    ansible.builtin.systemd_service:
      name: ssh.service
      state: started
      enabled: true

Когда я смотрю в логи, я вижу:

systemd[1]: ssh.service: Найден остаточный процесс 1119 (sshd) в контрольной группе при запуске единицы. Игнорируется.
systemd[1]: ssh.service: Обычно это указывает на некорректное завершение предыдущего запуска или недостатки в реализации службы.
sshd[2769]: ошибка: Привязка к порту 22 на 0.0.0.0 не удалась: Адрес уже используется.
sshd[2769]: фатальная ошибка: Невозможно привязать любой адрес.
systemd[1]: ssh.service: Основной процесс завершился, код=exited, статус=255/EXCEPTION

Но это происходит не каждый раз, поэтому, может быть, кто-то знает, что происходит, когда все работает, а когда нет?

Я добавляю вывод netsta -tulpn, когда это работало:

      tcp6       0      0 :::22                   :::*                    LISTEN      1116/sshd: /usr/sbi

и когда это не работало.

      tcp6       0      0 :::22                   :::*                    LISTEN      1108/sshd: /usr/sbi

Это было зафиксировано до того, как я действительно перезапустил демон ssh

.

Ответ или решение

Проблема с состоянием гонки при использовании SSH в Ubuntu 24.04

Ваша проблема связана с изменениями, введенными в управлении службой SSH в Ubuntu 22.10 и более поздних версиях, которые теперь используют активацию по сокетам (socket-based activation). Давайте разберемся в сути происходящего и выясним, почему вы сталкиваетесь с проблемами при переключении на старое поведение службы SSH.

Что такое активация по сокетам?

Активация по сокетам позволяет системным службам запускаться по мере необходимости, когда приходит запрос на обслуживание. В случае SSH это означает, что служба ssh.socket может автоматически запускать ssh.service при попытке подключения.

Действия, выполняемые с помощью Ansible

Вы предпринимаете попытки отключить ssh.socket и запустить ssh.service через Ansible, чтобы воссоздать прежнее поведение. Ваш блок задач выглядит следующим образом:

- name: ssh | Use old behaviour
  when: ansible_distribution_version is version('22.04', '>=')
  block:

  - name: ssh | Disable ssh.socket service
    ansible.builtin.systemd_service:
      name: ssh.socket
      state: stopped
      enabled: false

  - name: ssh | Enable ssh.service service
    ansible.builtin.systemd_service:
      name: ssh.service
      state: started
      enabled: true

Причины непостоянного поведения

Ваша проблема с непостоянным поведением при включении и отключении служб может быть связана с состоянием гонки (race condition) между процессами sshd, как видно из логов:

error: Bind to port 22 on 0.0.0.0 failed: Address already in use.

Это сообщение об ошибке указывает на то, что при попытке запуска ssh.service служба уже была активной, и другой экземпляр sshd уже слушает тот же порт, что приводит к ошибке биндинга.

Почему это происходит?

  1. Асинхронные операции: Когда вы останавливаете ssh.socket, процесс разрывается, но systemd может еще не успеть полностью освободить ресурсы, связанные с этим сокетом, прежде чем вы пытаетесь запустить ssh.service. Это приводит к конфликту, когда управление уже заведомо недоступно для нового экземпляра службы.

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

Рекомендации по исправлению

Чтобы предотвратить возникновение состояния гонки и добиться более предсказуемого поведения, вы можете внести некоторые изменения в ваши Ansible задачи.

  1. Используйте задержки: Вставьте задержку между остановкой ssh.socket и запуском ssh.service:
- name: ssh | Disable ssh.socket service
  ansible.builtin.systemd_service:
    name: ssh.socket
    state: stopped
    enabled: false

- name: Wait for SSH socket to stop
  ansible.builtin.pause:
    seconds: 1

- name: ssh | Enable ssh.service service
  ansible.builtin.systemd_service:
    name: ssh.service
    state: started
    enabled: true
  1. Проверьте состояния: Убедитесь, что оба сервиса действительно остановлены перед запуском нового экземпляра. Вы можете использовать модуль ansible.builtin.systemd для проверки статуса.

  2. Логи и отладка: Всегда полезно проверять системные логи на наличие конфликтующих сообщений при отладке, например, с помощью journalctl -u ssh.service.

Заключение

Состояние гонки в вашей конфигурации Ansible для службы SSH связано с асинхронной природой остановки и услуги обработки. Применив рекомендации, вышеупомянув, вы должны увидеть улучшение в предсказуемости запуска SSH-сервиса на вашей системе Ubuntu 24.04.

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

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