AWS EKS
Deploy the Watchlight AI Agent Runtime Governance control plane (Beacon) on Amazon Elastic Kubernetes Service.
Prerequisites
| Requirement | Details |
|---|---|
| EKS cluster | Kubernetes 1.27+ with managed node groups |
| AWS CLI | v2.x, configured with appropriate IAM credentials |
| kubectl | Configured for your EKS cluster |
| Helm | v3.12+ |
| AWS Load Balancer Controller | Installed in the cluster (docs) |
| ACM certificate | For TLS termination on the ALB |
| GHCR access | Image pull secret for ghcr.io/watchlight-ai-beacon |
Required IAM permissions
The IAM principal running the deployment needs:
eks:DescribeCluster,eks:ListClustersrds:CreateDBInstance,rds:DescribeDBInstances(if provisioning RDS)acm:DescribeCertificate,acm:ListCertificatesecr:GetAuthorizationToken(for cross-registry pulls)
Infrastructure Setup
1. Create the EKS cluster
If you do not already have a cluster:
eksctl create cluster \
--name watchlight-beacon \
--region us-east-1 \
--version 1.29 \
--nodegroup-name beacon-nodes \
--node-type m5.large \
--nodes 3 \
--nodes-min 2 \
--nodes-max 5
2. Install the AWS Load Balancer Controller
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=watchlight-beacon \
--set serviceAccount.create=true \
--set serviceAccount.name=aws-load-balancer-controller
3. Provision RDS PostgreSQL
For production, use Amazon RDS instead of the built-in PostgreSQL chart:
aws rds create-db-instance \
--db-instance-identifier beacon-db \
--db-instance-class db.r6g.large \
--engine postgres \
--engine-version 16.4 \
--master-username beacon \
--master-user-password "$(openssl rand -base64 24)" \
--allocated-storage 50 \
--storage-type gp3 \
--vpc-security-group-ids sg-xxxxxxxx \
--db-subnet-group-name beacon-db-subnet \
--multi-az \
--storage-encrypted \
--backup-retention-period 7
Record the endpoint from:
aws rds describe-db-instances \
--db-instance-identifier beacon-db \
--query 'DBInstances[0].Endpoint.Address' --output text
4. Create the GHCR image pull secret
kubectl create namespace watchlight
kubectl create secret docker-registry ghcr-credentials \
-n watchlight \
--docker-server=ghcr.io \
--docker-username=YOUR_GITHUB_USERNAME \
--docker-password=YOUR_GITHUB_PAT
5. Create the database connection secret
kubectl create secret generic beacon-db-credentials \
-n watchlight \
--from-literal=DATABASE_URL="postgres://beacon:PASSWORD@beacon-db.xxx.us-east-1.rds.amazonaws.com:5432/beacon"
Helm Installation
Review the values file
The AWS-specific values file is at deploy/helm/watchlight-beacon/values-aws.yaml. Key settings:
global:
imageRegistry: ghcr.io/watchlight-ai-beacon
imagePullSecrets:
- name: ghcr-credentials
storageClass: gp3
ingress:
className: alb
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
alb.ingress.kubernetes.io/ssl-redirect: "443"
# Set your ACM certificate ARN:
# alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:ACCOUNT:certificate/CERT-ID
Before installing, update the values file with:
- Your ACM certificate ARN (uncomment
alb.ingress.kubernetes.io/certificate-arn) - Your domain name under
wl-registry.ingress.hosts[].hostandwl-registry-frontend.ingress.hosts[].host - Your RDS connection string under
global.externalDatabase.url(and setpostgresql.enabled: false)
Install
helm install beacon ./deploy/helm/watchlight-beacon \
-n watchlight \
-f ./deploy/helm/watchlight-beacon/values-aws.yaml
To use an external RDS database instead of the built-in PostgreSQL, add these overrides:
helm install beacon ./deploy/helm/watchlight-beacon \
-n watchlight \
-f ./deploy/helm/watchlight-beacon/values-aws.yaml \
--set postgresql.enabled=false \
--set global.externalDatabase.url="postgres://beacon:PASSWORD@beacon-db.xxx.us-east-1.rds.amazonaws.com:5432/beacon"
Validation
Check pod status
kubectl get pods -n watchlight
All pods should reach Running status within a few minutes.
Verify the ALB ingress
kubectl get ingress -n watchlight
The ADDRESS column should show an ALB DNS name (e.g., k8s-watchlig-xxx.us-east-1.elb.amazonaws.com).
Health checks
# Registry API
curl -s https://registry.example.com/api/v1/health | jq .
# Registry frontend
curl -s -o /dev/null -w "%{http_code}" https://registry.example.com/
Smoke test
# List registered agents (should return empty array on fresh install)
curl -s https://registry.example.com/api/v1/agents | jq .
# Check wl-discover logs
kubectl logs -n watchlight -l app.kubernetes.io/name=wl-discover --tail=20
Production Hardening
High availability
The AWS values file enables HPA and PodDisruptionBudgets by default:
wl-registry: 2-10 replicas, scales at 70% CPU, minimum 1 available during disruptionswl-registry-frontend: 2 replicas
Ensure your node group spans at least 2 availability zones for zone-redundant scheduling.
Monitoring
Install the Prometheus stack and enable ServiceMonitor resources:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack \
-n monitoring --create-namespace
Beacon services expose /metrics endpoints. The Helm chart includes ServiceMonitor resources that Prometheus discovers automatically when servicemonitor.enabled: true.
Backup
- RDS: Enable automated backups with at least 7-day retention. Consider enabling cross-region read replicas for disaster recovery.
- Configuration: Store your values file in version control. The Helm release state is stored in Kubernetes secrets by default.
Scaling considerations
| Component | Scaling strategy |
|---|---|
| wl-registry | HPA on CPU (included in values). Add memory-based scaling for large catalogs. |
| wl-registry-frontend | HPA or fixed 2+ replicas behind the ALB. |
| wl-discover | DaemonSet -- one per node, scales automatically with cluster size. |
| PostgreSQL (RDS) | Vertical scaling via instance class change. Read replicas for read-heavy workloads. |
Network security
- Restrict the ALB security group to only allow traffic from your CIDR ranges or a WAF.
- Use VPC private subnets for RDS. Ensure the EKS node security group can reach the RDS security group on port 5432.
- Consider enabling AWS PrivateLink if Beacon should not be exposed to the public internet.
IAM roles for service accounts (IRSA)
For least-privilege access, bind Kubernetes service accounts to IAM roles instead of using node-level instance profiles:
eksctl create iamserviceaccount \
--name beacon-registry \
--namespace watchlight \
--cluster watchlight-beacon \
--role-name BeaconRegistryRole \
--attach-policy-arn arn:aws:iam::ACCOUNT:policy/BeaconRegistryPolicy \
--approve