← Back to notes

Namespaces


Namespace — механизм виртуального разделения кластера на изолированные сегменты. Позволяет нескольким командам или проектам использовать один кластер без конфликтов имён ресурсов. Имена объектов уникальны внутри одного namespace, но могут повторяться в разных.

source: kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/

Встроенные namespace

Kubernetes создаёт четыре namespace при инициализации кластера:

NamespaceНазначение
defaultПространство по умолчанию для объектов без явного namespace
kube-systemСистемные компоненты: API Server, CoreDNS, kube-proxy, kube-scheduler
kube-publicДанные, читаемые без аутентификации (в том числе cluster-info)
kube-node-leaseОбъекты Lease для heartbeat узлов — механизм определения доступности node

Не трогай kube-system без понимания последствий — это системное пространство кластера.

Cluster-scoped ресурсы

Не все ресурсы привязаны к namespace. Cluster-scoped ресурсы: Node, PersistentVolume, Namespace, ClusterRole, ClusterRoleBinding, StorageClass, IngressClass.

# Посмотреть, какие ресурсы привязаны к namespace
kubectl api-resources --namespaced=true

# Какие нет (cluster-scoped)
kubectl api-resources --namespaced=false

Создание Namespace

Через YAML (рекомендуется)

apiVersion: v1
kind: Namespace
metadata:
  name: dev
  labels:
    environment: development
    team: backend
kubectl apply -f namespace.yaml

Императивно

kubectl create namespace dev
kubectl create namespace staging
kubectl create namespace production

Работа с namespace через kubectl

# Список namespace
kubectl get namespaces
kubectl get ns

# Ресурсы в конкретном namespace
kubectl get pods --namespace=dev
kubectl get pods -n dev

# Все ресурсы в namespace
kubectl get all -n dev

# Ресурсы во всех namespace
kubectl get pods --all-namespaces
kubectl get pods -A

# Удалить namespace (удалит ВСЕ объекты внутри)
kubectl delete namespace dev

Переключение контекста по умолчанию

Чтобы не указывать -n при каждой команде, устанавливают namespace для текущего контекста:

# Посмотреть текущий контекст
kubectl config current-context

# Установить namespace по умолчанию
kubectl config set-context --current --namespace=dev

# Проверить
kubectl config view --minify | grep namespace

# Вернуться в default
kubectl config set-context --current --namespace=default

Инструменты вроде kubens (из пакета kubectx) упрощают переключение до одной команды:

kubens dev        # переключиться в namespace dev
kubens -          # вернуться к предыдущему

ResourceQuota

ResourceQuota ограничивает суммарное потребление ресурсов в namespace. Хорошая практика — устанавливать квоты для каждой команды или окружения.

source: kubernetes.io/docs/concepts/policy/resource-quotas/

apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: dev
spec:
  hard:
    # Вычислительные ресурсы
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    # Количество объектов
    pods: "20"
    services: "10"
    persistentvolumeclaims: "5"
    secrets: "20"
    configmaps: "20"
# Просмотр квот
kubectl get resourcequota -n dev
kubectl describe resourcequota dev-quota -n dev

Важно: при активной ResourceQuota с requests.cpu или requests.memory каждый Pod в namespace обязан указать соответствующие requests. Иначе API Server отклонит создание Pod. Поэтому ResourceQuota всегда используют вместе с LimitRange — который задаёт requests/limits по умолчанию (подробно в главе 13).

DNS и межнеймспейсная коммуникация

Каждый Service получает DNS-запись:

<service-name>.<namespace>.svc.cluster.local

source: kubernetes.io/docs/concepts/services-networking/dns-pod-service/

Внутри одного namespace — достаточно имени Service:

curl http://my-service
curl http://my-service:8080

Между namespace — нужен FQDN или краткая форма с namespace:

# Из namespace "frontend" к Service в namespace "backend"
curl http://api-service.backend.svc.cluster.local
# Или краткая форма (также работает)
curl http://api-service.backend

Пример: многокомандная структура

# Создать namespace для команд
kubectl create namespace team-alpha
kubectl create namespace team-beta
kubectl create namespace shared-services

# Команда разворачивает приложение в своём namespace
kubectl apply -f app.yaml -n team-alpha

# Применить квоты для команды
kubectl apply -f quota-alpha.yaml -n team-alpha

# Проверить потребление
kubectl describe resourcequota -n team-alpha
# Приложение из team-alpha обращается к shared-сервису
# через FQDN: redis.shared-services.svc.cluster.local
apiVersion: v1
kind: Pod
metadata:
  name: app
  namespace: team-alpha
spec:
  containers:
    - name: app
      image: myapp:1.0
      env:
        - name: REDIS_HOST
          value: "redis.shared-services.svc.cluster.local"

Namespace как граница мультитенантности

