Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Пространства имен — критически важный ресурс для поддержки мультитенантной архитектуры кластера Kubernetes. Но ими трудно управлять при работе с крупномасштабными мультитенантными кластерами. К счастью, процесс можно упростить, добавив в Kubernetes функцию иерархических пространств имен. Команда VK Cloud перевела статью о том, как это сделать.
Это статья для тех, у кого есть общее представление о Kubernetes, кластерах, контейнерах и подах. Также потребуются базовые знания о пространствах имен в Kubernetes.
Пространства имен Kubernetes 101
Пространства имен — это ресурс Kubernetes, позволяющий изолировать друг от друга ресурсы других типов. Как и в случае с большинством ресурсов Kubernetes, можно создать пространство двумя способами: определить в файле манифеста с помощью декларативного подхода или императивно, в командной строке. Ниже для примера приведен код файла манифеста для создания пространства coolapp. Это декларативный подход:
apiVersion: v1
kind: Namespace
metadata:
name: coolapp
Следующий набор команд императивно создает пространство имен с помощью инструмента kubectl CLI:
kubectl create namespace coolapp
После создания пространства имен инженеры назначают ему другие ресурсы Kubernetes. Пример ниже показывает, как императивно запустить под Kubernetes с контейнером nginx и назначить ему пространство coolapp, отображающееся в результате выполнения команды.
# kubectl run ngnix --image nginx -n coolapp pod/ngnix created
Чтобы перечислить ресурсы в этом пространстве имен, его нужно декларировать. Вот код получения подов в пространство имен coolapps и результаты его выполнения:
# kubectl get pods -n coolapp
NAME READY STATUS RESTARTS AGE
ngnix 1/1 Running 0 3m5s
Если ресурс назначен какому-то пространству имен, то доступ к нему можно получить только через это пространство. Этот код показывает результат получения подов в пространстве имен по умолчанию, у которого в данном случае нет подов:
# kubectl get pods
No resources found in default namespace.
Почему не удалось найти поды? Потому что созданный ранее под nginx назначен пространству coolapp, а не пространству имен по умолчанию. Под nginx виден только в пространстве coolapp.
Безопасность как преимущество пространства имен
Если ресурс доступен только в определенном пространстве имен, это повышает его уровень безопасности. В пространствах имен Kubernetes с помощью контроля доступа на основе ролей (RBAC) можно назначать права доступа пользователям, группам и другим ресурсам. Например, инженер может создать группу coolapp-admins и предоставить ей полный доступ к любым ресурсам в пространстве имен coolapp. Полный доступ означает, что пользователи из группы coolapp-admins могут создавать, перечислять, обновлять, исправлять и удалять ресурсы.
С другой стороны, инженер может создать группу coolapp-devs, у которой есть разрешения только на создание, обновление и удаление подов в пространстве имен coolapp. Права этой группы касаются только подов и определенных действий, которые можно совершать с ними.
При назначении разрешений ресурсам и ролям в пространствах имен поддерживается очень высокая детализация. Такой уровень безопасности оказывается очень кстати при поддержке мультитенантной архитектуры.
Основы мультитенантной архитектуры Kubernetes
Мультитенантный кластер Kubernetes — это кластер, в котором сосуществуют несколько организаций (см. рис. 1 ниже).
Kubernetes может работать с несколькими арендаторами в одном кластере
Мультитенантная архитектура экономичнее и проще в управлении по сравнению с выделением отдельных кластеров каждому отделу или организации.
В выделенной архитектуре у каждой организации есть собственный Control Plane и виртуальные машины с рабочими нодами. Это довольно дорогое решение. Кроме того, для каждого кластера понадобится выделенный технический персонал. Все это может привести к высоким избыточным расходам. А если ресурсы не используются в полном объеме, это просто трата денег впустую.
С другой стороны, поскольку в мультитенантной архитектуре все операции сконцентрированы в одном кластере, повышается эффективность использования физических ресурсов и трудозатрат ИТ-специалистов.
Упрощаем управление мультитенантным пространством имен
В мультитенантном кластере Kubernetes изоляция организаций реализуется именно с помощью пространств имен. Как мы уже писали выше, в отдельно взятом кластере Kubernetes с помощью пространства можно разделить права доступа пользователей, групп и ресурсов. Таким образом, если инженерам нужно выделить ресурсы на тенант в кластере Kubernetes, они назначают тенант одному или нескольким пространствам имен в этом кластере. Разрешения для ресурсов предоставляются в конкретном пространстве (см. рис. 2 ниже).
В мультитенантном кластере тенанты отделяются друг от друга с помощью пространств имен Kubernetes
Для примера представьте мультитенантный кластер с тремя тенантами: компаниями A, B и C. В каждой из этих компаний есть тенанты, которым разрешено использовать условное общее корпоративное приложение Acme-App, которое размещается на одном кластере.
Теперь давайте представим, что в каждой компании есть несколько подразделений, имеющих право использовать разные функции приложения. В нашем примере это будут HR, финансовый отдел и отдел планирования.
Итак, если в кластере Kubernetes нужно завести и изолировать друг от друга три компании, инженеры создают набор пространств имен:
acme-app-company-a-hr
acme-app-company-a-finance
acme-app-company-a-scheduling
acme-app-company-b-hr
acme-app-company-b-finance
acme-app-company-b-scheduling
acme-app-company-c-hr
acme-app-company-c-finance
acme-app-company-c-scheduling
Для реализации разрешений понадобилось создать девять пространств имен для тенантов. Это вполне подходящая структура, которая, однако, может превратиться в головную боль для техподдержки. Например, если инженерам понадобится изменить разрешение, действующее для всех подразделений одной компании, то им придется вносить изменения как минимум в три пространства имен. А если нужно изменить разрешение для всех компаний, использующих Acme-App, то придется назначать разрешения для всех девяти пространств. Подробности можно узнать из видео, посвященного этой теме.
Очевидно, нужен более рациональный подход. И это как раз иерархические пространства имен. Если они реализованы в кластере Kubernetes, можно создать такую структуру:
acme-app
├── company-a
│ ├── company-a-hr
│ ├── company-a-finance
│ └── company-a-scheduling
├── company-b
│ ├── company-b-hr
│ ├── company-b-finance
│ └── company-b-scheduling
├── company-c
│ ├── company-c-hr
│ ├── company-c-finance
│ └── company-c-scheduling
Как видите, в иерархических пространствах имен реализуется упрощенная организационная структура. В дополнение к организационной простоте такие пространства позволяют распределять разрешения на подчиненные пространства имен.
Вернемся к дереву acme-app с иллюстрации выше. Если в корневом пространстве имен acme-app изменяется разрешение, такое изменение будет распространяться на все подчиненные пространства в структуре дерева. А если инженерам нужно внести изменение во все подчиненные пространства компании A, им нужно всего лишь изменить разрешения в пространстве имен компании A. Подчиненные пространства имен — company-a-hr, company-a-finance и company-a-scheduling — откорректируются автоматически.
Иерархические пространства не только упрощают работу с тенантами в мультитенантном кластере Kubernetes, они еще и повышают операционную эффективность в плане общей эксплуатации и безопасности. К сожалению, на момент написания этой статьи иерархические пространства имен не поставляются с Kubernetes «из коробки», их нужно установить.
Добавляем иерархические пространства имен в кластер Kubernetes
Установка иерархических пространств имен в кластер Kubernetes — дело нехитрое. Ниже приведен пример кода, который делает это под Linux. Кроме того, скрипт устанавливает плагин hns для инструмента командной строки kubectl. Плагин и kubectl предназначены для создания и поддержки иерархических пространств имен. Пример взят из официальной инструкции, VK Cloud тоже будет работать.
kubectl label ns kube-system hnc.x-k8s.io/excluded-namespace=true --overwrite
kubectl label ns kube-public hnc.x-k8s.io/excluded-namespace=true --overwrite
kubectl label ns kube-node-lease hnc.x-k8s.io/excluded-namespace=true --overwrite
Это нужно для того, чтобы исключить проблемы с сервисными пространствами.
HNC_VERSION=v1.0.0
kubectl apply -f https://github.com/kubernetes-sigs/hierarchical-namespaces/releases/download/${HNC_VERSION}/default.yaml
HNC_VERSION=v1.0.0
HNC_PLATFORM=linux_amd64 # также поддерживаются: darwin_amd64, darwin_arm64, windows_amd64
curl -L https://github.com/kubernetes-sigs/hierarchical-namespaces/releases/download/${HNC_VERSION}/kubectl-hns_${HNC_PLATFORM} -o ./kubectl-hns
chmod +x ./kubectl-hns
kubectl hns
Bash-скрипт для установки иерархических пространств имен в кластере Kubernetes
После выполнения скрипта кластер Kubernetes начнет поддерживать иерархические пространства имен. Теперь можно выполнить еще один код, чтобы создать иерархические пространства имен для приложения acme-app, которое уже фигурировало в нашей статье.
#!/bin/bash
# Root namespace
kubectl create namespace acme-app
sleep 2 # Take a rest so the namespace can provision
# Company A namespaces
kubectl hns create company-a -n acme-app
sleep 2 # Take a rest so the namespace can provision
kubectl hns create company-a-hr -n company-a
kubectl hns create company-a-finance -n company-a
kubectl hns create company-a-scheduling -n company-a
# Company B namespaces
kubectl hns create company-b -n acme-app
sleep 2 # Take a rest so the namespace can provision
kubectl hns create company-b-hr -n company-b
kubectl hns create company-b-finance -n company-b
kubectl hns create company-b-scheduling -n company-b
# Company C namespaces
kubectl hns create company-c -n acme-app
sleep 2 # Take a rest so the namespace can provision
kubectl hns create company-c-hr -n company-c
kubectl hns create company-c-finance -n company-c
kubectl hns create company-c-scheduling -n company-c
# Display the hierarchical namespaces tree
kubectl hns tree acme-app
Скрипт для создания набора иерархических пространств имен для мультитенантного приложения acme-app
Так выглядит дерево, созданное в результате выполнения вышеприведенного кода:
acme-app
├── [s] company-a
│ ├── [s] company-a-finance
│ ├── [s] company-a-hr
│ └── [s] company-a-scheduling
── [s] company-b
│ ├── [s] company-b-finance
│ ├── [s] company-b-hr
│ └── [s] company-b-scheduling
└── [s] company-c
├── [s] company-c-finance
├── [s] company-c-hr
└── [s] company-c-scheduling
[s] indicates subnamespaces
Иерархия пространств имен, созданная скриптом, отражает иерархию, которую мы представили выше в этой статье.
Подведем итоги
Иерархические пространства имен дают однозначные преимущества при ведении нескольких тенантов в одном кластере Kubernetes. Благодаря им можно управлять разрешениями в каскадном режиме. Любое изменение разрешений, актуальных для родительского пространства имен, будет применяться и к подчиненным пространствам. Эффективность очевидна.
Как мы уже упоминали, иерархические пространства имен нужно устанавливать для каждого кластера. Они не реализованы в стандартной версии Kubernetes. Вам придется встроить процесс их подготовки в рабочий процесс развертывания, реализуемый у вас в компании. Это потребует некоторых усилий, но оно того стоит. Если в компании поддерживаются мультитенантные кластеры Kubernetes, то имеет смысл сделать иерархические пространства стандартным компонентом архитектуры Kubernetes: в долгосрочной перспективе это сэкономит вам время и деньги.
Попробуйте Kubernetes as a Service на платформе VK Cloud. Мы даем новым пользователям 3000 бонусных рублей на тестирование кластера или любых других сервисов.