Что следует знать при использовании Docker для развертывания решений AI / ML

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

Краткий обзор

Что такое Docker и почему он так популярен?

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

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

  1. Виртуализация на уровне операционной системы, обеспечивающая переносимость и согласованность. В результате этого уровня абстракции контейнеры Docker часто намного быстрее по сравнению с виртуальными машинами, поскольку нет необходимости тратить время на раскручивание операционной системы при каждом ее запуске [1 ].
  2. Легковесный (т. е. содержат только необходимые зависимости). В результате (1) контейнеры Docker также более легкие, что приводит к меньшему количеству необходимых системных ресурсов. Кроме того, чаще всего модели машинного обучения развертываются как микросервисы API и, следовательно, требуют лишь минимума зависимостей. Прохождение трудного процесса согласования UAT и производственной среды часто оказывается намного более сложным, чем должно быть. Таким образом, контейнеры Docker образуют де-факто архитектуру микросервисов для развертывания моделей машинного обучения.
  3. Менее дорого - это просто результат двух вышеуказанных пунктов.

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

Как работает Docker

Чтобы понять, как работает Docker, нам нужно понять две основные функции ядра Linux, преимущества которых использует Docker.

Пространства имён

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

Когда контейнер Docker запускается, Docker создает набор namespaces для этого конкретного контейнера, и его доступ ограничен этим пространством имен. Примеры namespaces, используемых в Docker, можно найти в [2] и обычно используются для управления процессами, сетью, монтированием тома, управлением доступом к межпроцессным коммуникационным ресурсам и изоляции идентификаторов ядра / версии (Unix Time-Sharing). Это изолирует среду выполнения, поскольку она не может видеть другие пространства имен, контейнеры и приложения в системе.

Контрольные группы

Эта функция ядра Linux, также известная как cgroups, ограничивает, учитывает и изолирует использование ресурсов (ЦП, память, дисковый ввод-вывод, сеть и т. Д.) Набора процессов [4]. По сути, это позволяет подсистеме Docker совместно использовать доступные аппаратные ресурсы хоста с контейнерами и, при необходимости, применять ограничения и ограничения. Это гарантирует, что каждый контейнерный микросервис не будет использовать больше ресурсов, чем должен. С точки зрения безопасности, это предотвращает случайную атаку распределенного отказа в обслуживании (DDoS), которая приведет к «сбою» контейнера и, следовательно, хост-системы.

Чем n amespaces отличаются от cgroups?

Пространства имен ограничивают то, что вы можете видеть (и, следовательно, использовать), в то время как контрольные группы ограничивают то, что вы можете использовать.

Следовательно, когда мы выполняем команду docker run, Docker за кулисами создает набор из namespaces и cgroups для контейнера. С точки зрения контейнера, он не знает, что это на самом деле «машина внутри машины» [1].

Проблемы безопасности

Теперь, когда мы знаем, как работает Docker, каковы потенциальные проблемы при развертывании микросервиса контейнера? На официальной странице Docker, посвященной безопасности Docker [5], перечислены четыре основные области, которые следует учитывать, в том числе:

  1. Внутренняя безопасность ядра Linux и его поддержка namespaces и cgroups
  2. Поверхность атаки самого демона Docker
  3. Лазейки в профиле конфигурации контейнера, и
  4. «усиление» функций безопасности ядра и их взаимодействия с контейнерами.

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

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

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

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

Давайте рассмотрим некоторые способы повышения безопасности наших контейнеров за счет уменьшения поверхности атаки демона и самих контейнеров.

Укрепление хозяина

№1. Используйте сканер изображений контейнера

Сканер изображений предназначен для анализа содержимого и процесса построения образа контейнера с целью обнаружения проблем безопасности, уязвимостей или недобросовестных действий. Некоторые из имеющихся на рынке инструментов включают Docker Bench, Clair и Anchore. Я только лично опробовал Docker Bench и показал ниже снимок экрана, чтобы показать, какой результат он показывает.

На мой взгляд, это хорошее место для начала знакомства с лучшими практиками безопасности после того, как вы научились создавать базовый образ Docker, поскольку он выявляет потенциальные проблемы безопасности, связанные с:

  • Конфигурация хоста Linux
  • Конфигурация и файлы конфигурации демона Docker
  • Образы контейнеров и файл сборки
  • Время выполнения контейнера
  • Конфигурация Docker Swarm (если есть)
  • Конфигурация предприятия Docker (если есть)

Некоторые проверки соответствуют лучшим практикам при создании образов Docker, а также вдохновлены CIS Docker Benchmark v1.2.0. Также, возможно, стоит изучить, как реализовать эти проверки в вашем конвейере CI / CD.

Комментарии: у меня возникли проблемы с запуском команды MacOS docker run на моем локальном компьютере, и я прибег к клонированию репозитория и непосредственному запуску sudo sh docker-bench-security.sh сценария.

№2. Повысьте безопасность ядра с помощью современных ядер Linux, таких как SELinux, AppArmor и т. д.

AppArmor - это модуль безопасности ядра Linux, который ограничивает возможности процессов, запущенных в операционной системе хоста. По умолчанию развернутый контейнер Docker остается защищенным с помощью автоматически сгенерированного профиля с именем docker-default, созданного на основе этого шаблона, и обеспечивает умеренную безопасность на уровне приложения. Чтобы повысить безопасность, профиль безопасности AppArmor можно связать с контейнером с помощью параметра --security-opt в течение docker run, чтобы обеспечить соблюдение профиля безопасности, который работает на уровне процесса / программы приложение [10].

Как и AppArmor, Security-Enhanced Linux (SELinux) - это модуль безопасности ядра Linux, который предоставляет механизм для поддержки политик безопасности контроля доступа, включая обязательный контроль доступа (MAC) [11 ]. Он обеспечивает готовый дополнительный уровень безопасности, давая администраторам больше контроля над тем, кто может получить доступ к системе. Это особенно важно, поскольку злоумышленник может сделать с хостом практически все, что угодно, если он / она может запустить контейнер Docker с root привилегиями. (Обратите внимание, что использование SELinux с контейнерами поддерживается только в CentOS и Red Hat Enterprise Linux.)

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

№1: Не запускайте контейнер как root пользователь (если возможно) - после выполнения необходимых установок на начальных этапах Dockerfile измените пользователя на непривилегированного, используя что-то вроде:

FROM alpine
RUN groupadd -r myuser && useradd -r -g myuser myuser
<Install dependencies, etc>
# Switch user
USER myuser

№2. Создайте временные контейнеры

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

  • Ограничение возможностей ядра Linux путем отказа от всех возможностей и добавления только того, что необходимо (например, docker run --cap-drop all --cap-add CHOWN alphine)
  • Предотвращение повышения привилегий внутри контейнера с помощью параметра --security-opt=no-new-privileges
  • Отключение межконтейнерного взаимодействия с помощью параметра -icc=false
  • Ограничение ресурсов, доступных для контейнера
  • Настройка файловой системы (например, docker run --read-only alpine sh) и томов (например, docker run -v volume-name:/path/in/container:ro alpine) только для чтения (если не требуется)

№3. Используйте образ без дистрибутива в многоэтапной сборке Docker

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

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

Заключительное слово

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

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

Примечание от редакторов Data Science. Хотя мы разрешаем независимым авторам публиковать статьи в соответствии с нашими правилами и рекомендациями, мы не поддерживаем вклад каждого автора. Не стоит полагаться на работы автора без консультации с профессионалами. См. Подробности в наших Условиях для читателей.

Поддержите меня! - Если вам нравится мой контент и вы не подписаны на Medium, рассмотрите возможность поддержки меня и подписки по моей реферальной ссылке здесь (ПРИМЕЧАНИЕ: часть ваших членских взносов будет распределена мне как реферальные взносы).

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

[1]: Что такое контейнерные микросервисы?

[2]: Пространства имен Linux

[3]: Документация Docker: технология, лежащая в основе

[4]: cgroups

[5]: Докерская безопасность

[6]: Памятка по безопасности Docker

[7]: Безопасность Docker Bench

[8]: Как укрепить ваш контейнер с помощью образов Docker без дистрибутива

[9]: 12 лучших практик сканирования изображений в контейнерах для использования в производственной среде

[10]: Профили безопасности AppArmor для Docker

[11]: Использование SELinux с контейнерами

[12]: Защитите свои контейнеры с помощью SELinux