概要
Rustで書かれたHTTP APIをコンテナ化し、Kubernetesクラスタへデプロイするまでの実践手順を解説します。マルチステージビルドによる最小イメージの作り方、非特権ユーザでの実行、水平オートスケール設定までカバーします。
Rustプロジェクトの準備
以下のディレクトリ構成で新規プロジェクトを作成します。
.
├── Cargo.toml
├── src
│ └── main.rs
├── Dockerfile
└── k8s
├── deployment.yaml
└── service.yaml
Cargo.toml(抜粋)
[package]
name = "rust-api"
version = "0.1.0"
edition = "2021"
[dependencies]
tokio = { version = "1", features = ["full"] }
axum = "0.7"
serde = { version = "1.0", features = ["derive"] }
anyhow = "1.0"
最小構成のDockerfile
ランタイムに不要なビルドツールを含まない、distrolessベースのマルチステージビルドを採用します。
# ---------- ビルドステージ ----------
FROM rust:1.76-slim AS builder
WORKDIR /app
COPY Cargo.toml Cargo.lock ./
RUN mkdir src && echo "fn main(){}" > src/main.rs \
&& cargo build --release \
&& rm -rf src
# 依存キャッシュを活かして再ビルド
COPY src ./src
RUN touch src/main.rs \
&& cargo build --release
# ---------- ランタイムステージ ----------
FROM gcr.io/distroless/cc-debian12
# 非ルートユーザを追加
COPY --from=builder /etc/passwd /etc/passwd
USER 65534:65534
COPY --from=builder /app/target/release/rust-api /usr/local/bin/app
EXPOSE 8080
ENTRYPOINT ["/usr/local/bin/app"]
イメージサイズは約20 MBにまで削減されます。
コンテナレジストリへプッシュ
docker build -t ghcr.io/your-org/rust-api:1.0.0 .
docker push ghcr.io/your-org/rust-api:1.0.0
Kubernetesマニフェスト
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: rust-api
spec:
replicas: 2
selector:
matchLabels:
app: rust-api
template:
metadata:
labels:
app: rust-api
spec:
securityContext:
runAsNonRoot: true
runAsUser: 65534
fsGroup: 65534
containers:
- name: app
image: ghcr.io/your-org/rust-api:1.0.0
ports:
- containerPort: 8080
env:
- name: RUST_LOG
value: "info"
resources:
requests:
cpu: 50m
memory: 32Mi
limits:
cpu: 200m
memory: 128Mi
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 3
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
Serviceベースの水平オートスケーラー
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: rust-api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: rust-api
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Service & Ingress
---
apiVersion: v1
kind: Service
metadata:
name: rust-api-svc
spec:
selector:
app: rust-api
ports:
- port: 80
targetPort: 8080
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rust-api-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: rust-api-svc
port:
number: 80
CI/CD(GitHub Actions)例
name: build-and-deploy
on:
push:
tags: [ 'v*.*.*' ]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/your-org/rust-api:${{ github.ref_name }}
deploy:
needs: docker
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set image tag in manifest
run: |
sed -i "s|:latest|:${{ github.ref_name }}|" k8s/deployment.yaml
- name: Deploy to cluster
uses: azure/k8s-deploy@v4
with:
manifests: |
k8s/deployment.yaml
k8s/service.yaml
k8s/hpa.yaml
kubeconfig: ${{ secrets.KUBECONFIG }}
トラブルシューティングTips
- Out-of-memory:メモリリークを疑う場合は
kubectl top podで使用量を監視し、limits.memoryを段階的に増やす。 - 起動遅延:
scratchイメージだと/etc/ssl/certsが欠落しHTTPS通信が失敗する場合がある。必要に応じてca-certificates.crtをコピーする。 - 非特権ポート:1024番以下を使う場合は
securityContext.capabilitiesでNET_BIND_SERVICEを付与するか、8080番などに変更。
次のステップ
本番投入後はPrometheus+Grafanaでメトリクスを可視化し、ServiceMonitorを追加して自動的にスクラップ設定を行うと、Rustアプリのパフォーマンスを継続的に追跡できます。