Установка и конфигурация kubectl
Прежде чем разбирать команды, договоримся об одной вещи, которая снимает половину магии вокруг Kubernetes. kubectl — это обычный HTTP-клиент. Он не знает про Pod-ы, Deployments и Services больше, чем знает curl про эти ресурсы. Внутри kubectl читает файл ~/.kube/config, формирует TLS-соединение с kube-apiserver (обычно на порту 6443), отправляет JSON-запросы, парсит ответы и форматирует их в таблицу для вашего терминала. Всё, что вы будете делать в курсе, — это HTTP GET/POST/PATCH/DELETE на REST endpoints /api/v1/... и /apis/<group>/<version>/.... Когда вы это окончательно усвоите, фраза «kubectl не работает» перестанет существовать — будет «TLS handshake failed», «401 Unauthorized», «context указывает на мёртвый кластер». Каждое из этих сообщений лечится одним конкретным способом.
SSH в глубину: ключи, config, tunneling, multiplexing
Установка под все ОС
Бинарь kubectl поставляется отдельно от cluster. Это критично понимать: вы можете иметь один kubectl и десяток разных кластеров (production EKS, staging GKE, локальный kind), и переключаться между ними сменой контекста — не переустанавливая бинарь.
Универсальный способ — прямое скачивание с dl.k8s.io:
# Linux amd64
curl -LO "https://dl.k8s.io/release/v1.35.0/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# macOS Apple Silicon
curl -LO "https://dl.k8s.io/release/v1.35.0/bin/darwin/arm64/kubectl"
chmod +x kubectl && sudo mv kubectl /usr/local/bin/
# Windows (PowerShell)
curl.exe -LO "https://dl.k8s.io/release/v1.35.0/bin/windows/amd64/kubectl.exe"
После установки убедитесь, что версия — та, которую ожидаете:
kubectl version --client
# Client Version: v1.35.0
# Kustomize Version: v5.x.x
Skew policy: версия kubectl и cluster
Kubernetes даёт официальную гарантию совместимости между версиями. kubectl поддерживается в пределах +/-1 minor от cluster version. То есть кластер v1.35 совместим с kubectl v1.34, v1.35, v1.36. С kubectl v1.32 — undefined behaviour: часть команд может работать, часть — нет, поля могут не сериализоваться.
В команде, где кто-то держит cluster v1.30, а на лаптопе уже v1.35 — kubectl apply для новых полей будет молча отбрасывать их, потому что apiserver их не знает. Версия kubectl должна следовать за версией production cluster, не опережая её слишком сильно.
| Cluster | Поддерживаемые kubectl |
|---|---|
| v1.35 | v1.34, v1.35, v1.36 |
| v1.34 | v1.33, v1.34, v1.35 |
| v1.33 | v1.32, v1.33, v1.34 |
На CKAD-экзамене это редко становится проблемой — там фиксированная версия kubectl и cluster, оба соответствуют экзаменационному релизу. Но в реальной работе вы будете держать несколько kubectl рядом (через asdf, mise или симлинки kubectl-1.33, kubectl-1.35) и переключаться под кластер.
kubeconfig: где хранятся credentials
Когда вы запускаете kubectl get pods, он должен ответить на три вопроса:
- На какой apiserver слать запрос (URL и его CA-сертификат)?
- Под каким пользователем (cert+key, bearer token, exec plugin)?
- В каком namespace искать ресурсы?
Все три ответа лежат в файле ~/.kube/config — это kubeconfig. Обычный YAML, который вы можете открыть и прочитать.
# Путь по умолчанию
ls -la ~/.kube/config
# Альтернативный путь через флаг
kubectl --kubeconfig=/path/to/other.yaml get pods
# Несколько файлов через env (Linux/macOS: ":", Windows: ";")
export KUBECONFIG="$HOME/.kube/config:$HOME/.kube/work-config:$HOME/.kube/eks-prod"
kubectl config view # merged view всех файлов
Когда KUBECONFIG содержит несколько путей, kubectl мерджит их в один логический view: clusters, users, contexts со всех файлов объединяются. Если есть конфликт имён — приоритет у первого файла в списке. Это удобно: храните каждый кластер в отдельном файле, не редактируя один большой ~/.kube/config.
Структура kubeconfig
Файл состоит из трёх списков (clusters, users, contexts) и одного указателя (current-context). Минимальный пример:
apiVersion: v1
kind: Config
current-context: dev-cluster
clusters:
- name: dev-cluster
cluster:
server: https://192.168.1.10:6443
certificate-authority-data: LS0tLS1CRUdJTi... # base64(CA cert)
users:
- name: dev-admin
user:
client-certificate-data: LS0tLS1CRUdJTi... # base64(cert)
client-key-data: LS0tLS1CRUdJTi... # base64(private key)
contexts:
- name: dev-cluster
context:
cluster: dev-cluster
user: dev-admin
namespace: dev
Ключевая идея: cluster и user независимы. Один кластер можно использовать под разными user (admin, viewer, ci-bot) — это разные context, ссылающиеся на один cluster. Один user может работать с несколькими кластерами (dev и staging) — это разные context с одним user.
Варианты аутентификации в user-entry
Это самая запутанная часть kubeconfig — поэтому разберём по типам:
1. Client cert + key (статическая mTLS):
users:
- name: admin
user:
client-certificate-data: <base64>
client-key-data: <base64>
Так выглядит kubeconfig, который генерирует kubeadm для админа cluster. Сертификат подписан CA, который apiserver принимает. CN в сертификате становится username, O — группами (для RBAC).
2. Bearer token (для ServiceAccount или OIDC):
users:
- name: ci-bot
user:
token: eyJhbGciOiJSUzI1NiIs...
ServiceAccount token, JWT от OIDC-провайдера, static token из --token-auth-file apiserver. kubectl добавит заголовок Authorization: Bearer <token> к каждому запросу.
3. Exec plugin (динамический token):
users:
- name: eks-user
user:
exec:
apiVersion: client.authentication.k8s.io/v1
command: aws
args: ["eks", "get-token", "--cluster-name", "my-cluster"]
kubectl запускает внешнюю команду (aws, gcloud, az), получает свежий token, использует его. Так работают managed clusters — token живёт 10-15 минут, exec plugin обновляет его прозрачно.
4. OIDC через auth-provider (устаревает в v1.35):
users:
- name: dex-user
user:
auth-provider:
name: oidc
config:
idp-issuer-url: https://dex.company.com
client-id: kubernetes
refresh-token: <token>
Этот формат deprecated в пользу exec plugins (kubelogin).
Managed K8s: автоматическая генерация kubeconfig
В production вы редко руками редактируете kubeconfig для облачных кластеров. У каждого provider есть команда, которая аппендит нужный context в ваш ~/.kube/config:
# AWS EKS
aws eks update-kubeconfig --region us-east-1 --name prod-cluster
# Создаёт context arn:aws:eks:us-east-1:123456:cluster/prod-cluster
# user — exec aws eks get-token
# Google GKE
gcloud container clusters get-credentials prod-cluster \
--region us-central1 --project my-project
# Создаёт context gke_my-project_us-central1_prod-cluster
# user — exec gke-gcloud-auth-plugin
# Azure AKS
az aks get-credentials --resource-group prod --name prod-cluster
# Создаёт context prod-cluster
# user — exec kubelogin (или legacy token)
# Yandex Cloud Managed K8s
yc managed-kubernetes cluster get-credentials prod-cluster --external
После любой из этих команд kubectl config get-contexts покажет новый context. Дальше — kubectl config use-context <name> и работаете.
Команды update-kubeconfig / get-credentials — идемпотентны. Запускайте сколько угодно раз — они только обновят запись, не сломают ничего другого. На новом ноутбуке после git clone infrastructure-as-code обычно достаточно прогнать список всех нужных команд — и весь набор кластеров готов.
Безопасность: kubeconfig — это secret
То, что в ~/.kube/config лежит plaintext YAML, может ввести в заблуждение. Это файл, дающий полный доступ к кластеру для того user, на который он указывает. Если у вас admin-context — получивший этот файл получает кластер.
Никогда не коммитьте ~/.kube/config в git. Никогда не передавайте через Slack/email. Если случайно опубликовали — немедленно: (1) сделайте kubectl config view --raw -o yaml чтобы понять, какой user скомпрометирован, (2) revoke его в IAM/IdP, (3) сгенерируйте новые credentials. Просто удалить файл из git history недостаточно — он уже в копиях, кэшах и forks.
Хорошие практики:
- Права файла:
chmod 600 ~/.kube/config— читать только owner. - Никаких long-lived static tokens. Только exec plugins или OIDC с коротким TTL.
- Один user — одни RBAC permissions (виду нужен viewer, ci-bot — отдельный SA с deploy-правами).
- Для prod кластеров — отдельный
KUBECONFIG=~/.kube/prod.yaml, который вы экспортируете в shell только когда действительно работаете с prod. - Включить
--token-ttlминимальным где можно. exec plugin AWS возвращает токен на 14 минут — это нормально, ничего удлинять не нужно.
Быстрая проверка после установки
После любых манипуляций с kubectl и kubeconfig прогоните три команды. Если все три работают — окружение готово:
kubectl version # client + server version, проверка skew
kubectl config current-context # какой context активен
kubectl get nodes # реальный запрос к apiserver
Если version показывает server version: <unknown> или nodes падает с connection refused — apiserver недостижим (firewall, VPN, кластер выключен). Если Unauthorized — credentials битые (cert истёк, token revoked). Если forbidden — auth прошёл, но RBAC запрещает действие. Каждое из этих сообщений локализует проблему до одного уровня.
Что дальше
В следующем уроке — два паттерна работы с API: imperative и declarative. На CKAD вы будете чередовать оба — imperative для генерации заготовок, declarative для финальных манифестов. И поймём, какие fields kubectl на самом деле отправляет в apiserver — потому что между YAML на диске и состоянием в etcd есть пара трансформаций, которые иногда удивляют.