237 lines
8.9 KiB
Markdown
237 lines
8.9 KiB
Markdown
# AgentOps Deployment Infrastructure
|
|
|
|
Multi-tenant Kubernetes deployment system for CrewAI agents with ALB ingress routing.
|
|
|
|
## Architecture Overview
|
|
|
|
- **Kubernetes Cluster**: EKS cluster running agent deployments
|
|
- **Application Load Balancer**: Shared ALB with host-based routing for multi-tenant isolation
|
|
- **Instance Files**: ConfigMap-based deployment with content hashing
|
|
- **Container Registry**: ECR for storing built agent images
|
|
- **Build System**: Kaniko-based image building with S3 cache in dedicated builder namespace
|
|
|
|
## Load Balancer Setup
|
|
|
|
The deployment system uses AWS Application Load Balancer (ALB) with the AWS Load Balancer Controller for internet-facing traffic routing.
|
|
|
|
### Architecture
|
|
|
|
```
|
|
Internet → ALB (host-based routing) → Kubernetes Services → Pods
|
|
```
|
|
|
|
- Each project gets its own hostname: `{project-uuid}.deploy.agentops.ai`
|
|
- **Shared ALB**: All deployments use a single ALB instance (`alb-deployments` group) providing one IP address for wildcard DNS routing
|
|
- ALB routes traffic based on hostname to the correct service using host-based routing
|
|
- Services use `ClusterIP` type (not LoadBalancer) for cost efficiency
|
|
- ALB Ingress Controller manages ALB lifecycle automatically
|
|
- Deployments are tagged with `deployment` and `hostname` labels for routing
|
|
|
|
### Prerequisites
|
|
|
|
1. **EKS Cluster** with appropriate IAM permissions
|
|
2. **AWS CLI** configured with ELB permissions
|
|
3. **Domain** configured for wildcard DNS (*.deploy.agentops.ai)
|
|
4. **Subnets** tagged with `kubernetes.io/role/elb=1` for ALB creation
|
|
5. **AWS credentials** available via `aws-credentials` secret in `kube-system` namespace
|
|
6. **Builder namespace** configured for image building operations
|
|
|
|
### Step 1: Install AWS Load Balancer Controller
|
|
|
|
Install the AWS Load Balancer Controller to manage ALBs:
|
|
|
|
```bash
|
|
# Install cert-manager (required dependency)
|
|
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.yaml
|
|
|
|
# Wait for cert-manager to be ready
|
|
kubectl wait --for=condition=ready pod -l app=cert-manager -n cert-manager --timeout=60s
|
|
|
|
# Install required CRDs for ALB controller
|
|
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.2/config/crd/bases/elbv2.k8s.aws_targetgroupbindings.yaml
|
|
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.7.2/config/crd/bases/elbv2.k8s.aws_ingressclassparams.yaml
|
|
|
|
# Copy AWS credentials to kube-system namespace
|
|
kubectl get secret aws-credentials -n default -o yaml | sed 's/namespace: default/namespace: kube-system/' | kubectl apply -f -
|
|
|
|
# Apply the ALB controller and webhook configurations
|
|
kubectl apply -f configs/aws-load-balancer-controller.yaml
|
|
kubectl apply -f configs/aws-load-balancer-webhook.yaml
|
|
|
|
# Tag public subnets for ALB creation (replace with your subnet IDs)
|
|
aws ec2 create-tags --resources subnet-07bb9663fa1d8f572 subnet-0b0bc494208f4d020 --tags Key=kubernetes.io/role/elb,Value=1
|
|
```
|
|
|
|
### Step 2: Configure Services
|
|
|
|
Services should use `ClusterIP` type to work with ALB ingress:
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: svc-{project-uuid}
|
|
spec:
|
|
type: ClusterIP # Important: NOT LoadBalancer
|
|
ports:
|
|
- port: 80
|
|
targetPort: 8080
|
|
selector:
|
|
app: {project-uuid}
|
|
```
|
|
|
|
### Step 3: Ingress Configuration
|
|
|
|
The deployment system automatically creates ingress resources with proper ALB annotations:
|
|
|
|
```yaml
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: ing-{project-uuid}
|
|
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: '[{"HTTP": 80}, {"HTTPS": 443}]'
|
|
alb.ingress.kubernetes.io/ssl-redirect: "443"
|
|
alb.ingress.kubernetes.io/group.name: group-ing-{project-uuid} # Ensures separate ALB per project
|
|
spec:
|
|
rules:
|
|
- host: {project-uuid}.deploy.agentops.ai
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: svc-{project-uuid}
|
|
port:
|
|
number: 80
|
|
```
|
|
|
|
### Key Features
|
|
|
|
- **Project Isolation**: Each project gets its own ALB group for complete isolation
|
|
- **Host-based Routing**: Traffic routed by hostname to correct service
|
|
- **SSL Termination**: ALB handles HTTPS with automatic redirects
|
|
- **Health Checks**: ALB performs HTTP health checks on `/health` endpoint
|
|
- **Cost Effective**: One ALB per project vs individual Classic ELBs
|
|
|
|
## Instance Files Management
|
|
|
|
Instance files (server.py, providers/) are managed via Kubernetes ConfigMaps with content hashing.
|
|
|
|
### How It Works
|
|
|
|
1. **Content Hashing**: Files are hashed to create unique ConfigMap names
|
|
2. **Tar Archive**: All instance files packaged into base64-encoded tar.gz
|
|
3. **ConfigMap**: Tar archive stored in ConfigMap with hash-based name
|
|
4. **Build Process**: ConfigMap mounted to builder and extracted into image
|
|
5. **Immutable Deployments**: Hash changes force new ConfigMap creation
|
|
|
|
### Benefits
|
|
|
|
- **No Stale Files**: Hash-based naming prevents stale file reuse
|
|
- **Fast Updates**: Only changed files create new ConfigMaps
|
|
- **Version Control**: Each deployment gets exactly the files it was built with
|
|
- **No External Dependencies**: No EFS or external storage required
|
|
|
|
## Deployment Process
|
|
|
|
The deployment system automatically handles ALB creation:
|
|
|
|
1. **Service Creation**: Creates ClusterIP service for each deployment
|
|
2. **Ingress Creation**: Creates ingress with unique group name for ALB isolation
|
|
3. **ALB Provisioning**: AWS Load Balancer Controller creates dedicated ALB
|
|
4. **DNS Configuration**: Update DNS to point hostname to ALB IP addresses
|
|
|
|
### Verifying ALB Creation
|
|
|
|
```bash
|
|
# Check ALB controller status
|
|
kubectl get pods -n kube-system -l app.kubernetes.io/name=aws-load-balancer-controller
|
|
|
|
# Check ingress status (should show ALB address when ready)
|
|
kubectl get ingress
|
|
|
|
# Check ingress events for troubleshooting
|
|
kubectl describe ingress ing-{project-uuid}
|
|
|
|
# List ALBs via AWS CLI
|
|
aws elbv2 describe-load-balancers --query 'LoadBalancers[*].[LoadBalancerName,DNSName,State.Code]' --output table
|
|
|
|
# Get ALB IP addresses for /etc/hosts
|
|
nslookup {alb-dns-name}
|
|
```
|
|
|
|
### Troubleshooting
|
|
|
|
Common issues and solutions:
|
|
|
|
- **Subnet discovery failed**: Ensure public subnets are tagged with `kubernetes.io/role/elb=1`
|
|
- **No credentials**: Verify `aws-credentials` secret exists in `kube-system` namespace
|
|
- **Certificate errors**: Use HTTP-only ingress or configure SSL certificates
|
|
- **Permission errors**: Check ALB controller logs and ensure all CRDs are installed
|
|
|
|
## Environment Configuration
|
|
|
|
### Builder Namespace
|
|
|
|
The deployment system uses a dedicated namespace for image building operations to simplify management and logging.
|
|
|
|
**Environment Variable**: `BUILDER_NAMESPACE` (default: `builder`)
|
|
|
|
All Kaniko builder jobs run in this namespace, which allows for:
|
|
- Centralized builder pod management
|
|
- Simplified logging with `jockey logs-builder`
|
|
- Cleaner separation between build and deployment concerns
|
|
- Easy builder resource monitoring
|
|
|
|
### Setup Builder Namespace
|
|
|
|
Use the built-in command to create the builder namespace and AWS credentials:
|
|
|
|
```bash
|
|
# Create builder namespace and AWS credentials secret
|
|
jockey setup-builder
|
|
|
|
# View builder logs (automatically uses builder namespace)
|
|
jockey logs-builder
|
|
|
|
# Or specify a different namespace
|
|
jockey logs-builder --namespace custom-builder
|
|
```
|
|
|
|
The builder namespace requires the `aws-credentials` secret to authenticate with ECR for image pushing.
|
|
|
|
## Shared ALB Management
|
|
|
|
The deployment system uses a shared ALB (`alb-deployments` group) for all deployments to enable wildcard DNS routing with a single IP address. This allows `*.deploy.agentops.ai` to point to one ALB that handles all subdomain routing. All deployments automatically use the shared ALB configuration.
|
|
|
|
### ALB Configuration
|
|
|
|
- **Group Name**: `alb-deployments` (configurable via `ALB_SHARED_GROUP_NAME` environment variable)
|
|
- **Host-based Routing**: Each deployment gets its own hostname for traffic routing
|
|
- **Tagging**: Each ingress is tagged with `deployment` and `hostname` for identification
|
|
- **Health Checks**: Configured to use `/health` endpoint with fast deregistration (30s)
|
|
|
|
### Management Commands
|
|
|
|
```bash
|
|
# Check the status of the shared ALB
|
|
jockey alb-status
|
|
|
|
# List all ingresses using the shared ALB
|
|
jockey list-alb-ingresses --namespace default
|
|
|
|
# Validate ALB routing for a specific hostname
|
|
jockey validate-alb-routing yourdomain.deploy.agentops.ai
|
|
```
|
|
|
|
### Environment Variables
|
|
|
|
- `ALB_SHARED_GROUP_NAME`: Name of the shared ALB group (default: `alb-deployments`)
|
|
- `DEPLOYMENT_DOMAIN`: Base domain for deployments (default: `deploy.agentops.ai`)
|
|
|
|
The shared ALB is automatically provisioned when the first ingress is created and will handle all subsequent deployments through host-based routing. This provides a single IP address that can be used for wildcard DNS records (`*.deploy.agentops.ai`), simplifying DNS management and enabling seamless subdomain routing. |