Pull to refresh
VK
Building the Internet

Gatekeeper в production: полезные практики и шаги, которые не стоит допускать

Reading time7 min
Views6.6K


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

Я — Александр Прохоров, программист компании VK Cloud. Моя команда отвечает за кластеры Kubernetes и их безопасность. На примере наших кейсов покажу, какие есть уязвимости при эксплуатации Kubernetes-кластеров, как с ними помогает бороться Open Policy Agent Gatekeeper и какие проблемы могут встретиться при интеграции Gatekeeper в production-среду.

Материал подготовлен на основе моего выступления на конференции VK Kubernetes Conf «Gatekeeper в production: полезные практики и шаги, которые не стоит допускать».

Базовые меры обеспечения безопасной работы с кластерами


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

  • использование образов только из доверенных registry;
  • запрет на использование тега Latest в образах;
  • обязательное использование limits и requests;
  • запуск привилегированных контейнеров;
  • запрет на использование hostPID и hostIPC.

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

  • работать с политиками;
  • валидировать действия;
  • настраивать не только кластеры Kubernetes, но и другие сервисы или приложения.

Нам нужен был именно такой инструмент. Под наши требования подошел Gatekeeper.

OPA (Open policy agent) и Gatekeeper 


Open Policy Agent — универсальный инструмент, который интегрирован с различными сервисами и позволяет настраивать политики по их использованию.



Gatekeeper — специфическая реализация Open Policy Agent для Kubernetes, которая работает в качестве Webhook для валидации манифестов. Этот инструмент предназначен для аудита и автоматического применения к ресурсам Kubernetes политик безопасности, написанных на языке Rego.

Gatekeeper встраивается между сервером API Kubernetes и OPA в качестве admission-контроллера, принимает все поступающие в кластер запросы на создание каких-либо объектов от kube-apiserver и в реальном времени проверяет их на соответствие предварительно настроенным политикам безопасности.



Условно алгоритм работы со встроенным Gatekeeper следующий:

  • При создании объекта в Kubernetes запрос попадает в KubeAPI.
  • Для проверки отправителя и его прав выполняется аутентификация и авторизация пользователя.
  • После авторизации и аутентификации выполняется мутация данных: к объекту добавляются новые поля или значения в них меняются.
  • Объект валидируется на соответствие валидационной схеме: проверяется наличие ключей, корректность значений и другие параметры.
  • Далее следует этап validation admission, на котором отрабатывают настроенные пользователем политики Gatekeeper. Например, проверяется, есть ли запуск привилегированных контейнеров или контейнеры, у которых в образах есть тег Latest.
  • После успешной проверки объект сохраняется в etcd-хранилище. 



Исходные проблемы нашего Kubernetes 


До внедрения Gatekeeper пользователи нашего Kubernetes сталкивались с рядом проблем. Среди них:

  • неравномерное распределение нагрузки на ноды;
  • несанкционированное выселение с ноды приоритетных подов;
  • невозможность Cluster autoscaler правильно оценить загруженность нод и корректно выделить новые ресурсы для запуска пода.

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

Почему важно соблюдать практику limits/requests


В кластере Kubernetes за размещение подов на конкретной ноде отвечает KubeScheduler. Этот компонент работает по определенному алгоритму, который включает фильтрацию и ранжирование:

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



При этом KubeScheduler получает информацию о загрузке нод из etcd-хранилища, где хранится значение суммы всех контейнеров по лимитам и реквестам для каждого пода. Соответственно, если limits/requests не указаны, KubeScheduler будет распределять нагрузки «вслепую», и они станут неравномерными — возникнут проблемы.

Pod Quality of Service


Также наличие limits/requests влияет на контейнеры Pod Quality of Service, среди которых выделяют три класса:

  • Guaranteed-класс. Самый надежный класс качества. Выдается подам, у которых контейнеры имеют лимиты и реквесты по CPU и Memory. 
  • Burstable-класс. Имеет в поде минимум один контейнер, у которого заданы реквесты и лимиты по CPU и памяти. Причем значение реквестов ниже значения лимитов. 
  • Best effort-класс. Присваивается всем подам, контейнеры которых не имеют ограничений по лимитам ресурсов — limits/requests не заданы.



Best effort-класс самый уязвимый: если при росте нагрузки на ноды не будет хватать ресурсов, Kubernetes начнет освобождать место, выселяя в первую очередь поды с классом best effort. То есть отсутствие limits/requests может стать причиной несанкционированного выселения с ноды приоритетных подов.

Таким образом, соблюдение практики limits/requests:

  • обеспечивает равномерность распределения нагрузки на ноды;
  • исключает выселение с ноды под с высоким приоритетом;
  • помогает Cluster autoscaler понимать, сколько ресурсов нужно выделить для размещения ноды.

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

  • на добавление limits/requests во всех запускаемых контейнерах нужно время;
  • Helm-чарты в репозитории по умолчанию не содержат limits/requests;
  • нужно все правильно подсчитать.

