Files
Alexander Abakumov 15e744da49 Initial commit: Complete Software Architecture course with 11 modules
- Added comprehensive course structure with 11 modules
- Included theoretical content, practical examples, and tasks
- Multi-language code examples (Java, Rust, Node.js, Python)
- Detailed analysis of architectural approaches and trade-offs
- Complete caching strategies documentation
- Architecture examples from real-world systems (Twitter, Netflix, Uber)
- Structured navigation and learning path
- Ready for educational use
2025-09-09 22:08:07 +03:00

2009 lines
50 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Модуль 3: Контейнеризация и оркестрация
## Содержание модуля
1. [Основы контейнеризации](#основы-контейнеризации)
2. [Docker](#docker)
3. [Kubernetes](#kubernetes)
4. [Infrastructure as Code](#infrastructure-as-code)
5. [CI/CD с контейнерами](#cicd-с-контейнерами)
6. [Мониторинг контейнеров](#мониторинг-контейнеров)
---
## Основы контейнеризации
### Что такое контейнеризация
**Контейнеризация** — это технология упаковки приложений и их зависимостей в легковесные, переносимые контейнеры.
### Преимущества контейнеризации
#### 1. Портабельность
- Одинаковая среда на всех платформах
- "Работает на моей машине" больше не проблема
- Легкая миграция между средами
#### 2. Изоляция
- Приложения изолированы друг от друга
- Контроль ресурсов
- Безопасность
#### 3. Масштабируемость
- Быстрое создание и удаление контейнеров
- Горизонтальное масштабирование
- Эффективное использование ресурсов
#### 4. Консистентность
- Одинаковая среда разработки, тестирования и продакшена
- Предсказуемое поведение
- Упрощение развертывания
### Контейнеры vs Виртуальные машины
| Аспект | Контейнеры | Виртуальные машины |
|--------|------------|-------------------|
| Изоляция | Процессная | Аппаратная |
| Размер | МБ | ГБ |
| Запуск | Секунды | Минуты |
| Ресурсы | Общие | Выделенные |
| Безопасность | Процессная | Аппаратная |
### Компоненты контейнеризации
#### 1. Container Runtime
- **containerd** — стандартный runtime
- **runc** — низкоуровневый runtime
- **CRI-O** — Kubernetes-специфичный runtime
#### 2. Container Image
- Неизменяемый образ приложения
- Слоистая структура
- Версионирование
#### 3. Container Registry
- Хранение образов
- Версионирование
- Безопасность
---
## Docker
### Основы Docker
**Docker** — платформа для разработки, доставки и запуска приложений в контейнерах.
### Архитектура Docker
```
┌─────────────────────────────────────┐
│ Docker Client │
├─────────────────────────────────────┤
│ Docker Daemon │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Images │ │ Containers │ │
│ └─────────────┘ └─────────────────┘ │
├─────────────────────────────────────┤
│ Container Runtime │
└─────────────────────────────────────┘
```
### Dockerfile
**Dockerfile** — текстовый файл с инструкциями для создания образа.
**Технический пример - Dockerfile для Spring Boot приложения:**
```dockerfile
# Многоэтапная сборка для оптимизации размера образа
# Этап 1: Сборка приложения
FROM maven:3.8.6-openjdk-17-slim AS build
# Установка рабочей директории
WORKDIR /app
# Копирование файлов pom.xml для кэширования зависимостей
COPY pom.xml .
COPY src ./src
# Сборка приложения
RUN mvn clean package -DskipTests
# Этап 2: Создание финального образа
FROM openjdk:17-jre-slim
# Установка рабочей директории
WORKDIR /app
# Создание пользователя для безопасности
RUN groupadd -r appuser && useradd -r -g appuser appuser
# Копирование собранного JAR файла
COPY --from=build /app/target/*.jar app.jar
# Изменение владельца файлов
RUN chown -R appuser:appuser /app
USER appuser
# Открытие порта
EXPOSE 8080
# Переменные окружения
ENV JAVA_OPTS="-Xmx512m -Xms256m"
ENV SPRING_PROFILES_ACTIVE=production
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
# Запуск приложения
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
```
**Dockerfile для микросервиса на Node.js:**
```dockerfile
# Базовый образ Node.js
FROM node:18-alpine AS base
# Установка рабочей директории
WORKDIR /app
# Установка системных зависимостей
RUN apk add --no-cache \
dumb-init \
curl
# Создание пользователя для безопасности
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
# Этап установки зависимостей
FROM base AS deps
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
# Этап сборки
FROM base AS builder
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Финальный этап
FROM base AS runner
ENV NODE_ENV=production
# Копирование зависимостей
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/public ./public
# Копирование конфигурационных файлов
COPY --from=builder /app/package.json ./package.json
# Изменение владельца файлов
RUN chown -R nextjs:nodejs /app
USER nextjs
# Открытие порта
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# Запуск приложения
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/index.js"]
```
**Дополнительные Node.js Dockerfile примеры:**
**Dockerfile для Express.js микросервиса с TypeScript:**
```dockerfile
# Многоэтапная сборка для TypeScript приложения
# Этап 1: Сборка приложения
FROM node:18-alpine AS build
WORKDIR /app
# Копирование package.json и package-lock.json
COPY package*.json ./
COPY tsconfig.json ./
# Установка всех зависимостей (включая dev)
RUN npm ci
# Копирование исходного кода
COPY src ./src
# Компиляция TypeScript
RUN npm run build
# Этап 2: Продакшн образ
FROM node:18-alpine AS production
WORKDIR /app
# Копирование package.json для установки только продакшн зависимостей
COPY package*.json ./
# Установка только продакшн зависимостей
RUN npm ci --only=production && npm cache clean --force
# Копирование собранного приложения
COPY --from=build /app/dist ./dist
# Создание пользователя для безопасности
RUN addgroup -g 1001 -S nodejs && \
adduser -S express -u 1001
# Изменение владельца файлов
RUN chown -R express:nodejs /app
USER express
# Открытие порта
EXPOSE 3000
# Переменные окружения
ENV NODE_ENV=production
ENV PORT=3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# Запуск приложения
CMD ["node", "dist/index.js"]
```
**Dockerfile для NestJS микросервиса:**
```dockerfile
# Многоэтапная сборка для NestJS приложения
FROM node:18-alpine AS build
WORKDIR /app
# Копирование файлов конфигурации
COPY package*.json ./
COPY tsconfig*.json ./
COPY nest-cli.json ./
# Установка зависимостей
RUN npm ci
# Копирование исходного кода
COPY src ./src
# Сборка приложения
RUN npm run build
# Продакшн образ
FROM node:18-alpine AS production
WORKDIR /app
# Копирование package.json
COPY package*.json ./
# Установка только продакшн зависимостей
RUN npm ci --only=production && npm cache clean --force
# Копирование собранного приложения
COPY --from=build /app/dist ./dist
# Создание пользователя
RUN addgroup -g 1001 -S nestjs && \
adduser -S nestjs -u 1001
# Изменение владельца
RUN chown -R nestjs:nestjs /app
USER nestjs
# Открытие порта
EXPOSE 3000
# Переменные окружения
ENV NODE_ENV=production
ENV PORT=3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# Запуск приложения
CMD ["node", "dist/main.js"]
```
**Dockerfile для Fastify микросервиса:**
```dockerfile
# Оптимизированный Dockerfile для Fastify
FROM node:18-alpine AS base
# Установка необходимых пакетов
RUN apk add --no-cache dumb-init
WORKDIR /app
# Копирование package.json
COPY package*.json ./
# Установка зависимостей
RUN npm ci --only=production && npm cache clean --force
# Копирование исходного кода
COPY . .
# Создание пользователя
RUN addgroup -g 1001 -S fastify && \
adduser -S fastify -u 1001
# Изменение владельца
RUN chown -R fastify:fastify /app
USER fastify
# Открытие порта
EXPOSE 3000
# Переменные окружения
ENV NODE_ENV=production
ENV PORT=3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# Использование dumb-init для правильной обработки сигналов
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "server.js"]
```
**Docker Compose для микросервисной архитектуры:**
```yaml
version: '3.8'
services:
# API Gateway
api-gateway:
build:
context: ./api-gateway
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka:8761/eureka/
depends_on:
- eureka
- user-service
- order-service
- payment-service
networks:
- microservices-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
# Service Discovery
eureka:
image: steeltoeoss/eureka-server:latest
ports:
- "8761:8761"
environment:
- EUREKA_CLIENT_REGISTER_WITH_EUREKA=false
- EUREKA_CLIENT_FETCH_REGISTRY=false
networks:
- microservices-network
# User Service
user-service:
build:
context: ./user-service
dockerfile: Dockerfile
ports:
- "8081:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- SPRING_DATASOURCE_URL=jdbc:postgresql://user-db:5432/userdb
- SPRING_DATASOURCE_USERNAME=user
- SPRING_DATASOURCE_PASSWORD=password
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka:8761/eureka/
depends_on:
- user-db
- eureka
networks:
- microservices-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
# Order Service
order-service:
build:
context: ./order-service
dockerfile: Dockerfile
ports:
- "8082:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- SPRING_DATASOURCE_URL=jdbc:postgresql://order-db:5432/orderdb
- SPRING_DATASOURCE_USERNAME=order
- SPRING_DATASOURCE_PASSWORD=password
- USER_SERVICE_URL=http://user-service:8080
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka:8761/eureka/
depends_on:
- order-db
- user-service
- eureka
networks:
- microservices-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
# Payment Service
payment-service:
build:
context: ./payment-service
dockerfile: Dockerfile
ports:
- "8083:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- SPRING_DATASOURCE_URL=jdbc:postgresql://payment-db:5432/paymentdb
- SPRING_DATASOURCE_USERNAME=payment
- SPRING_DATASOURCE_PASSWORD=password
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka:8761/eureka/
depends_on:
- payment-db
- eureka
networks:
- microservices-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
# Databases
user-db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=userdb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- user_data:/var/lib/postgresql/data
- ./init-scripts/user-db-init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- microservices-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d userdb"]
interval: 10s
timeout: 5s
retries: 5
order-db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=orderdb
- POSTGRES_USER=order
- POSTGRES_PASSWORD=password
volumes:
- order_data:/var/lib/postgresql/data
- ./init-scripts/order-db-init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- microservices-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U order -d orderdb"]
interval: 10s
timeout: 5s
retries: 5
payment-db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=paymentdb
- POSTGRES_USER=payment
- POSTGRES_PASSWORD=password
volumes:
- payment_data:/var/lib/postgresql/data
- ./init-scripts/payment-db-init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- microservices-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U payment -d paymentdb"]
interval: 10s
timeout: 5s
retries: 5
# Message Queue
rabbitmq:
image: rabbitmq:3.11-management-alpine
ports:
- "5672:5672"
- "15672:15672"
environment:
- RABBITMQ_DEFAULT_USER=admin
- RABBITMQ_DEFAULT_PASS=admin
volumes:
- rabbitmq_data:/var/lib/rabbitmq
networks:
- microservices-network
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "ping"]
interval: 30s
timeout: 10s
retries: 3
# Monitoring
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
networks:
- microservices-network
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
- ./monitoring/grafana/dashboards:/etc/grafana/provisioning/dashboards
- ./monitoring/grafana/datasources:/etc/grafana/provisioning/datasources
networks:
- microservices-network
volumes:
user_data:
order_data:
payment_data:
rabbitmq_data:
prometheus_data:
grafana_data:
networks:
microservices-network:
driver: bridge
```
**Docker Compose для Node.js микросервисной архитектуры:**
```yaml
version: '3.8'
services:
# API Gateway (Express.js)
api-gateway:
build:
context: ./api-gateway
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- PORT=3000
- USER_SERVICE_URL=http://user-service:3001
- ORDER_SERVICE_URL=http://order-service:3002
- PAYMENT_SERVICE_URL=http://payment-service:3003
depends_on:
- user-service
- order-service
- payment-service
networks:
- microservices-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
# User Service (Express.js + TypeScript)
user-service:
build:
context: ./user-service
dockerfile: Dockerfile
ports:
- "3001:3001"
environment:
- NODE_ENV=production
- PORT=3001
- DATABASE_URL=postgresql://user:password@user-db:5432/userdb
- REDIS_URL=redis://redis:6379
depends_on:
- user-db
- redis
networks:
- microservices-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
interval: 30s
timeout: 10s
retries: 3
# Order Service (NestJS)
order-service:
build:
context: ./order-service
dockerfile: Dockerfile
ports:
- "3002:3002"
environment:
- NODE_ENV=production
- PORT=3002
- DATABASE_URL=postgresql://order:password@order-db:5432/orderdb
- PAYMENT_SERVICE_URL=http://payment-service:3003
- RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672
depends_on:
- order-db
- rabbitmq
networks:
- microservices-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3002/health"]
interval: 30s
timeout: 10s
retries: 3
# Payment Service (Fastify)
payment-service:
build:
context: ./payment-service
dockerfile: Dockerfile
ports:
- "3003:3003"
environment:
- NODE_ENV=production
- PORT=3003
- DATABASE_URL=postgresql://payment:password@payment-db:5432/paymentdb
- PAYMENT_GATEWAY_URL=https://api.payment-gateway.com
- PAYMENT_GATEWAY_KEY=${PAYMENT_GATEWAY_KEY}
depends_on:
- payment-db
networks:
- microservices-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3003/health"]
interval: 30s
timeout: 10s
retries: 3
# Databases
user-db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=userdb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- user_data:/var/lib/postgresql/data
networks:
- microservices-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d userdb"]
interval: 10s
timeout: 5s
retries: 5
order-db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=orderdb
- POSTGRES_USER=order
- POSTGRES_PASSWORD=password
volumes:
- order_data:/var/lib/postgresql/data
networks:
- microservices-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U order -d orderdb"]
interval: 10s
timeout: 5s
retries: 5
payment-db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=paymentdb
- POSTGRES_USER=payment
- POSTGRES_PASSWORD=password
volumes:
- payment_data:/var/lib/postgresql/data
networks:
- microservices-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U payment -d paymentdb"]
interval: 10s
timeout: 5s
retries: 5
# Redis for caching
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- microservices-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
# RabbitMQ for messaging
rabbitmq:
image: rabbitmq:3-management-alpine
ports:
- "5672:5672"
- "15672:15672"
environment:
- RABBITMQ_DEFAULT_USER=guest
- RABBITMQ_DEFAULT_PASS=guest
volumes:
- rabbitmq_data:/var/lib/rabbitmq
networks:
- microservices-network
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "ping"]
interval: 30s
timeout: 10s
retries: 3
# Monitoring
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
networks:
- microservices-network
grafana:
image: grafana/grafana:latest
ports:
- "3001:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
networks:
- microservices-network
volumes:
user_data:
order_data:
payment_data:
redis_data:
rabbitmq_data:
grafana_data:
networks:
microservices-network:
driver: bridge
```
**Docker команды для управления контейнерами:**
```bash
# Сборка образа
docker build -t user-service:latest ./user-service
# Запуск контейнера
docker run -d --name user-service -p 8081:8080 \
-e SPRING_DATASOURCE_URL=jdbc:postgresql://host.docker.internal:5432/userdb \
user-service:latest
# Просмотр логов
docker logs -f user-service
# Выполнение команд в контейнере
docker exec -it user-service bash
# Мониторинг ресурсов
docker stats user-service
# Остановка и удаление
docker stop user-service
docker rm user-service
# Очистка неиспользуемых образов
docker system prune -a
# Запуск с Docker Compose
docker-compose up -d
docker-compose down
docker-compose logs -f user-service
```
# Копирование файлов зависимостей
COPY package*.json ./
# Установка зависимостей
RUN npm ci --only=production
# Копирование исходного кода
COPY . .
# Открытие порта
EXPOSE 3000
# Команда запуска
CMD ["npm", "start"]
```
### Команды Docker
#### Основные команды:
```bash
# Сборка образа
docker build -t myapp:latest .
# Запуск контейнера
docker run -p 3000:3000 myapp:latest
# Просмотр запущенных контейнеров
docker ps
# Просмотр всех контейнеров
docker ps -a
# Остановка контейнера
docker stop <container_id>
# Удаление контейнера
docker rm <container_id>
# Просмотр образов
docker images
# Удаление образа
docker rmi <image_id>
```
#### Продвинутые команды:
```bash
# Запуск в фоновом режиме
docker run -d -p 3000:3000 myapp:latest
# Подключение к контейнеру
docker exec -it <container_id> /bin/bash
# Просмотр логов
docker logs <container_id>
# Мониторинг ресурсов
docker stats <container_id>
```
### Docker Compose
**Docker Compose** — инструмент для определения и запуска многоконтейнерных приложений.
```yaml
# docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
depends_on:
- db
- redis
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:6-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
```
### Лучшие практики Docker
#### 1. Оптимизация размера образа
```dockerfile
# Используйте многоэтапную сборку
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
CMD ["npm", "start"]
```
#### 2. Безопасность
```dockerfile
# Создайте пользователя без root прав
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
USER nextjs
```
#### 3. Кэширование слоев
```dockerfile
# Копируйте package.json перед исходным кодом
COPY package*.json ./
RUN npm ci
COPY . .
```
#### 4. Health Checks
```dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
```
---
## Kubernetes
### Что такое Kubernetes
**Kubernetes (K8s)** — система оркестрации контейнеров для автоматизации развертывания, масштабирования и управления приложениями.
### Архитектура Kubernetes
```
┌─────────────────────────────────────────────────────────┐
│ Control Plane │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ API Server │ │ Scheduler │ │ Controller Mgr │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ etcd │ │ Cloud Ctlr │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────┐
│ Worker Nodes │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ kubelet │ │ kube-proxy │ │ Container Runtime│ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────┘
```
### Основные компоненты
#### Плоскость управления:
- **API Server** — центральный компонент управления
- **etcd** — хранилище конфигурации
- **Scheduler** — планировщик подов
- **Controller Manager** — контроллеры системы
#### Рабочие узлы:
- **kubelet** — агент на каждом узле
- **kube-proxy** — сетевой прокси
- **Container Runtime** — Docker, containerd, CRI-O
### Объекты Kubernetes
#### 1. Pod
**Pod** — наименьшая единица развертывания в Kubernetes.
**Технический пример - Pod для микросервиса:**
```yaml
apiVersion: v1
kind: Pod
metadata:
name: user-service-pod
labels:
app: user-service
version: v1.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/actuator/prometheus"
spec:
containers:
- name: user-service
image: user-service:latest
ports:
- containerPort: 8080
name: http
protocol: TCP
env:
- name: SPRING_PROFILES_ACTIVE
value: "kubernetes"
- name: SPRING_DATASOURCE_URL
valueFrom:
secretKeyRef:
name: user-db-secret
key: url
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: user-db-secret
key: username
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: user-db-secret
key: password
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: config-volume
mountPath: /app/config
readOnly: true
volumes:
- name: config-volume
configMap:
name: user-service-config
restartPolicy: Always
terminationGracePeriodSeconds: 30
```
#### 2. Deployment
**Deployment** — управляет репликами подов.
**Технический пример - Deployment для микросервиса:**
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service-deployment
labels:
app: user-service
version: v1.0.0
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
version: v1.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/actuator/prometheus"
spec:
containers:
- name: user-service
image: user-service:v1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
protocol: TCP
env:
- name: SPRING_PROFILES_ACTIVE
value: "kubernetes"
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: SPRING_DATASOURCE_URL
valueFrom:
secretKeyRef:
name: user-db-secret
key: url
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: user-db-secret
key: username
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: user-db-secret
key: password
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
volumeMounts:
- name: config-volume
mountPath: /app/config
readOnly: true
- name: logs-volume
mountPath: /app/logs
volumes:
- name: config-volume
configMap:
name: user-service-config
- name: logs-volume
emptyDir: {}
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
```
**HorizontalPodAutoscaler для автоматического масштабирования:**
```yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: user-service-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: user-service-deployment
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 50
periodSeconds: 60
```
#### 3. Service
**Service** — обеспечивает сетевой доступ к подам.
**Технический пример - Service для микросервиса:**
```yaml
apiVersion: v1
kind: Service
metadata:
name: user-service
labels:
app: user-service
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/actuator/prometheus"
spec:
selector:
app: user-service
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
- name: metrics
protocol: TCP
port: 9090
targetPort: 9090
type: ClusterIP
sessionAffinity: None
```
**Ingress для внешнего доступа:**
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: microservices-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- api.example.com
secretName: api-tls-secret
rules:
- host: api.example.com
http:
paths:
- path: /api/users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
- path: /api/orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80
- path: /api/payments
pathType: Prefix
backend:
service:
name: payment-service
port:
number: 80
```
**ConfigMap для конфигурации:**
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: user-service-config
labels:
app: user-service
data:
application.yml: |
server:
port: 8080
spring:
application:
name: user-service
datasource:
driver-class-name: org.postgresql.Driver
hikari:
maximum-pool-size: 10
minimum-idle: 5
connection-timeout: 20000
idle-timeout: 300000
max-lifetime: 1200000
jpa:
hibernate:
ddl-auto: validate
show-sql: false
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
rabbitmq:
host: rabbitmq-service
port: 5672
username: admin
password: admin
management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
endpoint:
health:
show-details: always
metrics:
export:
prometheus:
enabled: true
logback-spring.xml: |
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/app/logs/user-service.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/app/logs/user-service.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
```
**Secret для чувствительных данных:**
```yaml
apiVersion: v1
kind: Secret
metadata:
name: user-db-secret
labels:
app: user-service
type: Opaque
data:
url: cG9zdGdyZXNxbDovL3VzZXItZGItc2VydmljZToyNTQzMi91c2VyZGI= # base64 encoded
username: dXNlcg== # base64 encoded
password: cGFzc3dvcmQ= # base64 encoded
```
**PersistentVolumeClaim для базы данных:**
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: user-db-pvc
labels:
app: user-db
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: fast-ssd
```
**StatefulSet для базы данных:**
```yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: user-db
labels:
app: user-db
spec:
serviceName: user-db
replicas: 1
selector:
matchLabels:
app: user-db
template:
metadata:
labels:
app: user-db
spec:
containers:
- name: postgres
image: postgres:15-alpine
ports:
- containerPort: 5432
name: postgres
env:
- name: POSTGRES_DB
value: userdb
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: user-db-secret
key: username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: user-db-secret
key: password
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
exec:
command:
- pg_isready
- -U
- user
- -d
- userdb
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- pg_isready
- -U
- user
- -d
- userdb
initialDelaySeconds: 5
periodSeconds: 5
volumeClaimTemplates:
- metadata:
name: postgres-storage
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
storageClassName: fast-ssd
```
#### 4. ConfigMap
**ConfigMap** — хранит конфигурационные данные.
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
database_url: "postgresql://localhost:5432/mydb"
api_key: "secret-key"
```
#### 5. Secret
**Secret** — хранит чувствительные данные.
```yaml
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
username: YWRtaW4=
password: cGFzc3dvcmQ=
```
### Команды Kubernetes
#### Основные команды:
```bash
# Применение манифеста
kubectl apply -f deployment.yaml
# Просмотр подов
kubectl get pods
# Просмотр сервисов
kubectl get services
# Просмотр деплойментов
kubectl get deployments
# Описание ресурса
kubectl describe pod <pod-name>
# Логи пода
kubectl logs <pod-name>
# Подключение к поду
kubectl exec -it <pod-name> -- /bin/bash
# Масштабирование деплоймента
kubectl scale deployment my-deployment --replicas=5
```
### Сетевая модель Kubernetes
#### 1. Cluster Networking
- Каждый под имеет уникальный IP
- Поды могут общаться друг с другом
- Сервисы обеспечивают стабильные IP
#### 2. Service Types
- **ClusterIP** — внутренний IP кластера
- **NodePort** — доступ через порт узла
- **LoadBalancer** — внешний балансировщик нагрузки
- **ExternalName** — внешний DNS
#### 3. Ingress
**Ingress** — управляет внешним доступом к сервисам.
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
```
### Хранилище в Kubernetes
#### 1. Volumes
```yaml
apiVersion: v1
kind: Pod
spec:
containers:
- name: my-container
image: nginx
volumeMounts:
- name: my-volume
mountPath: /data
volumes:
- name: my-volume
persistentVolumeClaim:
claimName: my-pvc
```
#### 2. PersistentVolume
```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: fast-ssd
```
#### 3. PersistentVolumeClaim
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: fast-ssd
```
---
## Infrastructure as Code
### Что такое IaC
**Infrastructure as Code (IaC)** — подход к управлению инфраструктурой через код.
### Преимущества IaC
#### 1. Версионирование
- История изменений инфраструктуры
- Откат к предыдущим версиям
- Code review для инфраструктуры
#### 2. Повторяемость
- Одинаковая инфраструктура в разных средах
- Автоматизация развертывания
- Устранение дрейфа конфигурации
#### 3. Документация
- Код как документация
- Понятная структура инфраструктуры
- Автоматическая генерация диаграмм
### Terraform
**Terraform** — инструмент для управления инфраструктурой через код.
#### Основные концепции:
##### 1. Provider
```hcl
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
```
##### 2. Resource
```hcl
resource "aws_instance" "web" {
ami = "ami-0c02fb55956c7d316"
instance_type = "t2.micro"
tags = {
Name = "HelloWorld"
}
}
```
##### 3. Data Source
```hcl
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"]
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
}
```
##### 4. Variables
```hcl
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t2.micro"
}
variable "environment" {
description = "Environment name"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
```
##### 5. Outputs
```hcl
output "instance_ip" {
description = "Public IP of the instance"
value = aws_instance.web.public_ip
}
```
#### Команды Terraform
```bash
# Инициализация
terraform init
# Планирование изменений
terraform plan
# Применение изменений
terraform apply
# Уничтожение инфраструктуры
terraform destroy
# Просмотр состояния
terraform show
# Форматирование кода
terraform fmt
# Валидация конфигурации
terraform validate
```
#### Модули Terraform
```hcl
# main.tf
module "vpc" {
source = "./modules/vpc"
environment = var.environment
cidr_block = "10.0.0.0/16"
}
module "ec2" {
source = "./modules/ec2"
vpc_id = module.vpc.vpc_id
subnet_id = module.vpc.public_subnet_id
}
```
### Ansible
**Ansible** — инструмент автоматизации конфигурации и развертывания.
#### Пример Playbook:
```yaml
---
- name: Deploy web application
hosts: web_servers
become: yes
vars:
app_name: myapp
app_port: 3000
tasks:
- name: Install Node.js
package:
name: nodejs
state: present
- name: Install npm dependencies
npm:
path: /opt/{{ app_name }}
state: present
- name: Start application
systemd:
name: "{{ app_name }}"
state: started
enabled: yes
```
---
## CI/CD с контейнерами
### CI/CD Pipeline
```yaml
# .github/workflows/deploy.yml
name: Deploy to Kubernetes
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build Docker image
run: docker build -t ${{ secrets.REGISTRY }}/myapp:${{ github.sha }} .
- name: Push to registry
run: docker push ${{ secrets.REGISTRY }}/myapp:${{ github.sha }}
- name: Deploy to Kubernetes
run: |
kubectl set image deployment/myapp myapp=${{ secrets.REGISTRY }}/myapp:${{ github.sha }}
kubectl rollout status deployment/myapp
```
### GitOps
**GitOps** — подход к управлению инфраструктурой через Git.
#### Пример ArgoCD:
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/myapp
targetRevision: HEAD
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
```
---
## Мониторинг контейнеров
### Prometheus + Grafana
#### Конфигурация Prometheus:
```yaml
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
```
#### Дашборд Grafana:
```json
{
"dashboard": {
"title": "Kubernetes Cluster",
"panels": [
{
"title": "CPU Usage",
"type": "graph",
"targets": [
{
"expr": "rate(container_cpu_usage_seconds_total[5m])"
}
]
}
]
}
}
```
### ELK Stack
#### Elasticsearch + Logstash + Kibana:
```yaml
# docker-compose.yml
version: '3.8'
services:
elasticsearch:
image: elasticsearch:7.14.0
environment:
- discovery.type=single-node
ports:
- "9200:9200"
logstash:
image: logstash:7.14.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
ports:
- "5044:5044"
kibana:
image: kibana:7.14.0
ports:
- "5601:5601"
```
---
## Практические задания
### Задание 1: Docker
1. Создайте Dockerfile для Node.js приложения
2. Соберите образ и запустите контейнер
3. Создайте docker-compose.yml для многоконтейнерного приложения
### Задание 2: Kubernetes
1. Создайте Deployment для веб-приложения
2. Создайте Service для доступа к приложению
3. Настройте ConfigMap и Secret
4. Разверните приложение в кластере
### Задание 3: Terraform
1. Создайте инфраструктуру в AWS с помощью Terraform
2. Используйте модули для организации кода
3. Настройте переменные и outputs
---
## Дополнительные ресурсы
### Документация
- [Docker Documentation](https://docs.docker.com/)
- [Kubernetes Documentation](https://kubernetes.io/docs/)
- [Terraform Documentation](https://www.terraform.io/docs/)
### Книги
- "Kubernetes in Action" by Marko Lukša
- "Terraform: Up & Running" by Yevgeniy Brikman
---
## Контрольные вопросы
1. Что такое контейнеризация и каковы её преимущества?
2. Как работает Docker и какие основные команды вы знаете?
3. Что такое Kubernetes и какова его архитектура?
4. Какие основные объекты Kubernetes вы знаете?
5. Что такое Infrastructure as Code и зачем это нужно?
6. Как настроить CI/CD для контейнеризованных приложений?
7. Как мониторить контейнеры и кластеры?
8. Какие best practices для Docker и Kubernetes?