Deploying Rust on Kubernetes: A Basic Guide
Modern cloud development requires applications to have high performance, security, and efficient resource usage. Rust, with its ownership system and zero-cost abstractions, is ideally suited for creating microservices running in container orchestrators. Kubernetes, in turn, provides a powerful toolkit for managing containerized applications. In this guide, we will walk through step by step how to prepare a Rust application for deployment to Kubernetes, create a Docker image, and deploy it in a cluster.
1. Preparing the Rust Application
Before deploying an application to Kubernetes, it must be containerized. For demonstration, we will create a simple HTTP application based on the actix-web framework, which will respond to requests and return basic system information.
Let's create a new project:
cargo new rust-k8s-appcd rust-k8s-appAdd dependencies to Cargo.toml:
[dependencies]actix-web = "4"serde = { version = "1.0", features = ["derive"] }tokio = { version = "1", features = ["full"] }Let's write a simple application in 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}Let's verify that the application compiles and runs locally:
cargo build --releasecargo run --releaseAfter starting, open your browser and navigate to http://localhost:8080/health — you should see a JSON response.
2. Creating a Docker Image for the Rust Application
To minimize the image size and speed up the build, we will use a multi-stage build. The first stage is compiling the application, the second is creating a minimal image based on scratch or alpine.
Create a Dockerfile in the project root:
# Stage 1: BuildFROM rust:1.75-slim-buster AS builder
WORKDIR /appCOPY Cargo.toml Cargo.lock ./RUN mkdir src && echo "fn main() {}" > src/main.rsRUN cargo build --release 2>/dev/null || true
COPY src/ ./src/RUN cargo build --release
# Stage 2: Minimal imageFROM 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 8080CMD ["rust-k8s-app"]Build the image:
docker build -t rust-k8s-app:latest .Verify that the image works:
docker run -p 8080:8080 rust-k8s-app:latestThen push the image to Docker Hub or another container registry, replacing username with your username:
docker tag rust-k8s-app:latest username/rust-k8s-app:latestdocker push username/rust-k8s-app:latest