Введение: почему TypeScript и Kubernetes — идеальная пара
Современная веб-разработка немыслима без двух вещей: статической типизации и масштабируемой инфраструктуры. TypeScript даёт надёжность кода на этапе компиляции, а Kubernetes (K8s) — автоматическое управление контейнерами, балансировку нагрузки и self-healing. В этом руководстве мы пройдём полный путь от простого TypeScript-приложения до его запуска в кластере Kubernetes. Вы узнаете, как упаковать код в Docker-образ, написать манифесты и развернуть production-ready сервис.
Шаг 1: Подготовка TypeScript-приложения для контейнеризации
Прежде чем думать о Kubernetes, нужно убедиться, что ваше приложение готово к запуску в контейнере. Создадим простое Express-приложение на TypeScript. Убедитесь, что в корне проекта есть package.json, tsconfig.json и точка входа src/index.ts.
// src/index.ts
import express, { Request, Response } from 'express';
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/health', (_req: Request, res: Response) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
app.get('/', (_req: Request, res: Response) => {
res.send('Hello from TypeScript on Kubernetes!');
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Важный нюанс: в production мы не используем ts-node. Поэтому в package.json добавьте скрипт сборки:
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}
После выполнения npm run build в папке dist появится скомпилированный JavaScript. Именно эту папку мы будем копировать в Docker-образ.
Шаг 2: Создание Docker-образа с минимальным размером
Для production-деплоя критически важен размер образа. Используем multi-stage сборку: сначала компилируем TypeScript в контейнере с полным SDK, затем копируем результат в лёгкий образ на базе node:18-alpine.
# Dockerfile
# Stage 1: Build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY tsconfig.json ./
COPY src/ ./src/
RUN npm run build
# Stage 2: Production
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"]
Соберите образ и проверьте локально:
docker build -t my-ts-app:latest .
docker run -p 3000:3000 my-ts-app:latest
Откройте http://localhost:3000 — вы должны увидеть приветствие.
Шаг 3: Манифесты Kubernetes — Deployment и Service
Теперь перенесём наш образ в кластер. Для этого понадобятся два базовых манифеста: Deployment (управляет репликами и обновлениями) и Service (обеспечивает сетевой доступ).
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ts-app-deployment
spec:
replicas: 2
selector:
matchLabels:
app: ts-app
template:
metadata:
labels:
app: ts-app
spec:
containers:
- name: ts-app
image: my-ts-app:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000
env:
- name: PORT
value: "3000"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 3
periodSeconds: 5
service.yaml
apiVersion: v1
kind: Service
metadata:
name: ts-app-service
spec:
selector:
app: ts-app
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: ClusterIP
Примените манифесты в кластер (например, Minikube или облачный K8s):
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
Проверьте, что поды запущены:
kubectl get pods
kubectl get svc
Шаг 4: Ingress — открываем доступ извне (опционально)
Если вы используете облачный кластер или Minikube с включённым Ingress-контроллером, можно настроить Ingress для маршрутизации трафика по доменному имени.
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ts-app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: ts-app.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ts-app-service
port:
number: 80
Примените Ingress и добавьте запись в /etc/hosts (для локального теста):
kubectl apply -f ingress.yaml
# Добавьте в /etc/hosts: 127.0.0.1 ts-app.local
Теперь приложение доступно по адресу http://ts-app.local. Kubernetes автоматически балансирует нагрузку между двумя репликами и перезапускает под при падении.
Заключение: что дальше?
Мы разобрали базовый пайплайн деплоя TypeScript-приложения в Kubernetes: от написания кода до публикации через Ingress. Этот подход масштабируется на микросервисную архитектуру, CI/CD и автоматическое масштабирование (HPA).
Рекомендуем изучить дополнительные темы:
- ConfigMap и Secrets для управления конфигурацией
- PersistentVolume для работы с базой данных
- Helm-чарты для шаблонизации манифестов
- Мониторинг через Prometheus и Grafana
Помните: Kubernetes — мощный, но сложный инструмент. Начните с малого, автоматизируйте сборку образов через GitHub Actions и постепенно внедряйте продви