То есть мы не могли применить конкретную политику, обязывающую пользователей выставлять limits/requests. Вместо нее мы решили применить стандартную политику Kubernetes — LimitRange.

LimitRange и Shell-operator


LimitRange — политика ограничения распределения ресурсов (лимиты и запросы), которые можно указать для каждого применимого типа объекта (например, Pod или PersistentVolumeClaim) в пространстве имен.



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

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

Чтобы динамически применять настройку LimitRange на все неймспейсы, которые потенциально может создать клиент, мы применили Shell-operator компании «Флант». Shell-operator позволяет подписаться на события в Kubernetes и настроить на них запуск кастомных скриптов, в том числе хуков. Мы подписались на событие по созданию неймспейса и настроили скрипт, который применяет к нему LimitRange.

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


Помимо централизованного внедрения политик Gatekeeper также помог нам закрыть некоторые «дыры» в базовой системе безопасности Kubernetes. Например, в k8s есть директива hostPath, через которую клиент может реализовать много уязвимостей. Например, через hostPath можно:

  • монтировать Docker, CRI-O сокета в под и получить доступ ко всем контейнерам: запускать, удалять, создавать новые;
  • найти kuberconfig с правами Cluster admin и завладеть им;
  • смонтировать собственный файл с авторизационными ключами и получить неограниченный доступ к кластеру; 
  • примонтировать файл /etc/shadow и взломать хеши.

Чтобы закрыть все уязвимости hostPath, мы использовали hostfilesystem. Это политика Gatekeeper, которая позволяет указывать список директорий, доступных для монтирования, а также выставлять для них права на чтение.

Кроме hostPath, в своих кластерах мы также ограничиваем настройки hostPID и hostIPC, благодаря уязвимостям в которых злоумышленники могут:

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

Gatekeeper помог и в этом случае: закрыть уязвимости hostPID и hostIPC мы смогли с помощью готовой политики hostnamespace.

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



После этого кластерная политика превратится в политику, которая работает относительно неймспейса. 

Подводные камни, с которыми мы столкнулись


В теории работать с политиками просто: достаточно взять политику из репозитория, применить ее и пользоваться. На практике же нередко возникают трудности. Мы столкнулись с некоторыми из них.

  • Внедрение политик без подготовки может нарушить работоспособность рабочей среды Kubernetes. В нашем случае внедрение практики обязательного указания limits/requests сказалось на доступности нод клиентов, одновременно с этим многие пользователи были просто не готовы быстро и корректно указать limits/requests. Чтобы не допустить подобного нужно внедрять политики постепенно или искать альтернативный способ, который позволит применять ограничения нативно.  
  • Install job зачастую используют директиву hostPath и монтируют к себе в контейнер файлы, которые помогают развернуть тот или иной Helm-чарт. Установка чартов из Helm-репозитория может быть несовместима с используемыми политиками. Например, в нашем случае после установки политики hostPath была нарушена работа всех используемых Helm-чартов, а именно Install job в них — совместимость просто не была обеспечена. Чтобы решить проблему, мы выделили Install job Helm-чартов в отдельный KubeSystem.
  • При интеграции Gatekeeper нельзя применять политики к namespace KubeSystem и включать валидацию данного namespace Gatekeeper. Мы знали о таком запрете и не реализовывали его в production, но сделали небольшой тест: при включенной валидации в кластере с CNI-плагином Calico последний не сможет провалидировать свои действия, поскольку APIServer «поднимается» позже. В итоге Calico ждет, когда поднимется Gatekeeper, а Gatekeeper ждет, когда поднимется Calico, — кластер может «не завестись» вовсе. Избежать проблем помогает отключение валидации и отсутствие политик в отношении namespace KubeSystem.



Выводы из нашего опыта


  • Настройка кластеров для безопасного использования — обязательное требование для всех проектов на любом уровне развития. Это связано с тем, что у Kubernetes «из коробки» больше бэкдоров, чем фич, которыми эти бэкдоры можно закрыть. 
  • При работе с кластерами Kubernetes не стоит игнорировать best practice — их несоблюдение может дорого обойтись компании и потребовать много времени на приведение кластеров к соответствию правилам.
  • При настройке Gatekeeper следует отключать валидацию неймспейса KubeSystem, в противном случае кластер может «не завестись».
  • При использовании политик важно учитывать наличие Helm-чартов и их тип — политики безопасности Gatekeeper надо выбирать и настраивать так, чтобы они не влияли на работу Helm-чартов.

Присоединяйтесь к Telegram-каналу «Вокруг Kubernetes», чтобы быть в курсе новостей из мира K8s! Регулярные дайджесты, полезные статьи, а также анонсы конференций и вебинаров.

А также пробуйте наш Kubernetes aaS — новым пользователям для тестирования начисляем 3 000 бонусных рублей.
Tags:
Hubs:
Total votes 17: ↑17 and ↓0+17
Comments3

Articles

Information

Website
vk.com
Registered
Founded
Employees
5,001–10,000 employees
Location
Россия
Representative
Миша Берггрен