В этом руководстве по cgroups Hosting Я покажу вам, как я изолирую ресурсы сервера с помощью групп управления Linux, чтобы „шумные соседи“ не замедляли работу сервисов. Вы узнаете, как я ограничиваю, расставляю приоритеты и надежно контролирую процессор, оперативную память, блочный ввод-вывод и сеть для каждого сайта, контейнера или пользователя - практичным и осуществимым способом.
Центральные пункты
Следующие ключевые аспекты помогут вам принять самые важные решения и предпринять необходимые шаги.
- Изоляция: Чистое разделение процессов и приручение соседей
- УправлениеЦеленаправленно ограничивайте процессор, оперативную память, ввод/вывод и устройства.
- Приоритет: Взвешивание и защита услуг премиум-класса
- ПрозрачностьИзмерение нагрузки, использование сигналов тревоги и трендов
- ОбновлениеПереход от v1 к v2 для четкого управления
Как cgroups отключает ресурсы сервера
Группы управления распределяют процессы по группам и связывают эти группы с драйверами ресурсов, что позволяет мне Ресурсы на группу. На общем сервере это не позволяет одному сайту потреблять процессорное время или заполнять память до отказа. Для этого я создаю иерархии, в которых родительские группы задают верхние пределы, которые наследуются дочерними группами. Таким образом, нагрузка распределяется равномерно, и узкие места остаются в стороне. В частности, с помощью этого я заметно облегчаю проблему „шумных соседей“, поскольку сильные скачки происходят по изолированным дорожкам.
Контроллер и файловая система: инструменты для работы
Практическая работа начинается в файловой системе cgroup в каталоге /sys/fs/cgroup, где я создаю группы и устанавливаю ограничения, т.е. конкретные Система управления заботиться. Я использую такие контроллеры, как cpu, memory, blkio, cpuset и devices, чтобы распределить временные срезы, закрыть оперативную память, замедлить ввод-вывод, подключить ядра или заблокировать устройства. Я комбинирую эти строительные блоки в зависимости от приложения: например, приложения, требовательные к памяти, имеют жесткие ограничения по оперативной памяти, задания на сборку - по весу процессора, а базы данных - по пропускной способности ввода-вывода. Четкая схема именования важна для того, чтобы впоследствии я мог быстро найти нужные группы. Благодаря этому администрирование становится управляемым, а изменения не теряются из виду.
| Подсистема | Назначение |
|---|---|
| cpu / cpuacct | Распределите процессорное время, Вес и установите квоты |
| память | Ограничьте объем оперативной памяти, избегайте убийств OOM |
| blkio | Ввод/вывод дроссельного блока, скорость чтения/записи управляющих данных |
| cpuset | Назначение ядер процессора и узлов NUMA |
| устройства | Разрешить или заблокировать доступ к устройству |
| net_cls / net_prio | Маркировка и определение приоритетов сетевых классов |
cgroups v1 vs. v2 в хостинге
Старая версия v1 разделяет контроллеры на несколько деревьев, что, как мне показалось, быстро приводит к путанице в больших установках, поэтому я решил использовать Конверсия до v2. В cgroups v2 все объединено в понятное дерево, что упрощает администрирование, отладку и наследование. Кроме того, cpu.max, cpu.weight и memory.max в v2 обеспечивают согласованный набор рычагов, которые хорошо работают вместе. Оркестранты контейнеров также предпочитают использовать v2, поскольку семантика более стандартизирована. Поэтому для хостинговых сред с большим количеством клиентов v2 является более компактным и надежным выбором.
Тонкий контроль в cgroups v2: io, память, pids и PSI
В версии 2 я активирую контроллеры явно для каждого поддерева и таким образом получаю больше контроля над наследованием. Только когда я разрешаю их в родительском узле, я могу использовать их в дочерних группах - это предотвращает неконтролируемый рост и обеспечивает чистоту политик.
# Активируйте контроллер в корневом узле для дочерних узлов
echo "+cpu +io +memory +pids" > /sys/fs/cgroup/cgroup.subtree_control
# Создайте подгруппу и используйте ее в качестве рабочего пространства
mkdir /sys/fs/cgroup/prod-web
Для ввода/вывода я использую контроллер io в v2 (вместо blkio). Я устанавливаю ограничения пропускной способности или IOPS для каждого устройства с помощью спецификаций major:minor. Это гарантирует, что журналы, индексы или резервные копии не будут засорять диск.
# Устройство для /dev/sda (8:0) ограничено 50 Мб/с на чтение, 20 Мб/с на запись
echo "8:0 rbps=50M wbps=20M" > /sys/fs/cgroup/prod-web/io.max
# Распределите вес относительно (вместо жесткого ограничения, 100-10000, по умолчанию 100)
echo 500 > /sys/fs/cgroup/prod-web/io.weight
Я устанавливаю память в два этапа: memory.high замедляет работу раньше, memory.max - это жесткая остановка. Я также отключаю своп для критических сервисов, чтобы задержки не взрывались.
# Мягкий тормоз (плавное ограничение) и жесткая обложка
echo $((400*1024*1024)) > /sys/fs/cgroup/prod-web/memory.high
echo $((512*1024*1024)) > /sys/fs/cgroup/prod-web/memory.max
# запретить своп (0) или ограничить (например, 128 Мб)
echo 0 > /sys/fs/cgroup/prod-web/memory.swap.max
Я использую контроллер pids для предотвращения форкштормов и поддержания верхнего предела процессов и потоков на одного клиента - это эффективная защита от неправильной конфигурации и неправильного использования в общих средах.
# Максимум 512 процессов/потоков в группе
echo 512 > /sys/fs/cgroup/prod-web/pids.max
Для диагностики я использую cgroup.events и PSI (Pressure Stall Information) для каждой группы. PSI показывает, регулярно ли не хватает ресурсов процессора, памяти или ввода-вывода, что вызывает время ожидания. Это более ценный показатель, чем чистая утилизация, поскольку он позволяет увидеть узкие места до того, как их заметят пользователи.
# Считывание событий и давления
cat /sys/fs/cgroup/prod-web/cgroup.events
cat /sys/fs/cgroup/prod-web/cpu.pressure
cat /sys/fs/cgroup/prod-web/memory.pressure
cat /sys/fs/cgroup/prod-web/io.pressure
В ситуациях OOM я специально связываю убийства с помощью memory.oom.group, чтобы связанные процессы (например, рабочий + помощник) завершались последовательно, а не приводили систему в состояние частичного паралича. Для окон обслуживания я замораживаю группы на короткое время с помощью cgroup.freeze, а затем снова размораживаю их - полезно для миграции базы данных или атомарного развертывания.
Поведение # OOM в рамках всей группы
echo 1 > /sys/fs/cgroup/prod-web/memory.oom.group
# Пауза / возобновление работы группы
echo 1 > /sys/fs/cgroup/prod-web/cgroup.freeze
echo 0 > /sys/fs/cgroup/prod-web/cgroup.freeze
Шаг за шагом: установка ограничений в Linux
На серверах с текущим ядром я активирую cgroup v2, а затем создаю группы с соответствующими верхними ограничениями, что позволяет мне Управление непосредственно в системе. Следующие команды показывают минималистичный пример с ограничениями на процессор и оперативную память. Я выбираю квоты консервативно, слежу за нагрузкой и регулирую их итерациями. Таким образом, я поддерживаю низкое время отклика без излишнего сокращения полезных фаз серийной работы. Реализация остается близкой к ядру и работает независимо от программного обеспечения панели.
# смонтируйте cgroup v2 (если это не произошло автоматически через systemd)
mount -t cgroup2 none /sys/fs/cgroup
Создайте группу #
mkdir /sys/fs/cgroup/prod-web
Назначьте процесс # (пример: PID 1234) в группу
echo 1234 > /sys/fs/cgroup/prod-web/cgroup.procs
Квота процессора #: 100 мс из 200 мс => 50%
echo "100000 200000" > /sys/fs/cgroup/prod-web/cpu.max
Жесткий лимит оперативной памяти #: 512 МБ
echo $((512*1024*1024)) > /sys/fs/cgroup/prod-web/memory.max
Интеграция Systemd и постоянные срезы
В повседневной жизни я позволяю systemd управлять деревом cgroup. Таким образом, ограничения остаются постоянный и прозрачно документируются для каждой службы. Я работаю со срезами (system.slice, user.slice, machine.slice) и определяю свои собственные иерархии для клиентов или ролей. Я использую вставные файлы для установки весов и значений без необходимости писать вручную в /sys/fs/cgroup.
# Пример: создание собственного среза для веб-сервисов
cat > /etc/systemd/system/web.slice < /etc/systemd/system/php-fpm.service.d/10-slice.conf <<'EOF'
[Сервис]
Slice=web.slice
EOF
systemctl daemon-reload
systemctl restart php-fpm.service
Для специальных тестов я запускаю процессы в диапазонах без написания юнит-файлов. Это подходит для имитации пиков нагрузки или кратковременного опробования ограничений.
# Кратко установите ресурсы и запустите процесс под контролем
systemd-run --scope -p CPUWeight=200 -p MemoryMax=512M \
-p IOReadBandwidthMax=/dev/sda:50M -p IOWriteBandwidthMax=/dev/sda:20M \
stress-ng --vm 1 --vm-bytes 300M --cpu 1
Время выполнения контейнеров управляет своими собственными поддеревьями (machine.slice) под управлением systemd. Здесь важно делегирование: я позволяю службе времени выполнения управлять поддеревом (делегатом), чтобы подсы/контейнеры были чисто изолированы. Это означает, что политики хоста и контейнера не пересекаются.
Безопасное использование пределов контейнера
В контейнерных средах cgroups действуют как невидимые ограждения, которые я устанавливаю с помощью параметров времени выполнения, и таким образом Контейнер в справедливые ограничения. Например, Docker сопоставляет параметры -cpus, -memory и -blkio непосредственно с cgroups, а Kubernetes переводит запросы и лимиты в параметры v2. Последовательность имеет решающее значение: лимиты должны соответствовать реальной нагрузке, чтобы подсистемы и контейнеры не дросселировались без необходимости и не вызывали ошибок OOM. Я держу продуктивные сервисы в узких рамках, в то время как задания сборки или тестирования получают больше бюджета только в случае необходимости. Это обеспечивает предсказуемость развертываний и предотвращает их срыв.
Избегайте виртуального хостинга и шумных соседей
В общих средах я устанавливаю ограничения на уровне пакетов или подписки, чтобы можно было Справедливость между клиентами. Такие панели, как Plesk, облегчают эту задачу благодаря менеджеру Cgroups, который распределяет CPU, RAM и I/O по подпискам и отображает их наглядно. Я также активирую уведомления, чтобы немедленно распознавать и реагировать на пики нагрузки. Если вы хотите сравнить Tenant-Isolation в деталях, вы можете взглянуть на Изоляция арендатора Бросок. Это означает, что все сайты остаются отзывчивыми, даже если отдельные клиенты иногда генерируют больше трафика.
Установка правильных ограничений: cgroups против ulimits
cgroups ограничивает реальное использование, в то время как ulimits - это в основном жесткие ограничения для каждого процесса или оболочки, вот почему я использую Комбинации конкретно. Для процессора, оперативной памяти и ввода-вывода я устанавливаю четкие cgroups, а открытые файлы или процессы дополнительно контролирую через ulimit. Это позволяет избежать узких мест в дескрипторах файлов и при этом держать под контролем общую загрузку. Если вы хотите обновить информацию о системных ограничениях, вы можете найти хороший обзор на сайте Ограничения в хостинге. Оба уровня вместе обеспечивают тончайшие регулировочные винты для справедливого разделения клиентов.
Мониторинг и оповещение
Без измерений я принимаю решения вслепую, поэтому я постоянно использую метрики и устанавливаю Пороги для сигнализации. Такие инструменты, как systemd-cgtop, ps, pidstat или Prometheus-Exporter, показывают мне в реальном времени, какая группа в данный момент использует ресурсы. В панелях я связываю cgroups с панелями мониторинга, которые отмечают пороговые значения и визуализируют тенденции. Оповещения по электронной почте или в чате информируют меня, когда группы превышают лимиты или часто дросселируются. Это позволяет мне выявлять узкие места на ранних этапах и корректировать лимиты, расширять аппаратное обеспечение или оптимизировать пути кода.
Углубленный мониторинг: основные показатели, PSI и значимые сигналы тревоги
Я слежу не только за „утилизацией“, но и за „давлением“. В cgroups v2 я читаю cpu.stat (включая throttled_us), memory.current, memory.high, memory.events, io.stat и файлы давления. Я использую их для создания сигналов тревоги, которые реагируют на нехватку ресурсов на ранней стадии, не раздражая во время коротких пиков.
- CPU: Предупреждайте, если throttled_us постоянно увеличивается, а задержки одновременно ухудшаются. Тогда я увеличиваю CPUWeight или снижаю cpu.max.
- Память: memory.current вблизи memory.high - это предупреждающий сигнал. Если memory.events часто сообщает „high“, я увеличиваю high или оптимизирую кэш.
- Ввод/вывод: io.stat показывает скорость передачи данных в секунду/в секунду и время ожидания. Я исправляю постоянное дросселирование через io.weight или выделенные устройства.
- PSI: Постоянное „некоторое“/„полное“ давление - показатель того, что рабочие нагрузки регулярно ожидают ресурсов. Я использую этот показатель для планирования мощностей.
Лучшие практики для чистой конфигурации
Я всегда начинаю с консервативных значений, потому что слишком острые крышки в пиковые моменты Производительность расходы. Затем я специально нагружаю службу эталонами, такими как ab, siege или wrk, чтобы постепенно увеличивать квоты. Для хостов с несколькими приложениями я распределяю группы по кусочкам, чтобы приоритет отдавался важным службам, не лишая остальных всего. Я устанавливаю лимиты ввода-вывода таким образом, чтобы короткие пики проскакивали, а более длительные фазы замедлялись. Регулярные проверки предотвращают устаревание лимитов при изменении профилей нагрузки.
Переход с v1 на v2: вот как я действую
Я планирую переход на новую систему как обычное обновление инфраструктуры. Сначала я проверяю, активированы ли ядро и systemd v2 по умолчанию. Если необходимо, я запускаю подходящие параметры загрузки и проверяю, что унифицированное дерево активно. Затем я тестирую все интеграции (панели, агенты, резервное копирование, время выполнения контейнеров) в среде staging.
- Обнаружение: mount | grep cgroup2 или systemd-cgls показывает, запущена ли v2.
- Параметры загрузки: Если требуется, я устанавливаю cgroup_no_v1=all или унифицированные параметры, чтобы активным был только v2.
- Сопоставление контроллеров: blkio становится io; я заменяю некоторые функции v1 (net_cls/prio) на контроль трафика с помощью классификаторов cgroup или BPF.
- Перенесите политики: Используйте весовые коэффициенты вместо жестких квот, введите memory.high, ограничьте своп отдельно.
- Настройка мониторинга: Перенесите новые пути и поля (cgroup.events, cpu.stat) на панели мониторинга.
Добавьте изоляцию процессов
cgroups решают проблему ресурсов, но для доступа к системе я дополнительно разделяю Пространства для названий и представления файлов. Chroot, CageFS, пространства имен и тюрьмы закрывают пути, объекты ядра и устройства, чтобы клиенты не могли добраться друг до друга. Этот уровень защиты является полезным дополнением к лимитам, поскольку он уменьшает радиус поражения и площадь атаки. Краткий обзор наиболее важных вариантов можно найти здесь: Изоляция процессов. В сочетании с cgroups создается чистое разделение клиентов для хостинговых систем любого размера.
Практические сценарии и настройка
Во время пиков трафика в CMS я даю процессору кратковременную передышку, но держу оперативную память под контролем, чтобы я мог Безопасность против сбоев OOM. Для магазинов, интенсивно работающих с данными, я регулирую blkio, чтобы индексирование не замедляло все остальные процессы чтения. Я закрепляю аналитические или рабочие процессы за несколькими ядрами с помощью cpuset, чтобы веб-работники могли спокойно отвечать на других ядрах. Я перемещаю фоновые задания в группы с меньшим весом процессора, чтобы запросы фронтенда оставались плавными. Для выделенных клиентов я использую memory.min, чтобы обеспечить небольшую гарантированную базу оперативной памяти для премиум-приложений.
Устранение неполадок и типичные камни преткновения
Некоторые ошибки повторяются. Я обращаю внимание на следующие моменты, чтобы сэкономить время при устранении неполадок:
- Слишком жесткие квоты на процессор: постоянное дросселирование увеличивает задержки. Лучше работать с cpu.weight и cpu.max только в качестве страховочного пояса.
- Давление на память без OOM: memory.high ограничивает эффективно, но если кэш страниц слишком сильно ограничен, увеличиваются задержки ввода-вывода. Тонкая настройка и выборочная обрезка кэша.
- Влияние свопа: Слишком большой объем подкачки делает систему медлительной. Поэтому для работы критически важных служб используйте memory.swap.max=0, а для защиты всей системы используйте небольшой буфер.
- Поддеревья забыты: Без записи в cgroup.subtree_control дочерние ограничения не применяются. Всегда сначала активируйте контроллер в родительском узле.
- Неправильная группа: процессы иногда оказываются в неправильном срезе. Проверьте с помощью systemd-cgls и исправьте параметры единицы обслуживания (Slice=, Delegate=).
- pids.max слишком мал: демон с большим количеством рабочих потоков тихо выходит из строя. Выберите большой буфер и отслеживайте его в мониторинге.
- Ограничения ввода-вывода на устройство: для RAID/LVM используйте правильное соотношение major:minor или установите ограничения на видимые блочные устройства, которые реально используются рабочей нагрузкой.
- Приоритезация сети: net_cls/prio - это наследие v1. В v2 я полагаюсь на управление трафиком с помощью классификаторов cgroup или BPF для управления потоками трафика.
Роли, профили и модели справедливости
Мне нравится работать с четкими профилями услуг, которые я сохраняю в виде шаблонов и разворачиваю автоматически:
- Премиум (Gold): Высокий вес процессора и ввода-вывода, memory.min для гарантированной базы, жесткий лимит memory.max с достаточным запасом.
- Стандарт (серебро): Средний вес, умеренный вес io.weight, memory.high немного ниже пикового значения, чтобы избежать разрастания кэша.
- Фон (бронза): Низкий вес CPU/I/O, строгий cpu.max для разделения интерактивных нагрузок.
Я также резервирую ядра и оперативную память для хоста и центральной инфраструктуры (мониторинг, логирование, резервное копирование). Это предотвращает поглощение клиентами накладных расходов системы. Для NUMA-хостов я использую cpuset, чтобы память была локальна для используемых ядер - это уменьшает пики задержек для сервисов, требовательных к памяти.
Краткое содержание
С помощью cgroups я устанавливаю четкие ограждения для процессора, оперативной памяти, ввода-вывода и сети, что позволяет мне Справедливость между службами и устранять узкие места. Стандартизированная архитектура cgroups v2 упрощает планирование, эксплуатацию и устранение неполадок по сравнению с v1. В контейнерах, виртуальном хостинге и смешанных средах я могу держать под контролем „шумных соседей“ и защищать критически важные рабочие нагрузки. Мониторинг и полезные сигналы тревоги дают мне ранние сигналы, когда лимиты перестают соответствовать профилю нагрузки. Если объединить cgroups с изоляцией процессов, ulimits и чистым тюнингом, можно создать надежную хостинговую платформу, которая будет работать стабильно и справедливо относиться к клиентам.


