управление памятью в linux и openvz

Применимость: Linux, OpenVZ
Слова для поиска: memory, limit


Статья еще не завершена


Память - наиболее важный ресурс сервера. Обычно администраторы полагаются на базовые параметры систем предусмотренные разработчиками, но нередко этого недостаточно.

От умения администратора ориентироваться в аспектах управления памятью с зависит производительность, устойчивость, а нередко и работоспособность систем.

В этой статье я пытаюсь упрощенно и кратко изложить наиболее важные для системного администратора моменты по управлению памятью применительно к использованию OpenVZ.

Для подробностей обращайтесь к соответствующей документации.

Принципы работы менеджера памяти в Linux подробно изложены на 768 страницах книги Understanding the Linux Virtual Memory Manager (Мел Горман) и в книге Ядро Linux (Бовет, Чезати).


Общие принципы работы диспетчера памяти

Подсистема виртуальной памяти распределяет память между задачами (процессами). Каждая задача (процесс) считает, что ей выделен непрерывный участок памяти максимального размера, поддерживаемого на соответствующей архитектуре (для архитектуры x86 это 4GB). Из них один гигабайт (только для x86) резервируется для ядра.

Процесс

Основным средством организации работы операционной системы UNIX® (Linux) и единицей многозадачности является процесс - уникальным образом идентифицируемая программа, которая нуждается в получении доступа к ресурсам компьютера. Процесс представляет собой программный код которым манипулирует Операционная система. Операционная система координирует работу разделов данных процесса и определяет среду выполнения.

Память

Данные, связанные с процессом, также являются частью образа процесса. Некоторые из них хранятся в регистрах, обычно представленных регистрами процессора. И существуют динамические области хранения данных (куча), выделяемые процессу по ходу работы при необходимости.

Еще у процесса есть стек, содержащийся в памяти и используемый для хранения локальных переменных программы и передачи параметров. Когда процесс выполняет обращение к функции или подпрограмме, в стек отправляется новый фрейм. Одной из частей каждого фрейма является указатель на базу предыдущего фрейма, который позволяет легко вернуться из вызова функции.

Количество доступной памяти в Linux определяется совокупным значением RAM + swap (пространство подкачки на диске).

На самом же деле программа занимает только тот объем памяти, с которым она реально работает. Большинство памяти существует виртуально, но будет предоставлено программе в тот момент, когда она обратится в эту область.

Ядро распределяет память страницами фиксированного размера. Процедура, когда страница оперативной памяти объявляется частью адресного пространства процесса, называется отображением этой страницы в адресное пространство процесса.

Когда процесс обращается к некоторой странице своего адресного пространства, ядро проверяет, имеет ли он право на доступа к этой странице, и если проверка пройдена и доступ получен, то ядро переадресовывает обращение на реальный адрес этой страницы. Размер страницы фиксирован архитектурой процессора, и для x86 размер составляет 4096 байт.

Если свободных страниц больше нет, но существует файл подкачки, куда ядро может убрать одну из наиболее долго не использовавшихся страниц, и освободившуюся физическую страницу отдать запросившему память процессу.

Если нет ни незанятого пространства в файле подкачки, ни свободных страниц RAM, то развитие событий может быть следующим: либо запросивший память процесс прерван и “убит” системой, либо какой-то другой из процессов (это определяется специфическими алгоритмами) будет “убит” ядром, и освободившаяся память будет передана запросившему память процессу.

Ограничение адресного пространства в 4GB не означает, что система не сможет адресовать более этого объема памяти. На платформе x86 ядро Linux может использовать до 64GB, а ограничение в 4GB накладывается лишь на размер адресного пространства процесса.

Количество памяти в Linux определяется совокупным значением RAM + swap. Память процессам выделяется из этого пула посредством функций языка *alloc()1)

Память используется экономно, но ядро старается использовать всю память, если память не занята процессами, то ядро использует ее под буферизацию (кэширование) данных. Ценный ресурс не должен болтаться без дела.

