Введение: зачем деплоить JavaScript на Kubernetes?
Современная веб-разработка на JavaScript (особенно на Node.js) всё чаще требует не просто запуска приложения на одном сервере, а организации отказоустойчивой, масштабируемой и легко управляемой инфраструктуры. Kubernetes (K8s) — это стандарт де-факто для оркестрации контейнеров. Если вы пишете на Node.js и хотите, чтобы ваше приложение переживало пиковые нагрузки, автоматически восстанавливалось после сбоев и легко обновлялось без даунтайма — вам нужен Kubernetes.
В этом руководстве мы разберём базовый процесс деплоя простого Node.js приложения в кластер Kubernetes. Вы узнаете, как подготовить Docker-образ, написать необходимые YAML-манифесты (Deployment, Service, Ingress) и запустить приложение. Статья ориентирована на разработчиков, которые уже знакомы с основами Node.js и Docker, но только начинают свой путь в мир Kubernetes.
1. Подготовка Node.js приложения и Docker-образа
Первым делом нам нужно приложение, которое мы будем деплоить. Создадим простой HTTP-сервер на Express, который отвечает на GET-запросы.
1.1. Создание простого сервера (app.js)
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Hello from Node.js on Kubernetes!');
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Файл package.json (зависимости):
{
"name": "k8s-node-app",
"version": "1.0.0",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "^4.18.2"
}
}
1.2. Dockerfile для Node.js
Чтобы Kubernetes мог запустить наше приложение, его нужно упаковать в контейнер. Используем официальный образ Node.js (версию 18 LTS).
# Используем официальный образ Node.js
FROM node:18-alpine
# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /usr/src/app
# Копируем package.json и package-lock.json
COPY package*.json ./
# Устанавливаем зависимости
RUN npm install --production
# Копируем исходный код приложения
COPY . .
# Указываем порт, который будет слушать приложение
EXPOSE 3000
# Команда для запуска приложения
CMD ["node", "app.js"]
Сборка образа и отправка в реестр:
# Собираем образ
docker build -t my-registry/node-app:v1 .
# Пушим в Docker Hub или ваш приватный реестр
docker push my-registry/node-app:v1
Замените my-registry на имя вашего реестра (например, docker.io/username/node-app).
2. Создание YAML манифестов для Kubernetes
Kubernetes использует декларативный подход: мы описываем желаемое состояние системы в YAML-файлах, а K8s сам приводит всё к этому состоянию. Нам понадобятся три основных ресурса: Deployment, Service и Ingress.
2.1. Deployment (deployment.yaml)
Deployment отвечает за запуск и обновление подов (контейнеров). Он гарантирует, что нужное количество реплик всегда работает.
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-app-deployment
labels:
app: node-app
spec:
replicas: 3 # Количество реплик (копий) приложения
selector:
matchLabels:
app: node-app
template:
metadata:
labels:
app: node-app
spec:
containers:
- name: node-app
image: my-registry/node-app:v1
ports:
- containerPort: 3000
env:
- name: PORT
value: "3000"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
Ключевые моменты:
replicas: 3— запускаем 3 экземпляра приложения для отказоустойчивости.image— указываем образ, который мы загрузили ранее.resources— задаём лимиты и запросы по CPU и памяти (важно для эффективного планирования).
2.2. Service (service.yaml)
Service — это абстракция, которая обеспечивает стабильную точку доступа к подам. Поскольку поды могут создаваться и удаляться, их IP-адреса меняются. Service даёт нам постоянный IP и DNS-имя внутри кластера.
apiVersion: v1
kind: Service
metadata:
name: node-app-service
spec:
selector:
app: node-app # Должен совпадать с labels в Deployment
ports:
- protocol: TCP
port: 80 # Порт, по которому сервис доступен внутри кластера
targetPort: 3000 # Порт, на котором слушает приложение в контейнере
type: ClusterIP # Делает сервис доступным только внутри кластера
Для внешнего доступа мы будем использовать Ingress, а не Service типа LoadBalancer (это более гибкий подход).
2.3. Ingress (ingress.yaml)
Ingress — это "входные ворота" в ваш кластер. Он маршрутизирует HTTP/HTTPS трафик из интернета к вашему Service.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: node-app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx # Указываем, какой Ingress Controller используется (например, Nginx)
rules:
- host: your-domain.com # Ваш домен (или используйте тестовый)
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: node-app-service
port:
number: 80
Важно: Для работы Ingress в кластере должен быть установлен Ingress Controller (например, NGINX Ingress Controller). Если вы используете Minikube, его можно включить командой minikube addons enable ingress.
3. Деплой приложения в кластер
Теперь, когда все манифесты готов