Learning Platform
Глоссарий Troubleshooting
Урок 04.03 · 18 мин
Средний
kubectlcontextsnamespaceskubectxkubensDNSRBAC

Контексты, 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 сейчас использует».

Переключение между cluster
kubeconfigОдин файл ~/.kube/config содержит множество контекстов. Сам файл — статичный. current-context — единственный указатель, который меняется при switch.
current-context
eks-prodКонтекст для прод-кластера на AWS EKS. user — exec aws eks get-token, server — https://....eks.amazonaws.com.
gke-stagingКонтекст для GCP GKE staging. user — exec gke-gcloud-auth-plugin, server — https://....gke.googleapis.com.
kind-ckadЛокальный кластер kind в Docker. user — статический client-cert, server — https://127.0.0.1:50000+.

Альтернатива 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-leaseLease-объекты от 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
WARNING

Если делаете 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
DANGER

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, короткая форма
DNS resolve по namespace
Pod в namespace appЗапрашивает postgres. CoreDNS ищет: сначала postgres.app.svc.cluster.local (свой ns), нет → postgres.svc.cluster.local (root), нет → не нашли. ConfigMap /etc/resolv.conf задаёт search domain.
DNS
CoreDNSResolver внутри cluster. Pod-ам в /etc/resolv.conf прописано nameserver — это ClusterIP CoreDNS. search список: <ns>.svc.cluster.local svc.cluster.local cluster.local.
NS LOOKUP
postgres в db nsService postgres существует в namespace db. FQDN postgres.db.svc.cluster.local. ClusterIP — виртуальный IP, kube-proxy перенаправит на Pod-эндпоинты.
Pod-ы postgresEndpointSlice содержит реальные Pod IP. kube-proxy через iptables/IPVS делает DNAT на один из них.

Из этого следуют правила:

  • В одном 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 секунды. Не пропускать ни одной.
WARNING

Сделайте у себя при подготовке привычку: каждый раз, когда меняете задачу/окружение — 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 — главное оружие, когда забыл точное имя поля.


Проверка знанийKnowledge check
На CKAD-экзамене вы видите задачу: «Создайте Deployment с 3 репликами в namespace ckad-13 в cluster k8s». Перечислите по шагам, что вы делаете до первого `kubectl create deployment`.
ОтветAnswer
Шаги: (1) Первая команда — `kubectl config use-context k8s` (либо то, что написано в начале задачи). Без этого риск создать ресурс в чужом кластере. (2) Проверка: `kubectl config current-context` показывает k8s — поехали. (3) Проверка существования namespace: `kubectl get ns ckad-13` — если нет, создать `kubectl create ns ckad-13` (на CKAD обычно уже создан). (4) Опционально — `kubens ckad-13`, чтобы не передавать -n каждый раз; или установить namespace в текущем context: `kubectl config set-context --current --namespace=ckad-13`. (5) Теперь можно создавать: `kubectl create deployment web --image=nginx --replicas=3` — и оно ляжет в правильный namespace правильного cluster. Идеально — добавить `--dry-run=client -o yaml > deploy.yaml`, доработать, apply. (6) Проверка: `kubectl get deploy -n ckad-13` — Deployment в нужном месте.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 5. На CKAD задача начинается с инструкции `kubectl config use-context k8s`. Вы её пропустили, текущий context — задача №1 cluster. Что произойдёт с вашими ответами на эту задачу?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5