Однако ядро позволяет выделять памяти больше чем RAM + swap. Такое поведение ядра называется перевыделение (overcommitting) памяти. Как это возможно без ущерба для устойчивости? Например выполняется некоторое количество процессов вебсервера apache. Примерно 20-30% от пространства памяти выделенного каждому процессу apache зарезервирована, но не используется и потому может быть предоставлена другим процессам. Алгоритм использования этого пространства может регулироваться параметрами ядра.

Параметры использования памяти вы можете увидеть в файлах:

  • /proc/meminfo2)
  • /proc/sys/vm/swappines3)
  • /proc/sys/vm/vfs_cache_pressure4)
  • /proc/sys/vm/overcommit_memory5))
  • /proc/sys/vm/overcommit_ratio6))

Отличия x86 и x86_64

Из книги Linux Performance and
Tuning Guidelines (ibm.com/redbooks)

Ограничения sysctl и ulimit

Утилиты sysctl и ulimit через управление параметрами ядра позволяют ограничивать системные ресурсы. Это может помочь в ситуации когда , например, запускается слишком много процессов и система не отвечает на запросы. Или когда, напротив, заданных по умолчанию параметров недостаточно для эффективной работы приложения.

Через файловые системы sysfs и procfs ядро linux обеспечивает интерфейс управления в виде файлов каталогах /proc и /sys. Изменение значений в этих файлах позволяет вносить изменения параметров в работающее ядро без остановки или перезагрузки системы. Для взаимодействия с этими файлами обычно используют команду echo или утилиту sysctl ( man sysctl(8)). Использование текстовых редакторов для этих целей не допускается.

Просмотреть все параметры:

sysctl -a

Задать параметр:

sysctl -w параметр=значение

Заданный параметр будет действовать до перезагрузки системы.

Для внесения постоянных изменений используется файл /etc/sysctl.conf ( an sysctl.conf(8)).

ulimit - установка или определение ограничений для процессов пользователя.

Примеры использования ulimit:

 
ulimit -d 48000 # Ограничиваем максимальный размер сегмента данных в 48 MB 
ulimit -s 8192  # Ограничиваем максимальный размер стэка в 8 MB 
ulimit -m 48000 # Ограничиваем макс. размер резидентной части процесса (находящейся в ОЗУ) в  48 MB 
ulimit -u 64    # Ограничиваем максимальное часло запущенных этим пользователем процессов.
ulimit -n 128   # Ограничиваем максимальное часло открытых файлов.
ulimit -f 100000 # Ограничиваем максимальный размер создаваемого файла в 100 MB 
ulimit -v 100000 # Ограничиваем максимальный размер используемой виртуальной памяти в 100 MB 

Параметры ядра следует менять с контролем влияния на общую производительность. Например популярная в интернете методика экономии памяти на размере стека не всегда дает положительный эффект. Для опредления размера стека используется команда

ulimit -s 1024 

Это уменьшит размер стека и общее потребление памяти, но ухудшит стабильность и совсем не обязательно увеличит производительность. Если размер стека окажется хоть на байт меньше необходимого, то процессы будут обрываться с ошибками. Потому не торопитесь это использовать без нагрузочного тестирования.

Кроме стабильности придется побеспокоится и о безопасности. Приложение работающее на вашем сервере может быть хорошо защищено сам по себе, но вы может экспериментами с параметрами стека открыть широкую дверь злоумышленникам.

Есть несколько популярных методик преодоления защиты основанных на переполнении стека. Принцип их действия заключается в том, что в результате не предусмотренных разработчиком действий размер данных внутри программы для той или иной переменной превышают размер отведённой памяти для этой самой переменной. В результате чего часть данных попадает на чужой участок памяти и это может повлечь за собой иной исход работы программы.

ИМХО - если уменьшение размера стека не дает вам более 10% производительности (скорее всего не даст), то это вам не надо.

Управление памятью в OpenVZ

В контейнере OpenVZ есть особые принципы работы с памятью. Помимо общих проверок , выполняемых ядром при выделении памяти процессам, производятся проверки лимитов параметров памяти установленных для каждого контейнера. Внутри контейнера OpenVZ вы не увидите память выделенную под буферизацию (кэширование) и не увидите размер swap (кроме случая использования VSWAP). Тем не менее и то и другое обеспечивается. Но это происходит в пространстве физического сервера (HN)7) и скрыто от пользователя контейнера.

