Деплой JavaScript (Node.js) на Kubernetes: пошаговое руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: зачем деплоить 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. Деплой приложения в кластер

Теперь, когда все манифесты готов

Блоги

Рекомендаций по книгам