...

Изоляция серверных ресурсов с помощью cgroups в хостинге: полное руководство

В этом руководстве по 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 и чистым тюнингом, можно создать надежную хостинговую платформу, которая будет работать стабильно и справедливо относиться к клиентам.

Текущие статьи

Изоляция ресурсов сервера с помощью cgroups в Linux-хостинге
Серверы и виртуальные машины

Изоляция серверных ресурсов с помощью cgroups в хостинге: полное руководство

Изоляция серверных ресурсов с помощью cgroups в хостинге: оптимизация процессора, оперативной памяти и ввода-вывода для стабильной работы в средах с общим доступом.

Глобальное распределение нагрузки на DNS с серверами по всему миру
веб-хостинг

Распределение нагрузки DNS и GeoDNS: оптимальное распределение нагрузки

Распределение нагрузки DNS и GeoDNS оптимизируют трафик в глобальном масштабе. Откройте для себя распределение нагрузки dns для максимальной производительности и доступности.