Устранение распространенных проблем с подключением агентов Jenkins и их решения

Сталкиваетесь с ошибками 'offline' или 'connection refused' при работе с агентами Jenkins? Это подробное руководство предлагает пошаговые решения для типичных проблем с подключением. Вы научитесь диагностировать неполадки в сети, брандмауэре, JNLP, SSH и конфигурации агентов, обеспечивая постоянную доступность и эффективную работу ваших исполнителей сборок Jenkins. Включает практические советы и анализ журналов для быстрого устранения неисправностей.

Устранение распространенных проблем с подключением агентов Jenkins и их решения

Агенты Jenkins, также называемые узлами, — это место, где выполняется большая часть работы по сборке. Когда один из них переходит в автономный режим, симптомы очевидны: задания застревают в очереди, метки не могут быть удовлетворены, и команды начинают перезапускать сборки, которые никогда не должны были запускаться. Полезная работа заключается в выяснении того, какой уровень сломался: сетевая доступность, SSH, входящее удаленное взаимодействие, Java, учетные данные, диск или сам контроллер.

Понимание того, почему агент может стать недоступным, — это первый шаг к эффективному устранению неполадок. Эти проблемы могут быть вызваны неправильной настройкой сети, некорректной конфигурацией агента, ограничениями брандмауэра или проблемами с самим контроллером Jenkins. Систематически проверяя эти области, вы можете быстро определить первопричину и реализовать решение.

Распространенные причины отключения агента Jenkins

Несколько факторов могут привести к тому, что агент перейдет в автономный режим. Определение конкретного симптома является ключом к сужению круга потенциальных причин:

  • Агент недоступен: Контроллер Jenkins не может установить соединение с агентом.
  • Соединение отклонено: Машина агента активно отклоняет попытку подключения со стороны контроллера.
  • Агент сообщает об автономном режиме после успешного подключения: Агент был подключен, но с тех пор разорвал соединение.
  • Ошибки JSch (для агентов на основе SSH): Специфические ошибки, связанные с библиотекой Java Secure Channel, используемой для SSH-соединений.

Проблемы с сетью и брандмауэром

Сетевое подключение является наиболее частой причиной проблем с подключением агента. Обеспечение того, чтобы контроллер Jenkins мог связаться с машиной агента и наоборот, имеет первостепенное значение.

Проверка сетевой доступности

Прежде чем углубляться в специфические конфигурации Jenkins, убедитесь в базовой сетевой связности:

  1. Пинг агента: С машины контроллера Jenkins попробуйте выполнить пинг IP-адреса или имени хоста машины агента.
    ping <имя-хоста-или-ip-агента>
    
  2. Telnet к порту агента: Проверьте, открыт ли порт, который Jenkins использует для подключения к агенту, и прослушивается ли он. Для агентов JNLP это обычно порт 50000. Для агентов SSH это порт SSH (по умолчанию 22).
    telnet <имя-хоста-или-ip-агента> <порт-агента>
    
    Если время ожидания соединения истекло или оно отклонено, скорее всего, проблема в сети или брандмауэре, блокирующем порт.

Конфигурация брандмауэра

Брандмауэры на контроллере Jenkins, машине агента или промежуточных сетевых устройствах могут блокировать необходимые порты.

  • Брандмауэр контроллера Jenkins: Убедитесь, что контроллер может инициировать соединения с портом агента.
  • Брандмауэр машины агента: Убедитесь, что брандмауэр машины агента (например, ufw, firewalld, Брандмауэр Windows) разрешает входящие соединения на порту агента с IP-адреса контроллера Jenkins.
  • Сетевые брандмауэры: Если в вашей сети есть внутренние брандмауэры, убедитесь, что трафик разрешен между контроллером и агентом.

Пример: Разрешение порта 50000 на агенте (Linux с ufw)

# Разрешить соединения с определенного IP-адреса (контроллер Jenkins)
sudo ufw allow from <ip-контроллера-jenkins> to any port 50000

# Или разрешить с любого IP-адреса (менее безопасно)
sudo ufw allow 50000

# Перезагрузить правила брандмауэра
sudo ufw reload

Пример: Разрешение порта 22 на агенте (Linux с firewalld)

# Разрешить службу SSH постоянно с определенного исходного IP-адреса
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="<ip-контроллера-jenkins>" port protocol="tcp" port="22" accept'

# Перезагрузить правила брандмауэра
sudo firewall-cmd --reload

Совет: Всегда отдавайте предпочтение разрешению соединений с определенных IP-адресов для лучшей безопасности.

Проблемы конфигурации агента Jenkins

Неправильные настройки в Jenkins или на самом агенте являются распространенными источниками проблем с подключением.