Namespace — базовая единица soft multi-tenancy: несколько команд делят один кластер с некоторым уровнем доверия. Официальная документация прямо предупреждает: namespace сам по себе НЕ является жёсткой (hard) границей безопасности. Изоляция достигается только конфигурацией нескольких других механизмов поверх namespace.

source: kubernetes.io/docs/concepts/security/multi-tenancy/

Документация различает изоляцию control plane и data plane:

УровеньМеханизмЧто изолирует
Control planeRBAC (Role/RoleBinding, namespace-scoped)доступ к API-объектам чужого namespace
Control planeResourceQuota / LimitRangeпотребление ресурсов, защита от noisy neighbor
Control planePod Security Admissionчто разрешено запускать (privileged/baseline/restricted)
Data planeNetworkPolicyсетевой трафик между namespace
Data planeNode isolation (taints, nodeAffinity)физическое разделение workload по нодам
Data planeSandboxing (gVisor, Kata)изоляция ядра между контейнерами

Критично: если команда может читать/менять API-объекты чужого namespace, она может отключить любые другие политики — поэтому RBAC-изоляция первична.

soft-multitenancy: namespace-per-team

Типичный паттерн — namespace на команду/окружение (не на каждый микросервис). Полный набор границ для одного tenant:

apiVersion: v1
kind: Namespace
metadata:
  name: team-alpha
  labels:
    # Pod Security Admission  enforce restricted, warn/audit baseline
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: v1.36
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/audit: restricted

К нему добавляют: ResourceQuota + LimitRange (границы ресурсов), RBAC RoleBinding на команду (доступ только в свой namespace), default-deny NetworkPolicy (сетевая изоляция, глава 17).

Pod Security Admission (PSA)

Встроенный admission controller (stable с Kubernetes 1.25), enforce'ит Pod Security Standards. Настраивается labels на namespace — без CRD и внешних движков:

pod-security.kubernetes.io/<MODE>: <LEVEL>
pod-security.kubernetes.io/<MODE>-version: <VERSION>   # опционально, напр. v1.36 или latest

Три режима (<MODE>) и три уровня (<LEVEL>):

MODEЧто делает при нарушении
enforcePod отклоняется (применяется только к самим Pod, не к Deployment/Job)
auditPod допускается, нарушение пишется в audit log
warnPod допускается, клиент получает warning (работает и для workload-ресурсов)
LEVELСуть
privilegedбез ограничений; для системных/инфраструктурных workload
baselineзапрет известных privilege escalation: hostNetwork/hostPID/hostIPC, privileged, hostPath, host ports
restrictedbaseline + runAsNonRoot: true, allowPrivilegeEscalation: false, capabilities.drop: [ALL] (+ только NET_BIND_SERVICE), seccompProfile.type: RuntimeDefault/Localhost, ограниченный список volume-типов

source: kubernetes.io/docs/concepts/security/pod-security-admission/ source: kubernetes.io/docs/concepts/security/pod-security-standards/

Когда soft-tenancy недостаточно

Для враждебных tenant (SaaS с недоверенными клиентами) namespace недостаточно — атака идёт через data plane (ядро, узлы). Варианты сильнее:

  • Virtual control plane per tenant — отдельный виртуальный API-сервер на tenant (vCluster).
  • Кластер на tenant — вплоть до dedicated hardware, если VM не считается достаточной границей.

Типичные ошибки

Удаление namespace с живыми ресурсами. kubectl delete namespace dev удалит ВСЕ объекты в namespace — Pod, Service, Deployment, ConfigMap, Secret, PVC. Операция необратима (namespace переходит в Terminating).

Namespace застрял в Terminating. Причина — финализаторы (finalizers) на объектах внутри, которые не могут завершить очистку. Диагностика: kubectl get namespace dev -o yaml — смотреть поле finalizers. Решение: удалить финализаторы вручную или дождаться завершения очистки контроллером.

Не указывать namespace в CI/CD. Скрипты без -n <namespace> работают с default. При смене контекста kubectl или в другом окружении это приводит к деплою не туда. Всегда явно указывай namespace в автоматизации.

Предполагать изоляцию сети внутри кластера. По умолчанию Pod из разных namespace могут свободно общаться. Изоляция трафика — задача NetworkPolicy (глава 17).

Слишком много namespace. Один namespace на микросервис — антипаттерн. Namespace для изоляции команд/окружений, не для каждого приложения.

Альтернативы

Несколько кластеров — жёсткая изоляция, но дороже в эксплуатации. Актуально для compliance, мультирегиональных деплоев или разделения production/non-production.

Virtual Cluster (vCluster) — полноценный Kubernetes API внутри namespace родительского кластера. Даёт изоляцию на уровне кластера без накладных расходов на отдельные control plane.

Hierarchical Namespaces (HNC) — расширение для создания иерархии namespace с наследованием политик. Всё ещё требует отдельной установки, не встроено в core Kubernetes.


03: Labels, Selectors, Annotations

05: ReplicaSet и Deployment

Namespaces | Aleksandr Suprun