Больше не нужно искать работу мечты — присоединяйтесь к команде Клауда

Механизмы контейнеризации: cgroups

Команда Timeweb Cloud
Команда Timeweb Cloud
Наши инженеры, технические писатели, редакторы и маркетологи
18 февраля 2022 г.
1625
15 минут чтения
Средний рейтинг статьи: 2.5

Что представляет собой контейнер? Контейнеры — это способ упаковать код, чтобы позволить ему работать на любой машине. Для работы контейнера ОС выделяет пул изолированных ресурсов: память, ядра ЦП, диск и сетевое пространство. Контейнер работает на ядре хостовой ОС и отделяется средствами ОС, а не возможностями железа, как ВМ (виртуальная машина).

Механизмы Контейнеризации  Cgroups (1)

В Linux есть только несколько инструментов ядра, которыми можно ограничить доступ к ресурсам и изолировать системные процессы. С помощью Namespaces (неймспейсы) процессы объединяют в группы и изолируют. При этом с помощью cgroups можно задать лимиты по ресурсам. Cgroups — аббревиатура от Linux «control groups». Определяется как функция ядра Linux, контролирующая распределение ресурсов для пользовательских процессов.

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

Механизмы контейнеризации отличаются от традиционных подходов виртуализации. Контейнеры универсальны - они способны функционировать на обычных и облачных серверах и на отдельной виртуальной машине.

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

Как работают контейнеры

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

С помощью контейнеризации разработчики могут сами создавать ПО, чтобы гарантировать, что оно будет эффективно работать и не даст сбоев.

При контейнеризации есть два файла спецификации, которые определяют, какое ПО  требуется на машине и какое оборудование необходимо для ее работы. Это:

  • Dockerfile, управляющий средой выполнения и установкой необходимых пакетов для достаточного запуска.
  • Yaml-файл, контролирующий аппаратное обеспечение и требования к сетевой безопасности.

После создания контейнера формируется образ, который задается на выбранном узле.

Контейнеризация против виртуализации серверов

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

Этот слой действует как собственная виртуальная машина, создавая автономную среду для запуска одного приложения. Каждое приложение, которое виртуализируется, потребляет свою собственную версию ОС. Для разработки в виртуальной среде необходимо иметь несколько доступных версий ОС либо приобретать лицензии.

С другой стороны, контейнеры позволяют запускать несколько приложений на одной ВМ. Это ограничивает количество лицензий на ПО, в которые корпоративная компания должна инвестировать. Достигается такое за счет совместного использования ядер ОС, вместо того чтобы требовать свои собственные. По этой причине разработка в контейнере - это более ресурсоемкий подход к разработке корпоративного программного обеспечения, как в финансовом, так и в вычислительном плане.

Преимущества контейнеризации для предприятий

Контейнеры - это решение многих проблем, возникающих при разработке кода:

  • различные кодовые базы;
  • безопасность;
  • совместное использование кода в различных системах;
  • использование кода в различных средах выполнения.

Преимущества развертывания ПО на контейнерном движке приведены ниже.

Технология мультиоблачной платформы

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

  • платформы Amazon EC2;
  • платформы Google Compute Engine;
  • серверы Rackspace.

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

Тестирование и непрерывное развертывание

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

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

Контроль версий

Чтобы оставаться конкурентоспособными, контейнерные платформы должны обеспечивать контроль версий.

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

Изоляция

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

Контейнеры, по сравнению с виртуальными машинами, отличаются:

  • быстрым временем запуска;
  • меньшими затратами; 
  • оптимальным распределением ресурсов.

Безопасность

Когда Docker только появился, безопасность была слабой. Позже Docker исправил многие из основных проблем, например, запуск каждого контейнера из корневой папки.

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

Тем не менее, отдельные контейнеры подвержены атакам, но существуют способы их защиты с помощью особых служб мониторинга и современных методик.

Универсальность и удобство использования ресурсов

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

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

Переносимость

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

Воспроизводимость

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

Поддержка DevOps

Для любой среды разработки, требующей портативности и универсальности, DevOps и контейнеры предлагают оптимальное решение. Этому способствуют две ключевые тенденции:

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

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

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

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

Когда использовать контейнеры

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

При внедрении контейнеров рекомендуется выполнить следующие шаги:

  • оценить потребности бизнеса - пробуйте запуск контейнеров в небольших масштабах, чтобы оценить, как это вписывается в бизнес-модель и культуру;
  • запустите стадию производства и разверните контейнеры в своей инфраструктуре.

Управление ресурсами cgroups

Cgroups являются ключевым свойством, с помощью которого можно контролировать выделение ресурсов для конкретного процесса либо группы процессов (tasks). Cpuset Linux показывает, как отдельный контейнер может использовать памяти (Ram группа), cgroups CPU или средства ввода/ вывода. Каждый системный ресурс - это подсистема. Для подсистем создается иерархия. Каждый корневой каталог иерархии (корневая cgroup) и его подкаталоги (дочерние cgroup) содержат собственные файлы конфигурации, устанавливающие ограничения на распределение ресурсов операционной системы.

Image2

Kubernetes cgroup работает по умолчанию с двумя типами ресурсов: CPU и RAM. Каждый вычислительный узел в кластере, контролируемый Kubernetes, содержит определенные ресурсы.

Группы управления Linux

Отдельные программные приложения нуждаются в контроле или ограничении. Это необходимо как с целью стабильности, так и безопасности. Часто одна ошибка или просто плохой код может нарушить работу всей машины и привести к потенциальному сбою в экосистеме. Но есть способ держать приложения под контролем. Группы управления (cgroups) - функция ядра, с помощью которой можно ограничивать, оценивать и изолировать использование процессора, памяти, дискового ввода-вывода и сети одним или несколькими процессами.

Первоначально разработанная Google, технология cgroups в конечном итоге попала в основную часть ядра Linux в версии 2.6.24 (январь 2008 года). Переработка этой технологии - то есть добавление kernfs (для разделения части логики sysfs) - будет включена в ядра 3.15 и 3.16.

Основной целью разработки cgroups было предоставление унифицированного интерфейса для управления процессами или виртуализацией на уровне всей операционной системы, включая Linux Containers или LXC. Фреймворк cgroups обеспечивает следующее:

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

Группа cgroup может состоять из одного или нескольких процессов, которые привязаны к одному и тому же набору ограничений. Эти группы могут быть иерархическими - подгруппа наследует ограничения, установленные для ее родительской группы.

Ядро Linux предоставляет доступ к ряду контроллеров или подсистем для технологии cgroup. Контроллер отвечает за распределение определенного типа системных ресурсов для набора одного или нескольких процессов. Например, контроллер памяти ограничивает использование памяти, а контроллер cpuacct следит за использованием процессора.

Вы можете получить доступ к cgroups и управлять ими как напрямую, так и косвенно (с помощью LXC, libvirt или Docker). Рассмотрим на примере. В Red Hat Enterprise Linux или CentOS введите в командной строке следующее:

$ sudo yum install libcgroup libcgroup-tools

Ручной способ

Установив соответствующие пакеты, вы можете конфигурировать cgroups непосредственно через иерархию sysfs. Например, чтобы создать cgroup с именем foo в подсистеме памяти, создайте каталог с именем foo в /sys/fs/cgroup/memory:

$ sudo mkdir /sys/fs/cgroup/memory/foo

По умолчанию каждая вновь созданная cgroup наследует доступ ко всему пулу памяти системы. Для некоторых приложений, в первую очередь тех, которые продолжают выделять все больше памяти, но отказываются освобождать уже выделенную, это не совсем правильно. Чтобы ограничить приложение до разумного предела, необходимо обновить файл memory.limit_in_bytes.

Ограничьте память для всего, что работает под cgroup foo, до 50 МБ:

$ echo 50000000 | sudo tee /sys/fs/cgroup/memory/foo/memory.limit_in_bytes

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

$ sudo cat memory.limit_in_bytes
50003968

Обратите внимание, что значение, считанное обратно, всегда будет кратно размеру страницы ядра (то есть 4096 байт или 4 КБ). Это значение является наименьшим размером памяти, который можно выделить.

Запустите приложение:

$ sh ~/test.sh &

Используя идентификатор процесса (PID), переместите приложение в cgroup foo под контроллером памяти:

$ echo 2845 /sys/fs/cgroup/memory/foo/cgroup.procs

