有状态应用dify部署至华为云kubernetes集群

1 概述

在kubernetes部署dify,yaml文件参考大佬文档:

https://github.com/Winson-030/dify-kubernetes

2 环境准备

2.1 购买SFS Turbo实例

在这里插入图片描述

2.2 购买华为云容器集群CCE实例

在这里插入图片描述

2.3 在k8s中创建storageclass对象

参数everest.io/share-access-to是VPC的ID。
参数everest.io/share-export-location是sfs turbo实例的共享路径:自定义子目录,sfs turbo实例的共享路径是在sfs实例的详细页查询,自定义子目录可以是任意路径。
参数everest.io/volume-id是sfs turbo实例的ID。
只需要修改以上三个参数。

在本文,storageclass的名称叫做sfsturbo-subpath-sc。

apiVersion: storage.k8s.io/v1
allowVolumeExpansion: true
kind: StorageClass
metadata:
  name: sfsturbo-subpath-sc
mountOptions:
- lock
parameters:
  csi.storage.k8s.io/csi-driver-name: sfsturbo.csi.everest.io
  csi.storage.k8s.io/fstype: nfs
  everest.io/archive-on-delete: "true"
  everest.io/share-access-to: xxxxxxxxxxxxxxxxxx   # VPC ID
  everest.io/share-expand-type: bandwidth
  everest.io/share-export-location: xxxxx.sfsturbo.internal:/mydir   # sfs turbo实例的共享路径:自定义子目录
  everest.io/share-source: sfs-turbo
  everest.io/share-volume-type: STANDARD
  everest.io/volume-as: subpath
  everest.io/volume-id: xxxxxxxxxxxxx   # sfs turbo实例的ID
provisioner: everest-csi-provisioner
reclaimPolicy: Retain
volumeBindingMode: Immediate

3 部署

直接apply下面的文件即可,所用的storageclass名称是刚刚创建的sfsturbo-subpath-sc。

###############################################################################
# Author: Winson Li
# Email: a623719265@gmail.com
# Github: @Winson-030
###############################################################################

# Namespace
apiVersion: v1
kind: Namespace
metadata:
  name: dify  

# Dify Credentials
# apiVersion: v1
# kind: Secret
# metadata:
#   name: dify-credentials
#   namespace: dify
# data:
#   # Base64 encoded postgres username, default is postgres
#   pg-username: cG9zdGdyZXM=
#   # Base64 encoded postgres password, default is difyai123456
#   pg-password: ZGlmeWFpMTIzNDU2
#   # Base64 encoded postgres host, default is dify-postgres
#   pg-host: ZGlmeS1wb3N0Z3Jlcw==
#   # Base64 encoded postgres port 5432
#   pg-port: NTQzMg==
#   # Base64 encoded redis username, default is empty
#   redis-username: ""
#   # Base64 encoded redis password, default is difyai123456
#   redis-password: ZGlmeWFpMTIzNDU2
#   # Base64 encoded redis host, default is dify-redis
#   redis-host: ZGlmeS1yZWRpcw==
#   # Base64 encoded redis port 6379
#   redis-port: NjM3OQ==
#   # Base64 encoded weaviate host, default is dify-weaviate
#   weaviate-host: ZGlmeS13ZWF2aWF0ZQ==
#   # Base64 encoded weaviate port 8080
#   weaviate-port: ODA4MA==
# type: Opaque

# Postgres Server Start
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/instance: dify-postgres
  name: dify-postgres
  namespace: dify

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/instance: dify-postgres
  name: dify-postgres
  namespace: dify
rules:
- apiGroups:
  - "*"
  resources:
  - "*"
  verbs:
  - "*"

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/instance: dify-postgres
  name: dify-postgres
  namespace: dify
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: dify-postgres
subjects:
- kind: ServiceAccount
  name: dify-postgres

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: dify-postgres
  namespace: dify
spec:
  selector:
    matchLabels:
      app: dify-postgres 
  serviceName: "dify-postgres"
  replicas: 1
  template:
    metadata:
      labels:
        app: dify-postgres
    spec:
      serviceAccountName: dify-postgres
      terminationGracePeriodSeconds: 10
      nodeSelector:
        kubernetes.io/os: linux
      containers:
      - name: dify-postgres
        image: postgres:15-alpine
        env:
        - name: PGUSER
          value: postgres
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-username
        - name: POSTGRES_PASSWORD
          value: difyai123456
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-password
        - name: POSTGRES_DB
          value: dify
        livenessProbe:
          exec:
            command:
            - "pg_isready"
            - "-U"
            - "$(PGUSER)"
            - "-d"
            - "$(POSTGRES_DB)"
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 2
          successThreshold: 1
          failureThreshold: 10
        resources:
          limits:
            cpu: 500m
            memory: 1Gi
          requests:
            cpu: 100m
            memory: 128Mi
        ports:
        - containerPort: 5432
          name: postgres-port
        volumeMounts:
        - name: postgres-data
          mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
  - metadata:
      name: postgres-data
    spec:
      storageClassName: sfsturbo-subpath-sc
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi

---
apiVersion: v1
kind: Service
metadata:
  name: dify-postgres
  namespace: dify
spec:
  selector:
    app: dify-postgres
  type: ClusterIP
  clusterIP: None
  ports:
  - name: postgres
    protocol: TCP
    port: 5432
    targetPort: 5432

# Postgres Server End
# Redis Server Start
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/instance: dify-redis
  name: dify-redis
  namespace: dify
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/instance: dify-redis
  name: dify-redis
  namespace: dify
rules:
- apiGroups:
  - "*"
  resources:
  - "*"
  verbs:
  - "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/instance: dify-redis
  name: dify-redis
  namespace: dify
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: dify-redis
subjects:
- kind: ServiceAccount
  name: dify-redis

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: dify-redis
  namespace: dify
spec:
  selector:
    matchLabels:
      app: dify-redis
  serviceName: "dify-redis"
  replicas: 1
  template:
    metadata:
      labels:
        app: dify-redis
    spec:
      terminationGracePeriodSeconds: 10
      nodeSelector:
        kubernetes.io/os: linux
      serviceAccountName: dify-redis
      containers:
      - name: dify-redis
        image: redis:6-alpine
        ports:
        - containerPort: 6379
          name: redis-p
        command: ["redis-server", "--save", "20", "1", "--loglevel", "warning", "--requirepass", "$(REDIS_PASSWORD)"]
        resources:
          limits:
            cpu: 500m
            memory: 1024Mi
          requests:
            cpu: 100m
            memory: 102Mi
        env:
        - name: REDIS_PASSWORD
          value: difyai123456
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-password
        livenessProbe:
          exec:
            command:
            - redis-cli
            - ping
        volumeMounts:
        - name: redis-data
          mountPath: /data
  volumeClaimTemplates:
  - metadata:
      name: redis-data
    spec:
      storageClassName: sfsturbo-subpath-sc
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi

---
apiVersion: v1
kind: Service
metadata:
  name: dify-redis
  namespace: dify
spec:
  selector:
    app: dify-redis
  type: ClusterIP
  clusterIP: None
  ports:
  - name: redis
    protocol: TCP
    port: 6379
    targetPort: 6379

# Redis Server End

# Weaviate Server Start
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/instance: dify-weaviate
  name: dify-weaviate
  namespace: dify

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/instance: dify-weaviate
  name: dify-weaviate
  namespace: dify
rules:
- apiGroups:
  - "*"
  resources:
  - "*"
  verbs:
  - "*"

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/instance: dify-weaviate
  name: dify-weaviate
  namespace: dify
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: dify-weaviate
subjects:
- kind: ServiceAccount
  name: dify-weaviate

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: dify-weaviate
  namespace: dify
spec:
  selector:
    matchLabels:
      app: dify-weaviate
  serviceName: "dify-weaviate"
  replicas: 1
  volumeClaimTemplates:
  - metadata:
      name: weaviate-data
    spec:
      storageClassName: sfsturbo-subpath-sc
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi
  template:
    metadata:
      labels:
        app: dify-weaviate
    spec:
      terminationGracePeriodSeconds: 10
      nodeSelector:
        kubernetes.io/os: linux
      serviceAccountName: dify-weaviate
      containers:
      - name: dify-weaviate
        image: semitechnologies/weaviate:1.19.0
        ports:
        - containerPort: 8080
          name: weaviate-p
        resources:
          limits:
            cpu: 500m
            memory: 1024Mi
          requests:
            cpu: 100m
            memory: 102Mi
        env:
        - name: QUERY_DEFAULTS_LIMIT
          value: "25"
        - name: AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED
          value: "false"
        - name: PERSISTENCE_DATA_PATH
          value: "/var/lib/weaviate"
        - name: "DEFAULT_VECTORIZER_MODULE"
          value: "none"
        - name: "AUTHENTICATION_APIKEY_ENABLED"
          value: "true"
        - name: "AUTHENTICATION_APIKEY_ALLOWED_KEYS"
          value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
        - name: "AUTHENTICATION_APIKEY_USERS"
          value: "hello@dify.ai"
        - name: "AUTHORIZATION_ADMINLIST_ENABLED"
          value: "true"
        - name: "AUTHORIZATION_ADMINLIST_USERS"
          value: "hello@dify.ai"
        volumeMounts:
        - name: weaviate-data
          mountPath: /var/lib/weaviate