Конфигурация агента JNLP

Агенты Java Network Launch Protocol (JNLP) взаимодействуют с контроллером Jenkins, используя выделенный порт. Основная конфигурация включает метод запуска агента и доступные порты контроллера.

Агент находится в автономном режиме в веб-интерфейсе Jenkins

Если агент отображается как автономный в веб-интерфейсе Jenkins, это означает, что контроллер не смог установить или поддерживать соединение.

  1. Проверьте метод запуска агента: Убедитесь, что агент настроен на правильный запуск. Распространенные методы включают:
    • Запуск агента путем его подключения к мастеру: Требует ручной инициации со стороны агента.
    • Запуск агента через SSH: Настраивается с помощью учетных данных SSH и настроек хоста.
    • Запуск агента с использованием встроенных свойств узла: Для конкретных сценариев.
  2. Проверьте доступность порта JNLP: Контроллер Jenkins должен прослушивать настроенный порт JNLP (по умолчанию 50000). Перейдите в Manage Jenkins -> System -> Advanced -> File -> TCP port for JNLP agents и убедитесь, что он установлен и доступен.

Ошибка "Connection refused" при запуске агента JNLP

Это часто означает, что порт JNLP (по умолчанию 50000) на контроллере Jenkins не открыт или недоступен с машины агента. Проверьте правила брандмауэра на контроллере и убедитесь, что порт настроен правильно.

Совет: Перезапуск контроллера Jenkins иногда может решить временные проблемы с портом JNLP.

Конфигурация агента SSH

При использовании SSH для подключения к агентам несколько факторов могут вызвать проблемы:

  1. Неверные учетные данные SSH: Проверьте имя пользователя, пароль или закрытый ключ, настроенные в Jenkins для SSH-соединения. Убедитесь, что закрытый ключ имеет правильный формат (например, PEM) и правильные разрешения.
  2. SSH-сервер не запущен на агенте: Убедитесь, что демон SSH (sshd) запущен на машине агента.
    # На машине агента
    sudo systemctl status sshd
    # или
    sudo service ssh status
    
    Если не запущен, запустите его:
    sudo systemctl start sshd
    sudo systemctl enable sshd
    
  3. Несоответствие порта SSH: Убедитесь, что порт, настроенный в Jenkins для SSH, соответствует порту, который прослушивает SSH-сервер (по умолчанию 22).
  4. Разрешение имени хоста/IP агента: Контроллер Jenkins должен иметь возможность разрешить имя хоста или IP-адрес агента.
  5. Разрешения ключа SSH: На машине агента файл ~/.ssh/authorized_keys для пользователя, под которым Jenkins подключается, должен иметь правильные разрешения (обычно 600).

Пример: Ручное тестирование SSH-соединения

С машины контроллера Jenkins попробуйте подключиться по SSH к агенту, используя те же учетные данные и порт, что настроены в Jenkins:

ssh -p <ssh-порт> <пользователь-jenkins>@<имя-хоста-или-ip-агента>

Если эта ручная команда SSH завершается ошибкой, проблема лежит вне конфигурации SSH Jenkins, скорее всего, в настройках сети, брандмауэра или SSH-сервера на агенте.

Разрешения рабочего каталога агента

Jenkins требует определенных разрешений для работы в файловой системе агента. Пользователь, под которым Jenkins подключается к агенту (или пользователь, запускающий процесс агента), должен иметь права на запись в настроенный рабочий каталог агента.

  • Проверьте владельца и разрешения: На агенте проверьте права собственности и разрешения домашнего каталога Jenkins и его подкаталогов.
    ls -ld /путь/к/домашнему/каталогу/агента/jenkins
    ls -l /путь/к/домашнему/каталогу/агента/jenkins
    
  • Предоставьте разрешения (при необходимости): Убедитесь, что пользователь, под которым Jenkins подключается, имеет права на чтение и запись. Используйте chown и chmod с осторожностью.

Проблемы контроллера Jenkins

Иногда проблема может быть не в агенте, а в самом контроллере Jenkins.

Перегрузка контроллера

Если контроллер Jenkins находится под большой нагрузкой (много запущенных заданий, высокая загрузка ЦП/памяти), он может испытывать трудности с управлением подключениями агентов. Следите за использованием ресурсов контроллера.

Конфликты портов JNLP

Если порт JNLP (по умолчанию 50000) уже используется другим процессом на контроллере Jenkins, агенты не смогут подключиться.

  • Проверьте использование порта: На машине контроллера используйте netstat или ss, чтобы узнать, какой процесс использует порт.
    sudo netstat -tulnp | grep 50000
    # или
    sudo ss -tulnp | grep 50000
    
    Если его использует другой процесс, вам нужно будет перенастроить либо Jenkins, либо другое приложение на использование других портов.

