You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自建Kubernetes集群部署Novu:Helm Chart查询与部署方案咨询

Novu 自建K8s集群部署指南(适配v1.26裸金属环境)

官方Helm Chart状态

目前Novu官方尚未发布正式维护的Helm Chart,社区存在部分第三方贡献的Chart,但稳定性和适配性无法保障,建议基于官方docker-compose.yml手动拆解编写K8s资源清单,或自行封装专属Helm Chart。

手动编写清单的组件拆分结构

Novu组件按状态特性分为两类,拆分逻辑如下:

有状态组件(采用StatefulSet + PVC)

  • MongoDB:存储核心通知数据,需持久化,UAT用local-path存储类,生产切换为NFS存储类
  • Redis:处理异步任务队列与缓存,需持久化避免任务丢失
  • PostgreSQL(可选):启用事件归档等功能时部署
  • InfluxDB(可选):用于监控指标存储

无状态组件(采用Deployment)

  • Novu API:核心业务接口服务
  • Novu Web UI:前端管理界面
  • Novu Worker:异步任务处理(通知发送、重试等)
  • Novu Notification Center:用户端通知展示服务
  • Novu Subscriber:事件订阅服务

Novu环境变量安全处理

  • 敏感变量(如数据库密码、JWT_SECRET、第三方服务API密钥等):存入K8s Secret,通过envFrom或valueFrom注入Pod
  • 非敏感配置(如服务地址、端口、环境标识、日志级别等):存入K8s ConfigMap,同样通过envFrom注入
  • 严禁在Deployment/StatefulSet中硬编码敏感信息,所有敏感变量必须通过Secret管理

组件独立扩缩容最佳实践

  • API/Web UI:基于CPU/内存使用率配置HPA(Horizontal Pod Autoscaler),根据请求量自动扩缩;生产环境建议设置最小2副本、最大10副本
  • Worker组件:基于Redis队列长度配置自定义HPA指标(需部署Prometheus+Redis Exporter采集队列 metrics),队列积压时自动扩容,空闲时缩容至最小2副本
  • 有状态组件:
    • MongoDB:单实例场景直接调整StatefulSet的replicas数扩副本;生产环境建议部署3副本StatefulSet集群,通过MongoDB自身副本机制保障高可用
    • Redis:单实例扩副本需配置哨兵或集群模式避免单点故障;生产用Redis Cluster时按节点数扩容
  • 资源配额约束:为Novu所在Namespace配置ResourceQuota,限制总CPU/内存使用量;同时为每个Pod设置resources.requests和resources.limits,防止资源抢占

基础K8s资源清单示例

1. Namespace创建

apiVersion: v1
kind: Namespace
metadata:
  name: novu

2. Secret(敏感配置)

apiVersion: v1
kind: Secret
metadata:
  name: novu-secrets
  namespace: novu
type: Opaque
stringData:
  MONGO_PASSWORD: "your-mongo-password"
  REDIS_PASSWORD: "your-redis-password"
  JWT_SECRET: "your-jwt-secret-32chars-min"
  SMTP_PASSWORD: "your-smtp-password"

3. ConfigMap(非敏感配置)

apiVersion: v1
kind: ConfigMap
metadata:
  name: novu-config
  namespace: novu
data:
  NODE_ENV: "production"
  MONGO_URI: "mongodb://novu-mongo-0.novu-mongo.novu.svc.cluster.local:27017/novu?authSource=admin"
  REDIS_HOST: "novu-redis-0.novu-redis.novu.svc.cluster.local"
  REDIS_PORT: "6379"
  API_PORT: "3000"
  WEB_PORT: "4200"

4. PVC(MongoDB示例,生产用NFS存储类)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: novu-mongo-pvc
  namespace: novu
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: "nfs-storage" # UAT替换为local-path
  resources:
    requests:
      storage: 10Gi

5. StatefulSet(MongoDB)

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: novu-mongo
  namespace: novu
spec:
  serviceName: "novu-mongo"
  replicas: 1
  selector:
    matchLabels:
      app: novu-mongo
  template:
    metadata:
      labels:
        app: novu-mongo
    spec:
      containers:
      - name: mongo
        image: mongo:6.0
        ports:
        - containerPort: 27017
        env:
        - name: MONGO_INITDB_ROOT_USERNAME
          value: "novu"
        - name: MONGO_INITDB_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: novu-secrets
              key: MONGO_PASSWORD
        volumeMounts:
        - name: mongo-data
          mountPath: /data/db
  volumeClaimTemplates:
  - metadata:
      name: mongo-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "nfs-storage" # UAT替换为local-path
      resources:
        requests:
          storage: 10Gi

6. Deployment(Novu API)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: novu-api
  namespace: novu
spec:
  replicas: 2
  selector:
    matchLabels:
      app: novu-api
  template:
    metadata:
      labels:
        app: novu-api
    spec:
      containers:
      - name: novu-api
        image: novuhq/api:0.22.0
        ports:
        - containerPort: 3000
        envFrom:
        - secretRef:
            name: novu-secrets
        - configMapRef:
            name: novu-config
        resources:
          requests:
            cpu: "100m"
            memory: "256Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"

7. Service(API示例)

apiVersion: v1
kind: Service
metadata:
  name: novu-api
  namespace: novu
spec:
  selector:
    app: novu-api
  ports:
  - port: 3000
    targetPort: 3000
  type: ClusterIP

8. Ingress(Web UI + API)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: novu-ingress
  namespace: novu
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - novu.your-domain.com
    secretName: novu-tls-secret
  rules:
  - host: novu.your-domain.com
    http:
      paths:
      - path: /api/(.*)
        pathType: Prefix
        backend:
          service:
            name: novu-api
            port:
              number: 3000
      - path: /(.*)
        pathType: Prefix
        backend:
          service:
            name: novu-web
            port:
              number: 4200

9. ResourceQuota

apiVersion: v1
kind: ResourceQuota
metadata:
  name: novu-quota
  namespace: novu
spec:
  hard:
    requests.cpu: "2"
    requests.memory: "4Gi"
    limits.cpu: "4"
    limits.memory: "8Gi"
    pods: "20"

内容的提问来源于stack exchange,提问作者Darun Omar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 18:07:34