Ядро OpenVZ также позволяет использовать overcommitting памяти, но эффект от него может быть значительно большим. Однако использование overcommitting памяти требует правильного лимитирования памяти и постоянного наблюдения за фактическим использованием памяти, иначе пользователи виртуальных серверов увидят сообщение в логах

Out of  Memory: Killed process 3345 (postgres)

Это означает, что сработал OOM (out-of-memory killer)8) , процесс postgres был остановлен, так как не хватило памяти. Хотя существующие соединения с базой данных будут работать, новые соединения не будут приняты. Чтобы восстановить нормальную работу, необходимо перезапустить PostgreSQL.

Для обеспечения устойчивой работы системы, справедливого распределения ресурсов и изоляции контейнеров используется интерфейс ядра Linux предоставляемый как файл /proc/user_beancounters (**UBC**) посредством файловой системы ядра procfs.

Просмотр UBC

Большинство параметров (UBC) представленных в файле /proc/user_beancounters ограничивает ресурсы системы и эти параметры позволяют управлять потреблением этих ресурсов.

Исключения: - physpages (только считающий параметр) и vmguarpages (только управляющий), объяснены ниже. Ограничения должны обеспечивать достаточную производительность каждого виртуального сервера, стабильность и безопасность. Нагрузка на каждом отдельном контейнере не должна заметно влиять на все остальные.

Просмотреть список ограничений можно как изнутри контейнера так и снаружи на мастермашине (физическом сервере). Для этого достаточно прочитать содержимое файла /proc/user_beancounters с правами root.

cat /proc/user_beancounters

Можно использовать скрипт vzubc.pl или vzubc для получения информации в более гуманном виде.

./vzstats.pl

Значения колонок таблицы:

held означает текущее значение утилизации ресурса.

maxheld максимальное значение за все время работы

barrier Обозначает максимальное значение потребления ресурса, которое, в ряде случаев, может быть превышено (если на HN есть свободные ресурсы)

limit Обозначает максимальное значение потребления ресурса, которое никогда не может быть превышено контейнером

Текущее положение с выделением памяти можно оценить специальной утилитой vzmemcheck

По разнице значений в колонках commit и util вы можете оценить бонус какой вам дает система виртуализации.

barrier и limit

Каждый параметр имеет 2 переменные, названные barrier'ом и limit'ом.

Limit - предел, который не может быть превышен ни при каких обстоятельствах. Попытку процесса получить ресурс сверх limit ядро будет отбрасывать. Попытку процесса получить ресурс сверх barrier ядро будет разрешать, но на короткое время.

Значения параметров barrier не должны превышать значенияlimit.

Параметры управляют распределением ресурсов между Виртуальными окружениями в терминах:

limits - пределы, то есть верхние границы того, что это Виртуальное окружение может потреблять, и

guarantees - гарантии, то есть механизмы, гарантирующие, что это Виртуальное окружение может получить назначенные ресурсы независимо от деятельности и количества ресурсов, требуемых другими Виртуальными окружениями.

guar

Параметры, содержащие «guar» в названии, то есть vmguarpages и oomguarpages - это гарантии выделения памяти для Виртуального контейнера. Они гарантируют количество ресурсов и определенный уровень обслуживания до значения, определенного barrier, и не гарантируют выше значения barrier.

Однако, эти параметры не налагают ограничения использования.

Значение limit для параметров vmguarpages и oomguarpages должно устанавливаться в максимальное значение (то есть. MAX_ULONG)9).

Для некоторых ресурсов ограничивающих параметры, напирмер kmemsize, используются как barrier так и limit. Если использование ресурса превышает barrier, но не превышает limit, операции все еще могут резервировать новые ресурсы, а другие уже не могут. Промежуток между barrier и limit дает возможность процессам более гибко обращаться с ресурсами.

