Що таке namespace
Namespace — це квартири у великому багатоквартирному будинку:
🟢 Junior Level
30-секундна відповідь
Namespace (Простір імен) — це вбудований механізм Kubernetes для віртуального логічного розділення одного фізичного кластера на ізольовані робочі області для різних команд, проєктів або середовищ (dev, stage, prod).
- Усунення конфлікту імен: усередині одного namespace імена ресурсів мають бути унікальними, але в різних просторах імен можуть одночасно працювати поди або сервіси з абсолютно однаковими іменами (наприклад,
payment-serviceуdevтаpayment-serviceуprod). - Розподіл прав доступу (RBAC): адміністратор може надати розробникам повні права в просторі
developer-sandbox, але заборонити навіть читання логів у просторіproduction. - Обмеження ресурсів: кожному простору імен можна встановити жорсткий ліміт за сумарними витратами CPU та оперативної пам’яті (ResourceQuota).
Наочна аналогія з життя
Namespace — це квартири у великому багатоквартирному будинку:
- Сам будинок — це фізичний кластер серверів.
- Квартири 101, 102 та 103 — це простори імен (
dev,stage,prod). - У кожній квартирі на кухні стоїть свій холодильник із биркою «Холодильник» (однойменні поди
order-db). Мешканці різних квартир не плутають свої холодильники, тому що вони розташовані в ізольованих кімнатах.
Базовий маніфест і команди
apiVersion: v1
kind: Namespace
metadata:
name: billing-prod
labels:
environment: production
team: billing
# Переглянути список усіх просторів імен у кластері
kubectl get namespaces
# Запустити под у конкретному namespace
kubectl run test-pod --image=nginx -n billing-prod
# Перемкнути робочий namespace за замовчуванням (щоб не писати прапорець -n)
kubectl config set-context --current --namespace=billing-prod
[!WARNING] Namespace — це НЕ фізична і НЕ мережева ізоляція! За замовчуванням у Kubernetes увімкнена пласка мережа: будь-який под із простору
devможе вільно надсилати HTTP-запити в базу даних у просторіprod. Для реальної мережевої ізоляції потрібне налаштуванняNetworkPolicy.
🟡 Middle Level
Розподіл ресурсів: Namespace-Scoped vs Cluster-Scoped
[ Kubernetes Кластер ]
│
┌───────────────────────────┴───────────────────────────┐
▼ ▼
[ Namespace-Scoped Ресурси ] [ Cluster-Scoped Ресурси ]
Живуть строго всередині простору імен: Глобальні для всього кластера:
- Pod, Deployment, StatefulSet - Node (Фізичний сервер)
- Service, Ingress, EndpointSlice - PersistentVolume (PV)
- ConfigMap, Secret - StorageClass
- PersistentVolumeClaim (PVC) - ClusterRole, ClusterRoleBinding
- ServiceAccount, Role, RoleBinding - Namespace (Сам простір)
Міжмережева взаємодія: CoreDNS та FQDN
Поди з різних просторів імен можуть легко звертатися один до одного мережею з використанням повних доменних імен (FQDN):
http://<service-name>.<namespace-name>.svc.cluster.local:<port>
- Усередині одного namespace: достатньо короткого імені:
http://postgres:5432. - З іншого namespace: вимагається FQDN:
http://postgres.billing-prod.svc.cluster.local:5432.
Контроль місткості: ResourceQuota vs LimitRange
Для захисту кластера від неконтрольованого споживання ресурсів використовуються два взаємодоповнюючі механізми:
1. ResourceQuota (Сумарна стеля на весь Namespace)
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: dev-team
spec:
hard:
requests.cpu: "20" # Сума всіх requests.cpu не може перевищити 20 ядер
requests.memory: 50Gi # Сума всіх requests.memory не більше 50 ГБ
limits.cpu: "40"
limits.memory: 100Gi
pods: "30" # Максимум 30 подів у цьому namespace
2. LimitRange (Правила для кожного окремого контейнера)
apiVersion: v1
kind: LimitRange
metadata:
name: container-limits
namespace: dev-team
spec:
limits:
- default: # Ліміт за замовчуванням, якщо розробник забув вказати
cpu: "1"
memory: "1Gi"
defaultRequest: # Реквест за замовчуванням
cpu: "200m"
memory: "256Mi"
max: # Заборонити контейнери понад 4 CPU
cpu: "4"
memory: "4Gi"
type: Container
🔴 Senior Level
Ілюзія безпеки: чому Namespace не є межею довіри
На архітектурних співбесідах Senior-рівня поширене запитання:
«Чи безпечно розміщувати в одному кластері в різних Namespace застосунки публічного контуру та закриті банківські бази даних?»
Відповідь: НІ, якщо не вжито додаткових заходів. Namespace ізолює лише видимість через API Server, але:
- Спільне ядро Linux (Shared Kernel): поди з
devтаprodможуть бути запущені шедулером на одній і тій самій фізичній ноді. Вразливість ядра Linux (наприклад, Dirty Pipe, Dirty COW або баги в підсистемі eBPF) дозволяє процесу з ненадійного контейнера отримати root-доступ до хоста й захопити сусідні контейнериprod. - Пласка мережа (Flat Network): якщо в кластері не увімкнено CNI з підтримкою
NetworkPolicy(Cilium або Calico) і не оголошено політику «заборонити все за замовчуванням» (Default Deny), контейнери бачать трафік один одного. - Рішення для строгого Multi-Tenancy: фізичне розділення на різні кластери серверів, або ізоляція середовищ виконання на базі віртуалізації рівня гіпервізора (Kata Containers, gVisor).
Зависання Namespace у статусі Terminating (Finalizers Trap)
Класична аварійна ситуація: адміністратор виконує kubectl delete namespace staging, але видалення зависає в статусі Terminating на кілька днів.
Механізм зависання:
- Контролер
NamespaceLifecycleвстановлює статусTerminatingта запускає каскадне видалення всіх вкладених ресурсів. - У секції
spec.finalizersу простору імен за замовчуванням стоїть блокувальникkubernetes. - Якщо хоча б один вкладений ресурс містить незавершений фіналізатор (наприклад, PVC очікує відповіді від відключеного хмарного сховища AWS EBS, або користувацький CRD від оператора не може завершити graceful-очищення), видалення блокується назавжди.
Алгоритм реанімації:
# 1. Знайти ресурс, що блокує видалення
kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl get --show-kind --ignore-not-found -n staging
# 2. Очистити фіналізатори на проблемному об'єкті
kubectl patch pvc stuck-pvc -n staging -p '{"metadata":{"finalizers":null}}' --type=merge
# 3. Крайній хірургічний захід: пряме видалення фіналізатора через Raw API
kubectl get namespace staging -o json | jq '.spec.finalizers=[]' | kubectl replace --raw "/api/v1/namespaces/staging/finalize" -f -
Pod Security Standards (PSA) на рівні Namespace
У Kubernetes 1.25+ застарілі PodSecurityPolicy замінені на вбудований Admission Controller Pod Security Admission (PSA), який налаштовується простими лейблами на самому Namespace:
apiVersion: v1
kind: Namespace
metadata:
name: secure-prod
labels:
# Заборонити запуск root-контейнерів, hostPath, privileged mode
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/warn: restricted
API Server автоматично відхилить створення будь-якого пода, що порушує стандарти безпеки CIS Benchmark!
4 Tricky Questions
1. Що станеться при спробі створити Deployment без блоку resources.requests, якщо в даному Namespace активний об’єкт ResourceQuota з обмеженням за CPU?
Відповідь: API-сервер негайно відхилить створення пода з помилкою валідації admission-контролера:
Error from server (Forbidden): pods "order-app-xxx" is forbidden: failed quota: compute-quota: must specify cpu for: order-app
Якщо в ResourceQuota задано обмеження на сумарний обсяг requests.cpu, контролер квот вимагає, щоб абсолютно кожен контейнер у цьому namespace мав явно оголошений requests.cpu.
Єдиний спосіб уникнути цієї помилки без ручного прописування ресурсів у кожному маніфесті — створити в цьому ж просторі імен об’єкт LimitRange із секцією defaultRequest, який автоматично підставлятиме дефолтні значення в усі нові контейнери на етапі мутації маніфесту.
2. Чому PersistentVolume (PV) є об’єктом кластерного рівня (Cluster-Scoped), у той час як PersistentVolumeClaim (PVC) прив’язаний до конкретного Namespace?
Відповідь: Це фундаментальне архітектурне розділення зон відповідальності:
PersistentVolume(PV) являє собою фізичний дисковий ресурс (LUN у СЗД, том AWS EBS, локальний NVMe SSD). Ним розпоряджається адміністратор інфраструктури кластера. Цей ресурс глобальний і не повинен бути прив’язаний до ізольованих проєктів.PersistentVolumeClaim(PVC) — це користувацька заявка на ресурс від конкретного застосунку розробника (наприклад: «Мені в проєкті billing потрібно 50 ГБ SSD»). Вона створюється розробником у межах свого Namespace.- Kubernetes знаходить відповідний вільний глобальний PV і монопольно пов’язує (bind) його з локальним PVC. При видаленні Namespace видаляється лише заявка (PVC), а доля фізичного тома (PV) визначається його глобальною політикою
reclaimPolicy(RetainабоDelete).
3. Яким чином зловмисник, що скомпрометував под у Namespace development, може отримати доступ до бази даних у Namespace production при стандартній конфігурації Kubernetes?
Відповідь: При розгортанні кластера «з коробки»:
- Мережевий рівень: мережева модель Kubernetes CNI за замовчуванням є абсолютно пласкою та повністю дозвільною (Allow-All). Зловмисник із шелла пода в
devможе запуститиcurl http://db.production.svc.cluster.local:5432і отримати доступ до відкритого сокета бази даних. - Рівень DNS: CoreDNS кластера резольвить імена сервісів із будь-яких просторів імен для всіх клієнтів без обмежень.
Захист: обов’язкове створення маніфесту
NetworkPolicyз типомIngress, що дозволяє підключення до БД уproductionлише від подів, які мають строго визначенийnamespaceSelector.
4. Чи можна перенести вже працюючий Pod або Service з одного Namespace до іншого за допомогою команди kubectl?
Відповідь:
Ні, перенести працюючий об’єкт між просторами імен неможливо.
Поле metadata.namespace є незмінним (Immutable) з моменту створення об’єкта.
У базі даних etcd ключ ресурсу жорстко включає ім’я namespace: /registry/pods/<namespace>/<pod-name>.
Щоб перемістити сервіс, необхідно:
- Вивантажити його маніфест:
kubectl get deployment my-app -n old-ns -o yaml > app.yaml. - Змінити в маніфесті поле
metadata.namespace: new-ns. - Застосувати його в новому просторі:
kubectl apply -f app.yaml. - Видалити старий ресурс у колишньому просторі імен.
🎯 Шпаргалка для інтерв’ю
Головне про Namespace
- Суть: віртуальне логічне розділення кластера; дозволяє використовувати однакові імена ресурсів у різних середовищах.
- Головний міф: Namespace НЕ забезпечує фізичну та мережеву ізоляцію за замовчуванням.
- Міжмережевий DNS:
service-name.namespace-name.svc.cluster.local. - ResourceQuota: сумарний ліміт CPU/RAM/Pods на весь простір імен.
- LimitRange: дефолтні та граничні значення CPU/RAM на один контейнер.
- Зависання в Terminating: викликане блокуванням фіналізаторами (
spec.finalizers) на дочірніх ресурсах (PVC, CRD). - Безпека: Pod Security Admission (
restricted) налаштовується через лейбли на Namespace.
Типи ресурсів за областю видимості
| Область видимості | Приклади ресурсів |
| :— | :— |
| Namespaced | Pod, Service, Deployment, PVC, ConfigMap, Secret, ServiceAccount, Role |
| Cluster-wide | Node, PersistentVolume, StorageClass, ClusterRole, Namespace |
Червоні прапорці на співбесіді (Чого говорити не можна)
- ❌ «Namespace ізолює мережу, тому поди з dev не можуть підключитися до сервісів у prod» — мережа пласка, для ізоляції обов’язково потрібен NetworkPolicy.
- ❌ «Ми зберігаємо dev, stage та production в одному namespace default» — антипатерн, що призводить до хаосу та ризику випадкового видалення даних.
- ❌ «Щоб перенести Pod в інший namespace, достатньо змінити його через kubectl edit pod» — поле namespace незмінне в etcd.