☸️ 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.