Квоты второго уровня в OpenVZ - это квоты unix-пользователей внутри контейнера. Каждому контейнеру выделяется заданное количество записей в таблице, хранящей квоты. Это значение определяется в параметре QUOTAUGIDLIMIT. По умолчанию, все квоты второго уровня отключены и данный параметр для всех контейнеров выставлен в ноль. Чтобы разрешить квоты второго уровня в контейнере, необходимо установить значение QUOTAUGIDLIMIT в ненулевое значение:
# vzctl set 200 --save --quotaugidlimit 200
Параметры UBC Основные положения
UBC можно посмотреть для каждой VPS через интерфейс /proc:
held - счетчик, который показывает текущее потребление ресурса
maxheld - счетчик, который показывает пиковое значение потребления ресурса
barrier и limit - лимиты по данному ресурсу. Для каждого из параметров они могут иметь свое, особое значение
failcnt - количество неудачных попыток выделить данный ресурс
Первичные
К первичным параметрам относятся:
numproc
numtcpsock
numothersock
vmguarpages
numproc
Данный параметр определяет максимальное количество процессов и потоков, которые разрешено создать в контейнере. Единица измерения - 1 процесс (поток). Значения barrier и limit необходимо устанавливать равными.
Очень важно понимать, что процесс в Linux - это достаточно тяжеловесная структура, поэтому необходимо следить за балансом количества процессов в системе. В ядре Linux количество процессов ограничено следующим параметром:
# /proc/sys/kernel/threads-max
32726
Несмотря на то, что величина порядка 30k кажется достаточно большой, на практике такого суммарного количества процессов в системе достичь вряд ли удастся. Поэтому можно не думать о том, что сумма numproc по всем контейнерам должна быть меньше значения threads-max, этот лимит всё равно вряд ли будет достигнут. Считается, что для среднестатистической системы нужно ориентироваться на суммарное количество процессов порядка 8000.
Параметр numproc - это барьер, который защищает систему от лавинообразного создания процессов внутри какого-либо из контейнеров. Например, в случае fork bomb, или же в случае DDoS-атаки на сетевой сервер, создающий процессы на каждое сетевое соединение. В случае, когда количество процессов внутри контейнера достигнет значения numproc, ядро перестанет создавать новые процессы внутри данного контейнера.
numtcpsock
Параметр numtcpsock определяет максимальное количество TCP-сокетов (то есть количество обслуживаемых TCP-соединений). Единица измерения - 1 сокет. Значения barrier и limit необходимо устанавливать равными. Органичиваем количество сокетов мы по двум причинам:
(прямо) каждый сокет потребляет память (для хранения буферов приема и отправки), которая является ограниченным ресурсом
(косвенно) каждый сокет - это одно соединение, для обслуживания которого внутри контейнера может работать серверное приложение (если речь о входящих соединениях). Поэтому чем больше соединений через сокеты мы пропускаем внутрь контейнера - тем больше ресурсов будет потрачено на их обработку
numothersock
Ограничивает максимальное количество не-TCP-сокетов. Единица измерения - 1 сокет. Значения barrier и limit необходимо устанавливать равными.
Под данный параметр попадают все остальные сокеты (не являющиеся TCP) - UDP-сокеты, локальные сокеты (как, например, /tmp/opera-jimm.sock) и иные.
vmguarpages
Гарантированная контейнеру память (перед тем, как принять термин «гарантированная память» рекомендую ознакомиться с информацией о выделении памяти контейнерам) Единица измерения - 1 страница памяти (4 Кб на архитектурах x86 и x86_64)
С помощью данного параметра можно установить объем памяти, который гарантирован контейнеру для выделения из кучи с помощью функции malloc(3) или ей подобных. Для установки данного лимита используется barrier-значение. Например, при установке его в значение 262144 контейнеру будет обещано памяти 262144 * 4Кб = 1 Гб.
Значение limit при этом фактически не используется, его необходимо установить в значение MAX_ULONG
Еще одна интересная особенность данного лимита заключается в том, что он не имеет своего собственного счетчика. Количество страниц памяти, которое в данный момент выделено контейнеру учитывается в счетчике параметра privvmpages
Вторичные
К вторичным параметрам относятся:
kmemsize
tcpsndbuf
tcprcvbuf
othersockbuf
dgramrcvbuf
oomguarpages
privvmpages
kmemsize
Этот важный параметр определяет количество доступной ядерной памяти. Единица измерения - 1 байт. Между значениями barrier и limit рекомендуется оставлять интервал величиной в 10%
Данный параметр лимитирует тот объем памяти, которое ядро использует для своих внутренних нужд при обслуживании контейнера (например, для хранения дескрипторов процессов, кеширования объектов файловой системы и т.д.). Буферы сокетов в данный лимит не входят, они реализованы отдельно как tcpsndbuf, tcprcvbuf, othersockbuf и dgramrcvbuf
Характерная особенность ядерной памяти в том, что она не выгружается в swap. Поэтому соответствующие структуры данных, выделяемые ядром для своих нужд всегда находятся в RAM. Более того, они находятся не просто в оперативной памяти, а в нижней памяти (low memory). (Рекомендую на этом остановиться подробнее и изучить информацию о нижней памяти проследовав по ссылке).
tcpsndbuf
Общий размер буферов отправки TCP-сокетов Единица измерения - 1 байт
Эти буферы находятся в нижней памяти . Данный параметр связан с лимитом на количество сокетов numtcpsock, необходимо обеспечить выполнение соотношения ниже, чтобы всем сокетам хватало памяти:
Если данное соотношение не выполняется, то некоторые соединения могут без сообщения об ошибке застопориться и позже - быть закрытыми по таймауту. Отправка TCP-пакетов через эти сокеты будет невозможна. Увеличение данного параметра может повысить быстродействие сетевых соединений, однако это вовсе не обязательно, этого ускорения может и не быть.
tcprcvbuf
Общий размер буферов приёма TCP-сокетов Единица измерения - 1 байт
Эти буферы находятся в нижней памяти . Данный параметр связан с лимитом на количество сокетов numtcpsock, необходимо обеспечить выполнение соотношения ниже, чтобы всем сокетам хватало памяти:
Если данное соотношение не выполняется, то некоторые соединения могут без сообщения об ошибке застопориться и позже - быть закрытыми по таймауту. Увеличение данного параметра может повысить быстродействие сетевых соединений, однако это вовсе не обязательно, этого ускорения может и не быть.
othersockbuf
Общий размер буферов отправки UDP (и иных протоколов, использующих датаграммы) и буферов локальных сокетов Единица измерения - 1 байт
Эти буферы находятся в нижней памяти . Данный параметр связан с лимитом на количество прочих сокетов numothersock, необходимо обеспечить выполнение соотношения ниже, чтобы всем сокетам хватало памяти:
В достаточной мере большие буферы необходимы для высокой производительности UNIX-сокетов. Однако следует учитывать, что поскольку память для буферов выделяется из нижней памяти - стоит разумно подходить к увеличению значений данного параметра.
dgramrcvbuf
Общий размер буферов для временного хранения входящих UDP-пакетов и пакетов других протоколов, использующих датаграммы. Единица измерения - 1 байт. Значения barrier и limit необходимо устанавливать равными
Данный параметр зависит от количества не TCP-сокетов (numothersock). В большинстве случаев данный параметр не нужно устанавливать в большие значения, только если контейнер должен отправлять и принимать большие датаграммы есть смысл повысить значения barrier для параметров othersockbuf и dgramrcvbuf
В случае, если данный лимит сработал, некоторые входящие датаграммы могут быть не приняты контейнером. Однако, учитывая то, что UDP не является протоколом с гарантированной доставкой, все приложения контейнера, ожидающие приема датаграмм должны быть готовы к тому, что некоторая их часть будет утеряна в процессе доставки.
Не нужно устанавливать значение данного параметра в слишком большие величины - так как память для буферов выделяется из нижней памяти .
oomguarpages
Размер гарантированной контейнеру памяти для случаев возникновения на ноде ситуации out-of-memory (OOM) Единица измерения - 1 страница памяти (4 Кб на архитектурах x86 и x86_64)
Данный параметр очень похож на vmguarpages, но существенно отличается от него ситуацией в которой он применим. Параметр vmguarpages определяет количество гарантированной контейнеру для его приложений памяти, однако, гарантированной лишь в том случае, когда на сервере-ноде нет ситуации OOM.
Так вот, когда мы говорим о параметре oomguarpages, мы говорим о гарантированной контейнеру памяти на случай отсутствия на сервере ситуации OOM. Величина данного лимита определяется по значению barrier. Как и в случае с vmguarpages в качестве limit надо прописать значение MAX_ULONG для текущей архитектуры
Если текущее значение oomguarpages (которое показывает потребление виртуальной памяти процессами внутри контейнера) + текущее потребление ядерной памяти kmemsize + суммарное потребление памяти по всем буферам сокетов tcpsndbuf, tcprcvbuf, othersockbuf и dgramrcvbuf НЕ превышает размеров памяти определенной в barrier параметра oomguarpages, тогда ядро НЕ уничтожит процессы данного контейнера в случае наступления ситуации OOM
Рассмотрим на конкретном примере - возьмем UBC реального контейнера:
16436262 явно меньше 268435456, поэтому процессы данного контейнера будут в безопасности при наступлении ситуации OOM.
Если же есть несколько контейнеров, которые потребляют памяти сверх гарантированного параметром oomguarpages, то в случае наступления ситуации OOM в первую очередь будут уничтожаться процессы на том контейнере, где превышение максимально. Когда ядро будет уничтожать процесс на таком контейнере, оно увеличит failcnt параметра oomguarpages.
Если для какого-то контейнера подобную ситуацию необходимо исключить, единственный вариант - это не давать разрешать ему потреблять памяти более, чем гарантировано по oomguarpages. Для этого надо приравнять к этому гарантированному значению величину параметра privvmpages, что исключит оверселлинг по памяти (и строго говоря, приведет к неэффективному использованию ресурсов)
ВАЖНО! Для того чтобы гарантированная память, действительно была гарантированной - необходимо, чтобы сумма памяти обещанной всем контейнерам по параметрам oomguarpages, kmemsize и буферам tcpsndbuf, tcprcvbuf, othersockbuf и dgramrcvbuf не превышала установленного в сервере объема виртуальной памяти (RAM + swap). В противном случае, в случае наступления ситуации OOM ядро может уничтожать процессы даже на тех контейнерах, где условие гарантированности соблюдается
privvmpages
Верхний лимит памяти, выделяемой контейнеру
Единица измерения - 1 страница памяти (4 Кб на архитектурах x86 и x86_64)
Данный параметр определяет тот максимум виртуальной памяти, которая может быть выделена контейнеру. Данный объем памяти - не гарантирован (конечно, за исключением того случая, когда этот лимит равен oomguarpages).
Счетчик (held) у данного параметра показывает количество памяти, которое выделено приложениям данного контейнера, но, часть этой памяти возможно, еще реально не использована. Таким образом, счетчик privvmpages обычно показывает значение большее, нежели у счетчика oomguarpages, который отражает реальное потребление памяти контейнером
Необходимо обеспечить некоторый интервал между значениями barrier и limit параметра privvmpages. В случае срабатывания barrier, приложение все еще может выделить память до значения limit, но только для случая высокоприоритетных выделений, например, для расширения стека процесса. Для запросов на выделение памяти с нормальным приоритетом процесс получит отказ от ядра OpenVZ. Дополнительные
К дополнительным параметрам относятся:
lockedpages
shmpages
physpages
numfile
numflock
numpty
numsiginfo
dcachesize
numiptent
swappages
lockedpages
Страницы памяти процессов, которые не могут быть выгружены в swap (страницы, заблокированные с помощью системного вызова mlock)
Единица измерения - 1 страница памяти (4 Кб на архитектурах x86 и x86_64)
ВАЖНО! Размер этой памяти также учитывается в счетчике kmemsize
Значения barrier и limit можно устанавливать равными друг другу, а можно и оставить интервал между ними - в зависимости от природы приложений, использующих возможности блокировки страниц памяти. Обычные серверные приложения - такого типа как HTTP-, FTP-, почтовые серверы не используют возможности блокировки страниц памяти.
shmpages
Общий размер разделяемой памяти
Единица измерения - 1 страница памяти (4 Кб на архитектурах x86 и x86_64). Значения barrier и limit необходимо устанавливать равными
Эти страницы также учитываются в счетчике параметра privvmpages
physpages
Общее количество страниц оперативной памяти (RAM), используемое процессами данного контейнера
Единица измерения - 1 страница памяти (4 Кб на архитектурах x86 и x86_64). Значения barrier и limit необходимо устанавливать равными
В данный момент данный параметр используется только как счетчик. В будущих релизах OpenVZ данный параметр позволит устанавливать гарантированное количество памяти для приложений, которая выделяется из RAM и не выгружается в swap. А пока что контейнеру можно гарантировать только виртуальную память (RAM+swap), но не оперативную (RAM).
Для совместимости с будущими версиями необходимо значение barrier данного параметра установить в 0, а значение limit - в MAX_ULONG
numfile
Максимальное количество одновременно открытых файлов
Единица измерения - 1 файл. Значения barrier и limit необходимо устанавливать равными
numflock
Максимальное количество файловых блокировок
Единица измерения - 1 блокировка.
Между значениями barrier и limit необходимо оставить интервал.
numpty
Количество псевдотерминалов
Единица измерения - 1 псевдотерминал. Значения barrier и limit необходимо устанавливать равными
Ограничивает количество одновременных shell-сессий. Максимальное количество псевдотерминалов для одного контейнера ограничено значением 256.
numsiginfo
Количество структур siginfo
Единица измерения - 1 структура. Значения barrier и limit необходимо устанавливать равными
Объем памяти, занимаемый структурами siginfo в памяти также учитывается в счетчике параметра kmemsize. Обычно в Linux-системах по умолчанию данный лимит установлен в значение 1024 структуры на всю систему, OpenVZ позволяет устанавливать данный лимит для каждого контейнера в отдельности, но при этом очень нежелательно, чтобы у какого-либо из контейнеров данное значение превышало значение по умолчанию (1024). Слишком большие значения лимитов могут уменьшить время отклика системы.
dcachesize
Общий размер структур dentry и inode, удерживаемых в памяти.
Иными словами, данный параметр определяет размер кеша для хранения объектов файловой системы. Размер текущего потребления памяти по данному параметру также учитывается в счетчике параметра kmemsize. Между значениями barrier и limit необходимо предусмотреть интервал. Задача dcachesize как отдельного от kmemsize параметра - ограничить размер кеша для хранения объектов файловой системы с той целью, чтобы при работе со слишком большим количеством таких объектов (например, если открыто слишком много файлов и директорий), сработал лимит dcachesize и возникла ошибка файловых операций, но память по лимиту kmemsize при этом исчерпана бы не была
numiptent
Максимальное количество правил фаервола NETFILTER
Единица измерения - 1 правило. Значения barrier и limit необходимо устанавливать равными
Не рекомендуется устанавливать данный лимит в слишком большие значения по следующим причинам:
большое количество правил, через которое проходит пакет при обработке его фаерволом увеличивает время обработки этого пакета, что занимает лишние ресурсы и вызывает деградацию сети
большое количество правил требует большого количества памяти для хранения этих правил. Здесь речь идет о памяти, работа с которой производится с помощью vmalloc/vfree, на этом остановимся поподробнее
Ядро для собственных нужд выделяет память двумя способами:
в пространстве ядра с помощью kalloc/kfree - структуры, размещенные в такой памяти не могу быть выгружены в swap
в виртуальной памяти с помощью vmalloc/vfree - такая память может быть размещена и в swap-пространстве
Однако, не следует думать, что память выделяемая ядром с помощью vmalloc и память, которая выделяется пользовательскими приложениями - это одно и то же. Они находятся в виртуальной памяти, но, тем не менее, для vmalloc используется собственная область ограниченного размера:
Из-за этим ограничением и обусловлено порожденное ограничение на общее количество правил NETFILTER, которое можно создать. Величина, на которую следует ориентироваться ~250000 правил swappages
Видимый размер swap.
Единица измерения - 1 страница памяти (4 Кб на архитектурах x86 и x86_64)
Параметр, который, определяет - какого размера будет определяться swap внутри контейнера. Фактически не влияет на выделение памяти контейнеру никоим образом, а служит только для отображения нужной величины.
Если swappages установить в MAX_ULONG, то внутри контейнера значения SwapTotal, SwapUsed будут видны как 0
Значение выставляется по величине limit, при этом barrier полностью игнорируется. Соотношения между параметрами
Необходимо обеспечить достаточное количество ядерной памяти для ожидаемого количества процессов: