Деплой C++ на Kubernetes: базовое руководство на практике

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

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

Начать курс

Введение: Почему C++ и Kubernetes — это рабочая комбинация

Многие разработчики ошибочно полагают, что Kubernetes (K8s) — это экосистема исключительно для интерпретируемых языков вроде Python, JavaScript или Go. На самом деле, деплой C++ на Kubernetes — это не только возможная, но и крайне эффективная практика для высоконагруженных систем, где критичны производительность, низкое потребление памяти и предсказуемое время отклика. C++ отлично подходит для создания backend-сервисов, обработчиков данных, игровых серверов и сетевых приложений, а Kubernetes предоставляет удобную платформу для их оркестрации, масштабирования и управления.

В этом практическом руководстве мы шаг за шагом разберем, как собрать C++ приложение в Docker-образ, написать корректный манифест для Kubernetes и развернуть его в кластере. Вы увидите, что процесс почти не отличается от деплоя приложений на других языках, если правильно настроить сборку.

1. Подготовка C++ приложения и написание Dockerfile

Для начала нам нужно простое, но рабочее C++ приложение. Пусть это будет HTTP-сервер, который слушает порт и возвращает "Hello from C++ on K8s!". В реальных проектах это может быть REST API на базе Crow, Pistache или Drogon.

Пример файла main.cpp:

#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

int main() {
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in address;
    int opt = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(8080);
    bind(server_fd, (struct sockaddr *)&address, sizeof(address));
    listen(server_fd, 3);

    std::cout << "Server started on port 8080" << std::endl;

    while (true) {
        int new_socket = accept(server_fd, nullptr, nullptr);
        const char *response = "HTTP/1.1 200 OK\nContent-Type: text/plain\n\nHello from C++ on K8s!\n";
        send(new_socket, response, strlen(response), 0);
        close(new_socket);
    }
    return 0;
}

Теперь напишем Dockerfile. Ключевой момент — использовать многостадийную сборку (multi-stage build). Это позволяет держать финальный образ минимальным и безопасным.

# Стадия сборки
FROM gcc:latest AS builder
WORKDIR /app
COPY main.cpp .
RUN g++ -static -o server main.cpp

# Финальный образ (минимальный)
FROM alpine:latest
WORKDIR /app
# Копируем только скомпилированный бинарник
COPY --from=builder /app/server .
EXPOSE 8080
CMD ["./server"]

Собираем образ и пушим в реестр (например, Docker Hub):

docker build -t yourusername/cpp-server:latest .
docker push yourusername/cpp-server:latest

2. Написание манифестов для Kubernetes

Для деплоя C++ приложения в Kubernetes нам понадобятся как минимум два объекта: Deployment (для управления Pod'ами) и Service (для обеспечения доступа к приложению).

Манифест Deployment (deployment.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cpp-server-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cpp-server
  template:
    metadata:
      labels:
        app: cpp-server
    spec:
      containers:
      - name: cpp-server
        image: yourusername/cpp-server:latest
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10

Важные моменты:

  • replicas: 2 — запускаем 2 экземпляра для отказоустойчивости.
  • resources — указываем лимиты памяти и CPU. C++ приложения обычно потребляют меньше ресурсов, чем аналоги на Python, но лимиты защищают кластер.
  • livenessProbe — проверка, что приложение живо. Если C++ процесс упадет, Kubernetes перезапустит Pod.

Манифест Service (service.yaml)

apiVersion: v1
kind: Service
metadata:
  name: cpp-server-service
spec:
  selector:
    app: cpp-server
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: LoadBalancer

Сервис перенаправляет трафик с порта 80 на порт 8080 контейнера. Тип LoadBalancer даст внешний IP (если кластер поддерживает это, например, в облаке). Для локального тестирования (minikube) можно использовать NodePort.

3. Деплой приложения в кластер

Убедитесь, что у вас настроен kubectl и есть доступ к кластеру. Выполните команды:

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

Проверим статус:

kubectl get pods
kubectl get services

Вы должны увидеть два работающих Pod'а и сервис с внешним IP (или NodePort). Чтобы протестировать приложение, выполните:

# Если есть внешний IP
curl http://<EXTERNAL-IP>

# Если используете NodePort (порт 30080 например)
curl http://localhost:30080

Ответ должен быть: Hello from C++ on K8s!

4. Масштабирование и обновление

Одно из главных преимуществ Kubernetes — простое масштабирование. Чтобы увеличить количество реплик C++ сервера, выполните:

kubectl scale deployment cpp-server-deployment --replicas=5

Kubernetes автоматически запустит новые Pod'ы. Благодаря статической компиляции и малому размеру образа, C++ приложения стартуют за миллисекунды, что идеально для

Блоги

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