Контексты, namespaces и переключение
Главное, что нужно знать про контексты к этому уроку: никто никогда не работает с одним кластером. У вас всегда будет несколько — production, staging, dev, и десяток локальных kind-кластеров для экспериментов. Контекст — это переключатель «куда сейчас идёт kubectl». А namespace — это переключатель «в каком отсеке кластера». Перепутать одно или другое — и вы делаете kubectl delete pod в проде вместо dev. Этот урок — про инструменты, которые делают переключение явным и безопасным. И отдельно — про правило CKAD, проваливающее экзамен у тех, кто его не выучил.
Пользователи и группы в Linux: /etc/passwd и identity
Контекст: cluster + user + namespace
Из прошлого урока: контекст — это тройка «к какому apiserver, под каким user, в каком namespace по умолчанию». Один kubeconfig может содержать десятки контекстов; активен в каждый момент — один (current-context).
# Все контексты
kubectl config get-contexts
# CURRENT NAME CLUSTER AUTHINFO NAMESPACE
# * eks-prod eks-prod-cl aws-prod default
# gke-staging gke-stg-cl gcp-stg apps
# kind-ckad kind-ckad kind-admin default
# Какой активен
kubectl config current-context
# eks-prod
# Переключиться
kubectl config use-context kind-ckad
# Switched to context "kind-ckad".
# Посмотреть один context detail
kubectl config view --context=kind-ckad --minify
Флаг --minify показывает только тот subset kubeconfig, который relevant к текущему context — удобно для дебага «что именно kubectl сейчас использует».
Альтернатива switch: —context на одну команду
use-context меняет активный контекст глобально. Иногда нужно сделать одну команду в другом контексте, не меняя default:
# Глобальный switch
kubectl config use-context gke-staging
kubectl get pods # в staging
# Только эта команда — без switch
kubectl --context=gke-staging get pods
kubectl --context=eks-prod get pods # current-context остался kind-ckad
Это безопаснее в скриптах: явное указание контекста защищает от ситуации, когда кто-то параллельно переключил current-context, и ваш kubectl apply -f prod.yaml пошёл в чужой кластер.
Namespace: логическая изоляция
Namespace — это пространство имён внутри cluster. Внутри одного namespace имена ресурсов должны быть уникальными (Pod web в default и Pod web в prod — разные объекты). Между namespaces ресурсы изолированы:
- RBAC обычно scoped к namespace (Role, RoleBinding) — даёте права на
dev, человек видит толькоdev. - NetworkPolicy разрешает/запрещает трафик между namespaces.
- ResourceQuota ограничивает CPU/memory/количество объектов per-namespace.
- LimitRange задаёт дефолты и лимиты per-Pod per-namespace.
Системные namespaces, которые создаются автоматически:
| Namespace | Что внутри |
|---|---|
default | Ресурсы, для которых не указали namespace |
kube-system | Системные Pod-ы: kube-proxy, CoreDNS, CNI agents, etcd-operator |
kube-public | Публичные ресурсы, доступные всем без auth (cluster-info ConfigMap) |
kube-node-lease | Lease-объекты от kubelet — heartbeat узлов (одна Lease на Node) |
kubectl get namespaces
# NAME STATUS AGE
# default Active 30d
# kube-system Active 30d
# kube-public Active 30d
# kube-node-lease Active 30d
# prod Active 12d
# dev Active 3d
Cluster-scoped ресурсы
Не все ресурсы живут в namespace. Некоторые — глобальные:
# Все cluster-scoped resources
kubectl api-resources --namespaced=false
# Примеры:
# Node v1 Node
# Namespace v1 Namespace
# PersistentVolume v1 PersistentVolume
# ClusterRole rbac.authorization.k8s.io/v1
# ClusterRoleBinding rbac.../v1
# StorageClass storage.k8s.io/v1
# CustomResourceDefinition apiextensions.k8s.io/v1
# IngressClass networking.k8s.io/v1
Логика: ресурс cluster-scoped, если он не имеет смысла в namespace. Узлы (Node) принадлежат всему кластеру, не «namespace dev». PersistentVolume — реальный диск, доступен любому namespace через PVC. ClusterRole описывает права, охватывающие все namespaces.
Команды для cluster-scoped ресурсов игнорируют -n:
kubectl get nodes # без namespace
kubectl get nodes -n dev # тот же результат, флаг проигнорирован
kubectl get pv # PersistentVolume — cluster-scoped
Если делаете kubectl delete pv <name> — это глобальное действие, без namespace-фильтра. Двойная проверка перед удалением. PV без указания namespace — потому что PV у вас один, но PVC в его spec может claim его из любого namespace. Удалили PV — потеряли binding со всеми PVC, которые им владели.
Работа с namespace
# Создать namespace
kubectl create namespace prod
# или declarative
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: prod
EOF
# Получить ресурсы в namespace
kubectl get pods -n prod # explicit
kubectl get pods --namespace=prod # full flag
kubectl -n prod get pods # short, общая форма
# Все namespaces сразу
kubectl get pods --all-namespaces # --all-namespaces
kubectl get pods -A # короткая форма
# Удалить namespace (вместе со всеми ресурсами внутри!)
kubectl delete namespace prod
kubectl delete namespace — необратимое действие. Удалит ВСЕ Pod-ы, Services, ConfigMaps, Secrets, PVC внутри. PVC удалится → если StorageClass с reclaimPolicy=Delete, реальный диск тоже сотрётся. На prod кластере оборачивайте такие команды в подтверждение (read -p, конфирм во внутренних tools).
Смена namespace в текущем контексте
Постоянно писать -n prod утомительно. Можно зашить namespace в контекст:
# В текущем контексте установить default namespace
kubectl config set-context --current --namespace=prod
# Теперь kubectl get pods → ищет в prod без -n
# Проверить
kubectl config view --minify | grep namespace
# namespace: prod
Однако это меняет kubeconfig. Несколько терминалов — несколько вкладок — везде стало prod. Это путает. Лучше — отдельные контексты под каждый namespace:
# Создать context-alias для prod
kubectl config set-context eks-prod-app \
--cluster=eks-prod-cl --user=aws-prod --namespace=app
kubectl config set-context eks-prod-db \
--cluster=eks-prod-cl --user=aws-prod --namespace=db
kubectl config use-context eks-prod-app # сразу в app
kubectx, kubens, alias k
Стандартный workflow — установить три инструмента и больше не страдать:
# macOS
brew install kubectx # ставит kubectx + kubens
brew install fzf # для interactive выбора
# Linux: curl бинари из github.com/ahmetb/kubectx
Использование:
# kubectx — быстрое переключение context
kubectx # список + indicator текущего
kubectx eks-prod # switch
kubectx - # back to previous (как cd -)
# kubens — быстрое переключение namespace
kubens # список
kubens prod # switch
kubens - # previous
# Если установлен fzf — kubectx без аргумента откроет fuzzy picker
Алиас k=kubectl — must-have. Экономит 6 символов на каждую команду. На CKAD-экзамене вы наберёте k get pods -n prod десятки раз.
# Setup в начале сессии (или в .bashrc)
alias k=kubectl
# Включить autocomplete для k тоже
source <(kubectl completion bash)
complete -F __start_kubectl k
# zsh:
source <(kubectl completion zsh)
compdef __start_kubectl k
DNS внутри cluster: inter-namespace communication
Раз ресурсы изолированы по namespace, как Pod-у из app достучаться до Service в db? Через внутренний DNS.
CoreDNS внутри кластера резолвит имена Services по правилу:
<service>.<namespace>.svc.cluster.local
# Полное FQDN
curl http://postgres.db.svc.cluster.local:5432
# Если запрашивающий Pod в том же namespace (db) — можно короче
curl http://postgres:5432
curl http://postgres.db:5432 # из любого namespace, короткая форма
Из этого следуют правила:
- В одном namespace:
postgresдостаточно (CoreDNS пробует свой namespace первым). - Между namespaces:
postgres.dbили полноеpostgres.db.svc.cluster.local. - Для headless services (StatefulSet):
pod-0.postgres.db.svc.cluster.local— резолв конкретного Pod. - Externally-accessible services через kube-dns не резолвятся — нужен внешний DNS (Route53, Cloud DNS).
Правило CKAD: use-context перед каждой задачей
На реальном CKAD-экзамене вы работаете в одной shell-сессии, и в кандидатском окружении прописано 6-8 разных кластеров. Каждая задача начинается с инструкции:
Set Configuration Context:
[candidate@base] $ kubectl config use-context k8s
Это команда, которую нужно выполнить ПЕРВЫМ ДЕЛОМ при открытии каждой задачи. Не визуально, не «понятно, перейду к решению» — реально набрать и Enter.
Почему это критично:
- Задачи проверяются в разных кластерах. Если вы решили задачу 3, не переключившись на её кластер, ваш Pod создался в кластере задачи 2 — задача 3 получит 0 баллов, а кластер задачи 2 у вас сломан.
- Многие проваливают CKAD именно из-за этого, особенно на первых 1-2 задачах, когда волнение.
- Время на это — 2 секунды. Не пропускать ни одной.
Сделайте у себя при подготовке привычку: каждый раз, когда меняете задачу/окружение — kubectl config current-context, убедились, что в правильном кластере, дальше работаете. На экзамене это автоматическое движение пальцев.
Альтернативно — настройте prompt, чтобы он показывал текущий context:
# kube-ps1 — показывает (context:namespace) в PS1
brew install kube-ps1
echo 'source $(brew --prefix)/opt/kube-ps1/share/kube-ps1.sh' >> ~/.bashrc
echo 'PS1="[\u@\h \W \$(kube_ps1)]\$ "' >> ~/.bashrc
# Теперь prompt:
# [candidate@base ~ (⎈|eks-prod:default)]$
На CKAD — это не разрешено (нельзя ставить свой софт), но в реальной работе с продом — обязательно.
Что дальше
В следующем уроке — навигация по API: kubectl explain, api-resources, api-versions, OpenAPI schema apiserver. Это инструменты, которыми вы будете изучать новые ресурсы без открытия документации. На CKAD kubectl explain --recursive — главное оружие, когда забыл точное имя поля.