На удалённых серверах всё запускаю в докер контейнерах, чтобы в случае ЧП не заблокировать полностью материнскую систему из-за недостатка ресурсов. Иначе приходится бежать до сервера и делать жёсткую перезагрузку через кнопку. А это слишком хлопотно, долго и дорого.
Задать ограничение на ресурсы можно как работающему docker контейнеру, так и при его создании (вариант через командую строку). Расскажу оба варианта.
Контейнер уже запущен
Для запущенного docker контенера можно установить ограничение на ресурсы через команду update. Предположим, что необходимо выделить на контейнер 5 ядер CPU, 8 ГБ ОЗУ и 10 ГБ подкачки. Тогда ограничения будут устанавливаться следующими командами.
Ограничение на количество CPU:
docker update --cpus 5 id_контейнера
Ограничение на ОЗУ:
docker update --memory 8G id_контейнера
Ограничение на ОЗУ+подкачка:
docker update --memory-swap 18G id_контейнера
Обратите внимание, что размер для указания в "memory-swap" надо считать суммарный ОЗУ+подкачка (8 ГБ ОЗУ + 10 ГБ подкачка = 18 ГБ).
Docker может выдать ошибку, если попытаться установить только одно ограничение "memory" на работающем контейнере. Тогда придётся одновременно задать и ограничение на "memory-swap" в одной строке:
docker update --memory 8G --memory-swap 18G id_контейнера
Контейнер ещё не создан (через командную строку)
Заготовка bash-скрипта для запуска контейнера через командную строку с автоматическим выставлением ресурсов почти под максимум системы. То есть:
- Количество CPU = все ядра без одного.
- Количество ОЗУ = 90% всего системного.
- Размер подкачки = 90% системной.
# Количество ОЗУ ram=$( awk '/MemTotal/ {print $2}' /proc/meminfo | tr -d '\n' ) # в килобайтах ram=$(( ${ram}/1024 )) # переводим в мегабайты ram_to_use=$(( ${ram}*9/10 )) # оставляем запас 10% для системы # Количество swap swap=$( awk '/SwapTotal/ {print $2}' /proc/meminfo | tr -d '\n' ) # в килобайтах swap=$(( ${swap}/1024 )) # переводим в мегабайты swap_to_use=$(( ${swap}*9/10 )) # оставляем запас 10% для системы ram_plus_swap_to_use=$(( ${ram_to_use}+${swap_to_use} )) # надо считать сумму # Количество ядер cpu минус 1 (чтобы не повисло намертво) cpus=$( nproc --all | tr -d '\n' ) cpus_to_use=$(( ${cpus}-1 )) echo "Ограничение по ОЗУ ${ram_to_use}m, ОЗУ+подкачка ${ram_plus_swap_to_use}m, ЦПУ ${cpus_to_use}" docker run -dit \ --memory="${ram_to_use}m" \ --memory-swap="${ram_plus_swap_to_use}m" \ --cpus="${cpus_to_use}" \ --name=id_контейнера id_контейнера
Проверка установленных ограничений
Проверить ограничения легче всего такой командой:
docker inspect id_контейнера | grep -i 'NanoCpus\|Memory'
Она выведет части списка информации о контейнере. Там в ключе Memory будет доступное контейнеру количество байт ОЗУ, в MemorySwap размер ОЗУ+свап, а в NanoCpus количество ЦПУ (число делить на 10^9, чтобы получить целое, потому что "нано").
Заметка: часто 1 ядра в запасе не хватает для сильно нагруженных систем. Лучше оставлять минимум 2 свободных ядра для материнской системы. Иначе сервер может заглохнуть до жёсткой перезагрузки.