Validation Checklist: Azure Load Balancer and Ingress
Use this checklist to verify your Azure Load Balancer and Ingress deployment.
Prerequisites Validation
- [ ] Azure AKS cluster is running
- [ ] kubectl is configured and connected to the cluster
- [ ] ArgoCD is installed (optional, for GitOps deployment)
- [ ] Azure CLI is installed (for DNS and resource verification)
Task 2.1: nginx-ingress Controller
Deployment
- [ ] Applied ingress-nginx ArgoCD Application:
kubectl apply -f platform/apps/ingress-nginx/ingress-nginx-azure-application.yaml
- [ ] Namespace created:
kubectl get namespace ingress-nginx
# Expected: ingress-nginx namespace exists
- [ ] Deployment is ready:
kubectl get deployment ingress-nginx-controller -n ingress-nginx
# Expected: 2/2 READY
- [ ] Pods are running:
kubectl get pods -n ingress-nginx # Expected: 2+ controller pods in Running state
Load Balancer Configuration
- [ ] Service type is LoadBalancer:
kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.spec.type}'
# Expected: LoadBalancer
- [ ] External IP is assigned:
kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
# Expected: IP address (not <pending>)
- [ ] Azure Load Balancer health probe is configured:
kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.metadata.annotations.service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path}'
# Expected: /healthz
- [ ] External traffic policy is Local:
kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.spec.externalTrafficPolicy}' # Expected: Local
High Availability
- [ ] HorizontalPodAutoscaler is configured:
kubectl get hpa ingress-nginx-controller -n ingress-nginx
# Expected: HPA exists with min=2, max=10
- [ ] Pod anti-affinity is configured:
kubectl get deployment ingress-nginx-controller -n ingress-nginx -o jsonpath='{.spec.template.spec.affinity}' # Expected: podAntiAffinity configuration present
Metrics and Monitoring
- [ ] Metrics service exists:
kubectl get svc ingress-nginx-controller-metrics -n ingress-nginx
# Expected: Service exists
- [ ] ServiceMonitor is created (requires Prometheus Operator):
kubectl get servicemonitor ingress-nginx-controller -n ingress-nginx
# Expected: ServiceMonitor exists (or skip if Prometheus Operator not installed)
- [ ] PrometheusRule is created:
kubectl get prometheusrule ingress-nginx -n ingress-nginx # Expected: PrometheusRule exists (or skip if Prometheus Operator not installed)
Validation Script
- [ ] Run validation script:
./platform/apps/ingress-nginx/validate-azure.sh # Expected: All checks pass
Azure Resources
- [ ] Azure Load Balancer exists (requires Azure CLI):
az network lb list --resource-group MC_fawkes-rg_fawkes-aks_eastus -o table # Expected: Load Balancer listed with kubernetes prefix
Task 2.2: Azure DNS (Optional)
Terraform Configuration
- [ ] DNS variables configured in
infra/azure/terraform.tfvars:
dns_zone_name = "fawkes.yourdomain.com"
create_dns_records = true
- [ ] Terraform initialized:
cd infra/azure && terraform init
# Expected: Success
- [ ] Terraform planned:
terraform plan # Expected: Shows DNS zone and A records to be created
DNS Deployment
- [ ] Terraform applied:
terraform apply
# Expected: DNS zone and A records created
- [ ] DNS zone exists:
az network dns zone show -g fawkes-rg -n fawkes.yourdomain.com
# Expected: DNS zone details
- [ ] A records created:
az network dns record-set a list -g fawkes-rg -z fawkes.yourdomain.com -o table # Expected: @ and * records pointing to ingress IP
DNS Delegation
- [ ] Nameservers obtained:
terraform output dns_zone_name_servers
# Expected: 4 Azure DNS nameservers
-
[ ] Domain registrar updated with nameservers
-
[ ] DNS resolution working (may take up to 48 hours):
dig test.fawkes.yourdomain.com # Expected: Resolves to ingress IP
Task 2.3: cert-manager
Deployment
- [ ] Applied cert-manager ArgoCD Application:
kubectl apply -f platform/apps/cert-manager/cert-manager-application.yaml
- [ ] Namespace created:
kubectl get namespace cert-manager
# Expected: cert-manager namespace exists
- [ ] Deployments are ready:
kubectl get deployment -n cert-manager
# Expected: cert-manager, cert-manager-webhook, cert-manager-cainjector all ready
- [ ] Pods are running:
kubectl get pods -n cert-manager # Expected: All pods in Running state
CRDs Installation
- [ ] CRDs are installed:
kubectl get crd | grep cert-manager # Expected: 6 CRDs (certificates, certificaterequests, challenges, clusterissuers, issuers, orders)
ClusterIssuers Configuration
- [ ] Email address updated in ClusterIssuer files:
grep "email:" platform/apps/cert-manager/cluster-issuer-*.yaml
# Expected: Your actual email, not platform-team@example.com
- [ ] ClusterIssuers applied:
kubectl apply -f platform/apps/cert-manager/cluster-issuer-letsencrypt-staging.yaml
kubectl apply -f platform/apps/cert-manager/cluster-issuer-letsencrypt-prod.yaml
- [ ] ClusterIssuers are ready:
kubectl get clusterissuer # Expected: letsencrypt-staging and letsencrypt-prod both Ready=True
Validation Script
- [ ] Run validation script:
./platform/apps/cert-manager/validate.sh # Expected: All checks pass
Testing
Test Ingress Deployment
- [ ] Deploy test echo server:
kubectl apply -f platform/apps/ingress-nginx/test-ingress.yaml
- [ ] Test namespace created:
kubectl get namespace ingress-test
# Expected: Namespace exists
- [ ] Echo server running:
kubectl get pods -n ingress-test # Expected: echo-server pod in Running state
HTTP Testing
- [ ] Test HTTP access with nip.io:
EXTERNAL_IP=$(kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl http://test.${EXTERNAL_IP}.nip.io
# Expected: Echo server response (JSON with request details)
- [ ] Test HTTP access with custom domain (if DNS configured):
curl http://test.fawkes.yourdomain.com # Expected: Echo server response
TLS Certificate Testing
- [ ] Create test ingress with TLS:
# Create ingress with cert-manager annotation
# Use letsencrypt-staging first!
- [ ] Certificate resource created:
kubectl get certificate -n ingress-test
# Expected: Certificate resource exists
- [ ] CertificateRequest created:
kubectl get certificaterequest -n ingress-test
# Expected: CertificateRequest exists
- [ ] Certificate issued (may take 1-2 minutes):
kubectl get certificate -n ingress-test -o jsonpath='{.items[0].status.conditions[?(@.type=="Ready")].status}'
# Expected: True
- [ ] TLS secret created:
kubectl get secret -n ingress-test | grep tls
# Expected: TLS secret exists
- [ ] Test HTTPS access:
curl https://test.fawkes.yourdomain.com # Expected: Successful HTTPS connection
Azure Resources Verification
Load Balancer
- [ ] Load Balancer rules exist:
az network lb rule list --resource-group MC_fawkes-rg_fawkes-aks_eastus --lb-name kubernetes -o table
# Expected: Rules for ports 80 and 443
- [ ] Health probes configured:
az network lb probe list --resource-group MC_fawkes-rg_fawkes-aks_eastus --lb-name kubernetes -o table # Expected: Health probe for /healthz
Public IP
- [ ] Public IP exists:
az network public-ip list --resource-group MC_fawkes-rg_fawkes-aks_eastus -o table # Expected: Public IP with kubernetes prefix
Monitoring and Alerting
Prometheus Metrics
- [ ] Metrics endpoints accessible:
kubectl port-forward -n ingress-nginx svc/ingress-nginx-controller-metrics 9402:10254 &
curl http://localhost:9402/metrics | grep nginx_ingress_controller_requests
# Expected: Metrics data returned
- [ ] cert-manager metrics accessible:
kubectl port-forward -n cert-manager svc/cert-manager 9402:9402 & curl http://localhost:9402/metrics | grep certmanager_certificate # Expected: Certificate metrics data
Alerts
- [ ] PrometheusRules configured:
kubectl get prometheusrule -n ingress-nginx kubectl get prometheusrule -n cert-manager # Expected: Rules for ingress and certificates
Documentation
- [ ] Read setup guide:
docs/azure-ingress-setup.md - [ ] Read quickstart guide:
docs/azure-ingress-quickstart.md - [ ] Read implementation summary:
docs/azure-ingress-implementation-summary.md - [ ] Read nginx-ingress README:
platform/apps/ingress-nginx/README.md - [ ] Read cert-manager README:
platform/apps/cert-manager/README.md
Common Issues Resolved
If you encounter any issues, check the following:
External IP Pending
- Wait 2-3 minutes for Azure to provision the Load Balancer
- Check service events:
kubectl describe svc ingress-nginx-controller -n ingress-nginx
Certificate Not Issuing
- Verify DNS points to ingress IP:
dig +short yourapp.fawkes.yourdomain.com - Check challenge status:
kubectl get challenge -A - Check cert-manager logs:
kubectl logs -n cert-manager deployment/cert-manager - Verify ClusterIssuer is ready:
kubectl describe clusterissuer letsencrypt-prod
404 Not Found
- Verify ingress resource:
kubectl describe ingress <name> -n <namespace> - Check backend service exists:
kubectl get svc <name> -n <namespace> - Check controller logs:
kubectl logs -n ingress-nginx -l app.kubernetes.io/component=controller
DNS Not Resolving
- Wait up to 48 hours for DNS propagation
- Verify nameserver delegation:
dig NS fawkes.yourdomain.com - Check Azure DNS records:
az network dns record-set a list -g fawkes-rg -z fawkes.yourdomain.com
Final Verification
All items checked? You're ready to use Azure Load Balancer and Ingress!
Summary:
- ✅ nginx-ingress deployed with Azure Load Balancer
- ✅ Azure Load Balancer created with health probes
- ✅ Public IP assigned
- ✅ DNS configured (if enabled)
- ✅ cert-manager deployed
- ✅ Let's Encrypt ClusterIssuers configured
- ✅ Test ingress working
- ✅ TLS certificates issuing
Next steps:
- Deploy your application services
- Create Ingress resources with cert-manager annotations
- Monitor certificate status
- Set up alerts for expiring certificates
- Configure rate limiting and WAF (optional)