☸️ Kubernetes (kubectl)
Полный справочник: архитектура, kubectl, объекты (Pod, Deployment, Service, Ingress, ConfigMap, Secret, PVC, Job), пробы, ресурсы, RBAC, Helm, отладка и безопасность.
Шпаргалки · Инфраструктура · #kubernetes #k8s #kubectl #containers #devops
Архитектура
| Компонент | Роль |
|---|---|
| API Server | единая точка входа, REST API кластера |
| etcd | хранилище состояния |
| Scheduler | выбирает узел для Pod |
| Controller Manager | приводит фактическое состояние к желаемому |
| kubelet | агент на узле, запускает контейнеры |
| kube-proxy | сетевые правила Service |
| Container runtime | containerd, CRI-O |
Принцип: вы описываете желаемое состояние (YAML), контроллеры постоянно приводят к нему кластер.
Контекст и подключение
kubectl config get-contexts kubectl config use-context prod kubectl config current-context
kubectl config set-context --current --namespace=dev
export KUBECONFIG=~/.kube/config:~/.kube/other
kubectl cluster-info kubectl version kubectl api-resources
kubectl explain pod.spec.containers # справка по полям
alias k=kubectl; source <(kubectl completion bash)
Удобные утилиты: kubectx и kubens (переключение), k9s (терминальный интерфейс), stern (логи нескольких pod), kubecolor, Lens.
Просмотр
kubectl get pods [-n ns] [-A] [-o wide] [-l app=web] [-w]
kubectl get deploy,svc,ing,cm,secret,pvc,node
kubectl get pod web -o yaml kubectl get pod web -o jsonpath='{.status.podIP}'
kubectl get pods --field-selector=status.phase=Running
kubectl get events --sort-by=.lastTimestamp
kubectl describe pod web # события и причины
kubectl logs web [-f] [-c container] [--previous] [--tail=100] [-l app=web --all-containers]
kubectl top pod|node # нужен metrics-server
kubectl get all -n dev
Управление
kubectl apply -f app.yaml kubectl apply -f dir/ -R kubectl apply -k overlays/prod # kustomize
kubectl delete -f app.yaml kubectl delete pod web --grace-period=0 --force
kubectl diff -f app.yaml # что изменится
kubectl create deployment web --image=nginx --replicas=3 --dry-run=client -o yaml > web.yaml
kubectl scale deploy web --replicas=5 kubectl autoscale deploy web --min=2 --max=10 --cpu-percent=70
kubectl set image deploy/web web=nginx:1.27
kubectl rollout status|history|undo|restart deploy/web kubectl rollout undo deploy/web --to-revision=2
kubectl edit deploy web kubectl patch deploy web -p '{"spec":{"replicas":2}}'
kubectl label pod web tier=front kubectl annotate pod web note=x
kubectl exec -it web -- sh kubectl exec web -c sidecar -- env
kubectl port-forward svc/web 8080:80 kubectl cp web:/tmp/a.txt ./a.txt
kubectl run tmp --rm -it --image=busybox -- sh # временный pod для проверок
kubectl cordon|uncordon|drain node1 --ignore-daemonsets --delete-emptydir-data # обслуживание узла
kubectl taint nodes node1 key=val:NoSchedule
--dry-run=client -o yaml генерирует заготовки YAML. Предпочитайте декларативный apply императивным create и edit.
Объекты
| Объект | Назначение |
|---|---|
| Pod | один или несколько контейнеров с общей сетью и томами |
| ReplicaSet | поддерживает число копий Pod (обычно создаётся Deployment) |
| Deployment | реплики без состояния, обновления и откаты |
| StatefulSet | приложения с состоянием: стабильные имена и диски |
| DaemonSet | по одному Pod на каждый узел (агенты, логи) |
| Job / CronJob | разовые и регулярные задачи |
| Service | стабильный адрес и балансировка |
| Ingress / Gateway API | HTTP(S)-вход снаружи |
| ConfigMap / Secret | настройки / секреты |
| PersistentVolume / PVC / StorageClass | диски |
| Namespace | изоляция окружений |
| HPA / VPA | автомасштабирование по метрикам |
| NetworkPolicy | сетевые правила между Pod |
| ServiceAccount / Role / RoleBinding | права доступа |
| ResourceQuota / LimitRange | лимиты на namespace и Pod |
| PodDisruptionBudget | сколько Pod можно останавливать одновременно |
Deployment, Service, Ingress
apiVersion: apps/v1
kind: Deployment
metadata: { name: web, labels: { app: web } }
spec:
replicas: 3
strategy: { type: RollingUpdate, rollingUpdate: { maxSurge: 1, maxUnavailable: 0 } }
selector: { matchLabels: { app: web } }
template:
metadata: { labels: { app: web } }
spec:
containers:
- name: web
image: ghcr.io/me/web:1.4.2
ports: [{ containerPort: 8080 }]
env:
- { name: LOG_LEVEL, value: info }
- name: DB_PASSWORD
valueFrom: { secretKeyRef: { name: db, key: password } }
envFrom: [{ configMapRef: { name: web-config } }]
resources:
requests: { cpu: 100m, memory: 128Mi }
limits: { memory: 256Mi }
readinessProbe: { httpGet: { path: /ready, port: 8080 }, periodSeconds: 5 }
livenessProbe: { httpGet: { path: /healthz, port: 8080 }, initialDelaySeconds: 15, periodSeconds: 10 }
startupProbe: { httpGet: { path: /healthz, port: 8080 }, failureThreshold: 30, periodSeconds: 2 }
securityContext: { runAsNonRoot: true, readOnlyRootFilesystem: true, allowPrivilegeEscalation: false }
---
apiVersion: v1
kind: Service
metadata: { name: web }
spec:
type: ClusterIP
selector: { app: web }
ports: [{ port: 80, targetPort: 8080 }]
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: { name: web, annotations: { cert-manager.io/cluster-issuer: letsencrypt } }
spec:
ingressClassName: nginx
tls: [{ hosts: [example.com], secretName: web-tls }]
rules:
- host: example.com
http: { paths: [{ path: /, pathType: Prefix, backend: { service: { name: web, port: { number: 80 } } } }] }
| Тип Service | Доступ |
|---|---|
ClusterIP |
только внутри кластера (по умолчанию) |
NodePort |
порт на каждом узле |
LoadBalancer |
внешний балансировщик облака |
ExternalName |
CNAME на внешний адрес |
Headless (clusterIP: None) |
DNS отдаёт адреса Pod (для StatefulSet) |
Внутренний DNS: service.namespace.svc.cluster.local.
Пробы и ресурсы
- readiness: готов ли принимать трафик (иначе исключается из Service).
- liveness: жив ли процесс (иначе перезапуск). Не делайте её зависящей от внешних сервисов.
- startup: для медленного старта, отключает остальные пробы до успеха.
requestsиспользуются при планировании,limitsограничивают. Лимит памяти превышен →OOMKilled; лимит CPU → троттлинг. Классы QoS: Guaranteed, Burstable, BestEffort.
Конфигурация и секреты
kubectl create configmap web-config --from-literal=LOG_LEVEL=debug --from-file=app.properties
kubectl create secret generic db --from-literal=password='s3cr3t'
kubectl create secret tls web-tls --cert=tls.crt --key=tls.key
kubectl get secret db -o jsonpath='{.data.password}' | base64 -d
Secret по умолчанию лишь закодирован в base64, не зашифрован: включите шифрование etcd, используйте External Secrets, Sealed Secrets, SOPS, Vault.
Хранилище
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: data }
spec: { accessModes: [ReadWriteOnce], storageClassName: standard, resources: { requests: { storage: 10Gi } } }
Режимы доступа: ReadWriteOnce (один узел), ReadWriteMany (много узлов), ReadOnlyMany. Для баз используйте StatefulSet с volumeClaimTemplates.
Job и CronJob
apiVersion: batch/v1
kind: CronJob
metadata: { name: backup }
spec:
schedule: "0 2 * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: OnFailure
containers: [{ name: backup, image: me/backup:1, command: ["sh", "-c", "pg_dump ..."] }]
RBAC и безопасность
kubectl create serviceaccount ci -n dev
kubectl create role pod-reader --verb=get,list,watch --resource=pods -n dev
kubectl create rolebinding ci-read --role=pod-reader --serviceaccount=dev:ci -n dev
kubectl auth can-i delete pods --as system:serviceaccount:dev:ci -n dev
Практика: минимальные права, runAsNonRoot, readOnlyRootFilesystem, запрет privileged, NetworkPolicy «по умолчанию запретить», Pod Security Standards (restricted), сканирование образов, ограничение доступа к API.
Helm и Kustomize
helm repo add bitnami https://charts.bitnami.com/bitnami && helm repo update
helm search repo postgresql helm install db bitnami/postgresql -n data --create-namespace -f values.yaml
helm upgrade --install web ./chart -n dev --set image.tag=1.4.2 helm rollback web 1 helm uninstall web
helm template ./chart | kubectl apply -f - helm lint ./chart helm list -A
kubectl kustomize overlays/prod # оверлеи без шаблонов
Отладка по симптомам
| Статус Pod | Что смотреть |
|---|---|
Pending |
describe: нет ресурсов, taint, нет PV, не подходит nodeSelector |
ImagePullBackOff / ErrImagePull |
имя и тег образа, секрет доступа к реестру (imagePullSecrets) |
CrashLoopBackOff |
logs --previous, код выхода, проба, конфигурация |
OOMKilled |
лимит памяти, утечка |
CreateContainerConfigError |
нет ConfigMap или Secret |
Running, но 503 |
readiness не проходит, selector Service не совпадает с метками |
Terminating зависает |
finalizers, --force как крайняя мера |
| Нет связи | kubectl get endpoints svc, DNS, NetworkPolicy |
Порядок действий: get → describe (события) → logs → exec / временный pod netshoot → get events. Проверка Service: kubectl get endpoints web (пусто = метки не совпадают или Pod не готовы).
Практика эксплуатации
- Всегда задавайте
requests/limits, пробы,PodDisruptionBudget, несколько реплик на разных узлах (topologySpreadConstraints,podAntiAffinity). - Образы с фиксированными тегами или digest, не
latest. - Конфигурация в Git (GitOps: Argo CD, Flux).
- Мониторинг: Prometheus, Grafana, Loki; события и аудит.
- Автомасштабирование: HPA (
kubectl autoscale), Cluster Autoscaler, KEDA (по очередям). - Обновления кластера по минорным версиям поэтапно, резервные копии etcd и томов (Velero).
Локальные кластеры
minikube start, kind create cluster, k3d cluster create, Docker Desktop, k3s (лёгкий для серверов), microk8s. Управляемые: GKE, EKS, AKS, Yandex Managed Kubernetes, VK Cloud.