Docker и Kubernetes: от контейнеризации к оркестрации

Полное руководство по современной контейнерной инфраструктуре

Контейнеры стали стандартом разработки. 87% компаний используют Docker, 48% — Kubernetes в production. Но путь от "docker run" до production-ready K8s кластера требует глубокого понимания. Docker: основы контейнеризации Что такое контейнер Контейнер — это изолированный процесс со своей файловой системой, сетью и ресурсами. В отличие от VM, контейнеры используют ядро хоста. Docker vs VM: Размер: контейнеры 10-100 MB, VM 1-10 GB Старт: секунды vs минуты Изоляция: process-level vs hardware-level Overhead: минимальный vs значительный Dockerfile Best Practices Многоступенчатая сборка: # Build stage FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . RUN npm run build # Production stage FROM node:18-alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules EXPOSE 3000 CMD ["node", "dist/index.js"] Результат: образ 150 MB вместо 1.2 GB Оптимизация слоев: # Плохо - каждая команда = новый слой RUN apt-get update RUN apt-get install -y curl RUN apt-get install -y git # Хорошо - один слой RUN apt-get update && \ apt-get install -y curl git && \ rm -rf /var/lib/apt/lists/* Кэширование: # Сначала копируем package.json COPY package*.json ./ RUN npm install # Потом остальной код COPY . . # npm install кэшируется, если package.json не изменился Docker Compose: локальная разработка version: '3.8' services: app: build: . ports: - "3000:3000" environment: - DATABASE_URL=postgresql://user:pass@db:5432/mydb depends_on: - db - redis volumes: - ./src:/app/src # hot reload db: image: postgres:15-alpine environment: POSTGRES_PASSWORD: pass volumes: - db_data:/var/lib/postgresql/data redis: image: redis:7-alpine volumes: db_data: Команды: docker-compose up -d # запуск docker-compose logs -f app # логи docker-compose down -v # остановка + удаление volumes Kubernetes: оркестрация контейнеров Основные концепции: Pod — минимальная единица, 1+ контейнеров Deployment — управление репликами подов Service — сетевой доступ к подам Ingress — HTTP роутинг ConfigMap/Secret — конфигурация и секреты Deployment манифест: apiVersion: apps/v1 kind: Deployment metadata: name: my-app spec: replicas: 3 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: app image: myapp:1.0.0 ports: - containerPort: 3000 resources: requests: memory: "128Mi" cpu: "100m" limits: memory: "512Mi" cpu: "500m" livenessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 3000 initialDelaySeconds: 5 periodSeconds: 5 Service: apiVersion: v1 kind: Service metadata: name: my-app spec: selector: app: my-app ports: - port: 80 targetPort: 3000 type: LoadBalancer HorizontalPodAutoscaler: apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: my-app spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: my-app minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 Результат: автоматическое масштабирование при нагрузке ConfigMap и Secrets: apiVersion: v1 kind: ConfigMap metadata: name: app-config data: API_URL: "https://api.example.com" LOG_LEVEL: "info" --- apiVersion: v1 kind: Secret metadata: name: app-secrets type: Opaque data: DB_PASSWORD: cGFzc3dvcmQxMjM= # base64 encoded Ingress для роутинга: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress annotations: cert-manager.io/cluster-issuer: letsencrypt spec: tls: - hosts: - example.com secretName: example-tls rules: - host: example.com http: paths: - path: / pathType: Prefix backend: service: name: my-app port: number: 80 Helm: пакетный менеджер Helm упрощает управление K8s манифестами: # Установка chart helm install my-app bitnami/nginx # С кастомными значениями helm install my-app ./my-chart -f values.yaml # Обновление helm upgrade my-app ./my-chart # Откат helm rollback my-app 1 Структура Helm chart: my-chart/ Chart.yaml # метаданные values.yaml # дефолтные значения templates/ deployment.yaml service.yaml ingress.yaml Мониторинг и логирование Prometheus + Grafana: Сбор метрик из подов Алерты при проблемах Дашборды производительности ELK Stack (Elasticsearch, Logstash, Kibana): Централизованные логи Поиск по логам Анализ ошибок Команды для debugging: # Логи пода kubectl logs pod-name -f # Exec в контейнер kubectl exec -it pod-name -- /bin/sh # Описание пода kubectl describe pod pod-name # События kubectl get events --sort-by='.lastTimestamp' # Top nodes/pods kubectl top nodes kubectl top pods Security Best Practices Не запускайте как root: FROM node:18-alpine RUN addgroup -g 1001 -S nodejs RUN adduser -S nodejs -u 1001 USER nodejs Сканируйте образы на уязвимости: docker scan myapp:1.0.0 trivy image myapp:1.0.0 Network Policies: apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: api-network-policy spec: podSelector: matchLabels: app: api ingress: - from: - podSelector: matchLabels: app: frontend ports: - protocol: TCP port: 3000 Resource limits: предотвращение OOM RBAC: минимальные права доступа CI/CD с Kubernetes GitOps подход: 1. Developer push в main 2. CI builds Docker image 3. CI pushes image в registry 4. CI updates K8s manifests 5. ArgoCD/Flux applies changes Пример GitHub Actions: name: Deploy to K8s on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Build image run: docker build -t myapp:${{ github.sha }} . - name: Push image run: | echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin docker push myapp:${{ github.sha }} - name: Deploy to K8s run: | kubectl set image deployment/my-app app=myapp:${{ github.sha }} Managed Kubernetes: GKE (Google) — отличная интеграция, autopilot mode EKS (AWS) — глубокая интеграция с AWS сервисами AKS (Azure) — хорошая для enterprise DigitalOcean K8s — простота, low cost Стоимость и ROI До контейнеризации: Деплой: 30-60 минут Rollback: 30-60 минут Утилизация серверов: 20-30% После Docker + K8s: Деплой: 2-5 минут Rollback: 1 минута Утилизация серверов: 70-80% Экономия инфраструктуры: 40-60% Когда НЕ нужен Kubernetes Команда Простое монолитное приложение Нет требований к high availability Нет DevOps expertise Альтернативы: Docker Compose, Docker Swarm, managed PaaS (Heroku, Render) Заключение: Docker и Kubernetes — мощные инструменты для современной разработки. Начните с Docker для локальной разработки, освойте Docker Compose для мульти-контейнерных приложений. Переходите на Kubernetes только когда масштаб требует оркестрации. Инвестируйте в обучение команды — это окупится через ускорение деплоев и снижение стоимости инфраструктуры.