Kubernetes operator that automatically distributes Ingress objects across ALB group bins so no single ALB exceeds the listener rule limit.
Two modes: global (manages all Ingresses) and scoped (manages only listed group prefixes).
make build # binary → ./agm
make all # fmt + vet + fix + lint + test + build
docker build -t agm .make test # go test -race -cover ./...
make lint # golangci-lintThe manager reads a YAML config file (default /etc/agm/config.yaml,
override with --config):
mode: global
baseGroupName: "alb-group"
limits:
maxRulesPerGroup: 100
softLimitPercent: 95
aws:
region: "eu-west-1"
cacheItemTTL: 30s
cacheRefreshJitter: 5s
onAWSError: allowOnStale
rebalancer:
enabled: true
reconcileInterval: 60s
requeueDelay: 10s
maxConcurrentReconciles: 5
webhook:
port: 9443
tlsCertDir: /etc/webhook/certs
metrics:
port: 8080
logging:
level: info- A Kubernetes cluster with the AWS Load Balancer Controller installed
- cert-manager (for webhook TLS)
- An IAM role (IRSA) with read-only ELBv2 permissions:
elasticloadbalancing:DescribeLoadBalancers,elasticloadbalancing:DescribeListeners,elasticloadbalancing:DescribeRules,elasticloadbalancing:DescribeTags
# 0. Set your cluster-specific values
export ACCOUNT_ID=123456789012
export REGION=eu-west-1
export OIDC_ID=EXAMPLED539D4633E53DE1B71EXAMPLE
export NAMESPACE=kube-system
# 1. Create the IAM policy
aws iam create-policy \
--policy-name alb-ingress-group-manager \
--policy-document file://deploy/iam-policy.json
# 2. Create the role with IRSA trust
aws iam create-role \
--role-name alb-ingress-group-manager \
--assume-role-policy-document "$(envsubst < ./deploy/trust-policy.json)"
# 3. Attach the policy
aws iam attach-role-policy \
--role-name alb-ingress-group-manager \
--policy-arn "arn:aws:iam::${ACCOUNT_ID}:policy/alb-ingress-group-manager"helm install agm ./charts/agm \
--namespace kube-system \
--set config.aws.region=eu-west-1 \
--set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::123456789012:role/agmOverride defaults with a values file:
helm install agm ./charts/agm -n kube-system -f values-prod.yamlThe chart creates: Deployment (2 replicas), Service, ConfigMap, ClusterRole/Binding, ServiceAccount, MutatingWebhookConfiguration, and a cert-manager Certificate.
Leader election ensures only one pod runs the rebalancer; the webhook is active on all replicas.
# Webhook registered
kubectl get mutatingwebhookconfigurations | grep agm
# Pods ready
kubectl get pods -n kube-system -l app.kubernetes.io/name=agm
# Health check
kubectl -n kube-system exec deploy/agm -- wget -qO- http://localhost:8081/healthz
# Create a test Ingress and confirm group.name was set
kubectl apply -f test-ingress.yaml
kubectl get ingress test-ingress -o jsonpath='{.metadata.annotations}'