Kubernetes Deployment
Deploy Zero on Kubernetes for high availability, auto-scaling, and enterprise-grade infrastructure. This guide covers Helm chart installation and manual manifest deployment.
Prerequisites:
- Kubernetes 1.28+ cluster
- kubectl configured
- Helm 3.12+ installed
- Ingress controller (nginx-ingress or traefik)
- cert-manager (for automatic TLS)
Helm Installation (Recommended)
Add Helm Repository
# Add Zero Helm repo
helm repo add zero https://charts.zero.io
helm repo update
# Search available versions
helm search repo zero Create Namespace
kubectl create namespace zero Create Secrets
# Generate secrets
JWT_SECRET=$(openssl rand -base64 32)
ENCRYPTION_KEY=$(openssl rand -base64 32)
POSTGRES_PASSWORD=$(openssl rand -base64 24)
REDIS_PASSWORD=$(openssl rand -base64 24)
# Create Kubernetes secret
kubectl create secret generic zero-secrets \
--namespace zero \
--from-literal=jwt-secret=$JWT_SECRET \
--from-literal=encryption-key=$ENCRYPTION_KEY \
--from-literal=postgres-password=$POSTGRES_PASSWORD \
--from-literal=redis-password=$REDIS_PASSWORD Configure values.yaml
# values.yaml
global:
domain: zero.yourdomain.com
api:
replicaCount: 3
image:
repository: ghcr.io/zero/zero-api
tag: latest
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 2Gi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilization: 70
web:
replicaCount: 2
image:
repository: ghcr.io/zero/zero-web
tag: latest
postgresql:
enabled: true
auth:
existingSecret: zero-secrets
secretKeys:
adminPasswordKey: postgres-password
primary:
persistence:
size: 100Gi
storageClass: fast-ssd
redis:
enabled: true
auth:
existingSecret: zero-secrets
existingSecretPasswordKey: redis-password
master:
persistence:
size: 10Gi
vpn:
enabled: true
replicaCount: 2
service:
type: LoadBalancer
annotations:
# For AWS
service.beta.kubernetes.io/aws-load-balancer-type: nlb
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: api.zero.yourdomain.com
paths:
- path: /
pathType: Prefix
service: api
- host: console.zero.yourdomain.com
paths:
- path: /
pathType: Prefix
service: web
tls:
- secretName: zero-tls
hosts:
- api.zero.yourdomain.com
- console.zero.yourdomain.com
monitoring:
enabled: true
serviceMonitor:
enabled: true
grafanaDashboard:
enabled: true Install Chart
# Install with custom values
helm install zero zero/zero \
--namespace zero \
--values values.yaml \
--wait
# Verify installation
kubectl get pods -n zero
kubectl get svc -n zero
kubectl get ingress -n zero Manual Manifest Deployment
For more control, deploy using raw Kubernetes manifests:
API Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: zero-api
namespace: zero
spec:
replicas: 3
selector:
matchLabels:
app: zero-api
template:
metadata:
labels:
app: zero-api
spec:
containers:
- name: api
image: ghcr.io/zero/zero-api:latest
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: zero-secrets
key: database-url
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: zero-secrets
key: jwt-secret
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 2Gi
livenessProbe:
httpGet:
path: /api/v1/health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/v1/health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: zero-api
namespace: zero
spec:
selector:
app: zero-api
ports:
- port: 8080
targetPort: 8080 Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: zero-api-hpa
namespace: zero
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: zero-api
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80 Pod Disruption Budget
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: zero-api-pdb
namespace: zero
spec:
minAvailable: 2
selector:
matchLabels:
app: zero-api Database Configuration
Using External PostgreSQL
For production, we recommend using a managed database:
- AWS RDS PostgreSQL
- Google Cloud SQL
- Azure Database for PostgreSQL
- DigitalOcean Managed Databases
# Create secret for external database
kubectl create secret generic zero-db \
--namespace zero \
--from-literal=database-url="postgres://user:password@host:5432/zero?sslmode=require" Persistent Storage
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: zero-data
namespace: zero
spec:
accessModes:
- ReadWriteOnce
storageClassName: fast-ssd
resources:
requests:
storage: 100Gi Network Policies
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: zero-api-policy
namespace: zero
spec:
podSelector:
matchLabels:
app: zero-api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: postgresql
ports:
- port: 5432
- to:
- podSelector:
matchLabels:
app: redis
ports:
- port: 6379 Monitoring & Observability
Prometheus ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: zero-api
namespace: zero
spec:
selector:
matchLabels:
app: zero-api
endpoints:
- port: metrics
interval: 30s
path: /metrics Prometheus Alerts
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: zero-alerts
namespace: zero
spec:
groups:
- name: zero
rules:
- alert: ZeroAPIDown
expr: up{job="zero-api"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Zero API is down"
- alert: ZeroHighLatency
expr: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 1
for: 10m
labels:
severity: warning
annotations:
summary: "Zero API high latency" Upgrading
# Helm upgrade
helm upgrade zero zero/zero \
--namespace zero \
--values values.yaml \
--wait
# Rolling restart
kubectl rollout restart deployment/zero-api -n zero
# Check rollout status
kubectl rollout status deployment/zero-api -n zero Backup Strategy
# Using Velero for cluster backup
velero backup create zero-backup \
--include-namespaces zero \
--wait
# Scheduled backup
velero schedule create zero-daily \
--schedule="@daily" \
--include-namespaces zero Troubleshooting
# Check pod status
kubectl get pods -n zero -o wide
# View pod logs
kubectl logs -f deployment/zero-api -n zero
# Describe pod for events
kubectl describe pod -l app=zero-api -n zero
# Execute into pod
kubectl exec -it deployment/zero-api -n zero -- /bin/sh
# Check resource usage
kubectl top pods -n zero Next Steps
- VPN Server Configuration - Multi-region VPN setup
- Security Model - Understanding Zero security
- API Documentation - API integration