Skyvern 如何在 Kubernetes 部署生产环境并配置 PVC、TLS 与水平扩展?
【免费下载链接】skyvernAutomate browser based workflows with AI项目地址: https://gitcode.com/GitHub_Trending/sk/skyvern
如果你在需要水平扩展、高可用,或者要把 Skyvern 并入现有 Kubernetes 基础设施的环境中运行它,官方提供的路径是 kubernetes-deployment 目录下的原生 K8s 清单:用kubernetes-deployment/k8s-deploy.sh一键部署后端 API(含内嵌浏览器)、前端 UI(含 artifact 服务)和 PostgreSQL 三个服务。本环境要求集群版本 1.19+、已配置好kubectl、装有 Ingress Controller(清单按 Traefik 编写,其他控制器需自行改注解),以及一个可用的 LLM API key。
部署架构如下:Ingress 按路径分发——/api与/v1到skyvern-backend:8000,/artifacts到skyvern-frontend:9090,其余路径到skyvern-frontend:8080;后端直连集群内postgres:5432,并访问外部 LLM 服务。
| 组件 | 服务 | 职责 |
|---|---|---|
| Backend | skyvern-backend | API 服务 + 内嵌浏览器 |
| Frontend | skyvern-frontend | Web UI + artifact 服务器 |
| PostgreSQL | postgres | 任务、工作流、凭据数据库 |
官方文档对此有一条明确警告:不要在 Ingress 层加认证之前把这套部署暴露到公网。
准备条件
- 一个 1.19+ 的 Kubernetes 集群,
kubectl已指向该集群; - 集群中运行着 Ingress Controller(清单默认 Traefik,
ingressClassName和注解按实际控制器修改); - LLM API key(OpenAI、Anthropic、Azure 等任一);
- 克隆仓库并进入部署目录:
git clone https://github.com/Skyvern-AI/skyvern.git cd skyvern/kubernetes-deployment清单结构如下,后文所有修改都在这几个文件上进行:
kubernetes-deployment/ ├── namespace.yaml # 创建 'skyvern' 命名空间 ├── k8s-deploy.sh # 部署脚本 ├── ingress.yaml # Ingress 配置 ├── backend/ │ ├── backend-secrets.yaml # 环境变量 │ ├── backend-deployment.yaml # Pod 规格 │ └── backend-service.yaml # ClusterIP 服务 ├── frontend/ │ ├── frontend-secrets.yaml # 环境变量 │ ├── frontend-deployment.yaml # Pod 规格 │ └── frontend-service.yaml # ClusterIP 服务 └── postgres/ ├── postgres-secrets.yaml # 数据库凭据 ├── postgres-storage.yaml # PersistentVolumeClaim ├── postgres-deployment.yaml # Pod 规格 └── postgres-service.yaml # ClusterIP 服务配置 Secrets 与 Ingress
1. 后端 Secret
编辑 backend/backend-secrets.yaml,填入 LLM 凭据、数据库连接和浏览器设置。K8s 文档给出的示例形态:
apiVersion: v1 kind: Secret metadata: name: skyvern-backend-env namespace: skyvern type: Opaque stringData: ENV: local # LLM Configuration - set your provider ENABLE_OPENAI: "true" OPENAI_API_KEY: "sk-your-api-key-here" LLM_KEY: "OPENAI_GPT5_5" # Database - points to the PostgreSQL service DATABASE_STRING: "postgresql+psycopg://skyvern:skyvern@postgres/skyvern" # Browser settings BROWSER_TYPE: "chromium-headless" BROWSER_ACTION_TIMEOUT_MS: "5000" MAX_STEPS_PER_RUN: "10" # Server PORT: "8000" LOG_LEVEL: "INFO"把OPENAI_API_KEY换成你的真实 key,LLM_KEY按所选模型调整;其他 LLM 供应商的配置方式见 LLM Configuration。DATABASE_STRING指向集群内postgres服务,与 postgres/postgres-secrets.yaml 中的默认凭据skyvern/skyvern对应。
部署目录的 README 还建议:可先按仓库根目录的.env完成一次本地 Skyvern 初始配置,再把生成的值拷入backend-secrets.yaml,并增删不需要的变量。
2. 前端 Secret
编辑 frontend/frontend-secrets.yaml,其中的skyvern.example.com全部替换为你的实际域名:
apiVersion: v1 kind: Secret metadata: name: skyvern-frontend-env namespace: skyvern type: Opaque stringData: VITE_API_BASE_URL: "http://skyvern.example.com/api/v1" VITE_WSS_BASE_URL: "ws://skyvern.example.com/api/v1" VITE_ARTIFACT_API_BASE_URL: "http://skyvern.example.com/artifacts" ARTIFACT_ALLOWED_ORIGIN: "http://skyvern.example.com" VITE_SKYVERN_API_KEY: "" # 首次部署留空两点注意:
ARTIFACT_ALLOWED_ORIGIN必须填浏览器可见的 UI 源(如http://skyvern.example.com),而不是 artifact 服务器 URL(/artifacts那个地址);VITE_SKYVERN_API_KEY首次部署留空,部署完成后再回填(见下文第 7 步)。
3. Ingress
编辑 ingress.yaml:把ingressClassName改成你实际使用的控制器(清单默认traefik),同步调整对应的 router 注解,并把host改成你的域名。路由规则为/api、/v1→ 后端 8000 端口,/artifacts→ 前端 9090 端口,/→ 前端 8080 端口。
执行部署与验证
4. 运行部署脚本
chmod +x k8s-deploy.sh ./k8s-deploy.sh脚本按固定顺序kubectl apply:命名空间 → PostgreSQL(secrets、storage、deployment、service)→ 后端 → 前端 → Ingress。注意它是全量 apply 以上清单,重复执行即重新部署。
5. 检查 Pod 状态
kubectl get pods -n skyvern文档给出的示例输出(xxx为实际 Pod 后缀):
NAME READY STATUS RESTARTS AGE postgres-xxx 1/1 Running 0 2m skyvern-backend-xxx 1/1 Running 0 1m skyvern-frontend-xxx 1/1 Running 0 30s三个 Pod 都Running且 READY 为1/1即部署完成。后端 Pod 因为启动时要跑数据库迁移,就绪通常需要 1-2 分钟,属正常现象,不要在这期间重启它。
6. 访问 UI
在浏览器打开你配置的域名(如https://skyvern.example.com),能看到 Skyvern dashboard 即成功。
7. 获取 API key 并回填前端 Secret
先确认后端 Pod 在kubectl get pods -n skyvern的READY列显示1/1(API key 文件在启动时生成,Pod 未就绪前不存在),然后:
kubectl exec -n skyvern deployment/skyvern-backend -- cat /app/.skyvern/credentials.toml复制输出中的cred值,更新frontend/frontend-secrets.yaml:
VITE_SKYVERN_API_KEY: "eyJhbGciOiJIUzI1..."再重新应用并重启前端:
kubectl apply -f frontend/frontend-secrets.yaml -n skyvern kubectl rollout restart deployment/skyvern-frontend -n skyvern如果改完前端 Secret 后页面没生效,部署目录的 README 给出了处理方式:删除前端和后端 Pod 让 Deployment 重建(会中断服务,需确认无正在运行的任务):
kubectl delete pod -n skyvern -l app=skyvern-frontend kubectl delete pod -n skyvern -l app=skyvern-backend生产化存储:hostPath 换 PVC
默认清单里,PostgreSQL 数据用的是 postgres/postgres-storage.yaml 中的 PVC(postgres-data,5Gi,ReadWriteOnce);而后端和前端的 artifacts、videos、har、log、credentials 目录全部挂载hostPath卷(见 backend/backend-deployment.yaml)。hostPath 在单节点集群可用,但不适用于多节点生产部署。
生产环境的做法是把后端的hostPath卷替换为 PVC。编辑 backend/backend-deployment.yaml 的volumes段:
volumes: - name: artifacts persistentVolumeClaim: claimName: skyvern-artifacts-pvc - name: videos persistentVolumeClaim: claimName: skyvern-videos-pvc再创建对应的 PVC(文档示例中给出为skyvern-storage.yaml):
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: skyvern-artifacts-pvc namespace: skyvern spec: accessModes: - ReadWriteOnce resources: requests: storage: 50Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: skyvern-videos-pvc namespace: skyvern spec: accessModes: - ReadWriteOnce resources: requests: storage: 100Gi容量与accessModes需按你的 StorageClass 实际能力调整;若 StorageClass 不支持ReadWriteMany,注意后文水平扩展一节对存储的约束。
如果集群在云上,也可以不挂本地卷,而是通过后端环境变量把 artifact 存储切到 S3 或 Azure Blob(SKYVERN_STORAGE_TYPE=s3/azureblob等),具体变量见 Storage Configuration。该文档还说明:录像(videos)无论何种存储类型始终存本地VIDEO_PATH。
另一个生产选项是把数据库换成托管 PostgreSQL(RDS、Cloud SQL、Azure Database):从部署中移除postgres/下四个清单,并把backend-secrets.yaml的DATABASE_STRING改为postgresql+psycopg://user:password@your-db-host:5432/skyvern。
水平扩展
提高副本数
要跑多个后端实例,把 backend/backend-deployment.yaml 的replicas调大:
spec: replicas: 3 # Run 3 backend pods每个 Pod 各自运行独立的浏览器实例,任务在多个 Pod 间分布。
这里有一条硬性限制(文档以 Note 形式明确给出):水平扩展时存储后端必须支持并发访问——S3、Azure Blob,或ReadWriteManyPVC;ReadWriteOnce的本地 PVC 无法跨多个 Pod 工作。也就是说,如果你的存储仍是上一步的ReadWriteOncePVC,就不能直接扩后端副本,需先切到共享存储或云对象存储。
资源限制
给后端容器加资源限制,防止 Pod 挤占节点资源:
containers: - name: skyvern-backend resources: requests: memory: "2Gi" cpu: "500m" limits: memory: "4Gi" cpu: "2000m"浏览器实例内存占用较大,文档建议每个 Pod 至少 2GB 起步(即requests.memory不低于2Gi)。
配置 TLS(HTTPS)
启用 HTTPS 分三步:
- 在 ingress.yaml 中取消
spec.tls注释并填上你的值(清单里该段默认是注释状态):
spec: tls: - hosts: - skyvern.example.com secretName: skyvern-tls-secret- 创建 TLS Secret(
path/to/tls.crt、path/to/tls.key替换为你实际的证书与私钥文件路径):
kubectl create secret tls skyvern-tls-secret \ --cert=path/to/tls.crt \ --key=path/to/tls.key \ -n skyvern文档同时提到可以用 cert-manager 做证书自动管理。
- 把前端 Secret 的协议改为
https/wss,并重新应用:
VITE_API_BASE_URL: "https://skyvern.example.com/api/v1" VITE_WSS_BASE_URL: "wss://skyvern.example.com/api/v1"部署目录的 README 对 TLS 的说明与此一致:解开ingress.yaml中 TLS 相关行的注释、替换为自己的值,同时把frontend-secrets.yaml中需要 https 的地方改过来。
常见问题排查
- Pod 卡在 Pending:
kubectl describe pod -n skyvern <pod-name>。文档列出的常见原因:节点资源不足、PersistentVolume 不可用、镜像拉取失败。 - 后端启动即崩溃:
kubectl logs -n skyvern deployment/skyvern-backend。常见原因:LLM API key 无效、数据库连接失败、缺少环境变量。 - 前端显示 "Unauthorized":前端 Secret 里的 API key 与后端生成的 key 不匹配,重新从后端 Pod 拷贝
cred值回填(见上文第 7 步)。 - Ingress 不路由:确认 Ingress Controller 在运行,并检查资源本身:
kubectl get ingress -n skyvern kubectl describe ingress skyvern-ingress -n skyvern限制与清理
- 这是官方 README 定位为"基础 K8s 部署"的方案:README 明确说明它可以创建并运行工作流,但 9222/9090 端口利用、部署脚本改进等方面留待完善;不要把它当成完备的生产加固方案。
- 公网暴露前必须在 Ingress 层加认证(正文开头的警告与 README 提醒都强调这一点)。
- 卸载整个部署:
kubectl delete namespace skyvern这会删除skyvern命名空间内的所有资源。若此前用的是 hostPath 卷,节点上的/data/artifacts、/data/videos、/data/har、/data/log、/app/.skyvern不会被 K8s 清理;README 给出的清理命令是删除宿主机上的/app/与/data/目录——这会永久删除主机上这些目录内的全部数据(含未同步的 artifacts 与录像),执行前务必确认没有需要保留的文件。
- 后续方向(文档给出的 Next steps):按 Storage Configuration 配置 S3/Azure Blob 存储,按 LLM Configuration 增加 LLM 供应商。
【免费下载链接】skyvernAutomate browser based workflows with AI项目地址: https://gitcode.com/GitHub_Trending/sk/skyvern
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考