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

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

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

Начать курс

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

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

1. Подготовка Rust-приложения

Прежде чем деплоить приложение в Kubernetes, его необходимо контейнеризировать. Для демонстрации создадим простое HTTP-приложение на базе фреймворка actix-web, которое будет отвечать на запросы и возвращать базовую информацию о системе.

Создадим новый проект:

cargo new rust-k8s-app
cd rust-k8s-app

Добавим зависимости в Cargo.toml:

[dependencies]
actix-web = "4"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

Напишем простое приложение в src/main.rs:

use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
use serde::Serialize;

#[derive(Serialize)]
struct HealthResponse {
    status: String,
    version: String,
}

#[get("/health")]
async fn health_check() -> impl Responder {
    HttpResponse::Ok().json(HealthResponse {
        status: "ok".to_string(),
        version: env!("CARGO_PKG_VERSION").to_string(),
    })
}

#[get("/")]
async fn index() -> impl Responder {
    HttpResponse::Ok().body("Rust on Kubernetes! 🚀")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let host = std::env::var("HOST").unwrap_or_else(|_| "0.0.0.0".to_string());
    let port: u16 = std::env::var("PORT")
        .unwrap_or_else(|_| "8080".to_string())
        .parse()
        .expect("PORT must be a number");

    println!("Starting server at {}:{}", host, port);

    HttpServer::new(|| {
        App::new()
            .service(health_check)
            .service(index)
    })
    .bind((host.as_str(), port))?
    .run()
    .await
}

Проверим, что приложение компилируется и запускается локально:

cargo build --release
cargo run --release

После запуска откройте браузер и перейдите по адресу http://localhost:8080/health — вы должны увидеть JSON с ответом.

2. Создание Docker-образа для Rust-приложения

Для минимизации размера образа и ускорения сборки будем использовать многоэтапную сборку (multi-stage build). Первый этап — компиляция приложения, второй — создание минимального образа на основе scratch или alpine.

Создайте файл Dockerfile в корне проекта:

# Этап 1: Сборка
FROM rust:1.75-slim-buster AS builder

WORKDIR /app
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo build --release 2>/dev/null || true

COPY src/ ./src/
RUN cargo build --release

# Этап 2: Минимальный образ
FROM debian:buster-slim

RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/rust-k8s-app /usr/local/bin/rust-k8s-app

EXPOSE 8080
CMD ["rust-k8s-app"]

Соберите образ:

docker build -t rust-k8s-app:latest .

Проверьте, что образ работает:

docker run -p 8080:8080 rust-k8s-app:latest

Затем отправьте образ в Docker Hub или другой реестр контейнеров, заменив username на ваше имя пользователя:

docker tag rust-k8s-app:latest username/rust-k8s-app:latest
docker push username/rust-k8s-app:latest

3. Написание манифестов Kubernetes

Для деплоя приложения в Kubernetes нам понадобятся два основных ресурса: Deployment (управление репликами и обновлениями) и Service (обеспечение доступа к подам).

Создайте файл deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rust-k8s-app
  labels:
    app: rust-k8s-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: rust-k8s-app
  template:
    metadata:
      labels:
        app: rust-k8s-app
    spec:
      containers:
      - name: rust-app
        image: username/rust-k8s-app:latest
        ports:
        - containerPort: 8080
        env:
        - name: PORT
          value: "8080"
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 3
          periodSeconds: 5

Теперь создайте файл service.yaml для доступа к приложению:

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

Примените манифесты к кластеру:

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

Проверьте статус подов и сервиса:

kubectl get pods
kubectl get svc rust-k8s-service

Если вы используете локальный кластер (например, Minikube или Kind), получите URL для доступа:

minikube service rust-k8s-service

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

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

Блоги

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