CentOS 7 на продакшне: шпаргалка по systemd для тех, кто вырос на RHEL 6
Перевели первый продакшн-сервер на CentOS 7. Самое непривычное - journald и systemctl. Собрали шпаргалку equivalents для команд RHEL 6.
CentOS 7 с systemd требует переобучения администраторов: service/chkconfig и syslog заменены на systemctl и journald
В июле мы переносили init.d-скрипты на systemd units на тестовом стенде. Теперь первый боевой сервер клиента из управляемой инфраструктуры реально работает на CentOS 7 в продакшне. Разница между «разобрались на стенде» и «объясняешь коллеге в 23:00 почему service nginx restart не работает» - ощутимая.
Не то чтобы systemd сложный. Он просто другой. И мышечная память, выращенная на RHEL 6, работает против тебя первые несколько недель.
Откуда шпаргалка
Поводом стало конкретное происшествие. Один из администраторов работал с новым сервером, заметил что сервис не стартовал, и потратил минут двадцать прежде чем вспомнил что /etc/init.d/ на этой машине пустой, а chkconfig --list выдаёт половину юнитов и молчит про остальные. Это не его вина - просто на CentOS 7 половина привычных команд либо не работает, либо работает через слой совместимости и даёт неполную картину.
После того случая мы сели и составили таблицу equivalents: что было в RHEL 6 - что делать в CentOS 7. Теперь она висит в нашей внутренней Wiki и помогает при переключении между серверами разных поколений.
Управление сервисами: systemctl вместо service и chkconfig
Базовые операции с сервисами:
- Запустить/остановить/перезапустить. Было
service nginx start/service nginx stop/service nginx restart. Сталоsystemctl start nginx/systemctl stop nginx/systemctl restart nginx. - Статус. Было
service nginx status. Сталоsystemctl status nginx- и это объективно лучше: показывает последние строки из лога прямо в выводе, PID, время запуска, cgroup. - Включить автозапуск. Было
chkconfig nginx on. Сталоsystemctl enable nginx. Файл symlink создаётся в/etc/systemd/system/. - Отключить автозапуск. Было
chkconfig nginx off. Сталоsystemctl disable nginx. - Проверить включён ли автозапуск. Было
chkconfig --list nginx. Сталоsystemctl is-enabled nginx. - Список всех сервисов. Было
chkconfig --list. Сталоsystemctl list-units --type=service- показывает все загруженные юниты с их состоянием. - Перечитать конфиг без рестарта. Было
service nginx reload. Сталоsystemctl reload nginx- если юнит поддерживаетExecReload, иначеsystemctl reload-or-restart.
Отдельный нюанс: systemctl restart nginx и systemctl reload nginx - разные вещи. Reload - это SIGHUP или специфичный для приложения механизм перечитать конфиг без остановки. Restart - это stop + start. В RHEL 6 это тоже было разграничено, но в команде service легко перепутать, потому что слово «reload» звучит похоже на «restart». В systemctl разграничение нагляднее.
Журналы: journald вместо /var/log/messages
Вот здесь непривычность сильнее всего. На RHEL 6 всё шло в /var/log/messages через syslog, и типичный сеанс диагностики выглядел как tail -f /var/log/messages или grep "nginx" /var/log/messages. Файл, строки, grep - понятно и предсказуемо.
На CentOS 7 journald собирает логи в бинарный журнал, и читать его надо через journalctl:
- Все логи за последний час.
journalctl --since "1 hour ago" - Логи конкретного юнита.
journalctl -u nginx- и это главная команда, которую используем чаще всего. - Следить в реальном времени.
journalctl -u nginx -f- аналогtail -f, только для конкретного сервиса. - Последние N строк.
journalctl -u nginx -n 50 - Логи с момента последнего запуска.
journalctl -u nginx -b- показывает только с текущей загрузки, чтобы не листать старое. - Логи по PID.
journalctl _PID=1234 - Уровень важности.
journalctl -p err- только ошибки и выше.
Первые дни команду journalctl -u <имя-юнита> -n 100 приходилось вспоминать вместо привычного grep. Но она реально удобнее: логи сразу отфильтрованы по конкретному сервису, не надо вычищать строки от других процессов.
Одно ограничение, на которое наткнулись: по умолчанию journald хранит логи в памяти (/run/log/journal/) и они не переживают перезагрузку. Чтобы журнал сохранялся на диске между ребутами, нужно создать директорию /var/log/journal/ - тогда journald сам начнёт туда писать. Делаем это сразу при настройке нового сервера.
Что ещё поменялось
Несколько вещей помимо systemctl и journald, которые сбивают с толку:
- Firewall. В RHEL 6 - iptables +
service iptables save. В CentOS 7 по умолчанию стоит firewalld, управляется черезfirewall-cmd. Синтаксис другой, логика зон вместо прямых правил. Мы на некоторых серверах отключаем firewalld и ставим iptables-services - там где конфигурация уже выверена и нет смысла переписывать. - Сетевые интерфейсы. Именование изменилось: вместо
eth0теперь что-то вродеeno1илиenp2s0- predictable network interface names. Это ломает скрипты, которые хардкодятeth0. Находили такое в нескольких bash-скриптах клиентов. - Hostname. Команда
hostnameосталась, но для постоянного изменения теперьhostnamectl set-hostname. Запись напрямую в/etc/hostnameтоже работает, ноhostnamectlделает всё в одном месте. - netstat. Пакет
net-toolsне установлен по умолчанию.netstat -tulpnнадо заменить наss -tulpnиз пакетаiproute. Функционально почти одинаково, синтаксис чуть другой.
Где сейчас
Шпаргалка в нашей Wiki уже помогла нескольким раз - не только новым людям, но и опытным администраторам при переключении между серверами. CentOS 6 и 7 сейчас существуют одновременно в инфраструктуре, и постоянно держать в голове оба набора команд неудобно.
Самое ценное наблюдение после месяца на боевом сервере: journald с journalctl -u <сервис> реально удобнее чем grep по /var/log/messages. Это не уступка, это улучшение. А вот firewalld пока вызывает скорее раздражение - возможно просто потому что iptables выучен до автоматизма, и новая абстракция добавляет трение там, где его не ожидаешь.