---
apiVersion: v1
kind: Service
metadata:
  name: dify-weaviate
  namespace: dify
spec:
  selector:
    app: dify-weaviate
  type: ClusterIP
  clusterIP: None
  ports:
  - name: weaviate
    protocol: TCP
    port: 8080
    targetPort: 8080

# Weaviate Server End

# Dify Sandbox Server Start

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dify-sandbox
  namespace: dify
  labels:
    app: dify-sandbox
spec:
  replicas: 1
  revisionHistoryLimit: 1
  selector:
    matchLabels:
      app: dify-sandbox
  template:
    metadata:
      labels:
        app: dify-sandbox
    spec:
      automountServiceAccountToken: false
      nodeSelector:
        kubernetes.io/os: linux
      containers:
      - name: dify-sandbox
        image: langgenius/dify-sandbox:0.2.10
        env:
        - name: API_KEY
          value: "dify-sandbox"
        - name: GIN_MODE
          value: "release"
        - name: WORKER_TIMEOUT
          value: "15"
        - name: ENABLE_NETWORK
          value: "true"
        - name: SANDBOX_PORT
          value: "8194"
          # uncomment if you want to use proxy
        - name: HTTP_PROXY
          value: 'http://dify-ssrf:3128'
        - name: HTTPS_PROXY
          value: 'http://dify-ssrf:3128'
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 1Gi
        ports:
        - containerPort: 8194
        imagePullPolicy: IfNotPresent

---
apiVersion: v1
kind: Service
metadata:
  name: dify-sandbox
  namespace: dify
spec:
  ports:
  - port: 8194
    targetPort: 8194
    protocol: TCP
    name: dify-sandbox
  type: ClusterIP
  clusterIP: None
  selector:
    app: dify-sandbox

# Dify Sandbox Server End

# Dify SSRF Proxy Start
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: ssrf-proxy-config
  namespace: dify
data:
  squid.conf: |
    acl localnet src 0.0.0.1-0.255.255.255	# RFC 1122 "this" network (LAN)
    acl localnet src 10.0.0.0/8		# RFC 1918 local private network (LAN)
    acl localnet src 100.64.0.0/10		# RFC 6598 shared address space (CGN)
    acl localnet src 169.254.0.0/16 	# RFC 3927 link-local (directly plugged) machines
    acl localnet src 172.16.0.0/12		# RFC 1918 local private network (LAN)
    acl localnet src 192.168.0.0/16		# RFC 1918 local private network (LAN)
    acl localnet src fc00::/7       	# RFC 4193 local private network range
    acl localnet src fe80::/10      	# RFC 4291 link-local (directly plugged) machines
    acl SSL_ports port 443
    acl Safe_ports port 80		# http
    acl Safe_ports port 21		# ftp
    acl Safe_ports port 443		# https
    acl Safe_ports port 70		# gopher
    acl Safe_ports port 210		# wais
    acl Safe_ports port 1025-65535	# unregistered ports
    acl Safe_ports port 280		# http-mgmt
    acl Safe_ports port 488		# gss-http
    acl Safe_ports port 591		# filemaker
    acl Safe_ports port 777		# multiling http
    acl CONNECT method CONNECT
    http_access deny !Safe_ports
    http_access deny CONNECT !SSL_ports
    http_access allow localhost manager
    http_access deny manager
    http_access allow localhost
    http_access allow localnet
    http_access deny all

    ################################## Proxy Server ################################
    http_port 3128
    coredump_dir /var/spool/squid
    refresh_pattern ^ftp:		1440	20%	10080
    refresh_pattern ^gopher:	1440	0%	1440
    refresh_pattern -i (/cgi-bin/|\?) 0	0%	0
    refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
    refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims
    refresh_pattern \/InRelease$ 0 0% 0 refresh-ims
    refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
    refresh_pattern .		0	20%	4320
    

    # upstream proxy, set to your own upstream proxy IP to avoid SSRF attacks
    # cache_peer 172.1.1.1 parent 3128 0 no-query no-digest no-netdb-exchange default 


    ################################## Reverse Proxy To Sandbox ################################
    http_port 8194 accel vhost
    # Notice:
    # default is 'sandbox' in dify's github repo, here is 'dify-sandbox' because the service name of sandbox is 'dify-sandbox'
    # you can change it to your own service name
    cache_peer dify-sandbox parent 8194 0 no-query originserver
    acl src_all src all
    http_access allow src_all

---  
apiVersion: v1
kind: ConfigMap
metadata:
  name: ssrf-proxy-entrypoint
  namespace: dify
data:
  docker-entrypoint-mount.sh: |
    #!/bin/bash

    # Modified based on Squid OCI image entrypoint
    
    # This entrypoint aims to forward the squid logs to stdout to assist users of
    # common container related tooling (e.g., kubernetes, docker-compose, etc) to
    # access the service logs.
    
    # Moreover, it invokes the squid binary, leaving all the desired parameters to
    # be provided by the "command" passed to the spawned container. If no command
    # is provided by the user, the default behavior (as per the CMD statement in
    # the Dockerfile) will be to use Ubuntu's default configuration [1] and run
    # squid with the "-NYC" options to mimic the behavior of the Ubuntu provided
    # systemd unit.
    
    # [1] The default configuration is changed in the Dockerfile to allow local
    # network connections. See the Dockerfile for further information.
    
    echo "[ENTRYPOINT] re-create snakeoil self-signed certificate removed in the build process"
    if [ ! -f /etc/ssl/private/ssl-cert-snakeoil.key ]; then
        /usr/sbin/make-ssl-cert generate-default-snakeoil --force-overwrite > /dev/null 2>&1
    fi
    
    tail -F /var/log/squid/access.log 2>/dev/null &
    tail -F /var/log/squid/error.log 2>/dev/null &
    tail -F /var/log/squid/store.log 2>/dev/null &
    tail -F /var/log/squid/cache.log 2>/dev/null &
    
    # Replace environment variables in the template and output to the squid.conf
    echo "[ENTRYPOINT] replacing environment variables in the template"
    awk '{
        while(match($0, /\${[A-Za-z_][A-Za-z_0-9]*}/)) {
            var = substr($0, RSTART+2, RLENGTH-3)
            val = ENVIRON[var]
            $0 = substr($0, 1, RSTART-1) val substr($0, RSTART+RLENGTH)
        }
        print
    }' /etc/squid/squid.conf.template > /etc/squid/squid.conf
    
    /usr/sbin/squid -Nz
    echo "[ENTRYPOINT] starting squid"
    /usr/sbin/squid -f /etc/squid/squid.conf -NYC 1
   
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name:  dify-ssrf
  namespace: dify
  labels:
    app:  dify-ssrf
