Kubernetes Survival Guide

15 вещей, которые ты должен знать про K8s до того, как окажешься в продакшене. Это спасёт тебя от типичных «почему всё лежит» в 3 утра.

1. Requests и limits — без них ты слепой

resources:
  requests: {cpu: 100m, memory: 128Mi}
  limits:   {memory: 256Mi}    # CPU limits часто не ставят — см. ниже
Тонкий момент с CPU limits

CPU limits часто вредят latency (CFS throttling). Netflix, Uber, многие компании рекомендуют ставить requests без CPU limits. Memory limits — обязательны.

2. Probes — три типа, не путай

startupProbe:
  httpGet: {path: /healthz, port: 8000}
  failureThreshold: 30
  periodSeconds: 10            # даём 5 минут на старт

readinessProbe:
  httpGet: {path: /ready, port: 8000}
  periodSeconds: 5

livenessProbe:
  httpGet: {path: /healthz, port: 8000}
  periodSeconds: 10
  failureThreshold: 3
⚠️ Smartiest mistake

Liveness probe не должен проверять зависимости (БД, кэш). Иначе при падении БД все pod-ы пойдут в restart loop, не давая БД восстановиться.

3. PodDisruptionBudget — защита от eviction

При drain ноды (обновление) Kubernetes уважает PDB.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-pdb
spec:
  minAvailable: 2          # или maxUnavailable: 1
  selector:
    matchLabels: {app: api}

4. Anti-affinity для HA

Без anti-affinity все 3 replica могут оказаться на одной ноде. Нода упала — всё лежит.

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchLabels: {app: api}
          topologyKey: kubernetes.io/hostname

5. Imagepullpolicy и тег latest

С тегом :latest Kubernetes по умолчанию использует Always. С конкретным тегом — IfNotPresent. Используй конкретные теги или digest.

6. Namespace — изоляция

7. Secrets — это base64, не шифрование

K8s Secret — просто base64. Любой с RBAC доступом к Secret видит его.

Production: External Secrets Operator + Vault или SOPS + Sealed Secrets.

8. Service types — для чего что

9. Ingress → Gateway API

Старое API Ingress — лимиты по фичам. Gateway API — новый стандарт K8s. Учи Gateway API, Ingress на pension.

10. NetworkPolicy default deny

По умолчанию все pod-ы общаются со всеми. Это плохо. Запрети входящее по умолчанию, разрешай явно.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes: [Ingress]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api-from-ingress
spec:
  podSelector: {matchLabels: {app: api}}
  ingress:
    - from:
        - namespaceSelector: {matchLabels: {name: ingress-nginx}}
      ports:
        - port: 8000

11. RBAC: least privilege

12. Karpenter лучше Cluster Autoscaler

На AWS EKS — стандарт сейчас Karpenter. Быстрее, гибче, дешевле (через Spot).

13. Probes-friendly graceful shutdown

При rolling update K8s посылает SIGTERM. Дай приложению время:

  1. Pod уходит из Service endpoints (readiness fail)
  2. SIGTERM → приложение
  3. Подожди terminationGracePeriodSeconds (по умолчанию 30s)
  4. SIGKILL если не завершился
spec:
  terminationGracePeriodSeconds: 60
  containers:
    - name: api
      lifecycle:
        preStop:
          exec:
            command: ["sleep", "10"]   # дать времени LB обновиться

14. kubectl полезности

# Алиасы (сэкономят часы за карьеру)
alias k=kubectl
alias kgp='kubectl get pods'
alias kgs='kubectl get svc'
alias kctx='kubectl config use-context'
alias kns='kubectl config set-context --current --namespace'

# Дебаг
kubectl describe pod <name>
kubectl logs <name> --previous       # лог упавшего контейнера
kubectl get events --sort-by='.lastTimestamp'
kubectl debug pod/<name> -it --image=busybox

# Поиск
kubectl get pods --all-namespaces -o wide
kubectl get pods --field-selector=status.phase!=Running

# Тестирование DNS из кластера
kubectl run -it --rm test --image=nicolaka/netshoot --restart=Never -- /bin/bash

Установи k9s — TUI для K8s. Изменит жизнь.

15. Алгоритм дебага упавшего pod

  1. kubectl get pod <name> — STATUS
  2. kubectl describe pod <name> — Events внизу всегда
  3. kubectl logs <name> — текущий лог
  4. kubectl logs <name> --previous — лог упавшего контейнера
  5. kubectl exec -it <name> -- sh — войти внутрь
  6. kubectl get events --sort-by='.lastTimestamp' -n <ns>
  7. kubectl top pod / node (нужен metrics-server)

Частые ошибки

STATUSЧто делать
CrashLoopBackOffApp падает. logs --previous
ImagePullBackOffОбраз недоступен. Проверь tag, imagePullSecrets
PendingНет ресурсов. describe → Events
OOMKilledПревышен memory limit. Увеличь
EvictedНода под давлением. Проверь node conditions
ErrorGeneric. Смотри describe + logs

Если знаешь все 15 — ты production-ready. Дальше — CKA + CKS.