Для других параметров, типа numproc, ограничивающие значение barrier'а и limit'а должны иметь одинаковые значения.

Каждый параметр имеет «естественные единицы измерения» - единицы измерения значений, показанных через интерфейс /proc/user_beancounters и принятый vzctl.

Единицы UBC.
  • Параметры, которые имеют в названии слово «page», измеряются в страницах памяти (4 КБ на x86 и x86_64, 16 КБ для IA64). Это - privvmpages, oomguarpages и другие.
  • Параметры с названиями, содержащими «num» измерены в пунктах. То есть numproc - число процессов, numiptent - число iptables записей.
  • Другие параметры, как kmemsize, tcprcvbuf, tcpsndbuf измерены в байтах.

Лимиты для памяти

privvmpages

Лимит на количество выделяемой (резервируемой) памяти без гарантии выделения.

Этот объем памяти выделяется только в случае наличия свободных ресурсов на HN. В случае OOM на HN процессы в этой зоне убиваются..

Параметр задает объем памяти который видит пользователь контейнера по команде free: (колонка total)

[root@www /]# free
             total       used       free     shared    buffers     cached
Mem:       2097152     470516    1626636          0          0          0
-/+ buffers/cache:     470516    1626636
Swap:            0          0          0

Единица измерения - 1 страница памяти (4 Кб )

Выбор значения:

barrier(privvmpages) >= barrier(vmguardpages)

Сумма всех privvmpages должно соответствовать физическим ресурсам и реальной загрузке физических ресурсов. Важно не позволить любому VPS получить существенную часть всей памяти, чтобы избежать серьезной деградации производительности для других VPS. Политически более верным, при желании обеспечить некоторые VPS бО'льшим количеством памяти, будет использование параметров гарантирующих выделение.

Чтобы уменьшить количество неудачных попыток выделения памяти необходим зазор между barrier и limit. Этот зазор будет доступен только процессам с высоким приоритетом, например, для расширения стека (stack expansion)

А попытки выделения памяти для процессов с нормальным приоритетом будут завершены с ошибкой в том случае, когда достигнуто значение barrier параметра privvmpages

Примечание:

Поскольку VPS может не использовать объем памяти определенный privvmpages, с умма privvmpages по всем VPS МОЖЕТ превышать RAM+swap и это, благодаря overcommitting памяти, может не вызывать проблем. Все зависит от реальной нагрузки. Не брезгуйте мониторингом.

vmguardpages

Гарантия пространства для динамического выделения памяти.

Параметр определяет как много памяти доступно VPS Например, malloc() и другие механизмы выделения памяти в Linux будут видеть наличие свободной памяти если не исчерпана величина vmguardpages. Но в случае OOM на HN, процессы занимающие пространство в диапазоне между oomguardpages vmguardpages могут быть убиты ядром.

Единица измерения - 1 страница памяти (4 Кб )

Выбор значения: Количество гарантированной памяти указывается в значении barrier данного параметра. Значение limit должно быть установлено в максимальное значение MAX_ULONG.

Примечание:

Текущее количество выделенного размера памяти считается в параметре privvmpages, а параметр vmguarpages не имеет собственного учета (параметры held и maxheld всегда равны 0 ).

oomguardpages

Гарантируемое количество памяти для запущенных процессов на случай перераспределения памяти (нехватки памяти OOM (out-of-memory)).

Процессы не будут убиты если cумма oomguardpages по всем VPS не превышает количество RAM+swap сервере.

Единица измерения - 1 страница памяти (4 Кб)

Выбор значения: Значение параметра barrier для oomguardpages должно обеспечивать гарантию от нехватки памяти.

Значение limit должно быть установлено в значение MAX_ULONG.

Если нужна уверенность, что процессы никогда НЕ БУДУТ убиты, нужно установить privvmpages в значение не превышающее значение oomguardpages или даже меньше для большей гарантии. Примечания:

Если текущее использование RAM+swap + ядерная память (kmemsize) +буферная память (tcpsndbuf + tcprcvbuf+othersockbuf+dgramrcvbuf ) ниже значения barrier параметра oomguardpages, то процессы на данной VPS НЕ БУДУТ экстренно завершены в случае наступления ситуации out-of-memory

