Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Docker і обмеження ресурсів

with one comment

Раніше я вже писав собі шпаргалку по докеру, яка нікому крім мене майже не потрібна, тут буде додаток до неї.

Контейнери докера – це аналог процесів в ОС – тобто щось що запущено виконується. Запускаються імеджі (аналог виконуваної програми). Можна взяти готовий імедж, можна зробити свій за допомогою докерфайла (аналог коду програми), який описує як білдиться (аналог компіляції) імедж.

Загалом команда запуску контейнера виглядає так:

docker run $image_name [$command]

Наприклад якщо цікаво виконати якийсь код на останньому Python, але лінь його ставити, докер скачає і виконає:

docker run python:latest python -c "import sys; print(sys.version)"
# Unable to find image 'python:latest' locally
# latest: Pulling from library/python
# 22dbe790f715: Pull complete 
# ...
# 61b3f1392c29: Pull complete 
# Digest: sha256:c32b1a9fb8a0dc212c33ef1d492231c513fa326b4dae6dae7534491c857af88a
# Status: Downloaded newer image for python:latest
# 3.7.2 (default, Mar  5 2019, 06:22:51) 
# [GCC 6.3.0 20170516]

Якщо не передавати ніяку команду, контейнер виконуватиме ту що для нього задана за замовчуванням. Наприклад

docker run --name test_python_run python:latest # задаємо контейнеру ім'я щоб не сплутати з іншими:
docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                    NAMES
d95e1e13e3f2        python:latest       "python3"                5 seconds ago       Exited (0) 4 seconds ago                             test_python_run

Бачимо що контейнер запускав команду “python3” але вийшов з неї (бо термінал не приєднався). Щоб увійти в інтерактивну сесію, треба запускати так (-i вроді означає інтерактивно, тобто очікувати на stdin, -t – приєднати до поточного терміналу):

docker run -it python:latest

Тільки через командний рядок багато Python коду не передаш. Тому є два варіанти передати файли в контейнер. Перший – прямо в image, за допомогою dockerfile.

Візьмемо для експерименту такий скрипт що поступово пробує використати все більше й більше пам’яті:

import random
import time

data = []
for i in range(10 ** 6):
    data.append(random.random())
    if i % 1000 == 0:
        print(len(data))
        time.sleep(0.25)

Managing memory in Python is easy—if you just don’t care. Документація Theano.

Щоб створити з ним імедж достатньо такого докерфайлу:

FROM python:3.7
COPY script.py ./script.py
CMD python script.py

Тепер, щоб створити з нього імедж який називається наприклад memeater (зжирач пам’яті), треба виконати:

docker build -t memeater -f Dockerfile .

А щоб потім запустити цей контейнер:

docker run -t memeater

-t щоб бачити що він пише в stdout.

Далі ми можемо за допомогою команди docker stat спостерігати за тим скільки ресурсів цей контейнер їсть:

CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
8a58c19cc93c        exp                 0.28%               6.02MiB / 10MiB     60.20%              3.17kB / 0B         565kB / 1.01MB      2

Аби він не з’їв всю доступну пам’ять, можна йому обмежити ресурси:

docker run -t --name experiment --memory="10M" --cpus=0.1 memeater

Якщо вискакує повідомлення “WARNING: Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.”, значить у вас трохи не такий Linux, і обмеження стосуватиметься лише RAM, а не області підкачки. Задати параметр --memory-swap теж не допоможе.

Допоможе – взагалі відключити зберігання сторінок на диск.

docker run -t --name experiment --memory="20M" --memory-swappiness=0 --cpus=0.1 memeater

Якщо отримуєте помилку “docker: Error response from daemon: OCI runtime create failed: container_linux.go:344: starting container process caused “process_linux.go:424: container init caused \”\””: unknown.”, то це тому що обмеження по пам’яті за сильне. В мене при 10M вискакує, при 20 – ні.

Що відбувається коли пам’ять закінчується? Лог закінчується так:

492001
Killed

З цього експерименту можна зробити висновок що Python, запущений в системі з доступною пам’яттю 20 мегабайт може втримати в пам’яті трохи менше ніж пів мільйона чисел з плаваючою крапкою.

Advertisements

Written by bunyk

Березень 31, 2019 at 01:43

Опубліковано в Кодерство

Tagged with ,

Одна відповідь

Subscribe to comments with RSS.

  1. […] все в пам’яті, але аби комп’ютеру не стало погано якось обмежити доступну пам’ять. Але мої 4Gb використовувались лише щось трохи більше […]


Напишіть відгук

Заповніть поля нижче або авторизуйтесь клікнувши по іконці

Лого WordPress.com

Ви коментуєте, використовуючи свій обліковий запис WordPress.com. Log Out /  Змінити )

Google photo

Ви коментуєте, використовуючи свій обліковий запис Google. Log Out /  Змінити )

Twitter picture

Ви коментуєте, використовуючи свій обліковий запис Twitter. Log Out /  Змінити )

Facebook photo

Ви коментуєте, використовуючи свій обліковий запис Facebook. Log Out /  Змінити )

З’єднання з %s

Цей сайт використовує Akismet для зменшення спаму. Дізнайтеся, як обробляються ваші дані коментарів.

%d блогерам подобається це: