Развертывание в Kubernetes
Описание процесса деплоя документации
Развертывание в Kubernetes (K8s)
Платформа Манитон использует Kubernetes для управления всеми компонентами. Мы придерживаемся подхода GitOps и Infrastructure as Code (IaC).
Модель окружений
-
Local Hybrid (bun dev):
- Инфраструктура (Kafka, DB, Besu) в локальном K8s (Docker Desktop/Minikube).
- Микросервисы запущены локально через
turbo dev. - Проброс портов через
kubectl port-forward.
-
Local K8s Apps (bun dev --k8s-apps):
- Инфраструктура и микросервисы работают в локальном K8s.
- Nginx Ingress используется как единый gateway для фронтенда.
- Проброс портов через
kubectl port-forward.
-
Development (dev):
- Общий кластер для интеграционных тестов.
- Деплой всех компонентов в namespace
maniton.
-
Production (prod):
- Отказоустойчивый кластер (High Availability).
- Изоляция контуров, усиленная безопасность (Network Policies, RBAC).
Инструментарий
- Bun: Рантайм для управляющих скриптов.
- kubectl: Основной CLI для работы с кластером.
- Kustomize: Управление конфигурациями (встроено в
kubectl -k). - Make: Автоматизация команд деплоя (
infra/k8s/Makefile).
Команды управления
Мы используем обертку в виде dev.ts для упрощения ежедневных операций:
# Развернуть всё (инфра + локальные сервисы)
bun dev
# Только деплой манифестов в K8s
bun dev k8s deploy --env dev
# Проверка статуса
bun dev status
# Просмотр логов конкретного сервиса
bun dev logs --service authDockerfile: Микросервисы
Все микросервисы (NestJS) собираются по единому шаблону (multi-stage):
FROM oven/bun:1.2-slim AS base
WORKDIR /app
FROM base AS builder
COPY . .
RUN bun install
RUN bun run build
FROM base AS runner
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json .
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["bun", "dist/main.js"]Структура манифестов (infra/k8s)
base/: Базовые ресурсы (Namespace, Quotas).components/: Переиспользуемые блоки (PostgreSQL, Kafka, Besu, Monitoring).environments/: Специфичные настройки дляdev,dev-fullиproduction.
Развертывание сервисов
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-service
namespace: maniton
spec:
replicas: 2
selector:
matchLabels:
app: auth-service
template:
metadata:
labels:
app: auth-service
spec:
containers:
- name: auth-service
image: ghcr.io/maniton/auth-service:latest
ports:
- containerPort: 3001
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: auth-service-secrets
key: database-url
- name: KAFKA_BROKERS
value: 'kafka:9092'
resources:
requests:
memory: '512Mi'
cpu: '500m'
limits:
memory: '1Gi'
cpu: '1000m'
livenessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 3001
initialDelaySeconds: 5
periodSeconds: 5Service
apiVersion: v1
kind: Service
metadata:
name: auth-service
namespace: maniton
spec:
selector:
app: auth-service
ports:
- port: 3001
targetPort: 3001
type: ClusterIPIngress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: auth-service-ingress
namespace: maniton
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: 'true'
spec:
rules:
- host: api.maniton.io
http:
paths:
- path: /auth-service
pathType: Prefix
backend:
service:
name: auth-service
port:
number: 3001ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: auth-service-config
namespace: maniton
data:
NODE_ENV: 'production'
LOG_LEVEL: 'info'
KAFKA_CLIENT_ID: 'auth-service'Secret
apiVersion: v1
kind: Secret
metadata:
name: auth-service-secrets
namespace: maniton
type: Opaque
stringData:
database-url: 'postgresql://user:pass@postgres:5432/auth_db'
jwt-secret: 'your-secret-here'Kustomize
kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: maniton
resources:
- ../../base/namespace.yaml
- ../../components/postgres/
- ../../components/kafka/
- ../../components/besu/
images:
- name: auth-service
newName: ghcr.io/maniton/auth-service
newTag: v1.2.0
replicas:
- name: auth-service
count: 2
configMapGenerator:
- name: auth-service-config
literals:
- NODE_ENV=production
- LOG_LEVEL=info
secretGenerator:
- name: auth-service-secrets
literals:
- DATABASE_URL=postgresql://user:pass@postgres:5432/auth_db
patches:
- path: deployment-patch.yaml
target:
kind: Deployment
name: auth-servicedeployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-service
spec:
template:
spec:
containers:
- name: auth-service
env:
- name: LOG_LEVEL
value: 'debug'Helm Charts
Chart Structure
maniton-platform/
├── Chart.yaml
├── values.yaml
├── values-dev.yaml
├── values-prod.yaml
├── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ └── hpa.yaml
└── charts/
├── postgres/
├── kafka/
└── besu/values.yaml
global:
environment: production
domain: maniton.io
image:
registry: ghcr.io/maniton
tag: latest
services:
auth:
enabled: true
replicas: 2
resources:
requests:
memory: 512Mi
cpu: 500m
limits:
memory: 1Gi
cpu: 1000m
ingress:
enabled: true
host: auth.maniton.io
cfa-core:
enabled: true
replicas: 2
resources:
requests:
memory: 1Gi
cpu: 1000m
limits:
memory: 2Gi
cpu: 2000m
ledger:
enabled: true
replicas: 2
resources:
requests:
memory: 1Gi
cpu: 1000m
limits:
memory: 2Gi
cpu: 2000m
postgres:
enabled: true
primary:
persistence:
size: 200Gi
readReplicas:
replicas: 1
kafka:
enabled: true
replicas: 3
persistence:
size: 100Gi
besu:
enabled: true
replicas: 4
consensus: qbft
blockPeriod: 2000
monitoring:
enabled: true
prometheus:
retention: 15d
grafana:
enabled: true
loki:
retention: 30dAuto-scaling
Horizontal Pod Autoscaler (HPA)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: auth-service-hpa
namespace: maniton
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: auth-service
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80Rolling Updates
Стратегия обновления
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0Команды
# Rolling update
kubectl rollout restart deployment auth-service -n maniton
# Проверка статуса
kubectl rollout status deployment auth-service -n maniton
# Откат
kubectl rollout undo deployment auth-service -n maniton
# История
kubectl rollout history deployment auth-service -n manitonCanary Deployment
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: auth-service
namespace: maniton
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: auth-service
serviceRef:
name: auth-service
port: 80
analysis:
interval: 1m
threshold: 5
maxWeight: 50
trafficRouting:
nginx:
stableService: auth-service-stable
canaryService: auth-service-canaryTroubleshooting
Проблема: Pod не стартует
# Проверка логов
kubectl logs -n maniton auth-service-xxx
# Проверка событий
kubectl describe pod -n maniton auth-service-xxx
# Проверка ресурсов
kubectl top nodes
kubectl top pods -n manitonПроблема: Service недоступен
# Проверка endpoints
kubectl get endpoints -n maniton auth-service
# Проверка DNS
kubectl run test --image=busybox --rm -it -- nslookup auth-service.maniton.svc.cluster.local
# Проверка подключения
kubectl run test --image=busybox --rm -it -- wget -O- http://auth-service:3001/healthПроблема: Ingress не работает
# Проверка ingress controller
kubectl get pods -n ingress-nginx
# Проверка ingress
kubectl get ingress -n maniton
# Проверка DNS
dig api.maniton.io
# Проверка сертификатов
kubectl get secret -n maniton auth-service-tls