Deployment Guide¶
Production deployment strategies for Route ANS Resolver.
Docker Deployment¶
Basic Container¶
# Pull image
docker pull ghcr.io/route-ans/route-ans:latest
# Run with default config
docker run -d \
--name ans-resolver \
-p 8080:8080 \
ghcr.io/route-ans/route-ans:latest
# Run with custom config
docker run -d \
--name ans-resolver \
-p 8080:8080 \
-v /path/to/config.yaml:/etc/resolver/config.yaml \
ghcr.io/route-ans/route-ans:latest \
--config /etc/resolver/config.yaml
Docker Compose¶
version: '3.8'
services:
resolver:
image: ghcr.io/route-ans/route-ans:latest
ports:
- "8080:8080"
volumes:
- ./configs/resolver.yaml:/etc/resolver/config.yaml:ro
- ./certs:/etc/resolver/certs:ro
environment:
- ANS_LOG_LEVEL=info
- ANS_LOG_FORMAT=json
command: ["--config", "/etc/resolver/config.yaml"]
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
restart: unless-stopped
volumes:
redis-data:
With Redis Cache¶
version: '3.8'
services:
resolver:
image: ghcr.io/route-ans/route-ans:latest
depends_on:
- redis
ports:
- "8080:8080"
volumes:
- ./configs/resolver-redis.yaml:/etc/resolver/config.yaml:ro
environment:
- REDIS_HOST=redis
- REDIS_PORT=6379
restart: unless-stopped
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis-data:/data
restart: unless-stopped
volumes:
redis-data:
Kubernetes Deployment¶
Basic Deployment¶
See deployments/kubernetes/ for complete manifests.
# Apply all manifests
kubectl apply -k deployments/kubernetes/
# Check status
kubectl get pods -n ans-system
kubectl get svc -n ans-system
Production Setup¶
apiVersion: apps/v1
kind: Deployment
metadata:
name: ans-resolver
namespace: ans-system
spec:
replicas: 3
selector:
matchLabels:
app: ans-resolver
template:
metadata:
labels:
app: ans-resolver
spec:
containers:
- name: resolver
image: ghcr.io/route-ans/route-ans:v1.0.0
ports:
- containerPort: 8080
name: http
- containerPort: 9090
name: metrics
env:
- name: ANS_LOG_FORMAT
value: "json"
- name: REDIS_HOST
value: "redis-service"
volumeMounts:
- name: config
mountPath: /etc/resolver
readOnly: true
- name: certs
mountPath: /etc/resolver/certs
readOnly: true
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
volumes:
- name: config
configMap:
name: resolver-config
- name: certs
secret:
secretName: resolver-certs
---
apiVersion: v1
kind: Service
metadata:
name: ans-resolver
namespace: ans-system
spec:
type: LoadBalancer
selector:
app: ans-resolver
ports:
- name: http
port: 80
targetPort: 8080
- name: metrics
port: 9090
targetPort: 9090
Horizontal Pod Autoscaling¶
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ans-resolver-hpa
namespace: ans-system
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ans-resolver
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
Ingress Configuration¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ans-resolver-ingress
namespace: ans-system
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
ingressClassName: nginx
tls:
- hosts:
- resolver.example.com
secretName: resolver-tls
rules:
- host: resolver.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ans-resolver
port:
number: 80
Systemd Service¶
For bare metal or VM deployments:
[Unit]
Description=Route ANS Resolver
After=network.target
[Service]
Type=simple
User=ans
Group=ans
ExecStart=/usr/local/bin/ans-resolver --config /etc/ans-resolver/config.yaml
Restart=on-failure
RestartSec=5s
# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/ans-resolver
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=ans-resolver
[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable ans-resolver
sudo systemctl start ans-resolver
sudo systemctl status ans-resolver
Cloud Deployments¶
AWS ECS¶
{
"family": "ans-resolver",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"containerDefinitions": [
{
"name": "resolver",
"image": "ghcr.io/route-ans/route-ans:latest",
"portMappings": [
{
"containerPort": 8080,
"protocol": "tcp"
}
],
"environment": [
{"name": "ANS_LOG_FORMAT", "value": "json"}
],
"secrets": [
{
"name": "GODADDY_API_KEY",
"valueFrom": "arn:aws:secretsmanager:region:account:secret:ans/godaddy"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/ans-resolver",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
},
"healthCheck": {
"command": ["CMD-SHELL", "wget -q -O - http://localhost:8080/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3
}
}
]
}
Google Cloud Run¶
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
name: ans-resolver
spec:
template:
spec:
containers:
- image: ghcr.io/route-ans/route-ans:latest
ports:
- containerPort: 8080
env:
- name: ANS_LOG_FORMAT
value: json
resources:
limits:
memory: 512Mi
cpu: 1000m
Deploy:
gcloud run deploy ans-resolver \
--image ghcr.io/route-ans/route-ans:latest \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--port 8080 \
--memory 512Mi \
--cpu 1
Azure Container Instances¶
az container create \
--resource-group ans-resolver \
--name ans-resolver \
--image ghcr.io/route-ans/route-ans:latest \
--dns-name-label ans-resolver \
--ports 8080 \
--cpu 1 \
--memory 1 \
--environment-variables ANS_LOG_FORMAT=json
High Availability¶
Load Balancing¶
upstream ans_resolvers {
least_conn;
server resolver1.internal:8080 max_fails=3 fail_timeout=30s;
server resolver2.internal:8080 max_fails=3 fail_timeout=30s;
server resolver3.internal:8080 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name resolver.example.com;
location / {
proxy_pass http://ans_resolvers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Health check
proxy_next_upstream error timeout http_502 http_503;
}
}
Multi-Region Setup¶
Deploy to multiple regions with DNS-based routing:
# Region 1: us-east-1
resolver-us-east:
endpoint: resolver-us-east.example.com
# Region 2: eu-west-1
resolver-eu-west:
endpoint: resolver-eu-west.example.com
# Global
resolver:
endpoint: resolver.example.com
routing: geoproximity
Configuration Management¶
Environment Variables¶
Override config with environment variables:
export ANS_SERVER_PORT=8080
export ANS_LOG_LEVEL=info
export ANS_CACHE_TYPE=redis
export ANS_CACHE_REDIS_HOST=redis:6379
export ANS_REGISTRY_TYPE=godaddy
export ANS_REGISTRY_GODADDY_API_KEY=secret
Secrets Management¶
Kubernetes Secrets¶
kubectl create secret generic resolver-secrets \
--from-literal=godaddy-api-key=xxx \
--from-literal=godaddy-secret=yyy \
-n ans-system
HashiCorp Vault¶
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "ans-resolver"
vault.hashicorp.com/agent-inject-secret-godaddy: "secret/data/ans/godaddy"
Backup and Recovery¶
Configuration Backup¶
# Backup config
kubectl get configmap resolver-config -n ans-system -o yaml > backup.yaml
# Restore config
kubectl apply -f backup.yaml
State Backup (Redis)¶
# Backup Redis data
docker exec redis redis-cli BGSAVE
docker cp redis:/data/dump.rdb ./backup/
# Restore
docker cp ./backup/dump.rdb redis:/data/
docker restart redis
Rolling Updates¶
Zero-Downtime Deployment¶
# Update image
kubectl set image deployment/ans-resolver \
resolver=ghcr.io/route-ans/route-ans:v1.1.0 \
-n ans-system
# Watch rollout
kubectl rollout status deployment/ans-resolver -n ans-system
# Rollback if needed
kubectl rollout undo deployment/ans-resolver -n ans-system
Next Steps¶
- Monitoring - Metrics and observability
- Security - Security best practices
- Troubleshooting - Common issues