Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Мой опыт с Kubernetes
Да, я активно использовал Kubernetes в production уже более 4 лет. Начал с простых развертываний и дошел до управления сложными микросервисными архитектурами.
Начальный опыт (2020)
Первый проект с Kubernetes был стартапом в сфере fintech. До этого мы использовали Heroku, но нужна была большая гибкость и контроль над инфраструктурой.
Что пришлось учить:
- Основные концепции: Pods, Services, Deployments
- ConfigMaps и Secrets для управления конфигурацией
- PersistentVolumes для хранилища
- Ingress для маршрутизации
Первый deployment файл:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-server
namespace: production
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: api-server
template:
metadata:
labels:
app: api-server
version: v1
spec:
containers:
- name: api-server
image: myregistry.azurecr.io/api-server:1.2.3
ports:
- containerPort: 3000
name: http
env:
- name: NODE_ENV
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: connection-string
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 10
periodSeconds: 5
Масштабирование до production (2021)
Когда пришлось работать с реальными пользователями, столкнулся с настоящими проблемами.
1. Автоскейлинг
Первый раз был в production spike — все сломалось, потому что не настроили HPA.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-server-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-server
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
После этого система автоматически масштабировалась при нагрузке.
2. Graceful shutdown
Заметил, что при обновлении Pods некоторые запросы падали. Проблема была в том, что приложение не обрабатывало SIGTERM сигнал.
// В основном сервере
const server = app.listen(3000);
process.on('SIGTERM', async () => {
console.log('SIGTERM received, shutting down gracefully...');
// Закрываем server, чтобы не принимать новые запросы
server.close(async () => {
// Даем время завершить in-flight запросы
await new Promise(resolve => setTimeout(resolve, 5000));
// Закрываем соединения с БД
await database.close();
// Выходим
process.exit(0);
});
// Если даже после 30 секунд не закрылось, принудительно выходим
setTimeout(() => {
console.error('Graceful shutdown timeout, exiting forcefully');
process.exit(1);
}, 30000);
});
И обновил deployment для graceful shutdown:
spec:
template:
spec:
containers:
- name: api-server
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 5"]
terminationGracePeriodSeconds: 40
Продвинутая работа с K8s (2022-2023)
1. Service Mesh (Istio)
Когда микросервисов было много, нужна была лучшая обсервируемость и control over traffic.
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: api-server
spec:
hosts:
- api-server
http:
- match:
- headers:
user-type:
exact: premium
route:
- destination:
host: api-server
subset: v2
weight: 100
- route:
- destination:
host: api-server
subset: v1
weight: 90
- destination:
host: api-server
subset: v2
weight: 10
Так я могу делать canary deployments — новая версия идет только на 10% трафика, потом постепенно увеличиваю.
2. StatefulSets для database
Раньше базу держали вне Kubernetes, но потом внедрили PostgreSQL в виде StatefulSet.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: postgres-headless
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:14
ports:
- containerPort: 5432
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql
volumeClaimTemplates:
- metadata:
name: postgres-storage
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 50Gi
3. DaemonSets для мониторинга
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
hostNetwork: true
hostPID: true
containers:
- name: node-exporter
image: prom/node-exporter:latest
ports:
- containerPort: 9100
Практические вызовы и решения
Проблема 1: Memory leak в одном из Pods
Обнаружили через metrics что память растет. Решение:
resources:
limits:
memory: "512Mi" # Если превышит, Pod будет убит и перезагружен
Котобороли с memory leak в коде через profiling.
Проблема 2: Network policies
Первый раз включили network policies и все сломалось потому что по умолчанию все блокируется.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-server-netpol
spec:
podSelector:
matchLabels:
app: api-server
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 3000
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 5432 # БД
- to:
- namespaceSelector: {}
ports:
- protocol: TCP
port: 53 # DNS
Проблема 3: Secrets management
Первый раз использовали обычные Secrets в etcd — не безопасно.
Позже внедрили HashiCorp Vault:
// В Node.js приложении
import vault from '@hashicorp/vault-api';
const client = new vault.client({ endpoint: process.env.VAULT_ADDR });
const secret = await client.kv.read('secret/api-server/db');
const dbPassword = secret.data.data.password;
Текущие best practices, которые использую
1. Resource requests/limits
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
2. Health checks
livenessProbe: # Перезагрузить если dead
readinessProbe: # Удалить из load balancer если не ready
startupProbe: # Дать времени на старт
3. Pod Disruption Budgets
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-server-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: api-server
Это гарантирует что при обновлении узлов как минимум 1 Pod будет живым.
Инструменты которые использую
- kubectl — базовый CLI
- Helm — управление charts/конфигурациями
- ArgoCD — GitOps для deployment
- Prometheus + Grafana — мониторинг
- ELK stack — логирование
- cert-manager — SSL certificates
Основные learnings
- Kubernetes не магия, нужно разбираться в networking, storage, security
- Начинать с простого (plain YAML), потом переходить на Helm
- Мониторинг и алерты нужно настраивать сразу
- Graceful shutdown критичен
- Resource limits должны быть всегда
K8s дает невероятную гибкость, но требует глубокого понимания. Но когда всё настроено правильно, это просто вау!