Пространства имен — критически важный ресурс для поддержки мультитенантной архитектуры кластера 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 бонусных рублей на тестирование кластера или любых других сервисов.

Комментарии (2)


  1. lllamnyp
    00.00.0000 00:00
    +1

    А почему содержание перевода одно, а ссылка на источник ведёт на совсем другую статью про PodSecurityPolicy и его замены в новых версиях куба?


  1. seasadm
    00.00.0000 00:00
    +2

    Неймспейсы в кубе это с одной стороны группировка объектов, да. Но это не единственная и не самая важная функция.

    Во-первых неймспейсы это сервисдискавери. Полное DNS имя подов и сервисов формируется на основе неймспейсов.

    Во-вторых это безопасность. RBAC мы нарезаем в том числе в разрезе неймспейсов.

    В-третьих неймспейсы это управление ресурсами. Квотами, числом подов и прочее.

    В-четвёртых сетевые политики управляются также в разрезе неймспейсов.

    Вот вы включили иерархические неймспейсы в кубе. Как стали работать эти четыре пункта? Доменные имена теперь с поддержкой вложенных неймспейсов? Квоты и сетевые политики как работают?

    Про права вроде как написали. Интересно как именно это работает.