Перейти к содержанию

Основы

Kubernetes: основы

Kubernetes (K8s) — платформа для оркестрации контейнеров. Docker запускает контейнеры на одной машине, Kubernetes — на кластере из десятков/сотен машин, управляя масштабированием, отказоустойчивостью и деплоем.

Зачем DE: Airflow на K8s (KubernetesExecutor), Spark operator, CI/CD-пайплайны, изоляция задач — каждый ETL-job в своём Pod с нужными ресурсами.


Архитектура

Text Only
┌─────────────── Control Plane ──────────────┐
│  API Server ← kubectl, CI/CD               │
│  etcd (state store)                         │
│  Scheduler (назначает Pod → Node)           │
│  Controller Manager (следит за состоянием)  │
└─────────────────────────────────────────────┘
         │              │              │
    ┌────▼────┐    ┌───▼────┐    ┌───▼────┐
    │  Node 1 │    │ Node 2 │    │ Node 3 │
    │ kubelet │    │ kubelet │    │ kubelet │
    │ Pod Pod │    │  Pod   │    │ Pod Pod │
    └─────────┘    └────────┘    └────────┘
Компонент Что делает
API Server Точка входа для всех операций (REST API)
etcd Распределённое хранилище состояния кластера
Scheduler Решает, на какой Node запустить Pod
kubelet Агент на каждой Node, запускает контейнеры
Pod Минимальная единица — один или несколько контейнеров

Основные ресурсы

Pod — атомарная единица

YAML
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: etl-worker
  labels:
    app: etl
spec:
  containers:
    - name: python
      image: python:3.11-slim
      command: ["python", "etl_job.py"]
      resources:
        requests:
          memory: "256Mi"
          cpu: "250m"
        limits:
          memory: "512Mi"
          cpu: "500m"
      env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: url

Никогда не создавай Pod напрямую

Pod без Deployment не перезапустится при падении. Всегда используй Deployment, Job или CronJob.

Deployment — управление Pod'ами

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 3                    # 3 одинаковых Pod'а
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: api
          image: myregistry/backend:v1.2.0
          ports:
            - containerPort: 8000
          readinessProbe:
            httpGet:
              path: /health
              port: 8000
            initialDelaySeconds: 5
            periodSeconds: 10
          resources:
            requests:
              memory: "256Mi"
              cpu: "250m"
            limits:
              memory: "512Mi"
              cpu: "500m"
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1               # +1 Pod при обновлении
      maxUnavailable: 0          # Все старые Pod'ы живы до готовности нового

Service — сетевой доступ к Pod'ам

YAML
apiVersion: v1
kind: Service
metadata:
  name: backend-svc
spec:
  selector:
    app: backend                 # Направлять трафик на Pod'ы с label app=backend
  ports:
    - port: 80                   # Порт сервиса
      targetPort: 8000           # Порт контейнера
  type: ClusterIP                # Доступен только внутри кластера
Тип Описание
ClusterIP Внутренний IP (default)
NodePort Порт на каждой Node (30000-32767)
LoadBalancer Внешний балансировщик (cloud)

ConfigMap — конфигурация

YAML
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  LOG_LEVEL: "INFO"
  WORKERS: "4"
  config.yaml: |
    database:
      pool_size: 10
      timeout: 30
YAML
# Использование в Pod
env:
  - name: LOG_LEVEL
    valueFrom:
      configMapKeyRef:
        name: app-config
        key: LOG_LEVEL
# Или как volume (файл)
volumes:
  - name: config
    configMap:
      name: app-config

Secret — чувствительные данные

YAML
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
stringData:                      # stringData → автоматическое base64
  url: postgresql://user:pass@db:5432/etl
  password: strong_password
Bash
# Создать через kubectl
kubectl create secret generic db-secret \
    --from-literal=url='postgresql://user:pass@db:5432/etl'

Secret — не шифрование

Secret хранится в etcd в base64 (не шифрованном виде). Для серьёзной безопасности используй Sealed Secrets, HashiCorp Vault или cloud KMS.


kubectl — основные команды

Bash
# Получить ресурсы
kubectl get pods                      # Pod'ы
kubectl get pods -o wide              # + Node, IP
kubectl get deployments               # Deployment'ы
kubectl get svc                       # Service'ы
kubectl get all                       # Всё

# Детали
kubectl describe pod backend-7f8b9-xk2lm
kubectl logs backend-7f8b9-xk2lm     # Логи
kubectl logs -f backend-7f8b9-xk2lm  # Follow

# Выполнить команду в Pod
kubectl exec -it backend-7f8b9-xk2lm -- /bin/bash

# Применить манифест
kubectl apply -f deployment.yaml
kubectl apply -f k8s/                 # Всю директорию

# Масштабирование
kubectl scale deployment backend --replicas=5

# Удалить
kubectl delete pod backend-7f8b9-xk2lm
kubectl delete -f deployment.yaml

Namespace — изоляция

Bash
kubectl create namespace data-platform
kubectl get pods -n data-platform
kubectl apply -f job.yaml -n data-platform

# Переключить контекст на namespace
kubectl config set-context --current --namespace=data-platform

Типичная структура: - default — тестовое/дефолтное - data-platform — ETL-пайплайны - monitoring — Prometheus, Grafana - airflow — Airflow


Helm — пакетный менеджер

Helm — «apt/brew для Kubernetes». Helm chart — шаблон из K8s-манифестов с параметрами.

Bash
# Добавить репозиторий
helm repo add apache-airflow https://airflow.apache.org
helm repo update

# Установить Airflow
helm install airflow apache-airflow/airflow \
    --namespace airflow --create-namespace \
    --set executor=KubernetesExecutor \
    --set dags.gitSync.enabled=true \
    --set dags.gitSync.repo=git@github.com:org/dags.git

# Обновить
helm upgrade airflow apache-airflow/airflow -f values.yaml

# Удалить
helm uninstall airflow -n airflow

values.yaml

YAML
# values.yaml — параметры для Helm chart
executor: KubernetesExecutor
webserver:
  replicas: 2
  resources:
    limits:
      memory: 2Gi
postgresql:
  enabled: true
  postgresqlPassword: airflow
dags:
  gitSync:
    enabled: true
    repo: git@github.com:org/dags.git
    branch: main

Minikube — K8s на ноутбуке

Bash
# Установка
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

# Запуск
minikube start --cpus=4 --memory=8g --driver=docker

# Dashboard
minikube dashboard

# Доступ к сервису
minikube service backend-svc

Проверь себя


Источники