Added Kubernetes deployment files (#2719)

This commit is contained in:
Cristian Branet
2025-06-22 10:00:24 +03:00
committed by GitHub
parent 10785812e8
commit 681dab864c
14 changed files with 385 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
# Skyvern Kubernetes Deployment
## REMINDER: It is not recommended to deploy Skyvern on the Internet without using some form of authentication! It is recommended to use this deployment for network without exposure to the Internet.
## General
This README has the purpose to explain the way Skyvern is deployed using Kubernetes.
One should take into consideration how it wants to deploy the application, either by using a service type LoadBalancer, which directly exposes port 8000 and 8080 on the host IP or by using ClusterIP service type, which requires an ingress and consequently a domain name.
This latter results in having the following endpoints:
> FRONTEND: http(s)://skyvern.example.com/
> BACKEND: http(s)://skyvern.example.com/api/
There is also a simple deploy script called `k8s-deploy.sh`, which runs the necessary commands to create the namespace and apply the `yaml` files.
If you look to redeploy from zero, make sure to delete the folders created on the hosts:
```
rm -rf /app/ /data/
```
## Environment variables
Environment variables must be set before running. So, before this type of deployment, the user is recommended to do the initial Skyvern setup to generate the backend's `.env` file, then copy the values from it to `backend-secrets.yaml` and add or either removed unused variables. You also have to replace the values in the `frontend-secrets.yaml` where needed
For the SKYVERN_API_KEY, run initially without setting any value, then copy the correct value from the `application frontend > settings > copy API key` and add it to the secrets files. Then, run `./k8s-deploy` again. If changes don't apply, delete the pods using:
```
kubectl delete pod -n skyvern -l app=skyvern-frontend
kubectl delete pod -n skyvern -l app=skyvern-backend
```
## TLS
If you decide to use TLS, uncomment the lines from the `ingress.yaml` related to it and replace with your own values, also make sure you modify the values in the `frontend-secrets.yaml` where https needs to be used instead of http.
> This is a basic K8s deployment of Skyvern and can be successfully used to create and run workflows. Further improvements may be made considering the use of the ports 9222 and 9090, improving the deployment scripts and integrating it with existing ones, etc.

View File

@@ -0,0 +1,63 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: skyvern-backend
namespace: skyvern
spec:
replicas: 1
selector:
matchLabels:
app: skyvern-backend
template:
metadata:
labels:
app: skyvern-backend
spec:
containers:
- name: skyvern-backend
image: public.ecr.aws/skyvern/skyvern:latest
ports:
- containerPort: 8000
- containerPort: 9222
envFrom:
- secretRef:
name: skyvern-backend-env
volumeMounts:
- name: artifacts
mountPath: /data/artifacts
- name: videos
mountPath: /data/videos
- name: har
mountPath: /data/har
- name: log
mountPath: /data/log
- name: streamlit
mountPath: /app/.streamlit
readinessProbe:
exec:
command: ["test", "-f", "/app/.streamlit/secrets.toml"]
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 5
volumes:
- name: artifacts
hostPath:
path: /data/artifacts
type: DirectoryOrCreate
- name: videos
hostPath:
path: /data/videos
type: DirectoryOrCreate
- name: har
hostPath:
path: /data/har
type: DirectoryOrCreate
- name: log
hostPath:
path: /data/log
type: DirectoryOrCreate
- name: streamlit
hostPath:
path: /app/.streamlit
type: DirectoryOrCreate

View File

@@ -0,0 +1,44 @@
apiVersion: v1
kind: Secret
metadata:
name: skyvern-backend-env
namespace: skyvern
type: Opaque
stringData:
# Environment variables for the Skyvern backend
# You can use the ones from the .env file in the root of skyvern
ENV: local
ENABLE_OPENAI: ""
OPENAI_API_KEY: ""
ENABLE_ANTHROPIC: "false"
ANTHROPIC_API_KEY: ""
ENABLE_AZURE: "false"
AZURE_DEPLOYMENT: ""
AZURE_API_KEY: ""
AZURE_API_BASE: ""
AZURE_API_VERSION: ""
ENABLE_AZURE_GPT4O_MINI: "false"
AZURE_GPT4O_MINI_DEPLOYMENT: ""
AZURE_GPT4O_MINI_API_KEY: ""
AZURE_GPT4O_MINI_API_BASE: ""
AZURE_GPT4O_MINI_API_VERSION: ""
ENABLE_GEMINI: "false"
GEMINI_API_KEY: ""
ENABLE_NOVITA: "false"
NOVITA_API_KEY: ""
LLM_KEY: OPENAI_GPT4_1
SECONDARY_LLM_KEY: ""
BROWSER_TYPE: chromium-headless
MAX_SCRAPING_RETRIES: "0"
VIDEO_PATH: ./videos
BROWSER_ACTION_TIMEOUT_MS: "5000"
MAX_STEPS_PER_RUN: "50"
LOG_LEVEL: INFO
LITELLM_LOG: CRITICAL
DATABASE_STRING: postgresql+psycopg://skyvern:skyvern@postgres/skyvern
PORT: "8000"
ANALYTICS_ID: ""
ENABLE_LOG_ARTIFACTS: "false"
ENABLE_OPENAI_COMPATIBLE: "false"
SKYVERN_BASE_URL: http://localhost:8000
SKYVERN_API_KEY: ""

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: skyvern-backend
namespace: skyvern
spec:
type: ClusterIP # Or LoadBalancer
ports:
- name: http
port: 8000
targetPort: 8000
- name: cdp
port: 9222
targetPort: 9222
selector:
app: skyvern-backend

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: skyvern-frontend
namespace: skyvern
spec:
replicas: 1
selector:
matchLabels:
app: skyvern-frontend
template:
metadata:
labels:
app: skyvern-frontend
spec:
containers:
- name: skyvern-frontend
image: public.ecr.aws/skyvern/skyvern-ui:latest
ports:
- containerPort: 8080
- containerPort: 9090
envFrom:
- secretRef:
name: skyvern-frontend-env
volumeMounts:
- name: artifacts
mountPath: /data/artifacts
- name: videos
mountPath: /data/videos
- name: har
mountPath: /data/har
- name: streamlit
mountPath: /app/.streamlit
volumes:
- name: artifacts
hostPath:
path: /data/artifacts
type: DirectoryOrCreate
- name: videos
hostPath:
path: /data/videos
type: DirectoryOrCreate
- name: har
hostPath:
path: /data/har
type: DirectoryOrCreate
- name: streamlit
hostPath:
path: /app/.streamlit
type: DirectoryOrCreate

View File

@@ -0,0 +1,14 @@
apiVersion: v1
kind: Secret
metadata:
name: skyvern-frontend-env
namespace: skyvern
type: Opaque
stringData:
# You need to change the values below to match your environment
VITE_API_BASE_URL: http://skyvern.example.com/api/v1
VITE_ARTIFACT_API_BASE_URL: http://skyvern.example.com/artifacts
VITE_WSS_BASE_URL: ws://skyvern.example.com/api/v1
VITE_SKYVERN_API_KEY: ""
VITE_ENABLE_LOG_ARTIFACTS: "false"
VITE_ENABLE_CODE_BLOCK: "false"

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: skyvern-frontend
namespace: skyvern
spec:
type: ClusterIP # Or LoadBalancer
ports:
- name: http
port: 8080
targetPort: 8080
- name: artifact
port: 9090
targetPort: 9090
selector:
app: skyvern-frontend

View File

@@ -0,0 +1,40 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: skyvern-ingress
namespace: skyvern
annotations:
# You may need to change the ingress data to match your environment
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: skyvern.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: skyvern-backend
port:
number: 8000
- path: /artifacts
pathType: Prefix
backend:
service:
name: skyvern-frontend
port:
number: 9090
- path: /
pathType: Prefix
backend:
service:
name: skyvern-frontend
port:
number: 8080
#tls:
# - hosts:
# - skyvern.example.com
# secretName: ""

View File

@@ -0,0 +1,29 @@
#!/bin/bash
set -e
NAMESPACE=skyvern
echo "Creating namespace..."
kubectl apply -f namespace.yaml
echo "Deploying Postgres..."
kubectl apply -f postgres/postgres-secrets.yaml -n $NAMESPACE
kubectl apply -f postgres/postgres-storage.yaml -n $NAMESPACE
kubectl apply -f postgres/postgres-deployment.yaml -n $NAMESPACE
kubectl apply -f postgres/postgres-service.yaml -n $NAMESPACE
echo "Deploying Skyvern Backend..."
kubectl apply -f backend/backend-secrets.yaml -n $NAMESPACE
kubectl apply -f backend/backend-deployment.yaml -n $NAMESPACE
kubectl apply -f backend/backend-service.yaml -n $NAMESPACE
echo "Deploying Skyvern Frontend..."
kubectl apply -f frontend/frontend-secrets.yaml -n $NAMESPACE
kubectl apply -f frontend/frontend-deployment.yaml -n $NAMESPACE
kubectl apply -f frontend/frontend-service.yaml -n $NAMESPACE
echo "Deploying Ingress..."
kubectl apply -f ingress.yaml -n $NAMESPACE
echo "Deployment complete!"

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: skyvern

View File

@@ -0,0 +1,37 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: skyvern
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:14-alpine
ports:
- containerPort: 5432
envFrom:
- secretRef:
name: postgres-secrets
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
readinessProbe:
exec:
command: ["pg_isready", "-U", "skyvern"]
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 5
volumes:
- name: postgres-data
persistentVolumeClaim:
claimName: postgres-data

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
name: postgres-secrets
namespace: skyvern
type: Opaque
stringData:
PGDATA: /var/lib/postgresql/data/pgdata
POSTGRES_USER: skyvern
POSTGRES_PASSWORD: skyvern
POSTGRES_DB: skyvern

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: skyvern
spec:
type: ClusterIP
ports:
- port: 5432
targetPort: 5432
selector:
app: postgres

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data
namespace: skyvern
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi