K8S部署 RustFS S3 对象存储实战指南

Max
Max
发布于 2026-09-18 / 2 阅读
0
0

K8S部署 RustFS S3 对象存储实战指南

在现代云原生环境中,构建轻量级、高性能的对象存储服务是许多应用场景的核心需求。RustFS 作为一个基于 Rust 编写的高性能 S3 兼容对象存储解决方案,因其资源占用低、性能优异而受到关注。本文记录在单节点 Kubernetes 环境中,使用 HostPath 持久化部署 RustFS,并通过 Gateway API + Envoy Gateway + MetalLB 将 S3 API 与 Web Console 暴露到集群外。整体方案适合实验、测试与个人环境,生产环境建议替换为更高可用的存储与部署架构。

1. 环境信息

组件 版本 / 说明
Kubernetes v1.34.6+rke2r3
MetalLB 已部署,用于为 LoadBalancer Service 分配外部 IP
Gateway API v1.4.1
Envoy Gateway v1.9.1
部署方式 非 Helm,单主机单节点
持久化 HostPath + 静态 PV/PVC
S3 Endpoint rustfs.me.com
Web Console Endpoint s3.me.com

最终访问方式:

  • S3 API:https://rustfs.me.com
  • Web Console:https://s3.me.com

MetalLB 会自动为 Envoy Gateway 创建的 LoadBalancer Service 分配外部地址,例如本文中的 10.0.10.100。在本地配置 hosts 后,即可通过域名访问。


2. 前置条件

开始前请确认以下组件已经可用:

  1. Kubernetes 集群正常运行;
  2. Gateway API CRD 已安装;
  3. Envoy Gateway 已安装,并存在 GatewayClass/eg;
  4. MetalLB 已配置地址池,可以为 LoadBalancer Service 分配 EXTERNAL-IP;
  5. 已在 rustfs 命名空间中创建 TLS Secret,例如 rustfs-tls。

检查 GatewayClass:

kubectl get gatewayclass eg

创建 TLS Secret 示例:

kubectl create secret tls rustfs-tls -n rustfs \
  --cert=/path/to/fullchain.pem \
  --key=/path/to/privkey.pem

注意:证书需要覆盖 rustfs.me.com 和 s3.me.com。如果是自签证书,浏览器或客户端访问时可能需要额外信任。


3. 部署 RustFS

创建 rustfs.yaml,内容如下。该文件包含 Namespace、PV、PVC、Deployment 与 Service。

apiVersion: v1
kind: Namespace
metadata:
  name: rustfs
---
# ========== PV: 数据目录 ==========
apiVersion: v1
kind: PersistentVolume
metadata:
  name: rustfs-data-pv
spec:
  capacity:
    storage: 500Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /r5/rustfs/data
    type: DirectoryOrCreate
---
# ========== PV: 日志目录 ==========
apiVersion: v1
kind: PersistentVolume
metadata:
  name: rustfs-logs-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  hostPath:
    path: /r5/rustfs/logs
    type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: rustfs-data
  namespace: rustfs
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Gi
  volumeName: rustfs-data-pv
  storageClassName: ""
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: rustfs-logs
  namespace: rustfs
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  volumeName: rustfs-logs-pv
  storageClassName: ""
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rustfs
  namespace: rustfs
  labels:
    app: rustfs
spec:
  replicas: 1
  strategy:
    type: Recreate            # hostPath + RWO,使用 Recreate 避免多 Pod 同时挂载
  selector:
    matchLabels:
      app: rustfs
  template:
    metadata:
      labels:
        app: rustfs
    spec:
      initContainers:
        - name: rustfs-perms
          image: alpine:3.20
          command: ["sh", "-c", "chown -R 10001:10001 /data /logs"]
          securityContext:
            runAsUser: 0
          volumeMounts:
            - name: data
              mountPath: /data
            - name: logs
              mountPath: /logs

      containers:
        - name: rustfs
          image: rustfs/rustfs:latest
          imagePullPolicy: IfNotPresent
          ports:
            - name: api
              containerPort: 9000
            - name: console
              containerPort: 9001
          env:
            - name: RUSTFS_ADDRESS
              value: ":9000"
            - name: RUSTFS_CONSOLE_ADDRESS
              value: ":9001"
            - name: RUSTFS_CONSOLE_ENABLE
              value: "true"
            - name: RUSTFS_OBS_LOGGER_LEVEL
              value: "error"
            - name: RUSTFS_OBS_LOG_DIRECTORY
              value: "/var/log/rustfs/"
            - name: RUSTFS_SERVER_URL
              # 如果客户端通过 HTTPS 访问,建议改为 https://rustfs.me.com
              value: "http://rustfs.me.com"
          volumeMounts:
            - name: data
              mountPath: /data
            - name: logs
              mountPath: /var/log/rustfs/
          securityContext:
            runAsUser: 10001
            runAsGroup: 10001
          readinessProbe:
            tcpSocket:
              port: 9000
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            tcpSocket:
              port: 9000
            initialDelaySeconds: 30
            periodSeconds: 20
          resources:
            requests:
              cpu: "100m"
              memory: "256Mi"
            limits:
              cpu: "2"
              memory: "2Gi"

      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: rustfs-data
        - name: logs
          persistentVolumeClaim:
            claimName: rustfs-logs
