16: Service LoadBalancer
16: Service LoadBalancer
Objective
Learn how the LoadBalancer Service type works in AKS, understand how Azure automatically provisions an Azure Load Balancer, and practice creating both public and internal LoadBalancer Services.
Theory
LoadBalancer Extends ClusterIP
A LoadBalancer Service is a superset of a ClusterIP Service. When you create a LoadBalancer Service, Kubernetes:
- Creates a ClusterIP (internal virtual IP)
- Requests the cloud provider (Azure) to provision an external load balancer
- Azure creates an Azure Load Balancer with a public (or internal) IP
- Traffic from the external IP is routed through the Azure LB to the Service’s ClusterIP, and then to the Pods
ClusterIP vs LoadBalancer Comparison
| Feature | ClusterIP | LoadBalancer |
|---|---|---|
| Accessible from | Inside the cluster only | Internet or internal Azure network |
| External IP | None | Assigned by Azure |
| Azure resource created | None | Azure Load Balancer + Public IP |
| Use case | Internal microservice communication | Exposing services to external clients |
| Cost | Free | Azure LB and Public IP costs apply |
Public vs Internal Load Balancer
| Type | Description | Use Case |
|---|---|---|
| Public | Gets a public IP address accessible from the Internet | Web applications, public APIs |
| Internal | Gets a private IP address from your VNet | Backend services, internal APIs, hybrid connectivity |
To create an internal Load Balancer, add the annotation:
metadata:
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
Traffic Flow Diagram
graph TB
Internet["Internet / Client"]
subgraph Azure["Azure"]
ALB["Azure Load Balancer<br/>External IP: 20.50.100.200"]
end
subgraph AKS["AKS Cluster"]
SVC["Service: nginx-lb-XX<br/>ClusterIP: 10.0.100.50"]
subgraph Pods["Pods"]
P1["Pod 1<br/>10.244.0.5:80"]
P2["Pod 2<br/>10.244.1.8:80"]
P3["Pod 3<br/>10.244.2.3:80"]
end
end
Internet -->|"http://20.50.100.200"| ALB
ALB --> SVC
SVC --> P1
SVC --> P2
SVC --> P3
style Azure fill:#e1f5fe,stroke:#0288d1,stroke-width:2px
style AKS fill:#e8f5e9,stroke:#388e3c,stroke-width:1px
style Internet fill:#fff3e0,stroke:#f57c00,stroke-width:1px
Practical Tasks
Task 1: Create a Public LoadBalancer Service
Create a file called nginx-loadbalancer.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-lb-XX # Replace XX with your student number
namespace: student-XX
labels:
app: nginx-lb-XX
spec:
replicas: 3
selector:
matchLabels:
app: nginx-lb-XX
template:
metadata:
labels:
app: nginx-lb-XX
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
name: http
---
apiVersion: v1
kind: Service
metadata:
name: nginx-lb-XX # Replace XX with your student number
namespace: student-XX
spec:
type: LoadBalancer
selector:
app: nginx-lb-XX
ports:
- protocol: TCP
port: 80
targetPort: 80
name: http
Deploy and wait for the external IP:
kubectl apply -f nginx-loadbalancer.yaml
Watch the Service until EXTERNAL-IP changes from <pending> to an actual IP address:
kubectl get svc nginx-lb-XX -n student-XX -w
Note: It may take 1-3 minutes for Azure to provision the Load Balancer and assign a public IP.
Once the external IP is assigned, test it in your browser:
http://<EXTERNAL-IP>
You should see the default nginx welcome page.
You can also test from the command line:
curl http://<EXTERNAL-IP>
Task 2: Create an Internal LoadBalancer Service
Create a file called nginx-internal-lb.yaml:
apiVersion: v1
kind: Service
metadata:
name: nginx-internal-lb-XX # Replace XX with your student number
namespace: student-XX
annotations:
service.beta.kubernetes.io/azure-load-balancer-internal: "true"
spec:
type: LoadBalancer
selector:
app: nginx-lb-XX # Reuses the same Deployment from Task 1
ports:
- protocol: TCP
port: 80
targetPort: 80
name: http
Deploy and verify:
kubectl apply -f nginx-internal-lb.yaml
kubectl get svc nginx-internal-lb-XX -n student-XX -w
Notice that the EXTERNAL-IP is a private IP address from your VNet (e.g., 10.0.x.x), not a public IP.
This Service is accessible from:
- Other Pods within the cluster
- Other resources in the same VNet (VMs, other AKS clusters)
- On-premises networks connected via VPN or ExpressRoute
It is not accessible from the public Internet.
Clean Up
Important: Each LoadBalancer Service creates Azure resources (Load Balancer rules, Public IPs) that incur costs. Always clean up LoadBalancer Services promptly when you are done with the exercise to avoid unnecessary charges.
kubectl delete -f nginx-loadbalancer.yaml
kubectl delete -f nginx-internal-lb.yaml
AKS Diagnostics (Instructor Reference)
Note: The following Azure CLI commands and Azure Portal tasks require access to the Azure subscription. In this training, these are performed by the instructor as a demo. Participants can observe but should focus on the
kubectlcommands in the practical tasks above.
Check the MC_ Resource Group
Azure creates Load Balancer resources in the managed resource group (prefixed with MC_). The instructor can inspect them:
# List resources in the managed resource group
az resource list --resource-group MC_<resource-group>_<cluster-name>_<region> --output table
# List Load Balancers specifically
az network lb list --resource-group MC_<resource-group>_<cluster-name>_<region> --output table
Check NSG Rules
Network Security Groups control traffic flow. Verify that the NSG allows inbound traffic on the Service port:
az network nsg list --resource-group MC_<resource-group>_<cluster-name>_<region> --output table
az network nsg rule list --resource-group MC_<resource-group>_<cluster-name>_<region> --nsg-name <nsg-name> --output table
Check LB Health Probes in Azure Portal (Instructor Demo)
In the Azure Portal:
- Navigate to the managed resource group (
MC_...) - Open the Load Balancer resource
- Check Health probes — these must be healthy for traffic to flow
- Check Backend pools — these should list your AKS nodes
- Check Load balancing rules — these map the external port to backend port
Useful Commands
| Command | Description |
|---|---|
kubectl get svc -n student-XX |
List all Services |
kubectl get svc nginx-lb-XX -n student-XX -o wide |
Show Service with additional details |
kubectl describe svc nginx-lb-XX -n student-XX |
Detailed Service info including events |
kubectl get events -n student-XX --sort-by=.lastTimestamp |
Check events for LB provisioning status |
Common Problems
| Problem | Possible Cause | Solution |
|---|---|---|
EXTERNAL-IP stays <pending> for more than 5 minutes |
AKS service principal/managed identity lacks permissions to create Azure resources | Check cluster identity permissions on the MC_ resource group |
EXTERNAL-IP is <pending> |
Azure LB quota exceeded | Check Azure subscription quotas for Load Balancers and Public IPs |
| Cannot reach external IP from browser | NSG blocking inbound traffic on the port | Check NSG rules in the MC_ resource group |
| Internal LB gets a public IP | Missing annotation | Verify the azure-load-balancer-internal: "true" annotation is present |
| Service exists but no traffic flows | LB health probes failing | Check health probes in Azure Portal (see next exercise) |
| Slow LB provisioning | Azure API throttling | Wait and retry; check kubectl get events for details |
Best Practices
- Use LoadBalancer only when you need external access — For internal communication, ClusterIP is simpler and free.
- Prefer internal LB for backend services — If a service only needs to be accessed from within the VNet, use the internal annotation.
- Be aware of costs — Each LoadBalancer Service creates an Azure LB rule and potentially a Public IP, which incur costs.
- Consider Ingress for HTTP workloads — Instead of creating multiple LoadBalancer Services, use an Ingress controller to consolidate external access behind a single Load Balancer.
- Monitor LB health probes — Unhealthy probes mean Azure LB will not route traffic to your nodes.
Summary
In this exercise you learned:
- LoadBalancer is a superset of ClusterIP that provisions an Azure Load Balancer
- Azure automatically creates and configures the LB, public IP, health probes, and NSG rules
- Public LoadBalancer exposes services to the Internet; internal LoadBalancer uses a private VNet IP
- How to create both public and internal LoadBalancer Services in AKS
- Where to find and diagnose Azure LB resources in the MC_ resource group
- Common issues: pending EXTERNAL-IP, NSG blocking, health probe failures