Если в момент OOM на нескольких VPS наблюдается превышение oomguardpages, то будут убиваться процессы на VPS где самое большое превышение oomguardpages.

Так barrier для oomguardpages имеет другой смысл, нежели для других параметров.

И значение failcnt10) увеличивается для oomguardpages не в случае достижения barrier как обычно, а для каждого убитого процесса по причине out-of-memory.

Если суммарный размер выданных гарантий по параметру oomguardpages превышает объем физической памяти, то в данной ситуации приложения в VPS-ах с гарантированным уровнем сервиса и системные демоны (как sshd, например) могут быть принудительно завершены в случае наступления ситуации out-of-memory

Алгоритм предоставления памяти в контейнере OpenVZ

Запросы процессов на выделение памяти удовлетворяются или отклоняются на основании следующих правил:

  • Если текущее количество выделенной памяти меньше vmguardpages — запрос удовлетворяется
  • Если текущее количество выделенной памяти превышает vmguardpages, но меньше barrier параметра privvmpages - память выделяется при наличии свободных ресурсов на HN.
  • Если текущее количество выделенной памяти больше barrier параметра privvmpages, то память будет выделена только процессам с высоким приоритетом.
  • Если текущее количество выделенной памяти превышает limit параметра privvmpages - память НЕ БУДЕТ выделена.

Low memory

Из-за особенностей 32-битных процессоров архитектуры x86, RAM компьютера не может использоваться однородно.

Самая важная область памяти - так называемая «low memory», часть памяти, находящаяся в более нижних адресах и непосредственно доступная ядру. Для текущих ядер Linux, размер нижней области памяти - 832 МБ (или, если компьютер имеет меньше RAM, чем 832 МБ, то размер RAM).

Эта область памяти используется для нужд ядра (kmemsize) и буферизации сетевых и локальных соединений (tcprcvbuf, tcpsndbuf, dgramrcvbuf, othersockbuf). Если вы позволите себе распределить между контейнерами больше памяти чем имеет в наличии, будут проблемы.

Количество этой памяти вы можете выяснить командой

grep Low /proc/meminfo 

Если вы используете 32-битный CPU, непременно изучите этот документ:

kmemsize

Размер несвоппируемой памяти для нужд ядра.

Эта память включает в себя все внутренние структуры данных, ассоциированные с процессами, за исключением сетевых буферов (для которых есть отдельные параметры).

Единица измерения - 1 байт

Выбор значения:

Размер kmemsize должен быть достаточен для ожидаемого количества процессов

barrier(kmemsize) >= 40 Кб * avnumproc

avnumproc - ожидаемое среднее количество процессов.

Если правило не выполняется, то приложения могут прерываться во время работы вместо того, чтобы прерываться в момент создания новых процессов.

Зазор между barrier и limit необходимо сделать приблизительно в 10%

Сумма kmemsize для всех VPS должна быть ограничена значением менее 832мб для x86 и физическим объемом RAM минус сумма лимитов для буферной памяти для x86_64.

Буферная память - tcpsndbuf, tcprcvbuf, othersockbuf, dgramrcvbuf

Лимит в нижней памяти (low memory)для буферизации данных TCP-соединений. othersockbuf - для UDP или других протоколов. dgramrcvbuf определяет размер буфера для данных входящих соединений UDP или других протоколов.

Выбор значения:

limit(tcpsndbuf) - barrier(tcpsndbuf)>= 2,5 Кб %%*%% numtcpsock
limit(tcprcvbuf) - barrier(tcprcvbuf)>= 2,5 Кб %%*%% numtcpsock
limit(othersockbuf) - barrier(othersockbuf)>= 2,5 Кб %%*%% numothersock
barrier(tcprcvbuf)>= 64 Кб
barrier(tcpsndbuf)>= 64 Кб
barrier(dgramrcvbuf)>= 32 Кб
barrier(othersockbuf)>= 32 Кб

Если HN имеет достаточно памяти, для повышения производительности желательно:

barrier(dgramrcvbuf)>= 129 Кб
barrier(othersockbuf)>= 129 Кб

В отличие от других параметров для буферной памяти сокетов для dgramrcvbuf значения barrier и limit должны быть одинаковы

Единица измерения - 1 байт

Примечание:

Если это условия выбора значения не выполняются, то некоторые сетевые соединения могут обрываться из-за невозможности отправки данных

Установка больших значений может привести к увеличению производительности, но это не обязательно. Срабатывание limit при выделении памяти для буфера сокета не имеет ярко выраженного негативного эффекта и немного снижает скорость соединений.

Параметр dgramrcvbuf обычно не нуждается в высоких значениях лимитов. Только если VPS должна принимать или отправлять очень большие датаграммы, имеет смысл увеличивать barrier как для othersockbuf, так и для dgramrcvbuf

При срабатывании лимита dgramrcvbuf некоторые датаграммы будут отброшены, что может быть или не быть важным для функционирования приложений. Так как протокол UDP неявляется протоколом с гарантированной доставкой пакетов - то данный лимит не является таким уж и критичным.

UBC вспомогательные параметры для памяти

physpages

Общее количество страниц RAM, используемых процессами в этой Виртуальном окружении. Используется как счетчик реального потребления паямяти.

Единица измерения - 1 страница памяти (4 Кб)

Выбор значения:

barrier = 0

limit должно быть установлено в значение MAX_ULONG.

Примечание:

Для памяти, используемой несколькими различными VPS (отображение, планирование (mapping) разделяемых библиотек, например), только часть страницы приписывают к каждому VPS. Сумма physpages всех VPS соответствует общему количеству памяти используемой на HN всеми VPS.

shmpages

Полный размер совместно используемой памяти (IPC и объекты tmpfs). Эта память учитывается в составе privvmpages.

Единица измерения - 1 страница памяти (4 Кб)

Выбор значения:

shmpages должен быть меньше privvmpages

Значение barrier должно быть установлено равным значению limit

Параметр не влияет на безопасность, стабильность или изоляцию между VPS. Его конфигурация затрагивает функциональные возможности и реакцию приложений на нехватку ресурсов только в данном Виртуальном окружении.

dcachesize

Общий размер заблокированных в памяти структур dentry и inode. Значения dcachesize включены в kmemsize

Единица измерения - 1 структура

Параметр dcachesize управляет памятью для операций с файлами - кеш directory entry (dentry) или inode-кеш.

Параметр dcachesize существует как отдельный параметр для того, чтобы предотвратить сбои связанные с выделением памяти для операций с файлами.

Этот параметр должен иметь зазор между значениями barrier и limit (около 10%)

lockedpages

Страницы, которые не могут быть перемещены в swap (страницы, заблокированные mlock (2)). Эта память учитывается в параметре kmemsize.

Единица измерения - 1 страница памяти (4 Кб)

Выбор значения:

Значение barrier может быть равно limit или несколько меньше.

Примечание:

Следует учитывать, что Web,FTP,почтовые-серверы НЕ используют механизм блокировки страниц с помощью mlock. Конфигурирование данного параметра не влияет на безопасность или стабильность системы в целом или на изоляцию между VPS.

Управление параметрами контейнера OpenVZ

Параметры контейнера задаются параметрами конфигурационного файла /etc/vz/conf/<VEID>.conf
(man ctid.conf(5))

Для изменения параметров используйте утилиту vzctl
(man vzctl (8))

Пример команды определения лимита для контейнера с VEID=1010:

vzctl set 1010 –oomguarpages 128M:2147483647 —save

Примечание:

vzctl не полностью проверяет корректность вводимых аргументов (например, позволяет задавать разный лимит и барьер для таких параметров, как numproc и numfile, для которых лимит и барьер обязаны совпадать), поэтому рекомендуется проводить дополнительную проверку конфигурационных файлов с помощью утилиты vzcfgvalidate:

примеры:

проверить один контейнер:

vzcfgvalidate /etc/vz/conf/1097.conf