Используя тот же номер PID, перечислите запущенный процесс и убедитесь, что он запущен в нужной cgroup:

$ ps -o cgroup 2845
CGROUP
8:memory:/foo,1:name=systemd:/user.slice/user-0.slice/
session-4.scope

Вы также можете следить за тем, что в настоящее время используется этой cgroup, читая нужные файлы. В данном случае вы можете увидеть объем памяти, выделенной вашему процессу (подпроцессам):

$ cat /sys/fs/cgroup/memory/foo/memory.usage_in_bytes
253952

Когда процесс сбился

Теперь давайте повторим тот же сценарий. Вместо того, чтобы ограничить cgroup foo 50 МБ памяти, ограничьте ее 500 байтами:

$ echo 500 | sudo tee /sys/fs/cgroup/memory/foo/
memory.limit_in_bytes

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

Если считать значение обратно, то оно будет кратно размеру страницы ядра. Несмотря на то, что было установлено значение 500 байт, на самом деле оно равно 4 КБ:

$ cat /sys/fs/cgroup/memory/foo/memory.limit_in_bytes
4096

Запустите приложение, переместите его в группу cgroup, следите за системными журналами.

Итак, Out-Of-Memory Killer  (или oom-killer) ядра вмешался, как только приложение достигло предела в 4 КБ. Оно уничтожило приложение, которое больше не выполняется. Вы можете убедиться в этом, набрав:

$ ps -o cgroup 2687
CGROUP

Использование libcgroup

Многие из описанных выше шагов упрощаются благодаря утилитам администрирования, входящим в пакет libcgroup. Например, процесс создания записей и файлов sysfs выполняется одним вызовом команды cgcreate.

Чтобы создать группу с именем foo в подсистеме памяти, введите следующее:

$ sudo cgcreate -g memory:foo

Примечание: libcgroup предоставляет механизм для управления задачами в группах управления.

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

$ echo 50000000 | sudo tee
/sys/fs/cgroup/memory/foo/memory.limit_in_bytes

Проверка настроенных параметров:

$ sudo cat memory.limit_in_bytes
50003968

Запустите приложение в cgroup foo с помощью бинарного файла cgexec:

$ sudo cgexec -g memory:foo ~/test.sh

Используя его PID номер, проверьте, что приложение запущено в cgroup и под определенной подсистемой (память):

$  ps -o cgroup 2945
CGROUP
6:memory:/foo,1:name=systemd:/user.slice/user-0.slice/session-1.scope

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

$ sudo cgdelete memory:foo

Постоянные группы

Вы также можете выполнить все вышеперечисленное с помощью простого конфигурационного файла и запуска службы. Можно определить все имена и атрибуты cgroup в файле /etc/cgconfig.conf.

Параметры cpu.shares определяют приоритет ЦП для группы. По умолчанию все группы наследуют 1,024 доли или 100% процессорного времени. Если уменьшить это значение до более консервативного, например, 100, то группа будет ограничена примерно 10% процессорного времени.

Процесс, запущенный в cgroup, также может быть ограничен количеством CPU (ядер), к которым он может получить доступ. Добавьте следующий раздел в тот же файл cgconfig.conf и под нужным именем группы:

cpuset {
  cpuset.cpus="0-5";
}

При таком ограничении эта cgroup привяжет приложение к ядрам от 0 до 5 - то есть оно будет видеть только первые шесть ядер процессора в системе.

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

$ sudo systemctl enable cgconfig
Create symlink from /etc/systemd/system/sysinit.target.wants/
cgconfig.service
to /usr/lib/systemd/system/cgconfig.service.

Теперь запустите службу cgconfig и загрузите тот же файл конфигурации вручную (можно пропустить этот шаг и перезагрузить систему):

$ sudo systemctl start cgconfig

Запустите приложение в cgroup foo и привяжите его к ограничениям памяти и процессора:

$ sudo cgexec -g memory,cpu,cpuset:foo ~/test.sh &

За исключением запуска приложения в предопределенной cgroup, все остальное будет сохраняться при перезагрузке системы. Но можно автоматизировать этот процесс, определив сценарий запуска init, зависящий от службы cgconfig, для запуска того же приложения.

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

18 февраля 2022 г.
1625
15 минут чтения
Средний рейтинг статьи: 2.5
Пока нет комментариев