Cloud Load Balancer & DNS
In Docker Desktop Kubernetes (Lesson 5 of Chapter 50), you used NodePort services to access your applications from outside the cluster. NodePort worked because Docker Desktop simulates external access on your laptop. But NodePort has limitations: you access services on high port numbers (30000-32767), and there's no real load balancer distributing traffic.
On a real cloud provider, you get something better: LoadBalancer services that provision actual cloud load balancers. When you create a LoadBalancer service on DigitalOcean, Kubernetes talks to the DigitalOcean API and creates a real load balancer with a public IP address. Your service becomes accessible at standard ports (80, 443) without any port mapping tricks.
This lesson covers how LoadBalancer services work differently in the cloud, how to watch external IP provisioning, how to configure DNS to point your domain at your service, and what this costs.
LoadBalancer vs NodePort: The Cloud Difference
In Chapter 50, you learned three Service types: ClusterIP (internal), NodePort (external via high ports), and LoadBalancer (external via cloud LB). On Docker Desktop, LoadBalancer services behave like NodePort because there's no cloud provider to provision a real load balancer.
On DigitalOcean DOKS (or any cloud Kubernetes), the LoadBalancer type triggers cloud provider integration:
| Aspect | NodePort | LoadBalancer (Cloud) |
|---|---|---|
| Access Port | 30000-32767 | Standard ports (80, 443) |
| External IP | Node IP + nodePort | Dedicated public IP |
| Traffic Path | Client -> Node -> Pod | Client -> LB -> Node -> Pod |
| Load Balancing | None (client picks node) | Cloud LB distributes traffic |
| Cost | Free (uses nodes) | Additional (~$12/month on DigitalOcean) |
| Production Ready | Development only | Yes |
The key insight: LoadBalancer is the production pattern because it provides a stable public IP, handles traffic distribution, and works with standard ports.
Creating a LoadBalancer Service
Here's a LoadBalancer service for your Task API:
apiVersion: v1
kind: Service
metadata:
name: task-api
namespace: default
spec:
type: LoadBalancer
selector:
app: task-api
ports:
- name: http
port: 80
targetPort: 8000
protocol: TCP
Save this as task-api-lb.yaml and apply it:
kubectl apply -f task-api-lb.yaml
Output:
service/task-api created
Watching External IP Provisioning
When you create a LoadBalancer service on a cloud cluster, the external IP doesn't appear immediately. Kubernetes requests a load balancer from the cloud provider, and provisioning takes 30-60 seconds.
Watch the service to see the transition:
kubectl get svc task-api -w
Output (initial state):
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
task-api LoadBalancer 10.245.0.100 <pending> 80:31234/TCP 10s
The <pending> status means Kubernetes has requested a load balancer from DigitalOcean, but it's still being provisioned. Keep watching:
Output (after ~45 seconds):
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
task-api LoadBalancer 10.245.0.100 143.198.x.x 80:31234/TCP 55s
The EXTERNAL-IP column now shows a real public IP address. Your service is accessible at http://143.198.x.x (your actual IP will differ).
Press Ctrl+C to stop watching.
What Happened Behind the Scenes
When you created the LoadBalancer service:
- Kubernetes detected LoadBalancer type and contacted the DigitalOcean cloud controller
- Cloud controller called DigitalOcean API to create a load balancer
- DigitalOcean provisioned the LB with a public IP and configured it to forward traffic to your cluster nodes
- Cloud controller updated the Service with the external IP
- Kubernetes updated the Endpoints to route traffic to your Pods
This integration is automatic. You don't manage the load balancer directly—Kubernetes does it for you.
Verify the Load Balancer Exists
You can see the load balancer in the DigitalOcean console (Control Panel -> Networking -> Load Balancers) or via doctl:
doctl compute load-balancer list
Output:
ID Name IP Status Created At
abc123... k8s-lb-task-api-abcd1234... 143.198.x.x active 2025-01-15T10:30:00Z
The load balancer was automatically created and named based on your service.
Cost Implications
Each LoadBalancer service creates a separate cloud load balancer. On DigitalOcean, regional HTTP load balancers cost $12 per month per node (starting with 1 node). This adds up quickly:
| Number of LoadBalancer Services | Monthly Cost |
|---|---|
| 1 | $12 |
| 3 | $36 |
| 5 | $60 |
| 10 | $120 |
For a single service, $12/month is reasonable. But if you have 10 microservices each with a LoadBalancer, you're paying $120/month just for load balancers—often more than your compute costs.
The Ingress Solution
In production, teams use Ingress controllers (covered in later chapters) to expose multiple services through a single load balancer:
Single LB ($12/mo)
│
┌────┴────┐
│ Ingress │
└────┬────┘
┌─────────────┼─────────────┐
│ │ │
┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
│ Service A │ │ Service B │ │ Service C │
│ ClusterIP │ │ ClusterIP │ │ ClusterIP │
└───────────┘ └───────────┘ └───────────┘
Instead of 3 LoadBalancers ($36/mo), you have 1 LoadBalancer with an Ingress routing to 3 ClusterIP services ($12/mo).
For this chapter, you'll use a LoadBalancer for simplicity. Just remember: production deployments typically use Ingress to consolidate costs.
DNS Configuration Options
Your LoadBalancer has a public IP (e.g., 143.198.x.x), but users access applications via domain names, not IP addresses. You need DNS to map your domain to the external IP.
Option 1: Real Domain with A-Record
If you own a domain (e.g., example.com), create an A-record pointing to your LoadBalancer IP:
-
Log into your DNS provider (DigitalOcean, Cloudflare, Route53, GoDaddy, etc.)
-
Create an A-record:
- Type: A
- Name:
api(ortask-api, or@for root) - Value:
143.198.x.x(your LoadBalancer IP) - TTL: 300 (5 minutes, good for testing)
-
Result:
api.example.comresolves to143.198.x.x
Example in DigitalOcean DNS:
Type Name Value TTL
A api 143.198.x.x 300
Option 2: Wildcard DNS for Testing (nip.io / sslip.io)
If you don't have a domain or want quick testing, use wildcard DNS services. These services resolve any hostname containing an IP address back to that IP:
| Service | Pattern | Example |
|---|---|---|
| nip.io | <anything>.<ip>.nip.io | api.143.198.1.2.nip.io -> 143.198.1.2 |
| sslip.io | <anything>.<ip>.sslip.io | task-api.143.198.1.2.sslip.io -> 143.198.1.2 |
With your LoadBalancer IP 143.198.x.x, you can immediately access:
curl http://task-api.143.198.x.x.nip.io/health
No DNS configuration required. The nip.io service extracts the IP from the hostname and returns it.
Limitations of wildcard DNS:
- Not suitable for production (depends on third-party service)
- No HTTPS without additional configuration
- Looks unprofessional in URLs
Use nip.io/sslip.io for testing. Use real domains for production.
Verifying DNS Propagation
After creating DNS records, verify they propagate correctly using dig or nslookup.
Using dig
dig api.example.com
Output:
;; QUESTION SECTION:
;api.example.com. IN A
;; ANSWER SECTION:
api.example.com. 300 IN A 143.198.x.x
;; Query time: 45 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
The ANSWER SECTION shows your A-record resolving to the LoadBalancer IP.
Using nslookup
nslookup api.example.com
Output:
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: api.example.com
Address: 143.198.x.x
Troubleshooting DNS
If DNS doesn't resolve immediately:
-
Wait for propagation: DNS changes can take up to TTL seconds (plus caching). With TTL 300, wait 5 minutes.
-
Flush local DNS cache:
# macOS
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
# Linux
sudo systemd-resolve --flush-caches
# Windows
ipconfig /flushdns -
Check with a public DNS server:
dig @8.8.8.8 api.example.com -
Verify the record exists at your DNS provider using their control panel.
Complete Workflow: LoadBalancer to DNS
Here's the full sequence for making your Task API accessible at a real domain:
Step 1: Apply LoadBalancer Service
kubectl apply -f task-api-lb.yaml
Step 2: Wait for External IP
kubectl get svc task-api -w
Wait until EXTERNAL-IP shows a real IP (not <pending>).
Step 3: Create DNS Record
In your DNS provider, create:
Type: A
Name: api
Value: <your-external-ip>
TTL: 300
Step 4: Verify DNS
dig api.yourdomain.com
Confirm it resolves to your LoadBalancer IP.
Step 5: Test Access
curl http://api.yourdomain.com/health
Output:
{"status": "healthy"}
Your Task API is now accessible via a real domain name.
Try With AI
You've learned how LoadBalancer services provision cloud load balancers and how DNS connects domains to IPs. Now practice with your AI companion.
Prompt 1: Diagnose EXTERNAL-IP Stuck on Pending
My LoadBalancer service has been stuck on EXTERNAL-IP <pending> for 5 minutes.
The cluster is on DigitalOcean DOKS. Help me debug this.
What should I check first? What are the common causes?
What you're learning: Systematic debugging of cloud controller integration issues—permissions, quotas, and cloud provider errors.
Prompt 2: Calculate Multi-Service Costs
I'm planning a microservices deployment with 8 services that need external access.
If I use one LoadBalancer per service at $12/month each, that's $96/month.
Help me design an alternative using Ingress. What would the architecture look like?
What's the cost difference? What are the tradeoffs?
What you're learning: Cost-aware architecture design. Understanding when to consolidate load balancers vs when dedicated LBs make sense.
Prompt 3: DNS for Multiple Environments
I need DNS configuration for three environments:
- dev.api.example.com -> development cluster
- staging.api.example.com -> staging cluster
- api.example.com -> production cluster
Each environment has its own LoadBalancer IP. Show me the DNS records I need
and explain how to manage this at scale.
What you're learning: Multi-environment DNS patterns and the operational considerations for managing multiple cluster endpoints.
Safety Note
When configuring DNS, remember that changes propagate globally. Use low TTL values (300 seconds) during initial setup so you can fix mistakes quickly. For production, increase TTL to reduce DNS query load.
Reflect on Your Skill
Test your multi-cloud-deployer skill with what you learned about LoadBalancer services and DNS.
Test Your Skill
Using my multi-cloud-deployer skill, explain the difference between NodePort
and LoadBalancer services. Does my skill include the PENDING to IP transition?
Does it explain the cost implications of LoadBalancer services?
Identify Gaps
Ask yourself:
- Does my skill explain how cloud LoadBalancer provisioning works (the cloud controller integration)?
- Does it include DNS configuration steps (A-records, TTL, verification with dig)?
- Does it warn about per-LoadBalancer costs and suggest Ingress as an alternative?
- Does it cover wildcard DNS services (nip.io/sslip.io) for testing?
Improve Your Skill
If you found gaps:
My multi-cloud-deployer skill is missing LoadBalancer and DNS patterns.
Update it to include:
- The PENDING to external IP transition and how to watch it
- Cost implications (~$12/month per LB on DigitalOcean)
- DNS A-record configuration steps
- Wildcard DNS alternatives (nip.io, sslip.io) for testing
- DNS verification using dig and nslookup
By the end of this chapter, your skill will be a comprehensive cloud deployment reference.