---
apiVersion: v1
kind: Service
metadata:
  name: rustfs
  namespace: rustfs
spec:
  type: ClusterIP
  selector:
    app: rustfs
  ports:
    - name: api
      port: 9000
      targetPort: 9000
    - name: console
      port: 9001
      targetPort: 9001

应用部署:

kubectl apply -f rustfs.yaml

检查 Pod 状态:

kubectl get pods -n rustfs

预期输出类似:

NAME                      READY   STATUS    RESTARTS   AGE
rustfs-666cf84994-9z69k   1/1     Running   0          22h

4. 配置 Gateway API

创建 rustfs-gateway.yaml,通过 Gateway API 将 RustFS 的 S3 API 与 Web Console 暴露出去。

注意:原示例中有一个空的 gpu listener,缺少 protocol、port 等必填字段,会导致 Gateway 不合法。本文已移除该 listener,只保留实际使用的 s3 与 console。

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: rustfs-gateway
  namespace: rustfs
spec:
  gatewayClassName: eg
  listeners:
    - name: s3
      protocol: HTTPS
      port: 443
      hostname: "rustfs.me.com"
      tls:
        mode: Terminate
        certificateRefs:
          - name: rustfs-tls

    - name: console
      protocol: HTTPS
      port: 443
      hostname: "s3.me.com"
      tls:
        mode: Terminate
        certificateRefs:
          - name: rustfs-tls
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: rustfs-route
  namespace: rustfs
spec:
  parentRefs:
    - name: rustfs-gateway
      sectionName: s3
  hostnames:
    - "rustfs.me.com"
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: rustfs
          port: 9000
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: rustfs-console
  namespace: rustfs
spec:
  parentRefs:
    - name: rustfs-gateway
      sectionName: console
  hostnames:
    - "s3.me.com"
  rules:
    - backendRefs:
        - name: rustfs
          port: 9001

应用 Gateway 配置:

kubectl apply -f rustfs-gateway.yaml

5. 验证部署

查看 Gateway:

kubectl get gateway -n rustfs

预期输出:

NAME             CLASS   ADDRESS      PROGRAMMED   AGE
rustfs-gateway   eg      10.0.10.100   True         157m

查看 HTTPRoute:

kubectl get httproute -n rustfs

预期输出:

NAME              HOSTNAMES               AGE
rustfs-console    ["s3.me.com"]           28m
rustfs-route      ["rustfs.me.com"]       156m

此时 MetalLB 已为 Envoy Gateway 分配外部地址,例如 10.0.10.100。

在本地配置 hosts:

10.0.10.100 rustfs.me.com s3.me.com

Linux / macOS:

sudo tee -a /etc/hosts <<'EOF'
10.0.10.100 rustfs.me.com s3.me.com
EOF

Windows 编辑:

C:\Windows\System32\drivers\etc\hosts

然后访问:

  • Web Console:https://s3.me.com
  • S3 API:https://rustfs.me.com

也可以用 curl 检查:

curl -k -I https://s3.me.com
curl -k -I https://rustfs.me.com

如果使用 AWS CLI,可以测试 S3 Endpoint:

aws --endpoint-url https://rustfs.me.com s3 ls

6. 注意事项与踩坑记录

6.1 Gateway listener 必须完整

Gateway API 中每个 listener 都必须包含 name、protocol、port。如果存在空的 listener,例如只有 name: gpu,会导致 Gateway 创建失败或状态异常。

6.2 TLS Secret 必须存在且域名匹配

certificateRefs 引用的 rustfs-tls 必须位于同一个 Namespace,并且证书 SAN 需要覆盖:

  • rustfs.me.com
  • s3.me.com

否则 Gateway listener 可能无法正常提供服务。

6.3 MetalLB 地址分配

如果 kubectl get gateway -n rustfs 的 ADDRESS 为空,可以检查 Envoy Gateway 创建的 LoadBalancer Service:

kubectl get svc -n envoy-gateway-system | grep rustfs

确认 MetalLB 已正确配置地址池和 L2Advertisement。

6.4 HostPath 仅适合单节点实验

本文使用 HostPath + RWO PV,并设置 Deployment 策略为 Recreate。该方式只适合单节点、测试或个人环境。生产环境建议:

  • 使用分布式存储或云盘;
  • 部署多副本 RustFS;
  • 使用固定镜像版本,而不是 latest;
  • 配置备份、监控、告警;
  • 使用 cert-manager 等工具管理证书。

7. 总结

本文完整记录了在单节点 Kubernetes 上部署 RustFS,并通过 Gateway API、Envoy Gateway 与 MetalLB 暴露 S3 API 和 Web Console 的过程。

核心链路如下:

外部客户端
  -> https://rustfs.me.com / https://s3.me.com
  -> MetalLB 分配的 Gateway 地址
  -> Envoy Gateway HTTPS listener
  -> HTTPRoute
  -> rustfs Service
  -> rustfs Pod: 9000 / 9001

该方案配置简单、结构清晰,适合快速验证 RustFS 与 Gateway API 的集成。如果需要用于生产,建议进一步优化存储、副本、证书管理与高可用架构。


评论