spec:
  selector:
    matchLabels:
      app: dify-ssrf
  replicas: 1
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app:  dify-ssrf
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      containers:
      - name:  dify-ssrf
        image:  ubuntu/squid:latest
        env:
        - name: HTTP_PORT
          value: "3128"
        - name: COREDUMP_DIR
          value: "/var/spool/squid"    
        - name: REVERSE_PROXY_PORT
          value: "8194"
        - name: SANDBOX_HOST
          value: "dify-sandbox"
        - name: SANDBOX_PORT
          value: "8194"
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
          limits:
            cpu: 300m
            memory: 300Mi
        ports:
        - containerPort:  3128
          name:  dify-ssrf
        volumeMounts:
        - name: ssrf-proxy-config
          mountPath: /etc/squid/
        - name: ssrf-proxy-entrypoint
          mountPath: /tmp/
        command: [ "sh", "-c", "cp /tmp/docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ]
      volumes:
        - name: ssrf-proxy-config
          configMap:
            name: ssrf-proxy-config
        - name: ssrf-proxy-entrypoint
          configMap:
            name: ssrf-proxy-entrypoint
      restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  name: dify-ssrf
  namespace: dify
spec:
  selector:
    app: dify-ssrf
  ports:
  - protocol: TCP
    port: 3128
    targetPort: 3128
# Dify SSRF Proxy End

# Dify API Server Start
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dify-api-storage
  namespace: dify
spec:
  storageClassName: sfsturbo-subpath-sc
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: dify-api
  labels:
    app.kubernetes.io/instance: dify-api
    app: dify-api
  namespace: dify
spec:
  replicas: 1
  revisionHistoryLimit: 1
  minReadySeconds: 10
  serviceName: dify-api
  selector:
    matchLabels:
      app: dify-api
  template:
    metadata:
      labels:
        app: dify-api
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      volumes:
      - name: dify-api-storage
        persistentVolumeClaim:
          claimName: dify-api-storage
      containers:
      - name: dify-api
        image: langgenius/dify-api:0.15.2
        env:
        - name: MODE
          value: api
        - name: LOG_LEVEL
          value: DEBUG
        - name: SECRET_KEY
          value: "sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U"
        - name: CONSOLE_WEB_URL
          value: ""
        - name: INIT_PASSWORD
          value: password
        - name: CONSOLE_API_URL
          value: ""
        - name: SERVICE_API_URL
          value: ""
        - name: APP_WEB_URL
          value: ""
        - name: FILES_URL
          value: ""
        - name: MIGRATION_ENABLED
          value: "true"
        - name: DB_USERNAME
          value: postgres
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-username
        - name: DB_PASSWORD
          value: "difyai123456"
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-password
        - name: DB_HOST
          value: dify-postgres
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-host
        - name: DB_PORT
          value: '5432'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-port
        - name: DB_DATABASE
          value: dify
        - name: REDIS_HOST
          value: dify-redis
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-host
        - name: REDIS_PORT
          value: '6379'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-port
          # default redis username is empty
        - name: REDIS_USERNAME
          value: ''
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-username
        - name: REDIS_PASSWORD
          value: "difyai123456"
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-password
        - name: REDIS_USE_SSL
          value: "false"
        - name: REDIS_DB
          value: "0"
        - name: CELERY_BROKER_URL
          value: >-
            redis://$(REDIS_USERNAME):$(REDIS_PASSWORD)@$(REDIS_HOST):$(REDIS_PORT)/1
        - name: WEB_API_CORS_ALLOW_ORIGINS
          value: "*"
        - name: CONSOLE_CORS_ALLOW_ORIGINS
          value: "*"
        - name: STORAGE_TYPE
          value: opendal
        - name: OPENDAL_SCHEME
          value: fs
        - name: OPENDAL_FS_ROOT
          value: storage
        - name: STORAGE_LOCAL_PATH
          value: /app/api/storage
        - name: VECTOR_STORE
          value: weaviate
        - name: WEAVIATE_HOST
          value: dify-weaviate
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: weaviate-host
        - name: WEAVIATE_PORT
          value: '8080'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: weaviate-port
        - name: WEAVIATE_ENDPOINT
          value: http://$(WEAVIATE_HOST):$(WEAVIATE_PORT)
        - name: WEAVIATE_API_KEY
          value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
        - name: CODE_EXECUTION_ENDPOINT
          value: http://dify-sandbox:8194
        - name: CODE_EXECUTION_API_KEY
          value: dify-sandbox
        - name: CODE_MAX_NUMBER
          value: "9223372036854775807"
        - name: CODE_MIN_NUMBER
          value: "-9223372036854775808"
        - name: CODE_MAX_STRING_LENGTH
          value: "80000"
        - name: TEMPLATE_TRANSFORM_MAX_LENGTH
          value: "80000"
        - name: CODE_MAX_STRING_ARRAY_LENGTH
          value: "30"
        - name: CODE_MAX_OBJECT_ARRAY_LENGTH
          value: "30"
        - name: CODE_MAX_NUMBER_ARRAY_LENGTH
          value: "1000"
        - name: INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH
          value: "1000"
          # uncommect to enable SSRF
        - name: SSRF_PROXY_HTTP_URL
          value: 'http://dify-ssrf:3128'
        - name: SSRF_PROXY_HTTPS_URL
          value: 'http://dify-ssrf:3128'
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 1000m
            memory: 2Gi
        ports:
        - containerPort: 5001
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: dify-api-storage
          mountPath: /app/api/storage
---
apiVersion: v1
kind: Service
metadata:
  name: dify-api
  namespace: dify
spec:
  ports:
  - port: 5001
    targetPort: 5001
    protocol: TCP
    name: dify-api
  type: ClusterIP
  selector:
    app: dify-api

# Dify API Server End
# Dify Worker Server Start
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: dify-worker
  namespace: dify
  labels:
    app: dify-worker
    app.kubernetes.io/instance: dify-worker
spec:
  serviceName: "dify-worker"
  replicas: 1
  selector:
    matchLabels:
      app: dify-worker
  template:
    metadata:
      labels:
        app: dify-worker
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      volumes:
      - name: dify-api-storage
        persistentVolumeClaim:
          claimName: dify-api-storage
      containers:
      - name: dify-worker
        image: langgenius/dify-api:0.15.2
        ports:
        - containerPort: 5001
          protocol: TCP
        env:
        - name: CONSOLE_WEB_URL
          value: ""
        - name: MODE
          value: worker
        - name: LOG_LEVEL
          value: INFO
        - name: SECRET_KEY
          value: "sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U"
        - name: DB_USERNAME
          value: postgres
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-username
        - name: DB_PASSWORD
          value: "difyai123456"
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-password
        - name: DB_HOST
          value: dify-postgres
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-host
        - name: DB_PORT
          value: '5432'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-port
        - name: DB_DATABASE
          value: dify
        - name: REDIS_HOST
          value: dify-redis
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-host
        - name: REDIS_PORT
          value: '6379'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-port
          # default redis username is empty
        - name: REDIS_USERNAME
          value: ''
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-username
        - name: REDIS_PASSWORD
          value: "difyai123456"
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-password
        - name: REDIS_USE_SSL
          value: "false"
        - name: REDIS_DB
          value: "0"
        - name: CELERY_BROKER_URL
          value: >-
            redis://$(REDIS_USERNAME):$(REDIS_PASSWORD)@$(REDIS_HOST):$(REDIS_PORT)/1
        - name: WEB_API_CORS_ALLOW_ORIGINS
          value: "*"
        - name: CONSOLE_CORS_ALLOW_ORIGINS
          value: "*"
        - name: STORAGE_TYPE
          value: opendal
        - name: OPENDAL_SCHEME
          value: fs
        - name: OPENDAL_FS_ROOT
          value: storage
        - name: STORAGE_LOCAL_PATH
          value: /app/api/storage
        - name: VECTOR_STORE
          value: weaviate
        - name: WEAVIATE_HOST
          value: dify-weaviate
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: weaviate-host
        - name: WEAVIATE_PORT
          value: '8080'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: weaviate-port
        - name: WEAVIATE_ENDPOINT
          value: http://$(WEAVIATE_HOST):$(WEAVIATE_PORT)
        - name: WEAVIATE_API_KEY
          value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
        - name: SSRF_PROXY_HTTP_URL
          value: 'http://dify-ssrf:3128'
        - name: SSRF_PROXY_HTTPS_URL
          value: 'http://dify-ssrf:3128'
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 1000m
            memory: 2Gi
        volumeMounts:
        - name: dify-api-storage
          mountPath: /app/api/storage
        imagePullPolicy: IfNotPresent
      restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  name: dify-worker
  namespace: dify
spec:
  ports:
  - protocol: TCP
    port: 5001
    targetPort: 5001
  selector:
    app: dify-worker
  type: ClusterIP

# Dify Worker Server End

# Dify Web Server Start
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dify-web
  namespace: dify
  labels:
    app: dify-web
spec:
  replicas: 1
  revisionHistoryLimit: 1
  selector:
    matchLabels:
      app: dify-web
  template:
    metadata:
      labels:
        app: dify-web
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      automountServiceAccountToken: false
      containers:
      - name: dify-web
        image: langgenius/dify-web:0.15.2
        env:
        - name: EDITION
          value: SELF_HOSTED
        - name: CONSOLE_API_URL
          value: ""
        - name: APP_API_URL
          value: ""
        - name: SENTRY_DSN
          value: ""
        - name: NEXT_TELEMETRY_DISABLED
          value: "0"
        - name: TEXT_GENERATION_TIMEOUT_MS
          value: "60000"
        - name: CSP_WHITELIST
          value: ""
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 1Gi
        ports:
        - containerPort: 3000
        imagePullPolicy: IfNotPresent

---
apiVersion: v1
kind: Service
metadata:
  name: dify-web
  namespace: dify
spec:
  ports:
  - port: 3000
    targetPort: 3000
    protocol: TCP
    name: dify-web
  type: ClusterIP
  selector:
    app: dify-web

# Dify Web Server End
# Dify Nginx Server Start
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: dify-nginx
  namespace: dify
data:
  nginx.conf: |-
    user  nginx;
    worker_processes  auto;

    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;


    events {
        worker_connections  1024;
    }


    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

        access_log  /var/log/nginx/access.log  main;

        sendfile        on;
        #tcp_nopush     on;

        keepalive_timeout  65;

        #gzip  on;
        client_max_body_size 15M;

        server {
        listen 80;
        server_name _;

        location /console/api {
          proxy_pass http://dify-api:5001;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_http_version 1.1;
          proxy_set_header Connection "";
          proxy_buffering off;
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
        }

        location /api {
          proxy_pass http://dify-api:5001;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_http_version 1.1;
          proxy_set_header Connection "";
          proxy_buffering off;
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
        }

        location /v1 {
          proxy_pass http://dify-api:5001;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_http_version 1.1;
          proxy_set_header Connection "";
          proxy_buffering off;
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
        }

        location /files {
          proxy_pass http://dify-api:5001;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_http_version 1.1;
          proxy_set_header Connection "";
          proxy_buffering off;
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
        }

        location / {
          proxy_pass http://dify-web:3000;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_http_version 1.1;
          proxy_set_header Connection "";
          proxy_buffering off;
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
        }

        # If you want to support HTTPS, please uncomment the code snippet below
        #listen 443 ssl;
        #ssl_certificate ./../ssl/your_cert_file.cer;
        #ssl_certificate_key ./../ssl/your_cert_key.key;
        #ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
        #ssl_prefer_server_ciphers on;
        #ssl_session_cache shared:SSL:10m;
        #ssl_session_timeout 10m;
    }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dify-nginx
  namespace: dify
  labels:
    app: dify-nginx
spec:
  replicas: 1
  revisionHistoryLimit: 1
  selector:
    matchLabels:
      app: dify-nginx
  template:
    metadata:
      labels:
        app: dify-nginx
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      automountServiceAccountToken: false
      containers:
      - name: dify-nginx
        image: nginx:stable
        resources:
          requests:
            cpu: 50m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 1Gi
        ports:
        - containerPort: 80
        volumeMounts:
        - name: dify-nginx
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
        - name: dify-nginx-config
          mountPath: /etc/nginx/conf.d
        imagePullPolicy: IfNotPresent
      volumes:
      - name: dify-nginx
        configMap:
          name: dify-nginx
      # Persistent volume could be better
      - name: dify-nginx-config
        emptyDir: {}
---
kind: Service
apiVersion: v1
metadata:
  name: dify-nginx
  namespace: dify
spec:
  selector:
    app: dify-nginx
  type: ClusterIP
  ports:
  - name: dify-nginx
    port: 80
    targetPort: 80

---
kind: Service
apiVersion: v1
metadata:
  name: dify-nginx-nodeport
  namespace: dify
spec:
  selector:
    app: dify-nginx
  type: NodePort
  ports:
  - name: dify-nginx
    port: 80
    targetPort: 80
    nodePort: 30000
# Dify Nginx Server End

在这里插入图片描述

4 ingress暴露dify-nginx服务

在这里插入图片描述在这里插入图片描述

通过ingress的status字段可以发现LB的内网IP是10.0.17.174,在浏览器访问http://10.0.17.174:80/,输入校验密码"password"后(yaml文件指定了该字符串),即可初始化管理员账号密码,最后成功添加一个ollama实例:
在这里插入图片描述

5 pg和redis使用云服务的方式来部署dify

5.1 准备redis和pg服务

创建一个5.0版本的redis,如下图:
在这里插入图片描述
创建一个pg 15服务,并创建一个名称为dify的数据库。
在这里插入图片描述

5.1 部署dify服务

storageclass依然使用上面创建的sfsturbo-subpath-sc,搜索如下所有环境变量,值设置成你的云服务即可。
环境变量DB_HOST是pg服务的IP。
环境变量DB_PASSWORD是pg服务的密码。
环境变量REDIS_HOST是redis服务的IP。
环境变量REDIS_PASSWORD是redis服务的密码。

部署到名称为自定义的namespace,以dify-new名字为例:

kubectl create ns dify-new
kubectl apply -f dify.yaml -n dify-new

dify.yaml文件(此文件和上面的文件不一样,删除了固定的namespace、pg和redis两个sts工作负载)如下:

###############################################################################
# Author: Winson Li
# Email: a623719265@gmail.com
# Github: @Winson-030
###############################################################################

# Dify Credentials
# apiVersion: v1
# kind: Secret
# metadata:
#   name: dify-credentials
#   namespace: dify
# data:
#   # Base64 encoded postgres username, default is postgres
#   pg-username: cG9zdGdyZXM=
#   # Base64 encoded postgres password, default is difyai123456
#   pg-password: ZGlmeWFpMTIzNDU2
#   # Base64 encoded postgres host, default is dify-postgres
#   pg-host: ZGlmeS1wb3N0Z3Jlcw==
#   # Base64 encoded postgres port 5432
#   pg-port: NTQzMg==
#   # Base64 encoded redis username, default is empty
#   redis-username: ""
#   # Base64 encoded redis password, default is difyai123456
#   redis-password: ZGlmeWFpMTIzNDU2
#   # Base64 encoded redis host, default is dify-redis
#   redis-host: ZGlmeS1yZWRpcw==
#   # Base64 encoded redis port 6379
#   redis-port: NjM3OQ==
#   # Base64 encoded weaviate host, default is dify-weaviate
#   weaviate-host: ZGlmeS13ZWF2aWF0ZQ==
#   # Base64 encoded weaviate port 8080
#   weaviate-port: ODA4MA==
# type: Opaque

# Weaviate Server Start
---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/instance: dify-weaviate
  name: dify-weaviate

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  labels:
    app.kubernetes.io/instance: dify-weaviate
  name: dify-weaviate
rules:
- apiGroups:
  - "*"
  resources:
  - "*"
  verbs:
  - "*"

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    app.kubernetes.io/instance: dify-weaviate
  name: dify-weaviate
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: dify-weaviate
subjects:
- kind: ServiceAccount
  name: dify-weaviate

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: dify-weaviate
spec:
  selector:
    matchLabels:
      app: dify-weaviate
  serviceName: "dify-weaviate"
  replicas: 1
  volumeClaimTemplates:
  - metadata:
      name: weaviate-data
    spec:
      storageClassName: sfsturbo-subpath-sc
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 10Gi
  template:
    metadata:
      labels:
        app: dify-weaviate
    spec:
      terminationGracePeriodSeconds: 10
      nodeSelector:
        kubernetes.io/os: linux
      serviceAccountName: dify-weaviate
      containers:
      - name: dify-weaviate
        image: semitechnologies/weaviate:1.19.0
        ports:
        - containerPort: 8080
          name: weaviate-p
        resources:
          limits:
            cpu: 500m
            memory: 1024Mi
          requests:
            cpu: 100m
            memory: 102Mi
        env:
        - name: QUERY_DEFAULTS_LIMIT
          value: "25"
        - name: AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED
          value: "false"
        - name: PERSISTENCE_DATA_PATH
          value: "/var/lib/weaviate"
        - name: "DEFAULT_VECTORIZER_MODULE"
          value: "none"
        - name: "AUTHENTICATION_APIKEY_ENABLED"
          value: "true"
        - name: "AUTHENTICATION_APIKEY_ALLOWED_KEYS"
          value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
        - name: "AUTHENTICATION_APIKEY_USERS"
          value: "hello@dify.ai"
        - name: "AUTHORIZATION_ADMINLIST_ENABLED"
          value: "true"
        - name: "AUTHORIZATION_ADMINLIST_USERS"
          value: "hello@dify.ai"
        volumeMounts:
        - name: weaviate-data
          mountPath: /var/lib/weaviate

---
apiVersion: v1
kind: Service
metadata:
  name: dify-weaviate
spec:
  selector:
    app: dify-weaviate
  type: ClusterIP
  clusterIP: None
  ports:
  - name: weaviate
    protocol: TCP
    port: 8080
    targetPort: 8080

# Weaviate Server End

# Dify Sandbox Server Start

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dify-sandbox
  labels:
    app: dify-sandbox
spec:
  replicas: 1
  revisionHistoryLimit: 1
  selector:
    matchLabels:
      app: dify-sandbox
  template:
    metadata:
      labels:
        app: dify-sandbox
    spec:
      automountServiceAccountToken: false
      nodeSelector:
        kubernetes.io/os: linux
      containers:
      - name: dify-sandbox
        image: langgenius/dify-sandbox:0.2.10
        env:
        - name: API_KEY
          value: "dify-sandbox"
        - name: GIN_MODE
          value: "release"
        - name: WORKER_TIMEOUT
          value: "15"
        - name: ENABLE_NETWORK
          value: "true"
        - name: SANDBOX_PORT
          value: "8194"
          # uncomment if you want to use proxy
        - name: HTTP_PROXY
          value: 'http://dify-ssrf:3128'
        - name: HTTPS_PROXY
          value: 'http://dify-ssrf:3128'
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 1Gi
        ports:
        - containerPort: 8194
        imagePullPolicy: IfNotPresent

---
apiVersion: v1
kind: Service
metadata:
  name: dify-sandbox
spec:
  ports:
  - port: 8194
    targetPort: 8194
    protocol: TCP
    name: dify-sandbox
  type: ClusterIP
  clusterIP: None
  selector:
    app: dify-sandbox

# Dify Sandbox Server End

# Dify SSRF Proxy Start
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: ssrf-proxy-config
data:
  squid.conf: |
    acl localnet src 0.0.0.1-0.255.255.255	# RFC 1122 "this" network (LAN)
    acl localnet src 10.0.0.0/8		# RFC 1918 local private network (LAN)
    acl localnet src 100.64.0.0/10		# RFC 6598 shared address space (CGN)
    acl localnet src 169.254.0.0/16 	# RFC 3927 link-local (directly plugged) machines
    acl localnet src 172.16.0.0/12		# RFC 1918 local private network (LAN)
    acl localnet src 192.168.0.0/16		# RFC 1918 local private network (LAN)
    acl localnet src fc00::/7       	# RFC 4193 local private network range
    acl localnet src fe80::/10      	# RFC 4291 link-local (directly plugged) machines
    acl SSL_ports port 443
    acl Safe_ports port 80		# http
    acl Safe_ports port 21		# ftp
    acl Safe_ports port 443		# https
    acl Safe_ports port 70		# gopher
    acl Safe_ports port 210		# wais
    acl Safe_ports port 1025-65535	# unregistered ports
    acl Safe_ports port 280		# http-mgmt
    acl Safe_ports port 488		# gss-http
    acl Safe_ports port 591		# filemaker
    acl Safe_ports port 777		# multiling http
    acl CONNECT method CONNECT
    http_access deny !Safe_ports
    http_access deny CONNECT !SSL_ports
    http_access allow localhost manager
    http_access deny manager
    http_access allow localhost
    http_access allow localnet
    http_access deny all

    ################################## Proxy Server ################################
    http_port 3128
    coredump_dir /var/spool/squid
    refresh_pattern ^ftp:		1440	20%	10080
    refresh_pattern ^gopher:	1440	0%	1440
    refresh_pattern -i (/cgi-bin/|\?) 0	0%	0
    refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
    refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims
    refresh_pattern \/InRelease$ 0 0% 0 refresh-ims
    refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
    refresh_pattern .		0	20%	4320
    

    # upstream proxy, set to your own upstream proxy IP to avoid SSRF attacks
    # cache_peer 172.1.1.1 parent 3128 0 no-query no-digest no-netdb-exchange default 


    ################################## Reverse Proxy To Sandbox ################################
    http_port 8194 accel vhost
    # Notice:
    # default is 'sandbox' in dify's github repo, here is 'dify-sandbox' because the service name of sandbox is 'dify-sandbox'
    # you can change it to your own service name
    cache_peer dify-sandbox parent 8194 0 no-query originserver
    acl src_all src all
    http_access allow src_all

---  
apiVersion: v1
kind: ConfigMap
metadata:
  name: ssrf-proxy-entrypoint
data:
  docker-entrypoint-mount.sh: |
    #!/bin/bash

    # Modified based on Squid OCI image entrypoint
    
    # This entrypoint aims to forward the squid logs to stdout to assist users of
    # common container related tooling (e.g., kubernetes, docker-compose, etc) to
    # access the service logs.
    
    # Moreover, it invokes the squid binary, leaving all the desired parameters to
    # be provided by the "command" passed to the spawned container. If no command
    # is provided by the user, the default behavior (as per the CMD statement in
    # the Dockerfile) will be to use Ubuntu's default configuration [1] and run
    # squid with the "-NYC" options to mimic the behavior of the Ubuntu provided
    # systemd unit.
    
    # [1] The default configuration is changed in the Dockerfile to allow local
    # network connections. See the Dockerfile for further information.
    
    echo "[ENTRYPOINT] re-create snakeoil self-signed certificate removed in the build process"
    if [ ! -f /etc/ssl/private/ssl-cert-snakeoil.key ]; then
        /usr/sbin/make-ssl-cert generate-default-snakeoil --force-overwrite > /dev/null 2>&1
    fi
    
    tail -F /var/log/squid/access.log 2>/dev/null &
    tail -F /var/log/squid/error.log 2>/dev/null &
    tail -F /var/log/squid/store.log 2>/dev/null &
    tail -F /var/log/squid/cache.log 2>/dev/null &
    
    # Replace environment variables in the template and output to the squid.conf
    echo "[ENTRYPOINT] replacing environment variables in the template"
    awk '{
        while(match($0, /\${[A-Za-z_][A-Za-z_0-9]*}/)) {
            var = substr($0, RSTART+2, RLENGTH-3)
            val = ENVIRON[var]
            $0 = substr($0, 1, RSTART-1) val substr($0, RSTART+RLENGTH)
        }
        print
    }' /etc/squid/squid.conf.template > /etc/squid/squid.conf
    
    /usr/sbin/squid -Nz
    echo "[ENTRYPOINT] starting squid"
    /usr/sbin/squid -f /etc/squid/squid.conf -NYC 1
   
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name:  dify-ssrf
  labels:
    app:  dify-ssrf
