apiVersion: v1 kind: Namespace metadata: name: cube-music --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: music-data namespace: cube-music spec: accessModes: - ReadWriteOnce resources: requests: # video / audio 大附件 + 初始 guitar 曲库(~? GB),50Gi 起步 storage: 50Gi # storageClassName 留空 → k3s 默认 local-path --- apiVersion: apps/v1 kind: Deployment metadata: name: music namespace: cube-music labels: app: music spec: replicas: 1 strategy: # PVC 是 RWO,rolling 上线时新旧 pod 抢 PVC 会卡住,直接 Recreate type: Recreate selector: matchLabels: app: music template: metadata: labels: app: music spec: imagePullSecrets: - name: registry-creds containers: - name: music image: registry.famzheng.me/mochi/music:latest imagePullPolicy: IfNotPresent ports: - containerPort: 8080 name: http env: - name: DB_PATH value: /data/app.db - name: BLOBS_DIR value: /data/blobs - name: CHORD_URL value: http://localhost:8001 - name: CHAT_GATEWAY value: http://3.135.65.204:8848/v1 - name: CHAT_MODEL value: gemma-4-31b-it - name: CHAT_TOKEN valueFrom: secretKeyRef: name: chat-creds key: token - name: TAVILY_TOKEN valueFrom: secretKeyRef: name: tavily-creds key: token readinessProbe: httpGet: path: /healthz port: http initialDelaySeconds: 1 periodSeconds: 5 livenessProbe: httpGet: path: /healthz port: http initialDelaySeconds: 5 periodSeconds: 15 resources: requests: cpu: 10m memory: 32Mi limits: cpu: 1000m memory: 512Mi volumeMounts: - name: data mountPath: /data - name: chord-fetcher image: registry.famzheng.me/mochi/music-chord:latest imagePullPolicy: IfNotPresent ports: - containerPort: 8001 name: chord env: - name: CHORD_OUT_DIR value: /data/chord-fetch readinessProbe: httpGet: path: /healthz port: chord initialDelaySeconds: 3 periodSeconds: 10 livenessProbe: httpGet: path: /healthz port: chord initialDelaySeconds: 30 periodSeconds: 30 resources: requests: cpu: 50m memory: 256Mi # chromium 内存峰值很容易飙到 ~600MB limits: cpu: 2000m memory: 1Gi volumeMounts: - name: data mountPath: /data volumes: - name: data persistentVolumeClaim: claimName: music-data --- apiVersion: v1 kind: Service metadata: name: music namespace: cube-music spec: selector: app: music ports: - name: http port: 80 targetPort: 8080 --- apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: bodylimit namespace: cube-music spec: buffering: # 单文件最大 1GiB(main.rs 里 SINGLE_FILE_BYTES),multipart 总和留 5GiB 余量 maxRequestBodyBytes: 5368709120 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: music namespace: cube-music annotations: traefik.ingress.kubernetes.io/router.middlewares: cube-music-bodylimit@kubernetescrd spec: ingressClassName: traefik rules: - host: music.famzheng.me http: paths: - path: / pathType: Prefix backend: service: name: music port: number: 80