## Введение В современном мире контейнеризации и виртуализации эффективное управление ресурсами системы становится критически важным. В Linux для этого существует механизм под названием **cgroups** (control groups) — подсистема ядра, которая позволяет группировать процессы и управлять ресурсами, выделяемыми этим группам. Docker активно использует cgroups для ограничения и контроля ресурсов контейнеров. Подробнее о Docker и управлении ресурсами можно прочитать в заметке [[Resource management in Docker]]. --- ## Что такое cgroups? **cgroups** — это механизм ядра Linux, который позволяет: ^WBQpB4KR - Группировать процессы в иерархические группы. - Ограничивать и контролировать использование ресурсов (CPU, память, диск, сеть и др.) для каждой группы. - Отслеживать статистику использования ресурсов. - Приоритизировать доступ к ресурсам. Это особенно полезно для контейнеров, где нужно гарантировать, что один контейнер не "захватит" все ресурсы хоста, нарушая работу других. --- ## Основные подсистемы cgroups Каждая подсистема (subsystem) отвечает за управление определённым типом ресурсов: | Подсистема | Управляемый ресурс | |------------|-----------------------------| | cpu | CPU shares, квоты | | cpuset | Привязка процессов к ядрам | | memory | Ограничение памяти и swap | | blkio | Ограничение скорости диска | | devices | Контроль доступа к устройствам| | net_cls | Классификация сетевого трафика| Подробнее о подсистемах и их настройках можно узнать в [[Resource management in Docker]]. --- ## Как работают cgroups в системе с systemd На современных системах с systemd каждый процесс помещается в дерево cgroups. Можно увидеть структуру cgroups и процессы в них с помощью команды: ```bash systemd-cgls ``` Пример вывода: ``` ├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 22 ├─system.slice │ ├─docker-4be96b853089bc6044b29cb873cac460b429cfcbdd0e877c0868eb2a901dbf80.scope │ │ ├─12345 /usr/bin/mycontainerprocess ``` Здесь видно, что процессы Docker-контейнера находятся в отдельном cgroup. --- ## Примеры управления ресурсами с помощью cgroups ### 1. Ограничение CPU с помощью Docker Docker использует cgroups для управления CPU через параметр `--cpu-shares` (относительный вес) и `--cpuset-cpus` (привязка к ядрам). Пример запуска контейнера с ограничением CPU: ```bash # Запуск контейнера с 512 CPU shares (по умолчанию 1024) docker run -it --rm -c 512 stress --cpu 4 # Привязка контейнера к первому и второму ядрам docker run -it --rm --cpuset-cpus="0,1" stress --cpu 2 ``` Подробнее о CPU ограничениях в [[Resource management in Docker]]. ### 2. Ограничение памяти По умолчанию контейнер может использовать всю память хоста. Чтобы ограничить память, используйте параметр `-m`: ```bash docker run -it --rm -m 128m stress --vm 1 --vm-bytes 128M --vm-hang 0 ``` Этот контейнер не сможет использовать больше 128 МБ памяти. ### 3. Ограничение скорости записи на диск Docker не предоставляет прямых опций для ограничения скорости диска, но cgroups и systemd позволяют это сделать через свойства `BlockIO*`. Пример ограничения скорости записи: ```bash # Найдите устройство, на котором смонтирована файловая система контейнера docker exec <container_id> mount | head -1 # Ограничьте скорость записи до 10MB/s для контейнера sudo systemctl set-property --runtime docker-<container_id>.scope "BlockIOWriteBandwidth=/dev/mapper/your-device 10M" ``` Подробнее о блокировке дисковых ресурсов — в [[Resource management in Docker]]. --- ## Работа с cgroups напрямую через файловую систему Информация и настройки cgroups доступны в виртуальной файловой системе `/sys/fs/cgroup/`. Пример просмотра CPU shares для контейнера: ```bash cat /sys/fs/cgroup/cpu/system.slice/docker-<container_id>.scope/cpu.shares ``` Изменение CPU shares (например, на 512): ```bash echo 512 | sudo tee /sys/fs/cgroup/cpu/system.slice/docker-<container_id>.scope/cpu.shares ``` --- ## Использование systemd для управления cgroups Поскольку systemd управляет cgroups, можно использовать `systemctl` для изменения свойств в реальном времени: ```bash sudo systemctl set-property docker-<container_id>.scope CPUShares=512 ``` Добавьте `--runtime` для временного изменения (до перезагрузки): ```bash sudo systemctl set-property --runtime docker-<container_id>.scope CPUShares=512 ``` --- ## Мониторинг использования ресурсов cgroups Для быстрого просмотра использования ресурсов cgroups можно использовать: ```bash systemd-cgtop ``` Вывод покажет, сколько CPU, памяти и ввода/вывода используют группы процессов. --- ## Важные моменты - CPU shares — это относительный вес, а не жёсткое ограничение по частоте. - Ограничения памяти включают swap, который по умолчанию равен размеру памяти. - Ограничение дискового пространства (квоты) для контейнеров пока не реализовано в Docker. - Инструменты вроде `top` внутри контейнера не показывают ограничения cgroups, так как они не cgroups-aware. --- ## Где находятся файлы cgroups для Docker Файлы cgroups расположены в виртуальной файловой системе, обычно по пути: ``` /sys/fs/cgroup/ ``` Внутри этой директории есть поддиректории для каждой подсистемы (cpu, memory, blkio и др.) и дальше — для каждой группы процессов (scope), например: ``` /sys/fs/cgroup/cpu/system.slice/docker-<container_id>.scope/ /sys/fs/cgroup/memory/system.slice/docker-<container_id>.scope/ /sys/fs/cgroup/blkio/system.slice/docker-<container_id>.scope/ ``` В этих директориях находятся файлы, управляющие ресурсами и показывающие статистику: - `tasks` — список PID процессов в группе - `cgroup.procs` — тоже список PID процессов - `cpu.shares` — вес CPU для группы - `memory.limit_in_bytes` — лимит памяти - `memory.usage_in_bytes` — текущее использование памяти - `blkio.throttle.write_bps_device` — ограничение скорости записи на диск - и другие файлы для мониторинга и управления --- ## Типовые скрипты для мониторинга cgroups Docker ### 1. Просмотр процессов в cgroup контейнера ```bash CONTAINER_ID=<container_id> cat /sys/fs/cgroup/cpu/system.slice/docker-$CONTAINER_ID.scope/tasks ``` Выведет список PID процессов, запущенных в контейнере. --- ### 2. Мониторинг использования CPU и памяти контейнером ```bash CONTAINER_ID=<container_id> echo "CPU shares:" cat /sys/fs/cgroup/cpu/system.slice/docker-$CONTAINER_ID.scope/cpu.shares echo "Memory limit (bytes):" cat /sys/fs/cgroup/memory/system.slice/docker-$CONTAINER_ID.scope/memory.limit_in_bytes echo "Memory usage (bytes):" cat /sys/fs/cgroup/memory/system.slice/docker-$CONTAINER_ID.scope/memory.usage_in_bytes ``` --- ### 3. Скрипт для вывода текущего использования ресурсов всех контейнеров ```bash #!/bin/bash for scope in /sys/fs/cgroup/cpu/system.slice/docker-*.scope; do CONTAINER=$(basename $scope | sed 's/docker-//;s/.scope//') CPU_SHARES=$(cat $scope/cpu.shares) MEM_USAGE=$(cat /sys/fs/cgroup/memory/system.slice/docker-$CONTAINER.scope/memory.usage_in_bytes) MEM_LIMIT=$(cat /sys/fs/cgroup/memory/system.slice/docker-$CONTAINER.scope/memory.limit_in_bytes) echo "Container: $CONTAINER" echo " CPU shares: $CPU_SHARES" echo " Memory usage: $MEM_USAGE bytes" echo " Memory limit: $MEM_LIMIT bytes" echo done ``` --- ### 4. Ограничение CPU и памяти для запущенного контейнера через systemd ```bash CONTAINER_ID=<container_id> # Ограничить CPU shares до 512 sudo systemctl set-property docker-$CONTAINER_ID.scope CPUShares=512 # Ограничить память до 256MB sudo systemctl set-property docker-$CONTAINER_ID.scope MemoryLimit=256M ``` --- ## Как устроена система cgroups - **Иерархия cgroups:** cgroups организованы в виде дерева. Каждый процесс принадлежит к одной или нескольким cgroups (по разным подсистемам). - **Подсистемы (controllers):** Каждая подсистема отвечает за управление определённым ресурсом (CPU, память, диск и т.д.). - **Файловая система cgroups:** Через виртуальную файловую систему `/sys/fs/cgroup/` можно читать и изменять параметры cgroups. - **Интеграция с systemd:** systemd создаёт и управляет cgroups для сервисов и контейнеров, что упрощает управление ресурсами. --- Если хотите, могу помочь с конкретными примерами или настройками под ваши задачи! --- Так документ станет удобнее для навигации и изучения связанных тем. ---