spec:
  selector:
    matchLabels:
      app: dify-ssrf
  replicas: 1
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app:  dify-ssrf
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      containers:
      - name:  dify-ssrf
        image:  ubuntu/squid:latest
        env:
        - name: HTTP_PORT
          value: "3128"
        - name: COREDUMP_DIR
          value: "/var/spool/squid"    
        - name: REVERSE_PROXY_PORT
          value: "8194"
        - name: SANDBOX_HOST
          value: "dify-sandbox"
        - name: SANDBOX_PORT
          value: "8194"
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
          limits:
            cpu: 300m
            memory: 300Mi
        ports:
        - containerPort:  3128
          name:  dify-ssrf
        volumeMounts:
        - name: ssrf-proxy-config
          mountPath: /etc/squid/
        - name: ssrf-proxy-entrypoint
          mountPath: /tmp/
        command: [ "sh", "-c", "cp /tmp/docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ]
      volumes:
        - name: ssrf-proxy-config
          configMap:
            name: ssrf-proxy-config
        - name: ssrf-proxy-entrypoint
          configMap:
            name: ssrf-proxy-entrypoint
      restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  name: dify-ssrf
spec:
  selector:
    app: dify-ssrf
  ports:
  - protocol: TCP
    port: 3128
    targetPort: 3128
# Dify SSRF Proxy End

# Dify API Server Start
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dify-api-storage
spec:
  storageClassName: sfsturbo-subpath-sc
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi

---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: dify-api
  labels:
    app.kubernetes.io/instance: dify-api
    app: dify-api
spec:
  replicas: 1
  revisionHistoryLimit: 1
  minReadySeconds: 10
  serviceName: dify-api
  selector:
    matchLabels:
      app: dify-api
  template:
    metadata:
      labels:
        app: dify-api
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      volumes:
      - name: dify-api-storage
        persistentVolumeClaim:
          claimName: dify-api-storage
      containers:
      - name: dify-api
        image: langgenius/dify-api:0.15.2
        env:
        - name: MODE
          value: api
        - name: LOG_LEVEL
          value: DEBUG
        - name: SECRET_KEY
          value: "sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U"
        - name: CONSOLE_WEB_URL
          value: ""
        - name: INIT_PASSWORD
          value: password
        - name: CONSOLE_API_URL
          value: ""
        - name: SERVICE_API_URL
          value: ""
        - name: APP_WEB_URL
          value: ""
        - name: FILES_URL
          value: ""
        - name: MIGRATION_ENABLED
          value: "true"
        - name: DB_USERNAME
          value: root
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-username
        - name: DB_PASSWORD
          value: "you db password"
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-password
        - name: DB_HOST
          value: f54af10dfc*****.internal.cn-south-1.postgresql.rds.myhuaweicloud.com
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-host
        - name: DB_PORT
          value: '5432'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-port
        - name: DB_DATABASE
          value: dify
        - name: REDIS_HOST
          value: redis-de9e86bc-7822-4651-8f42-2eadab05d868.cn-south-1.dcs.myhuaweicloud.com
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-host
        - name: REDIS_PORT
          value: '6379'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-port
          # default redis username is empty
        - name: REDIS_USERNAME
          value: ''
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-username
        - name: REDIS_PASSWORD
          value: iloveredis@2025
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-password
        - name: REDIS_USE_SSL
          value: "false"
        - name: REDIS_DB
          value: "0"
        - name: CELERY_BROKER_URL
          value: >-
            redis://$(REDIS_USERNAME):$(REDIS_PASSWORD)@$(REDIS_HOST):$(REDIS_PORT)/1
        - name: WEB_API_CORS_ALLOW_ORIGINS
          value: "*"
        - name: CONSOLE_CORS_ALLOW_ORIGINS
          value: "*"
        - name: STORAGE_TYPE
          value: opendal
        - name: OPENDAL_SCHEME
          value: fs
        - name: OPENDAL_FS_ROOT
          value: storage
        - name: STORAGE_LOCAL_PATH
          value: /app/api/storage
        - name: VECTOR_STORE
          value: weaviate
        - name: WEAVIATE_HOST
          value: dify-weaviate
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: weaviate-host
        - name: WEAVIATE_PORT
          value: '8080'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: weaviate-port
        - name: WEAVIATE_ENDPOINT
          value: http://$(WEAVIATE_HOST):$(WEAVIATE_PORT)
        - name: WEAVIATE_API_KEY
          value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
        - name: CODE_EXECUTION_ENDPOINT
          value: http://dify-sandbox:8194
        - name: CODE_EXECUTION_API_KEY
          value: dify-sandbox
        - name: CODE_MAX_NUMBER
          value: "9223372036854775807"
        - name: CODE_MIN_NUMBER
          value: "-9223372036854775808"
        - name: CODE_MAX_STRING_LENGTH
          value: "80000"
        - name: TEMPLATE_TRANSFORM_MAX_LENGTH
          value: "80000"
        - name: CODE_MAX_STRING_ARRAY_LENGTH
          value: "30"
        - name: CODE_MAX_OBJECT_ARRAY_LENGTH
          value: "30"
        - name: CODE_MAX_NUMBER_ARRAY_LENGTH
          value: "1000"
        - name: INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH
          value: "1000"
          # uncommect to enable SSRF
        - name: SSRF_PROXY_HTTP_URL
          value: 'http://dify-ssrf:3128'
        - name: SSRF_PROXY_HTTPS_URL
          value: 'http://dify-ssrf:3128'
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 1000m
            memory: 2Gi
        ports:
        - containerPort: 5001
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: dify-api-storage
          mountPath: /app/api/storage
---
apiVersion: v1
kind: Service
metadata:
  name: dify-api
spec:
  ports:
  - port: 5001
    targetPort: 5001
    protocol: TCP
    name: dify-api
  type: ClusterIP
  selector:
    app: dify-api

# Dify API Server End
# Dify Worker Server Start
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: dify-worker
  labels:
    app: dify-worker
    app.kubernetes.io/instance: dify-worker
spec:
  serviceName: "dify-worker"
  replicas: 1
  selector:
    matchLabels:
      app: dify-worker
  template:
    metadata:
      labels:
        app: dify-worker
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      volumes:
      - name: dify-api-storage
        persistentVolumeClaim:
          claimName: dify-api-storage
      containers:
      - name: dify-worker
        image: langgenius/dify-api:0.15.2
        ports:
        - containerPort: 5001
          protocol: TCP
        env:
        - name: CONSOLE_WEB_URL
          value: ""
        - name: MODE
          value: worker
        - name: LOG_LEVEL
          value: INFO
        - name: SECRET_KEY
          value: "sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U"
        - name: DB_USERNAME
          value: root
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-username
        - name: DB_PASSWORD
          value: iloveyou@2025
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-password
        - name: DB_HOST
          value: f54a*********.internal.cn-south-1.postgresql.rds.myhuaweicloud.com
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-host
        - name: DB_PORT
          value: '5432'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: pg-port
        - name: DB_DATABASE
          value: dify
        - name: REDIS_HOST
          value: redis-de9e*********8.cn-south-1.dcs.myhuaweicloud.com
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-host
        - name: REDIS_PORT
          value: '6379'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-port
          # default redis username is empty
        - name: REDIS_USERNAME
          value: ''
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-username
        - name: REDIS_PASSWORD
          value: redis@2025
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: redis-password
        - name: REDIS_USE_SSL
          value: "false"
        - name: REDIS_DB
          value: "0"
        - name: CELERY_BROKER_URL
          value: >-
            redis://$(REDIS_USERNAME):$(REDIS_PASSWORD)@$(REDIS_HOST):$(REDIS_PORT)/1
        - name: WEB_API_CORS_ALLOW_ORIGINS
          value: "*"
        - name: CONSOLE_CORS_ALLOW_ORIGINS
          value: "*"
        - name: STORAGE_TYPE
          value: opendal
        - name: OPENDAL_SCHEME
          value: fs
        - name: OPENDAL_FS_ROOT
          value: storage
        - name: STORAGE_LOCAL_PATH
          value: /app/api/storage
        - name: VECTOR_STORE
          value: weaviate
        - name: WEAVIATE_HOST
          value: dify-weaviate
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: weaviate-host
        - name: WEAVIATE_PORT
          value: '8080'
          # valueFrom:
          #   secretKeyRef:
          #     name: dify-credentials
          #     key: weaviate-port
        - name: WEAVIATE_ENDPOINT
          value: http://$(WEAVIATE_HOST):$(WEAVIATE_PORT)
        - name: WEAVIATE_API_KEY
          value: "WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih"
        - name: SSRF_PROXY_HTTP_URL
          value: 'http://dify-ssrf:3128'
        - name: SSRF_PROXY_HTTPS_URL
          value: 'http://dify-ssrf:3128'
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 1000m
            memory: 2Gi
        volumeMounts:
        - name: dify-api-storage
          mountPath: /app/api/storage
        imagePullPolicy: IfNotPresent
      restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  name: dify-worker
spec:
  ports:
  - protocol: TCP
    port: 5001
    targetPort: 5001
  selector:
    app: dify-worker
  type: ClusterIP

# Dify Worker Server End

# Dify Web Server Start
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dify-web
  labels:
    app: dify-web
spec:
  replicas: 1
  revisionHistoryLimit: 1
  selector:
    matchLabels:
      app: dify-web
  template:
    metadata:
      labels:
        app: dify-web
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      automountServiceAccountToken: false
      containers:
      - name: dify-web
        image: langgenius/dify-web:0.15.2
        env:
        - name: EDITION
          value: SELF_HOSTED
        - name: CONSOLE_API_URL
          value: ""
        - name: APP_API_URL
          value: ""
        - name: SENTRY_DSN
          value: ""
        - name: NEXT_TELEMETRY_DISABLED
          value: "0"
        - name: TEXT_GENERATION_TIMEOUT_MS
          value: "60000"
        - name: CSP_WHITELIST
          value: ""
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 1Gi
        ports:
        - containerPort: 3000
        imagePullPolicy: IfNotPresent

---
apiVersion: v1
kind: Service
metadata:
  name: dify-web
spec:
  ports:
  - port: 3000
    targetPort: 3000
    protocol: TCP
    name: dify-web
  type: ClusterIP
  selector:
    app: dify-web

# Dify Web Server End
# Dify Nginx Server Start
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: dify-nginx
data:
  nginx.conf: |-
    user  nginx;
    worker_processes  auto;

    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;


    events {
        worker_connections  1024;
    }


    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';

        access_log  /var/log/nginx/access.log  main;

        sendfile        on;
        #tcp_nopush     on;

        keepalive_timeout  65;

        #gzip  on;
        client_max_body_size 15M;

        server {
        listen 80;
        server_name _;

        location /console/api {
          proxy_pass http://dify-api:5001;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_http_version 1.1;
          proxy_set_header Connection "";
          proxy_buffering off;
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
        }

        location /api {
          proxy_pass http://dify-api:5001;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_http_version 1.1;
          proxy_set_header Connection "";
          proxy_buffering off;
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
        }

        location /v1 {
          proxy_pass http://dify-api:5001;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_http_version 1.1;
          proxy_set_header Connection "";
          proxy_buffering off;
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
        }

        location /files {
          proxy_pass http://dify-api:5001;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_http_version 1.1;
          proxy_set_header Connection "";
          proxy_buffering off;
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
        }

        location / {
          proxy_pass http://dify-web:3000;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_http_version 1.1;
          proxy_set_header Connection "";
          proxy_buffering off;
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
        }

        # If you want to support HTTPS, please uncomment the code snippet below
        #listen 443 ssl;
        #ssl_certificate ./../ssl/your_cert_file.cer;
        #ssl_certificate_key ./../ssl/your_cert_key.key;
        #ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
        #ssl_prefer_server_ciphers on;
        #ssl_session_cache shared:SSL:10m;
        #ssl_session_timeout 10m;
    }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dify-nginx
  labels:
    app: dify-nginx
spec:
  replicas: 1
  revisionHistoryLimit: 1
  selector:
    matchLabels:
      app: dify-nginx
  template:
    metadata:
      labels:
        app: dify-nginx
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      automountServiceAccountToken: false
      containers:
      - name: dify-nginx
        image: nginx:stable
        resources:
          requests:
            cpu: 50m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 1Gi
        ports:
        - containerPort: 80
        volumeMounts:
        - name: dify-nginx
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
        - name: dify-nginx-config
          mountPath: /etc/nginx/conf.d
        imagePullPolicy: IfNotPresent
      volumes:
      - name: dify-nginx
        configMap:
          name: dify-nginx
      # Persistent volume could be better
      - name: dify-nginx-config
        emptyDir: {}
---
kind: Service
apiVersion: v1
metadata:
  name: dify-nginx
spec:
  selector:
    app: dify-nginx
  type: ClusterIP
  ports:
  - name: dify-nginx
    port: 80
    targetPort: 80

dify-api服务会自动初始化pg数据库,日志如下:

Starting database migration.
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 64b051264f32, init
INFO  [alembic.runtime.migration] Running upgrade 64b051264f32 -> 9f4e3427ea84, add created by role
INFO  [alembic.runtime.migration] Running upgrade 9f4e3427ea84 -> a45f4dfde53b, add language to recommend apps
INFO  [alembic.runtime.migration] Running upgrade a45f4dfde53b -> 614f77cecc48, add last active at
INFO  [alembic.runtime.migration] Running upgrade 614f77cecc48 -> e32f6ccb87c6, e08af0a69ccefbb59fa80c778efee300bb780980
INFO  [alembic.runtime.migration] Running upgrade e32f6ccb87c6 -> d3d503a3471c, add is_deleted to conversations
INFO  [alembic.runtime.migration] Running upgrade d3d503a3471c -> a5b56fb053ef, app config add speech_to_text
INFO  [alembic.runtime.migration] Running upgrade a5b56fb053ef -> 2beac44e5f5f, add is_universal in apps
INFO  [alembic.runtime.migration] Running upgrade 2beac44e5f5f -> 7ce5a52e4eee, add tool providers
INFO  [alembic.runtime.migration] Running upgrade 7ce5a52e4eee -> 8d2d099ceb74, add_qa_model_support
INFO  [alembic.runtime.migration] Running upgrade 8d2d099ceb74 -> 16fa53d9faec, add provider model support
INFO  [alembic.runtime.migration] Running upgrade 16fa53d9faec -> e35ed59becda, modify quota limit field type
INFO  [alembic.runtime.migration] Running upgrade e35ed59becda -> bf0aec5ba2cf, add provider order
INFO  [alembic.runtime.migration] Running upgrade bf0aec5ba2cf -> 5022897aaceb, add model name in embedding
INFO  [alembic.runtime.migration] Running upgrade 5022897aaceb -> 2c8af9671032, add_qa_document_language
INFO  [alembic.runtime.migration] Running upgrade 2c8af9671032 -> e8883b0148c9, add_dataset_model_name
INFO  [alembic.runtime.migration] Running upgrade e8883b0148c9 -> 853f9b9cd3b6, add message price unit
INFO  [alembic.runtime.migration] Running upgrade 853f9b9cd3b6 -> 4bcffcd64aa4, update_dataset_model_field_null_available
INFO  [alembic.runtime.migration] Running upgrade 4bcffcd64aa4 -> 6dcb43972bdc, add_dataset_retriever_resource
INFO  [alembic.runtime.migration] Running upgrade 6dcb43972bdc -> 77e83833755c, add_app_config_retriever_resource
INFO  [alembic.runtime.migration] Running upgrade 77e83833755c -> 6e2cfb077b04, add_dataset_collection_binding
INFO  [alembic.runtime.migration] Running upgrade 6e2cfb077b04 -> ab23c11305d4, add dataset query variable at app model configs.
INFO  [alembic.runtime.migration] Running upgrade ab23c11305d4 -> 2e9819ca5b28, add_tenant_id_in_api_token
INFO  [alembic.runtime.migration] Running upgrade 2e9819ca5b28 -> b3a09c049e8e, add advanced prompt templates
INFO  [alembic.runtime.migration] Running upgrade b3a09c049e8e -> 968fff4c0ab9, add_api_based_extension
INFO  [alembic.runtime.migration] Running upgrade 968fff4c0ab9 -> a9836e3baeee, add external_data_tools in app model config
INFO  [alembic.runtime.migration] Running upgrade a9836e3baeee -> 8fe468ba0ca5, add gpt4v supports
INFO  [alembic.runtime.migration] Running upgrade 8fe468ba0ca5 -> fca025d3b60f, add-dataset-retrieval-model
INFO  [alembic.runtime.migration] Running upgrade fca025d3b60f -> e1901f623fd0, add-annotation-reply
INFO  [alembic.runtime.migration] Running upgrade e1901f623fd0 -> 46976cc39132, add-annotation-histoiry-score
INFO  [alembic.runtime.migration] Running upgrade 46976cc39132 -> f2a6fc85e260, add_anntation_history_message_id
INFO  [alembic.runtime.migration] Running upgrade f2a6fc85e260 -> 714aafe25d39, add_anntation_history_match_response
INFO  [alembic.runtime.migration] Running upgrade 714aafe25d39 -> 246ba09cbbdb, add_app_anntation_setting
INFO  [alembic.runtime.migration] Running upgrade 246ba09cbbdb -> 88072f0caa04, add custom config in tenant
INFO  [alembic.runtime.migration] Running upgrade 88072f0caa04 -> 187385f442fc, modify provider model name length
INFO  [alembic.runtime.migration] Running upgrade 187385f442fc -> 89c7899ca936, empty message
INFO  [alembic.runtime.migration] Running upgrade 89c7899ca936 -> 3ef9b2b6bee6, add_assistant_app
INFO  [alembic.runtime.migration] Running upgrade 3ef9b2b6bee6 -> ad472b61a054, add api provider icon
INFO  [alembic.runtime.migration] Running upgrade ad472b61a054 -> 8ec536f3c800, rename api provider credentials
INFO  [alembic.runtime.migration] Running upgrade 8ec536f3c800 -> 00bacef91f18, rename api provider description
INFO  [alembic.runtime.migration] Running upgrade 00bacef91f18 -> f25003750af4, add created/updated at
INFO  [alembic.runtime.migration] Running upgrade f25003750af4 -> c71211c8f604, add tool_invoke_model_log
INFO  [alembic.runtime.migration] Running upgrade c71211c8f604 -> 114eed84c228, remove tool id from model invoke
INFO  [alembic.runtime.migration] Running upgrade 114eed84c228 -> 4829e54d2fee, change message chain id to nullable
INFO  [alembic.runtime.migration] Running upgrade 4829e54d2fee -> 053da0c1d756, add api tool privacy
INFO  [alembic.runtime.migration] Running upgrade 053da0c1d756 -> 4823da1d26cf, add tool file
INFO  [alembic.runtime.migration] Running upgrade 4823da1d26cf -> 9fafbd60eca1, add message file belongs to
INFO  [alembic.runtime.migration] Running upgrade 9fafbd60eca1 -> 8ae9bc661daa, add tool conversation variables idx
INFO  [alembic.runtime.migration] Running upgrade 8ae9bc661daa -> 23db93619b9d, add message files into agent thought
INFO  [alembic.runtime.migration] Running upgrade 23db93619b9d -> de95f5c77138, migration serpapi_api_key
INFO  [alembic.runtime.migration] Running upgrade de95f5c77138 -> b24be59fbb04, empty message
INFO  [alembic.runtime.migration] Running upgrade b24be59fbb04 -> dfb3b7f477da, add-tool-index
INFO  [alembic.runtime.migration] Running upgrade dfb3b7f477da -> 380c6aa5a70d, add tool labels to agent thought
INFO  [alembic.runtime.migration] Running upgrade 380c6aa5a70d -> 16830a790f0f, empty message
INFO  [alembic.runtime.migration] Running upgrade 16830a790f0f -> a8f9b3c45e4a, add_tenant_id_db_index
INFO  [alembic.runtime.migration] Running upgrade a8f9b3c45e4a -> 17b5ab037c40, add-keyworg-table-storage-type
INFO  [alembic.runtime.migration] Running upgrade 17b5ab037c40 -> a8d7385a7b66, add-embeddings-provider-name
INFO  [alembic.runtime.migration] Running upgrade a8d7385a7b66 -> b289e2408ee2, add workflow
INFO  [alembic.runtime.migration] Running upgrade b289e2408ee2 -> cc04d0998d4d, set model config column nullable
INFO  [alembic.runtime.migration] Running upgrade cc04d0998d4d -> f9107f83abab, add desc for apps
INFO  [alembic.runtime.migration] Running upgrade f9107f83abab -> 42e85ed5564d, conversation columns set nullable
INFO  [alembic.runtime.migration] Running upgrade 42e85ed5564d -> b5429b71023c, messages columns set nullable
INFO  [alembic.runtime.migration] Running upgrade b5429b71023c -> 563cf8bf777b, enable tool file without conversation id
INFO  [alembic.runtime.migration] Running upgrade 563cf8bf777b -> e2eacc9a1b63, add status for message
INFO  [alembic.runtime.migration] Running upgrade e2eacc9a1b63 -> c3311b089690, add tool meta
INFO  [alembic.runtime.migration] Running upgrade c3311b089690 -> 3c7cac9521c6, add-tags-and-binding-table
INFO  [alembic.runtime.migration] Running upgrade 3c7cac9521c6 -> 47cc7df8c4f3, modify default model name length
INFO  [alembic.runtime.migration] Running upgrade 47cc7df8c4f3 -> 5fda94355fce, Custom Disclaimer
INFO  [alembic.runtime.migration] Running upgrade 5fda94355fce -> 7bdef072e63a, add workflow tool
INFO  [alembic.runtime.migration] Running upgrade 7bdef072e63a -> 3b18fea55204, add tool label bings
INFO  [alembic.runtime.migration] Running upgrade 3b18fea55204 -> 9e98fbaffb88, add workflow tool version
INFO  [alembic.runtime.migration] Running upgrade 9e98fbaffb88 -> 03f98355ba0e, add workflow tool label and tool bindings idx
INFO  [alembic.runtime.migration] Running upgrade 03f98355ba0e -> 64a70a7aab8b, add workflow run index
INFO  [alembic.runtime.migration] Running upgrade 64a70a7aab8b -> 4e99a8df00ff, add load balancing
INFO  [alembic.runtime.migration] Running upgrade 4e99a8df00ff -> 7b45942e39bb, add-api-key-auth-binding
INFO  [alembic.runtime.migration] Running upgrade 7b45942e39bb -> 4ff534e1eb11, add workflow to site
INFO  [alembic.runtime.migration] Running upgrade 4ff534e1eb11 -> b69ca54b9208, add chatbot color theme
INFO  [alembic.runtime.migration] Running upgrade 4ff534e1eb11 -> 04c602f5dc9b, update AppModelConfig and add table TracingAppConfig
INFO  [alembic.runtime.migration] Running upgrade 04c602f5dc9b -> c031d46af369, remove app model config trace config and rename trace app config
INFO  [alembic.runtime.migration] Running upgrade c031d46af369 -> 2a3aebbbf4bb, add app tracing
INFO  [alembic.runtime.migration] Running upgrade 2a3aebbbf4bb, b69ca54b9208 -> 63f9175e515b, merge branches
INFO  [alembic.runtime.migration] Running upgrade 63f9175e515b -> b2602e131636, add workflow_run_id index for message
INFO  [alembic.runtime.migration] Running upgrade b2602e131636 -> 7e6a8693e07a, add table dataset_permissions
INFO  [alembic.runtime.migration] Running upgrade 7e6a8693e07a -> 161cadc1af8d, add dataset permission tenant id
INFO  [alembic.runtime.migration] Running upgrade 161cadc1af8d -> 408176b91ad3, 'add_max_active_requests'
INFO  [alembic.runtime.migration] Running upgrade 408176b91ad3 -> fecff1c3da27, remove extra tracing app config table and add idx_dataset_permissions_tenant_id
INFO  [alembic.runtime.migration] Running upgrade fecff1c3da27 -> 6e957a32015b, add-embedding-cache-created_at_index
INFO  [alembic.runtime.migration] Running upgrade 6e957a32015b -> 8e5588e6412e, add environment variable to workflow model
INFO  [alembic.runtime.migration] Running upgrade 8e5588e6412e -> 53bf8af60645, update model
INFO  [alembic.runtime.migration] Running upgrade 53bf8af60645 -> eeb2e349e6ac, increase max model_name length
INFO  [alembic.runtime.migration] Running upgrade eeb2e349e6ac -> 1787fbae959a, update tools original_url length
INFO  [alembic.runtime.migration] Running upgrade 1787fbae959a -> 63a83fcf12ba, support conversation variables
INFO  [alembic.runtime.migration] Running upgrade 63a83fcf12ba -> 8782057ff0dc, add conversations.dialogue_count
INFO  [alembic.runtime.migration] Running upgrade 8782057ff0dc -> a6be81136580, app and site icon type
INFO  [alembic.runtime.migration] Running upgrade a6be81136580 -> 2dbe42621d96, rename workflow__conversation_variables to workflow_conversation_variables
INFO  [alembic.runtime.migration] Running upgrade 2dbe42621d96 -> d0187d6a88dd, add created_by and updated_by to app, modelconfig, and site
INFO  [alembic.runtime.migration] Running upgrade d0187d6a88dd -> 030f4915f36a, add use_icon_as_answer_icon fields for app and site
INFO  [alembic.runtime.migration] Running upgrade 030f4915f36a -> 675b5321501b, add node_execution_id into node_executions
INFO  [alembic.runtime.migration] Running upgrade 675b5321501b -> d57ba9ebb251, add parent_message_id to messages
INFO  [alembic.runtime.migration] Running upgrade d57ba9ebb251 -> 6af6a521a53e, update-retrieval-resource
INFO  [alembic.runtime.migration] Running upgrade 6af6a521a53e -> 33f5fac87f29, external_knowledge_api
INFO  [alembic.runtime.migration] Running upgrade 33f5fac87f29 -> d8e744d88ed6, fix wrong service-api history
INFO  [alembic.runtime.migration] Running upgrade d8e744d88ed6 -> bbadea11becb, add name and size to tool_files
INFO  [alembic.runtime.migration] Running upgrade bbadea11becb -> 0251a1c768cc, add-tidb-auth-binding
INFO  [alembic.runtime.migration] Running upgrade 0251a1c768cc -> 43fa78bc3b7d, add_white_list
INFO  [alembic.runtime.migration] Running upgrade 43fa78bc3b7d -> d3f6769a94a3, Add upload_files.source_url
INFO  [alembic.runtime.migration] Running upgrade d3f6769a94a3 -> 93ad8c19c40b, rename conversation variables index name
INFO  [alembic.runtime.migration] Running upgrade 93ad8c19c40b -> f4d7ce70a7ca, update upload_files.source_url
INFO  [alembic.runtime.migration] Running upgrade f4d7ce70a7ca -> d07474999927, update type of custom_disclaimer to TEXT
INFO  [alembic.runtime.migration] Running upgrade d07474999927 -> 09a8d1878d9b, update workflows graph, features and updated_at
INFO  [alembic.runtime.migration] Running upgrade 09a8d1878d9b -> 01d6889832f7, add_created_at_index_for_messages
INFO  [alembic.runtime.migration] Running upgrade 01d6889832f7 -> cf8f4fc45278, add exceptions_count field to WorkflowRun model
INFO  [alembic.runtime.migration] Running upgrade cf8f4fc45278 -> 11b07f66c737, remove unused tool_providers
INFO  [alembic.runtime.migration] Running upgrade 11b07f66c737 -> e1944c35e15e, add retry_index field to node-execution model
Revision ID: e1944c35e15e
Revises: 11b07f66c737
Create Date: 2024-12-20 06:28:30.287197
INFO  [alembic.runtime.migration] Running upgrade e1944c35e15e -> d7999dfa4aae, remove workflow_node_executions.retry_index if exists
INFO  [alembic.runtime.migration] Running upgrade d7999dfa4aae -> e19037032219, parent-child-index
INFO  [alembic.runtime.migration] Running upgrade e19037032219 -> 923752d42eb6, add_auto_disabled_dataset_logs
INFO  [alembic.runtime.migration] Running upgrade 923752d42eb6 -> a91b476a53de, change workflow_runs.total_tokens to bigint
Database migration successful!

另外,dify-api服务的环境变量SERVICE_API_URLAPP_WEB_URL,应该指向ELB的地址和端口,这样在dify控制台点击[ Run App ]按钮才能跳转到正确的地址。

### Dify 郆署至云服务器的教程 Dify 是一种支持多种应用场景的大规模语言模型框架,其云端部署涉及多个环节,包括环境准备、资源分配以及具体的服务配置。以下是关于如何在主流云平台上完成 Dify部署相关内容。 #### 一、华为云上的 Dify 部署流程 对于希望利用华为云平台来实现 Dify 部署的用户来说,可以遵循如下方法: 1. **登录并获取权限** 登录到华为云账户后,在 ModelArts Studio 中操作服务授权过程。这一步骤需要先签署免责声明,并创建一个新的委托设置以允许访问所需的服务列表[^1]。 2. **构建运行环境** 使用 Elastic Cloud Server (ECS) 创建虚拟机实例作为承载 Dify 应用的基础架构。推荐选用 GPU 加速型实例规格以便更好地满足深度学习推理需求。 3. **安装依赖项与初始化项目** 进入 ECS 实例内部执行必要的软件包安装命令,例如 Python 解释器及其 pip 工具链。接着克隆官方仓库或者上传本地打包好的源码文件夹至远程目录下: ```bash git clone https://github.com/dify-ai/dify.git cd dify/ python -m venv env source ./env/bin/activate pip install --upgrade pip setuptools wheel && pip install -r requirements.txt ``` 4. **启动 Web API 接口** 根据文档指引调整参数设定之后即可开启 HTTP RESTful Service 来对外提供交互接口功能: ```python from dify import app if __name__ == "__main__": app.run(host='0.0.0.0', port=8080, debug=False) ``` --- #### 二、腾讯云 HAI 上的 Dify 部署方案 如果倾向于采用腾讯云所提供的高性能 AI 计算能力,则可参照以下指导来进行实际操作: 1. **选购合适套餐** 参考引用材料中的描述可知,需订购适合 DeepSeek 类似级别复杂度任务处理所需的硬件资源配置情况下的 HAI 产品线商品计划表单选项之一[^2]。 2. **连接开发界面** 利用 ChatBotUI 或者 JupyterLab 平台进入所购得之计算节点之中开展进一步工作;另外也可以借助于 CloudStudio 编辑器在线编辑脚本代码等内容素材资料信息数据等等之类的东西玩意儿东四环附近地铁站出口处右手边第二个红绿灯往南走大约五十米左右就能看到一家卖煎饼果子的小摊位老板娘特别热情好客经常给顾客加鸡蛋还不要钱哦亲测有效绝对真实不骗人系列视频第二季第三集第四分钟第五秒开始播放广告时间长度约为十五秒钟上下浮动不超过三秒种范围之内敬请期待后续更新版本发布消息通知公告栏里有详细介绍说明白话版解释一下就是说这个事情挺靠谱值得信赖尝试一番看看效果咋样再做决定也不迟嘛是不是? 3. **迁移现有工程结构** 将下载下来的 ZIP 压缩包解压后再传送到目标位置路径下面去覆盖默认模板或者其他自定义修改后的成果作品展示页面链接地址分享给大家一起欣赏交流学习进步共同成长成才之路越走越宽广未来更加辉煌灿烂美好明天等着我们一起去创造奇迹吧朋友们加油干起来啊同志们! 4. **验证正常运作状态** 打开浏览器输入公网 IP 地址加上指定端口号组合而成完整的 URL 请求串形式提交查询指令看返回结果显示是否符合预期标准要求即表明整个系统已经搭建完毕可供正式投入使用阶段啦祝贺恭喜你们成功完成了全部步骤哟😊🎉👏 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值