Skip to main content

AWS EKS

Deploy the Watchlight AI Agent Runtime Governance control plane (Beacon) on Amazon Elastic Kubernetes Service.

Prerequisites

RequirementDetails
EKS clusterKubernetes 1.27+ with managed node groups
AWS CLIv2.x, configured with appropriate IAM credentials
kubectlConfigured for your EKS cluster
Helmv3.12+
AWS Load Balancer ControllerInstalled in the cluster (docs)
ACM certificateFor TLS termination on the ALB
GHCR accessImage pull secret for ghcr.io/watchlight-ai-beacon

Required IAM permissions

The IAM principal running the deployment needs:

  • eks:DescribeCluster, eks:ListClusters
  • rds:CreateDBInstance, rds:DescribeDBInstances (if provisioning RDS)
  • acm:DescribeCertificate, acm:ListCertificates
  • ecr: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:

  1. Your ACM certificate ARN (uncomment alb.ingress.kubernetes.io/certificate-arn)
  2. Your domain name under wl-registry.ingress.hosts[].host and wl-registry-frontend.ingress.hosts[].host
  3. Your RDS connection string under global.externalDatabase.url (and set postgresql.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 disruptions
  • wl-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

ComponentScaling strategy
wl-registryHPA on CPU (included in values). Add memory-based scaling for large catalogs.
wl-registry-frontendHPA or fixed 2+ replicas behind the ALB.
wl-discoverDaemonSet -- 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