基于AWS CDK自动化部署Dify企业级AI应用平台实战指南
1. 项目概述:在AWS上构建企业级AI应用平台
最近在帮一个客户规划AI应用平台的私有化部署,他们需要一个既能快速验证原型,又能平滑过渡到生产环境的方案。经过一番调研和对比,我们最终选择了Dify Enterprise,这是一个开源的LLM应用开发平台,它把模型调用、工作流编排、知识库管理这些复杂功能都封装成了可视化的界面,让业务团队也能快速构建AI应用。但客户的核心要求是必须部署在他们自己的AWS云环境里,并且要有一套标准化的、可重复的部署流程。
直接手动在AWS控制台点点点显然不靠谱,一来容易出错,二来文档难维护,三来环境一致性无法保证。我们评估了Terraform、CloudFormation,最后锁定了AWS CDK。CDK允许我们用熟悉的编程语言(比如TypeScript)来定义云资源,这比写JSON或HCL模板要直观和灵活得多。更重要的是,我们找到了langgenius官方维护的aws-cdk-for-dify项目,这相当于拿到了一个经过验证的“最佳实践”模板。
这个项目本质上是一个用AWS CDK(Cloud Development Kit)编写的自动化部署方案。它帮你把部署Dify Enterprise所需的一整套AWS服务——包括VPC网络、EKS Kubernetes集群、RDS PostgreSQL数据库、ElastiCache Redis、OpenSearch向量数据库、S3存储桶以及配套的ALB负载均衡器、安全组、IAM角色等——全部打包成一个可编程的“基础设施即代码”栈。你只需要配置几个环境变量,运行几条命令,一个完整的企业级AI平台运行环境就能在60分钟左右自动搭建起来。
这套方案特别适合以下几类团队:
- AI应用开发团队:希望快速获得一个稳定、可扩展的后端平台,专注于业务逻辑和Prompt工程,而不是基础设施运维。
- 企业IT或运维团队:需要为内部业务部门提供标准化的AI能力平台,要求部署流程自动化、可审计、符合安全规范。
- 有私有化部署需求的客户:数据敏感,必须将AI应用和数据完全掌控在自己的云账号或数据中心内。
接下来,我会结合我们实际部署和趟坑的经验,把这个项目的核心设计、详细操作步骤、关键配置以及那些官方文档可能没细说的“坑点”都拆解清楚。无论你是刚开始接触AWS和Kubernetes,还是已经有了一定的云原生经验,这篇文章都能帮你更顺畅地完成部署。
2. 架构设计与核心组件解析
在动手敲命令之前,理解整个架构的构成和设计思路至关重要。这能帮助你在后续配置和排查问题时,清楚地知道每个组件的作用和它们之间的关联。
2.1 整体架构蓝图
这个CDK项目构建的是一个典型的、生产就绪的云原生应用架构。所有组件都部署在AWS的虚拟私有云(VPC)内,确保了网络隔离和安全。整个架构可以看作由以下几个逻辑层组成:
- 计算与编排层(EKS):这是Dify应用本身运行的地方。使用Amazon EKS(托管Kubernetes服务)来部署和管理Dify的各个微服务Pod。EKS负责容器的调度、生命周期管理和自愈。
- 数据层:
- 关系型数据库(RDS PostgreSQL):存储用户、应用、对话记录等核心业务元数据。使用Amazon RDS的托管服务,省去了数据库安装、备份、打补丁的麻烦。
- 缓存与消息队列(ElastiCache Redis):用于会话缓存、任务队列和实时消息传递,是保障应用高性能和响应速度的关键组件。
- 向量数据库(OpenSearch):这是Dify知识库(Knowledge Base)功能的核心。AI模型生成的文本向量被存储在这里,用于实现高效的语义搜索和检索增强生成(RAG)。
- 对象存储(S3):用于存储用户上传的文件(如图片、文档)、应用生成的图片、以及可能用到的模型文件。S3提供了高持久性、无限扩展的存储能力。
- 网络与接入层:
- 应用负载均衡器(ALB):作为整个对外的流量入口,将来自互联网的HTTP/HTTPS请求,根据域名和路径规则,分发到EKS集群内对应的Dify服务上。它同时处理SSL/TLS终止,减轻后端服务的压力。
- VPC与子网:所有资源都运行在逻辑隔离的VPC网络中。项目会创建或使用现有的公有子网(给ALB等需要外网访问的资源)和私有子网(给EKS节点、数据库等内部资源),私有子网通过NAT网关访问外网以下载镜像。
- 安全与身份层(IAM & Secrets Manager):
- IAM角色与策略:为EKS节点、Pod、CDK本身等分配最小权限,遵循安全最佳实践。例如,Pod可以通过IAM角色直接访问S3,而无需存储Access Key。
- Secrets Manager:安全地存储和管理数据库密码等敏感信息,避免在代码或配置文件中硬编码。
2.2 测试环境与生产环境资源配置对比
项目通过环境变量ENVIRONMENT来区分test(测试)和prod(生产)部署,两者在资源配置上有显著差异,这是为了平衡成本与性能。理解这张表,能帮你更好地规划资源预算。
| 组件 | Helm Chart 对应配置项 | 测试环境 (test) | 生产环境 (prod) | 配置差异解读与选型建议 |
|---|---|---|---|---|
| S3 存储桶 | persistence | 1个 | 1个 | 两者都是1个,但生产环境应考虑启用版本控制、跨区域复制等高级功能,并在Helm values中配置相应的生命周期策略。 |
| Redis 缓存 | externalRedis | 1节点, 2 vCPU, 6.38 GB内存 | 1节点, 2 vCPU,12.93 GB内存 | 核心差异在内存。Dify重度使用Redis进行队列处理和缓存。测试环境6GB可能勉强够用,但生产环境下,如果并发任务多或缓存数据量大,12.93GB是更稳妥的起点。建议根据监控指标(内存使用率)后续再调整。 |
| RDS PostgreSQL | externalPostgres | 2节点(读写+只读?), 2 vCPU, 8 GB内存/节点 | 1节点,4 vCPU, 32 GB内存/节点 | 这里有个关键点:测试环境配置了2个节点,可能是为了高可用(Multi-AZ),但vCPU和内存较小。生产环境虽然只列了1个节点,但资源翻了好几倍。在实际生产部署中,强烈建议启用RDS Multi-AZ部署,即使CDK模板默认是单节点,你也应该手动修改prod.ts配置,将multiAZ设为true,以实现数据库故障自动切换。 |
| EKS 工作节点 | (Node Group配置) | 1个节点, 4 vCPU, 16 GB内存, 100 GB存储 | 6个节点,8 vCPU, 32 GB内存, 100 GB存储/节点 | 这是最明显的扩展性差异。测试环境单节点即可运行所有Pod。生产环境需要多节点保证高可用和承载更高负载。6个c5.2xlarge或m5.2xlarge实例组成的节点组,能提供足够的资源冗余和调度灵活性。 |
| OpenSearch 向量库 | vectorDB | 1节点, 2 vCPU, 16 GB内存, 100 GB存储 | 2节点,8 vCPU, 64 GB内存, 100 GB存储/节点 | 向量搜索是计算和内存密集型操作。测试环境单节点小规格仅供功能验证。生产环境必须多节点(至少2个),并采用更大的实例类型(如r5.2xlarge),以支持大规模的向量索引和并发查询。存储100GB是初始值,需根据知识库文档量预估。 |
实操心得:不要完全照搬模板的资源规格。在部署生产环境前,最好能用测试环境进行压力测试,记录下CPU、内存、数据库连接数、Redis内存使用量等关键指标,作为生产环境容量规划的依据。AWS成本计算器(Calculator)是你的好朋友,提前算一下月度费用。
2.3 为什么选择这套技术栈?
- AWS CDK vs. 原生CloudFormation/Terraform:
- 可编程性:CDK允许你使用循环、条件判断、函数等编程逻辑来生成资源模板,这在定义多个相似子网、安全组规则时特别高效。
- 抽象与复用:你可以将一套通用的网络或数据库配置封装成可复用的“构造块”(Construct),在不同项目间共享。
- 类型安全:使用TypeScript,能在编码阶段就发现许多配置错误,比如拼写错误或参数类型不匹配,这比在部署时才发现CloudFormation报错要省时得多。
- EKS vs. EC2自建K8s:
- 托管控制平面:AWS负责K8s Master节点(API Server, etcd等)的运维、升级和高可用,你只需要管理Worker节点,大大降低了运维复杂度。
- 与AWS服务深度集成:EKS Pod可以轻松地使用IAM角色进行权限管理(IRSA),服务可以方便地使用ALB Ingress Controller暴露,这种原生集成是自建集群难以比拟的。
- 使用外部托管数据库/缓存(RDS, ElastiCache):
- 核心优势是“不用操心”:备份、故障恢复、版本升级、性能监控,这些繁重的DBA工作都由AWS负责。对于Dify这样的应用,数据库的稳定性和可靠性是生命线,交给RDS是更明智的选择。
- 性能与扩展:RDS和ElastiCache都提供一键垂直扩展(修改实例类型)和只读副本等功能,能轻松应对业务增长。
3. 部署前关键准备与环境配置详解
万事开头难,部署前的准备工作决定了后续流程的顺畅程度。这一步的核心是理解并正确配置.env环境变量文件。
3.1 基础工具与AWS账号准备
- 安装并配置AWS CLI:这是与AWS交互的基石。确保安装最新版本,并使用
aws configure命令配置好具有足够权限的IAM用户的Access Key和Secret Key。这个用户需要拥有创建EC2、VPC、EKS、RDS等资源的权限。一个简单的办法是临时附加AdministratorAccess策略(仅用于部署,完成后应移除),或者根据CDK代码精确配置最小权限策略。 - 安装Node.js与CDK CLI:项目使用TypeScript编写,需要Node.js环境(建议LTS版本)。通过
npm install -g aws-cdk安装CDK命令行工具。安装后,运行cdk --version验证。 - Clone项目代码:
git clone https://github.com/langgenius/aws-cdk-for-dify.git,然后进入项目目录。
3.2 环境变量文件(.env)深度解析
执行cp .env.example .env复制模板,然后编辑.env文件。每一个变量都至关重要。
# .env 文件示例 (关键部分) ENVIRONMENT=prod CDK_DEFAULT_REGION=us-east-1 CDK_DEFAULT_ACCOUNT=123456789012 DEPLOY_VPC_ID=vpc-xxxxxxxENVIRONMENT:设置为test或prod。这会决定CDK去读取configs/目录下的test.ts或prod.ts配置文件,从而应用不同的资源规格。CDK_DEFAULT_REGION/ACCOUNT:指定部署的目标区域和账号ID。确保你CLI配置的用户有权在该区域操作。
关于VPC的决策:使用现有VPC还是新建VPC?
这是第一个关键决策点。DEPLOY_VPC_ID如果留空,CDK会为你创建一个全新的VPC。这很干净,但可能与你账号内现有的其他服务(如企业VPN网关、专线连接)网络不通。
强烈建议使用现有VPC,特别是生产环境。理由是你的Dify平台未来可能需要访问公司内网的其他服务(如AD域认证、内部API)。使用现有VPC,并在其安全组规则中配置好访问策略,是最佳实践。
使用现有VPC必须完成的子网标记工作!
如果你填写了DEPLOY_VPC_ID,必须手动为你计划使用的子网打上特定的标签。这是AWS Load Balancer Controller自动发现子网所必需的。如果漏了这一步,部署ALB时会失败。
| 子网类型 | 需要添加的标签键 (Tag Key) | 标签值 (Tag Value) | 说明 |
|---|---|---|---|
| 公有子网 | kubernetes.io/role/elb | 1 | 用于承载面向互联网的Application Load Balancer (ALB)。 |
| 私有子网 | kubernetes.io/role/internal-elb | 1 | 用于承载内部负载均衡器(本例中未使用,但按最佳实践标记)。实际上,EKS节点通常放在私有子网,这个标签对于某些内部服务暴露也有用。 |
踩坑记录:我第一次部署时,跳过了子网标记,CDK部署过程没有报错,但最后在创建Ingress资源时,ALB一直处于
provisioning状态。查看AWS Load Balancer Controller的Pod日志,才发现是找不到带有正确标签的子网。所以,务必在运行npm run deploy之前,去AWS控制台检查并补全子网标签。
子网ID列表配置
当你使用现有VPC时,需要明确指定各个服务使用的子网。这提供了极高的灵活性。所有值都是逗号分隔的子网ID列表,且不能有空格。
EKS_CLUSTER_SUBNETS=subnet-a1,subnet-b2 EKS_NODES_SUBNETS=subnet-c3,subnet-d4 REDIS_SUBNETS=subnet-c3 RDS_SUBNETS=subnet-c3,subnet-d4 OPENSEARCH_SUBNETS=subnet-c3,subnet-d4EKS_CLUSTER_SUBNETS:EKS控制平面(托管API Server)所在的子网。必须至少2个,且位于不同可用区(AZ),这是EKS高可用的要求。EKS_NODES_SUBNETS:EKS工作节点(EC2实例)所在的子网。同样建议至少2个不同AZ的子网。出于安全考虑,强烈建议使用私有子网。RDS_SUBNETS:RDS数据库实例的子网。必须至少2个不同AZ的子网,这是为了支持Multi-AZ部署(高可用模式)。即使你初始部署单实例,为未来扩展留好配置。REDIS_SUBNETS/OPENSEARCH_SUBNETS:ElastiCache和OpenSearch通常也建议部署在私有子网。它们可以和其他服务(如EKS节点)共享子网,但更好的做法是使用独立的、专门的数据子网,便于网络ACL管理。
OpenSearch主用户凭证
OPENSEARCH_ADMINNAME=admin OPENSEARCH_PASSWORD=YourStrongPassword123!- 这里设置的用户名和密码,后续在配置Helm Chart的
vectorDB部分时会用到。请务必使用强密码并妥善保存。
中国区用户特别注意
AWS_EKS_CHART_REPO_URL=https://xxxxxx- 如果你在AWS中国区(北京或宁夏)部署,必须配置此变量。因为AWS中国区的服务端点与国际区不同。这个URL需要联系Dify团队获取。如果不配置,在部署EKS集群时可能会因为拉取不到正确的AMI镜像或组件而失败。
3.3 CDK引导与部署
环境变量配好后,就可以开始部署了。
CDK引导(Bootstrap):运行
npm run init。这个命令背后是cdk bootstrap。它会在你指定的AWS账户和区域中,创建一个S3桶和少量其他资源,用于存储CDK生成的CloudFormation模板和执行过程中的资产。一个账户在一个区域只需要执行一次引导。执行部署:运行
npm run deploy。这是最核心的一步,CDK会开始执行:- 解析
lib/目录下的CDK代码。 - 根据
ENVIRONMENT变量选择配置文件,合成CloudFormation模板。 - 将模板上传到引导阶段创建的S3桶。
- 在CloudFormation中创建或更新一个栈(Stack),开始按依赖顺序创建所有AWS资源。
这个过程会持续45-60分钟。你可以在AWS CloudFormation控制台实时查看进度。首次部署时,建议打开一个终端窗口,运行
cdk deploy --require-approval never(或直接npm run deploy)并保持关注,因为创建EKS集群和OpenSearch域耗时较长。- 解析
4. 部署后配置与Dify安装实战
CDK成功运行后,AWS资源已经就绪,但Dify应用本身还没有安装。我们需要配置Kubernetes的访问权限,并修改Helm Chart的Values文件,将Dify连接到刚创建好的AWS服务上。
4.1 配置EKS集群访问权限
CDK创建的EKS集群,默认你的部署用户(通过AWS CLI配置)是没有Kubernetes RBAC权限的。需要手动添加。
更新
kubeconfig:使用AWS CLI命令让本地的kubectl能访问集群。aws eks update-kubeconfig --region us-east-1 --name Dify-Production-DifyStackProd-EKS--region:替换为你的部署区域。--name:替换为你的EKS集群名。集群名有固定格式,通常是Dify-{Environment}-DifyStack{Environment}-EKS,你可以在EKS控制台或CDK输出中找到。
运行后,可以执行
kubectl get nodes来验证,应该能看到对应数量的Worker节点处于Ready状态。为IAM用户/角色添加集群访问权限(关键步骤):
- 进入AWS EKS控制台,找到你的集群,进入“访问” > “管理访问”。
- 在“身份提供者”部分,确保你的IAM实体(用户或角色)已被添加。CDK通常会自动添加执行部署的IAM用户。
- 更重要的是,你需要为这个IAM实体绑定Kubernetes RBAC角色。点击“创建访问条目”。
- 选择你的IAM用户,在权限策略中,至少勾选
AmazonEKSClusterAdminPolicy(集群管理员)。为了保险起见,可以把AmazonEKSAdminPolicy和AmazonEKSAdminViewPolicy也勾上。 - 保存后,等待一两分钟,你的
kubectl命令就应该拥有完全权限了。
注意事项:如果你是在CI/CD流水线中部署,这里配置的应该是一个IAM角色(Role),而不是用户。确保该角色被正确添加到EKS的访问条目中。
4.2 详解Helm Values.yaml配置
这是连接Dify应用和AWS基础设施的桥梁。项目目录下应该有一个values.yaml文件,我们需要修改它。核心是配置“外部服务”。
1. 持久化存储 (S3)Dify需要存储文件。我们将使用CDK创建的S3桶。
persistence: type: "s3" s3: endpoint: "https://s3.us-east-1.amazonaws.com" # 替换为你的区域端点 region: "us-east-1" # 替换为你的区域 bucketName: "dify-production-stack-difyassetsxxxxx" # 替换为CDK创建的桶名 useAwsManagedIam: true # 关键!设为true,让Pod通过IAM角色访问S3bucketName:去AWS S3控制台,找到名字类似dify-{环境}-stack-difyassetsxxxxx的桶。useAwsManagedIam: true:这是最佳实践。CDK已经为EKS集群的Pod创建了一个IAM角色(通过ServiceAccount),并赋予了S3读写权限。这样就不需要在配置里写任何Access Key了。
2. 外部数据库 (RDS PostgreSQL)禁用内置的PostgreSQL,改用我们创建的RDS实例。
postgre: enabled: false # 关闭内置数据库 externalPostgres: enabled: true address: "dify-prod-postgres.xxxxxx.us-east-1.rds.amazonaws.com" # RDS终端节点 port: 5432 credentials: dify: database: "postgres" username: "clusteradmin" # 默认用户名,可在RDS控制台修改 password: "从SecretsManager获取" # 重要! sslmode: "disable" # 生产环境建议启用SSL,此处为简化先disableaddress:在RDS控制台,找到创建的数据库实例,查看其“终端节点”。password:密码在哪里?CDK将数据库主密码自动保存在了AWSSecrets Manager服务中。你需要:- 进入Secrets Manager控制台。
- 找到一个名字包含
DifyStackProd、RDS、Credentials的密钥。 - 点击“检索密钥值”,在
password字段中找到密码,复制到此处。
3. 外部缓存 (ElastiCache Redis)
redis: enabled: false externalRedis: enabled: true host: "dify-prod-redis.xxxxxx.ng.0001.use1.cache.amazonaws.com" # Redis主终端节点 port: 6379 username: "" # 如果启用Redis 6.0+的ACL,这里填用户名 password: "" # 如果启用认证,在此填写 useSSL: false # 生产环境建议启用host:在ElastiCache控制台,找到Redis集群,查看“主终端节点”。注意:只复制主机名部分,不要包含端口号(例如,dify-prod-redis.xxxxxx.ng.0001.use1.cache.amazonaws.com)。
4. 外部向量数据库 (OpenSearch)
vectorDB: useExternal: true externalType: "opensearch" externalOpenSearch: host: "search-dify-prod-opensearch-xxxxxx.us-east-1.es.amazonaws.com" # OpenSearch域终端节点 port: 443 user: "admin" # 即 .env 中的 OPENSEARCH_ADMINNAME password: "YourStrongPassword123!" # 即 .env 中的 OPENSEARCH_PASSWORD useTLS: true # 必须为true,因为端口是443host:在OpenSearch控制台,找到创建的域,查看“域终端节点”。同样,只复制主机名,去掉https://前缀。
5. 配置Docker镜像拉取密钥Dify Enterprise的镜像是私有的,需要凭证。
kubectl create secret docker-registry regcred \ --docker-server=registry.dify.ai \ --docker-username=你的用户名 \ --docker-password=你的密码 \ --namespace=default- 你需要联系Dify团队(support@dify.ai)获取有效的用户名和密码。
- 这个Secret必须在安装Helm Chart之前创建好。
6. 配置Ingress (ALB) 和 TLS(生产环境必做)对于测试,可以用简单的配置快速访问。但对于生产环境,必须配置HTTPS和自定义域名。
- 申请ACM证书:在AWS Certificate Manager (ACM) 中,为你计划使用的所有域名申请或导入SSL证书(例如
*.yourdomain.com或单域名证书)。证书必须和ALB在同一个AWS区域。 - 配置DNS:在你的域名服务商(如Route 53)那里,将以下域名的CNAME记录指向后续步骤中ALB的DNS名称。
console.yourdomain.comapi.yourdomain.comapp.yourdomain.comupload.yourdomain.comenterprise.yourdomain.com
- 修改
values.yaml中的域名和Ingress配置:# 设置你的域名 consoleApiDomain: "console.yourdomain.com" consoleWebDomain: "console.yourdomain.com" serviceApiDomain: "api.yourdomain.com" appApiDomain: "app.yourdomain.com" appWebDomain: "app.yourdomain.com" filesDomain: "upload.yourdomain.com" enterpriseDomain: "enterprise.yourdomain.com" # 启用TLS global: useTLS: true # 配置Ingress使用ALB并关联证书 ingress: enabled: true className: "alb" annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]' alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:123456789012:certificate/xxxx-xxxx-xxxx # 替换为你的ACM证书ARN alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06 # 推荐使用现代TLS策略certificate-arn:将你在ACM中创建的证书ARN填在这里。
4.3 执行Helm安装与验证
所有配置完成后,终于可以安装Dify了。
添加Helm仓库并更新:
helm repo add dify https://langgenius.github.io/dify-helm helm repo update安装或升级Dify:
helm upgrade --install dify dify/dify -f values.yaml--install:如果不存在则安装。-f values.yaml:指定我们修改好的配置文件。
监控安装状态:
kubectl get pods -w等待所有Pod都变成
Running状态。特别是初始化数据库的Job Pod(名字带init-db),必须成功完成(Completed状态)。获取访问地址:
- 测试环境(无域名):安装完成后,查看ALB的DNS名称:
kubectl get ingress。你会看到一个外部IP或主机名。将其映射到本地hosts文件(如/etc/hosts),指向前面配置的各个dify.local域名。 - 生产环境(有域名):DNS配置生效后(可能需要几分钟到几小时),直接通过你配置的域名访问,例如
https://console.yourdomain.com。
- 测试环境(无域名):安装完成后,查看ALB的DNS名称:
完成初始化:
- 首次访问
https://console.yourdomain.com,会进入Dify控制台的Web安装界面。按照提示设置管理员账号等信息。 - 重要顺序:必须先完成控制台(Console)的初始化,然后才能登录企业仪表盘(Enterprise Dashboard)。企业仪表盘的默认账号是
dashboard@dify.ai/difyai123456,登录后请立即修改密码。
- 首次访问
5. 常见问题排查与运维技巧
即使按照步骤操作,也可能会遇到问题。这里记录了一些我们遇到过的典型问题及其解决方法。
5.1 部署阶段问题
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| CDK部署失败,回滚 | 1. IAM权限不足。 2. 资源配额超限(如VPC数量、EIP数量)。 3. 子网配置错误(如AZ不支持某实例类型)。 | 1. 查看CloudFormation栈事件的错误信息,通常很明确。 2. 检查IAM用户的策略是否包含所需服务的全量操作权限(如 ec2:*,eks:*,rds:*等)。3. 去AWS服务配额控制台,检查相关配额(如 Running On-Demand Standard (A, C, D, H, I, M, R, T, Z) instances)。4. 确认子网所在的AZ是否支持你选择的RDS/OpenSearch实例类型。 |
EKS节点组创建失败,节点一直处于NotReady | 1. 节点IAM角色权限不足。 2. 节点无法拉取ECR镜像或访问其他AWS服务端点。 | 1. 检查EKS节点实例的IAM角色(名称类似DifyStackProd-NodeInstanceRole-XXXX),确保其附加了AmazonEKSWorkerNodePolicy,AmazonEC2ContainerRegistryReadOnly,AmazonEKS_CNI_Policy等托管策略。2. 确认私有子网已关联NAT网关或实例,可以访问互联网。检查节点的 /var/log/cloud-init-output.log日志。 |
| OpenSearch域创建超时(卡住) | OpenSearch域创建本身就很慢(20-30分钟),如果资源规格较大或启用精细访问控制,更慢。 | 耐心等待。可以在CloudFormation事件中查看具体进度。如果超过1小时仍失败,检查是否因为VPC配置问题(如安全组规则过严)导致健康检查失败。 |
5.2 安装后访问与配置问题
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 访问域名显示“502 Bad Gateway”或“503 Service Unavailable” | 1. ALB目标组健康检查失败。 2. Dify Pod没有成功启动。 3. Ingress资源未正确配置。 | 1. 在EC2控制台的“目标组”中,检查健康状态。如果是unhealthy,查看“详细信息”中的失败原因。2. 运行 kubectl get pods,查看是否有Pod处于CrashLoopBackOff或Error状态。用kubectl logs <pod-name>查看具体日志。3. 运行 kubectl describe ingress,查看Events和Rules,确认ALB监听器、规则、证书ARN是否正确关联。 |
| Dify控制台能打开,但登录或创建应用时报数据库连接错误 | 1.values.yaml中数据库连接信息错误。2. RDS安全组未允许EKS节点IP访问。 3. 数据库初始化未完成。 | 1. 仔细核对externalPostgres下的address、username、password。密码务必从Secrets Manager复制。2. 检查RDS实例的安全组入站规则,确保包含了EKS节点所在子网的安全组或IP段(端口5432)。 3. 查看初始化Job的日志: kubectl logs jobs/init-db-xxxx。 |
| 知识库上传文档失败,或向量处理报错 | 1. OpenSearch连接失败。 2. S3存储配置错误,导致文件无法上传。 3. Pod的IAM角色无权访问S3。 | 1. 检查values.yaml中externalOpenSearch的host、user、password。用curl或浏览器测试OpenSearch端点是否可访问(需要配置相同的认证)。2. 检查S3桶策略,确保对应IAM角色有 PutObject、GetObject等权限。检查values.yaml中useAwsManagedIam是否为true。3. 查看Dify API Server Pod的日志,通常会有明确的错误信息。 |
Pod提示ImagePullBackOff | 1. Docker镜像拉取密钥(regcred)未创建或创建在错误的命名空间。2. 密钥中的用户名密码无效。 | 1. 运行kubectl get secret regcred确认Secret存在。确保Helm Chart的imagePullSecrets配置正确引用了regcred(通常Chart已内置此配置)。2. 重新创建Secret,并确保密码正确。可以尝试用 docker login registry.dify.ai命令手动验证凭证。 |
5.3 日常运维与优化建议
监控与告警:
- 基础设施层:启用AWS CloudWatch对RDS、Redis、OpenSearch、ALB、EKS节点的关键指标监控(CPU、内存、连接数、延迟等),并设置告警。
- 应用层:在Dify企业仪表盘中查看应用使用情况。考虑部署Prometheus和Grafana到EKS集群,监控Pod级别的资源使用和业务指标。
备份策略:
- RDS:启用自动备份和时间点恢复(PITR)。根据业务要求设置备份保留期。
- OpenSearch:配置手动或自动快照到S3。
- S3:启用版本控制,防止误删除。对于重要数据,可以配置跨区域复制。
- EKS配置:定期备份Helm release状态和重要的K8s ConfigMap、Secret(例如
kubectl get all -o yaml > backup.yaml)。
成本优化:
- 非生产环境:设置自动启停。例如,使用AWS Instance Scheduler在晚上和周末关闭EKS节点、RDS、OpenSearch等资源。
- 资源规格:初期可按模板部署,运行一段时间后,根据CloudWatch监控数据,对资源进行垂直或水平缩放。例如,RDS实例规格、EKS节点数量、OpenSearch节点类型等都可以调整。
- 存储类型:S3中不常访问的文件可以配置生命周期策略,自动转移到更便宜的S3 Standard-IA或Glacier存储类别。
安全加固:
- 数据库SSL:将
values.yaml中的sslmode从disable改为require或verify-full,并在RDS中强制启用SSL。 - Redis认证:考虑启用ElastiCache Redis的AUTH令牌,并在配置中填写密码。
- 网络隔离:细化安全组规则,遵循最小权限原则。例如,只允许特定的办公网络IP访问EKS的SSH堡垒机(如果有),只允许ALB访问应用Pod。
- 镜像安全:定期更新Dify镜像版本,以获取安全补丁和新功能。
- 数据库SSL:将
6. 环境销毁与资源清理
当测试完成或需要彻底清理时,可以使用CDK销毁所有创建的资源,避免产生不必要的费用。
执行销毁命令:
npm run destroy这个命令会触发
cdk destroy,按照依赖关系的反向顺序删除CloudFormation栈中的所有资源。这个过程大约需要20分钟或更久,因为删除RDS、OpenSearch这类托管服务需要时间。关键检查与手动清理:
- CloudFormation栈状态:在AWS CloudFormation控制台,确认名为
DifyStackProd(或DifyStackTest)的栈已被成功删除,状态为DELETE_COMPLETE。 - VPC残留:这是最常见的“坑”。CDK创建的VPC,如果内部有依赖资源(如NAT网关的弹性IP)删除失败,可能导致整个VPC删除失败,从而栈状态卡在
DELETE_FAILED。你需要:- 进入VPC控制台,检查是否还有名为
DifyStackProd-VPC或类似的VPC存在。 - 如果存在,尝试手动删除其内部的子网、路由表、互联网网关、NAT网关等(如果还有残留)。
- 最后再尝试删除VPC本身。
- 回到CloudFormation,对卡住的栈选择“删除栈”,并勾选“保留失败资源”(这样至少能把栈记录清掉)。
- 进入VPC控制台,检查是否还有名为
- S3桶残留:如果S3桶里有数据,CDK可能无法自动删除。你需要手动清空桶后再尝试销毁栈,或者在销毁前手动删除桶内对象。
- Secrets Manager:检查Secrets Manager中是否还有Dify相关的密钥残留,手动删除。
- CloudFormation栈状态:在AWS CloudFormation控制台,确认名为
重要提醒:销毁操作是不可逆的,所有数据库内的数据、S3桶里的文件、OpenSearch中的向量索引都会丢失。请在操作前确认已做好必要的数据备份。对于生产环境,建议先通过修改CDK代码将资源规格缩到最小进行测试,确认无误后再执行完整销毁。
