Деплой реального приложения
Соберём всё изученное в один реальный стек: фронтенд, бэкенд и база данных в одном кластере.
Типичное приложение в Kubernetes — это несколько Deployment-ов и Service-ов, связанных по именам через DNS, плюс ConfigMap/Secret для настроек.
Развернём трёхзвенное приложение: frontend (отдаёт UI), backend (API), db (Postgres). Каждый компонент — свой Deployment и свой Service. Связи: frontend зовёт backend по имени, backend зовёт db по имени.
База данных: Secret + Deployment + Service
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
stringData: # stringData — без ручного base64
POSTGRES_PASSWORD: s3cr3t
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: db
spec:
replicas: 1
selector:
matchLabels: { app: db }
template:
metadata:
labels: { app: db }
spec:
containers:
- name: postgres
image: postgres:16
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef: { name: db-secret, key: POSTGRES_PASSWORD }
ports:
- containerPort: 5432
---
apiVersion: v1
kind: Service
metadata:
name: db
spec:
selector: { app: db }
ports:
- port: 5432
targetPort: 5432Несколько объектов в одном файле разделяют строкой ---. Service назван db — backend будет ходить по этому имени.
Бэкенд: Deployment + Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
spec:
replicas: 2
selector:
matchLabels: { app: backend }
template:
metadata:
labels: { app: backend }
spec:
containers:
- name: api
image: my-backend:1.0
env:
- name: DB_HOST
value: db # имя сервиса БД
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector: { app: backend }
ports:
- port: 8080
targetPort: 8080Бэкенд знает базу как db — DNS превратит это имя в адрес сервиса БД.
Фронтенд: Deployment + Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 2
selector:
matchLabels: { app: frontend }
template:
metadata:
labels: { app: frontend }
spec:
containers:
- name: web
image: my-frontend:1.0
env:
- name: API_URL
value: http://backend:8080
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
type: NodePort
selector: { app: frontend }
ports:
- port: 80
targetPort: 80Применяем всё
kubectl apply -f db.yaml
kubectl apply -f backend.yaml
kubectl apply -f frontend.yaml
kubectl get pods,servicesВывод:
pod/db-... 1/1 Running pod/backend-... 1/1 Running pod/backend-... 1/1 Running pod/frontend-... 1/1 Running pod/frontend-... 1/1 Running
Готово: фронтенд через backend ходит в API, тот через db — в базу. Всё связано именами, без единого жёсткого IP.
Итог
- Каждый компонент — отдельный Deployment + Service.
- Компоненты находят друг друга по именам сервисов через DNS.
- Секреты БД хранятся в Secret, объекты в файле разделяются
---.
Проверьте себя
1. Как backend в этом примере находит базу данных?
AПо жёстко прописанному IP пода
BПо имени сервиса db через DNS
CЧерез port-forward
DЧерез переменную из Ingress
2. Что разделяет несколько объектов в одном YAML-файле?
AЗапятая
BСтрока ---
CПустая строка
DТег <break>
3. Почему каждый компонент получает свой Service?
AЧтобы хранить логи
BЧтобы дать стабильное имя и балансировку для обращения других компонентов
CЭто обязательное требование для Deployment
DЧтобы зашифровать данные