Deployment Guide

Prerequisites

RequirementMinimumRecommended
Kubernetes1.26+1.28+
Nodes35+
CPU (total)8 cores16+ cores
Memory (total)16 GB32+ GB
Helm3.12+Latest
Storage ClassStandardSSD-backed

External dependencies:

  • PostgreSQL 14+ — AWS RDS, GCP Cloud SQL, Azure Database, or self-hosted
  • Redis 7+ — AWS ElastiCache, GCP Memorystore, or self-hosted
  • Load Balancer — AWS NLB, GCP Network LB, Azure LB, or MetalLB (on-premise)
  • TLS Certificates — cert-manager with Let’s Encrypt (recommended) or manual

Quick Start (Docker Compose)

For local development and evaluation:

git clone https://github.com/ShaneDolphin/avons-corners.git
cd avons-corners

docker compose up -d

docker compose ps

This starts all services locally:

ServicePortProtocol
Gateway4600UDP
Auth50051gRPC
CA50052gRPC
Pulse50053gRPC
Policy Engine8081HTTP
Admin API8080HTTP
PostgreSQL5432TCP
Redis6379TCP

Kubernetes Deployment

Step 1: Create Namespace

kubectl create namespace avon

Step 2: Configure Secrets

Create a secrets file — do not commit this to version control:

apiVersion: v1
kind: Secret
metadata:
  name: avon-secrets
  namespace: avon
type: Opaque
stringData:
  jwt-secret: "your-secure-jwt-secret-minimum-32-characters"
  database-url: "postgresql://avon:password@postgres-host:5432/avon"
  redis-url: "redis://:password@redis-host:6379"
  database-password: "your-database-password"
  redis-password: "your-redis-password"
kubectl apply -f secrets.yaml

Step 3: Install with Helm

Development:

helm install avon deploy/helm/avon 
  -f deploy/helm/avon/values-dev.yaml 
  --namespace avon 
  --set secrets.existingSecret=avon-secrets

Staging:

helm install avon deploy/helm/avon 
  -f deploy/helm/avon/values-staging.yaml 
  --namespace avon 
  --set secrets.existingSecret=avon-secrets

Production:

helm install avon deploy/helm/avon 
  -f deploy/helm/avon/values-production.yaml 
  --namespace avon 
  --set secrets.existingSecret=avon-secrets 
  --set externalDatabase.host=your-rds-endpoint.amazonaws.com 
  --set externalRedis.host=your-elasticache-endpoint.amazonaws.com

Step 4: Verify

kubectl get pods -n avon

Expected output:

NAME                                  READY   STATUS    RESTARTS   AGE
avon-gateway-xxxxx                    1/1     Running   0          2m
avon-gateway-xxxxx                    1/1     Running   0          2m
avon-gateway-xxxxx                    1/1     Running   0          2m
avon-auth-xxxxx                       1/1     Running   0          2m
avon-ca-0                             1/1     Running   0          2m
avon-pulse-xxxxx                      1/1     Running   0          2m
avon-policy-engine-xxxxx              1/1     Running   0          2m
avon-admin-api-xxxxx                  1/1     Running   0          2m

Get the gateway external IP:

kubectl get svc avon-gateway -n avon 
  -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

Cloud-Specific Deployments

AWS (EKS)

# values-aws.yaml
gateway:
  service:
    type: LoadBalancer
    annotations:
      service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
      service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
      service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"

ca:
  hsm:
    enabled: true
    provider: "aws-cloudhsm"

adminApi:
  ingress:
    enabled: true
    className: alb
    annotations:
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:ACCOUNT:certificate/CERT-ID
    hosts:
      - host: admin.avon.example.com
        paths:
          - path: /
            pathType: Prefix
helm install avon deploy/helm/avon 
  -f deploy/helm/avon/values-production.yaml 
  -f values-aws.yaml 
  --namespace avon 
  --set secrets.existingSecret=avon-secrets 
  --set externalDatabase.host=avon-db.cluster-xxxxx.us-east-1.rds.amazonaws.com 
  --set externalRedis.host=avon-cache.xxxxx.0001.use1.cache.amazonaws.com

GCP (GKE)

# values-gcp.yaml
gateway:
  service:
    type: LoadBalancer
    annotations:
      cloud.google.com/l4-rbs: "enabled"
      networking.gke.io/load-balancer-type: "External"

ca:
  hsm:
    enabled: true
    provider: "gcp-kms"

adminApi:
  ingress:
    enabled: true
    className: gce
    annotations:
      kubernetes.io/ingress.global-static-ip-name: avon-admin-ip
      networking.gke.io/managed-certificates: avon-admin-cert
    hosts:
      - host: admin.avon.example.com
        paths:
          - path: /
            pathType: Prefix
helm install avon deploy/helm/avon 
  -f deploy/helm/avon/values-production.yaml 
  -f values-gcp.yaml 
  --namespace avon 
  --set secrets.existingSecret=avon-secrets 
  --set externalDatabase.host=/cloudsql/PROJECT:REGION:INSTANCE 
  --set externalRedis.host=10.0.0.3

Azure (AKS)

# values-azure.yaml
gateway:
  service:
    type: LoadBalancer
    annotations:
      service.beta.kubernetes.io/azure-load-balancer-external: "true"

ca:
  hsm:
    enabled: true
    provider: "azure-dedicated-hsm"

adminApi:
  ingress:
    enabled: true
    className: nginx
    annotations:
      cert-manager.io/cluster-issuer: "letsencrypt-prod"
    hosts:
      - host: admin.avon.example.com
        paths:
          - path: /
            pathType: Prefix
    tls:
      - secretName: admin-tls
        hosts:
          - admin.avon.example.com
helm install avon deploy/helm/avon 
  -f deploy/helm/avon/values-production.yaml 
  -f values-azure.yaml 
  --namespace avon 
  --set secrets.existingSecret=avon-secrets 
  --set externalDatabase.host=avon-db.postgres.database.azure.com 
  --set externalRedis.host=avon-cache.redis.cache.windows.net

Bare Metal / On-Premise Deployment

For environments without cloud load balancers, use MetalLB and self-hosted databases.

Prerequisites

Install MetalLB for LoadBalancer service support:

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml

Configure an IP address pool:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: avon-pool
  namespace: metallb-system
spec:
  addresses:
    - 192.168.1.200-192.168.1.210
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: avon-l2
  namespace: metallb-system
spec:
  ipAddressPools:
    - avon-pool

Deployment

# values-bare-metal.yaml
gateway:
  service:
    type: LoadBalancer
    port: 4600

ca:
  persistence:
    enabled: true
    size: 10Gi
    storageClass: "local-path"

adminApi:
  ingress:
    enabled: true
    className: nginx
    annotations:
      cert-manager.io/cluster-issuer: "letsencrypt-prod"
    hosts:
      - host: admin.avon.example.com
        paths:
          - path: /
            pathType: Prefix
    tls:
      - secretName: admin-tls
        hosts:
          - admin.avon.example.com
helm install avon deploy/helm/avon 
  -f deploy/helm/avon/values-production.yaml 
  -f values-bare-metal.yaml 
  --namespace avon 
  --set secrets.existingSecret=avon-secrets 
  --set externalDatabase.host=postgres.internal.example.com 
  --set externalRedis.host=redis.internal.example.com

Firewall Rules

SourceDestinationPortProtocolPurpose
Agents (any)Gateway4600UDPAgent tunnels
GatewayAuth50051TCPAuthentication
GatewayPulse50053TCPHeartbeats
AuthCA50052TCPCertificate operations
AdminsAdmin API443TCPManagement interface