Проверить все контейнеры:

for n in /etc/vz/conf/*.conf;do echo Check $n; vzcfgvalidate $n; done

Обратите внимание, что проверяется именно файл (с указанием полного пути), а не текущие параметры, которые могут быть другими, если «vzctl set» запускался без ключа «–save». С другой стороны, vzcfgvalidate удобен тем, что может проверять параметры, когда контейнер не запущен.

Для исправления конфигурационного файла vzcfgvalidate следует запустить с ключом «-r» («repair mode», автоматическое исправление) или «-i» («interactive repair», ручное исправление).

Память и swap

Память, которое приложения могут использовать — это сумма RAM+swap. Если размер используемой памяти превышает RAM, ядро Linux перемещает некоторые данные в SWAP, и загружает их обратно, когда приложение нуждается в них. Часто используемые данные имеют тенденцию оставаться в RAM, редко используемые данные в основном находятся в SWAP`е.

Внутри VPS размер доступного пространства swap не отображается.

Там потребление виртуальной памяти (ram+swap) можно узнать по сумме oomguarpages, kmemsize, tcpsndbuf, tcprcvbuf, othersockbuf, dgramrcvbuf.

Хранение данных в SWAP` тормозит работу системы до некоторой степени. Однако, если нет постоянного обмена со swap, торможение будет незаметным.

SWAP необходим для сдержания пиков нагрузки системы. И он срабатывает как демпфер в случаях DOS атак. Рост нагрузки при DOS атаке приводит к увеличению количества активных процессов которые постепенно, вытесняясь в swap, реагируют на запросы все медленнее и интенсивность атаки падает.

Настоятельно рекомендуется иметь размера SWAP больше размера RAM. Для систем со значительным количеством RAM могут быть выбраны и меньшие значения.

Рекомендации размера swap от Red Hat Knowledgebase

  • Для системы с 4 Гб оперативной памяти или менее требуется как минимум 2 ГБ подкачки
  • Для системы от 4 ГБ до 16 ГБ оперативной памяти требуется как минимум 4 Гб подкачки
  • Для системы от 16GB 64 ГБ оперативной памяти требуется как минимум 8 ГБ подкачки
  • Для системы от 64 ГБ до 256 ГБ оперативной памяти требуется как минимум 16 Гб подкачки

vSWAP

Для эмуляции виртуальной памяти openvz использует технологию vSWAP.

vSWAP – в отличие от swap размещается не на разделе диска, а в оперативной памяти сервера виртуализации. Эта область памяти выделяется гостям с замедлением в несколько раз, что обеспечивает возможность использования ее в качестве замедляющего буфера при перегрузке и нехватке памяти. То есть действует это подобно физическому разделу swap размещенному на диске.

Если в контейнере без vswap процесс запросивший память за пределами лимита жестоко убивается ядром и данные связанные с процессом теряются, то здесь он помещается в замедленную область памяти vswap и выполнение соответствующего запроса замедляется или ожидает освобождения памяти.Клиент выполнивший запрос терпеливо ждет своей очереди, в случае же работы без vswap клиент получает обрыв связи.

Ссылки:

1)
*alloc() - функции выделения динамической памяти, входящие в стандартную библиотеку языка Си.
2)
/proc/meminfo - организация памяти
3)
/proc/sys/vm/swappines это уровень свободной памяти, при котором система начнет активно сбрасывать память в своп (%).
4)
/proc/sys/vm/vfs_cache_pressure - уровень выделяемой памяти под кэш.
5)
/proc/sys/vm/overcommit_memory — разрешение на перевыделение памяти (overcommitting
6)
/proc/sys/vm/overcommit_ratio уровень разрешения на перевыделение памяти (overcommitting
7)
HN — Hardware Node — физический сервер.
8)
OOM - Out of Memory — нехватка памяти, попытка процесса получить памяти больше чем есть в наличии.
9)
MAX_ULONG соответствует значению 2147483647 для архитектуры 32-бит (x86) и 9223372036854775807 для 64-бит (x86_64).
10)
failcnt - cчетчик случаев превышения лимита