Продвинутая диагностика и журналы

Когда стандартные проверки не выявляют проблему, требуется более глубокое исследование.

Журналы контроллера Jenkins

Просмотрите журналы контроллера Jenkins на предмет ошибок, связанных с подключениями агентов. Эти журналы могут предоставить конкретные сообщения об ошибках.

  • Расположение: Обычно находится в $JENKINS_HOME/jenkins.log или доступен через Manage Jenkins -> System Log.
  • Ищите: Сообщения, упоминающие имя хоста агента, IP-адрес, попытки подключения, исключения JSch или ошибки Connection refused.

Журналы агента

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

  • Агенты JNLP: Сам процесс агента может выводить журналы в свою консоль или в указанный файл журнала.
  • Агенты SSH: Журналы могут находиться в $JENKINS_HOME/agent.log на машине агента или быть связаны с sshd, если соединение не удается на уровне SSH.

Включение отладочного логирования

Для очень устойчивых проблем временное включение отладочного логирования для соответствующих компонентов Jenkins может предоставить более детальную информацию.

  • JNLP/Взаимодействие с агентом: Возможно, вам потребуется настроить системные свойства Java или использовать конфигурацию логирования Jenkins (Manage Jenkins -> System Log -> Log Recorders), чтобы увеличить подробность для hudson.slaves или связанных пакетов.

Практические привычки, предотвращающие повторные сбои

Устранение неполадок с подключением агентов Jenkins требует систематического подхода, начиная с базовых проверок сети и переходя к специфическим конфигурациям Jenkins.

  • Проверьте сеть: Всегда начинайте с ping и telnet/nc, чтобы убедиться в базовой сетевой доступности и доступе к порту.
  • Проверьте брандмауэры: Убедитесь, что брандмауэры как на контроллере, так и на агенте, а также любые сетевые брандмауэры разрешают трафик на требуемых портах.
  • Проверьте учетные данные: Перепроверьте ключи SSH, имена пользователей и пароли.
  • Подтвердите службу агента: Для агентов SSH убедитесь, что sshd запущен и доступен.
  • Мониторьте журналы Jenkins: Журналы контроллера являются вашим основным источником для понимания причин сбоев подключения.
  • Используйте конкретные IP-адреса: Там, где это возможно, настраивайте брандмауэры и Jenkins на использование конкретных IP-адресов, а не широких диапазонов или 0.0.0.0.

Следуя этим шагам, вы сможете эффективно диагностировать и устранять большинство распространенных проблем с подключением агентов Jenkins, поддерживая бесперебойную работу ваших конвейеров CI/CD.

Чтение сообщения об автономном режиме без догадок

Слово "offline" слишком широкое, чтобы диагностировать проблему только по нему. Прежде чем изменять настройки Jenkins, откройте страницу агента и прочитайте точную причину, которую дает Jenkins. Есть большая разница между "connection refused", "permission denied", "host key verification failed", "JNLP agent rejected" и "channel was closed". Все они приводят к автономному узлу, но указывают на разные уровни.

Обычно я записываю симптом простым языком: "контроллер не может достичь TCP-порта 22", "SSH-логин работает, но Java не может запуститься", "входящий агент запускается, но не может связаться с контроллером" или "агент подключается, а затем отключается во время сборок". Это одно предложение помогает сохранять фокус расследования.

Если агент никогда не подключался, подозревайте конфигурацию, DNS, брандмауэр, учетные данные или команду запуска. Если он подключался месяцами и начал давать сбой сегодня, проверьте недавние изменения: ротация ключей SSH, обновление Jenkins, обновление плагина, новое правило брандмауэра, истекший сертификат, пересборка образа агента или изменение облачной сети. Временная шкала часто бывает полезнее текста ошибки.

SSH-агенты: Отделяйте проблемы входа от проблем запуска

Для агентов на основе SSH протестируйте тот же путь, который использует Jenkins. С хоста контроллера подключитесь как пользователь, настроенный в Jenkins:

ssh -vvv jenkins-agent-user@agent-hostname

Подробный вывод сообщает вам, происходит ли сбой до аутентификации, во время аутентификации или после входа в систему. Если SSH никогда не достигает сервера, Jenkins не может это исправить. Проверьте маршрутизацию, группы безопасности, сетевые ACL, брандмауэры хоста и демон SSH. Если SSH достигает сервера, но отклоняет ключ, проверьте учетные данные в Jenkins, authorized_keys пользователя, разрешения файлов и не заблокирована ли учетная запись.

Если ручной вход по SSH работает, но Jenkins все равно не работает, посмотрите на удаленный корневой каталог и запуск Java. Jenkins требуется доступный для записи каталог для файлов удаленного взаимодействия, и пользователь агента должен иметь разрешение на создание там файлов. Распространенная ошибка — указывать удаленный корень на путь, принадлежащий root или очищаемый другим процессом.

Выполните эти проверки на агенте:

whoami
pwd
java -version
test -w /path/to/jenkins-agent && echo writable
df -h /path/to/jenkins-agent

Версия Java имеет значение, потому что современные контроллеры Jenkins требуют совместимых версий Java на агентах. Точное требование зависит от вашего релиза Jenkins, поэтому проверьте документацию Jenkins для вашей версии, а не предполагайте, что старый образ агента все еще действителен.

Входящие агенты: Путь обратного вызова — обычная ловушка

Входящие агенты часто используются, когда контроллер не может инициировать SSH к агенту, например, агенты за NAT или в ограниченных сетях. Процесс агента запускается вне Jenkins и подключается обратно к контроллеру. Это означает, что сетевой путь обратный: агент должен разрешить и достичь URL-адреса Jenkins.

На хосте агента проверьте URL-адрес Jenkins точно так, как он настроен:

curl -I https://jenkins.example.com/

Если Jenkins находится за обратным прокси, убедитесь, что публичный URL-адрес в Manage Jenkins > System правильный. Неправильный URL-адрес Jenkins может привести к тому, что сгенерированные команды агента будут указывать на внутреннее имя хоста, которое агент не может разрешить. Если для входящих агентов включен режим WebSocket, убедитесь, что прокси поддерживает заголовки обновления WebSocket. Если вы используете порт входящего агента TCP, убедитесь, что фиксированный порт настроен и доступен из сети агента.

Проблемы TLS могут выглядеть как проблемы Jenkins. Если агент работает в минимальном образе контейнера, в нем может отсутствовать ваш внутренний сертификат ЦС. curl обычно быстро это выявит. Установите сертификат ЦС в образ агента, а не отключайте проверку сертификата.

Агенты, которые отключаются во время сборок

Агент, который успешно подключается, а затем отключается во время сборки, обычно не является проблемой базового подключения. Посмотрите на давление ресурсов и жизненный цикл процесса.

Проверьте, не убила ли операционная система процесс агента:

dmesg -T | grep -i -E 'killed process|out of memory'
journalctl -u jenkins-agent --since '2 hours ago'

Также проверьте дисковое пространство. Удаленное взаимодействие Jenkins, извлечение кода, тестовые отчеты и архивированные артефакты — все это требует места. Полный том рабочей области может сделать агент ненадежным, потому что процесс удаленного взаимодействия не может записывать временные файлы или журналы.

Если отключения происходят во время большого вывода консоли, архивирования артефактов или публикации тестовых отчетов, посмотрите на стабильность сети и загрузку контроллера. Канал агента — это активное соединение. Длинные паузы сборки мусора на контроллере, перегруженные прокси, тайм-ауты бездействия соединения и потеря пакетов могут его закрыть. Для агентов, проходящих через балансировщики нагрузки или корпоративные прокси, проверьте настройки тайм-аута бездействия и поведение keepalive.

Проблемы DNS и ключа хоста

Изменения DNS легко пропустить. Jenkins может подключаться к build-agent-01, в то время как ваш ручной тест использует IP-адрес. Проверьте имя хоста с контроллера:

getent hosts build-agent-01
nc -vz build-agent-01 22

Если имя хоста разрешается в неправильный адрес, исправьте DNS или конфигурацию агента. Избегайте долгосрочных исправлений /etc/hosts, если у вас нет четкого процесса владения, потому что они становятся невидимой инфраструктурой.

Для агентов SSH проверка ключа хоста защищает Jenkins от подключения к неожиданной машине. Если агент был пересобран, его ключ хоста мог измениться. Не отключайте проверку вслепую. Подтвердите пересборку, удалите старый ключ из known_hosts пользователя контроллера и примите новый ключ через настроенную стратегию Jenkins.

Контрольный список восстановления для производственных агентов

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

  1. Был ли перезапущен или обновлен контроллер Jenkins?
  2. Были ли ротированы общие учетные данные?
  3. Изменился ли базовый образ агента?
  4. Было ли развернуто изменение брандмауэра, прокси, VPN или DNS?
  5. Находятся ли все отказавшие агенты в одной подсети, облачной учетной записи, пространстве имен Kubernetes или зоне доступности?

Если отказал только один агент, проверьте этот хост. Если целая группа отказала вместе, проверьте общую зависимость. Это экономит много времени в больших парках Jenkins.