1. Overview
In Kubernetes, the LoadBalancer service is the standard way of exposing network applications to the external world. The LoadBalancer service is preferred when assigning a dedicated IP address to each service.
In the public cloud platforms, the LoadBalancer service deploys the network load balancer in the cloud. However, minikube simulates it using the tunnel protocol, and by default, it shows the service’s external IP address as pending.
In this short tutorial, we’ll discuss how to address Minikube’s issue when the Kubernetes service shows its external IP as pending.
2. Setting up an Example
It’s a good practice to use Kubernetes namespaces to isolate the resources. So, let’s create the namespace with the name service-demo:
$ kubectl create ns service-demo
namespace/service-demo created
Next, let’s use the create command to deploy the Redis pod in the newly created namespace:
$ kubectl create deploy redis --image=redis:alpine -n service-demo
deployment.apps/redis created
Finally, let’s use the get command to verify that the redis pod is running:
$ kubectl get pods -n service-demo
NAME READY STATUS RESTARTS AGE
redis-8648874d67-d66wz 1/1 Running 0 35s
In this section, we created Kubernetes objects to use as an example. In the upcoming sections, we’ll discuss exposing the Redis server outside the cluster.
3. Assigning the External IP Using Minikube Tunnel
The LoadBalancer service is beneficial only if the Kubernetes cluster supports the deployment of external load balancers. For example, managed Kubernetes service in all major public cloud platforms supports the load balancer deployment.
By default, Kubernetes doesn’t provide an implementation of network load balancers for bare-metal clusters. However, we can simulate it by setting up the network routes. So, let’s see how to assign an external IP address to the LoadBalancer service in minikube using the tunnel protocol.
3.1. Creating a LoadBalancer Service
First, let’s use the expose command to create a Service with the type LoadBalancer:
$ kubectl expose deploy redis --port 6379 --type LoadBalancer -n service-demo
service/redis exposed
The expose command uses the selectors of the Deployment object and creates a Service using the same selectors. In this case, the Service uses the selectors of the Redis deployment.
Next, let’s find out the external IP address of the LoadBalancer service:
$ kubectl get service -n service-demo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
redis LoadBalancer 10.103.33.106 <pending> 6379:31794/TCP 12s
In the output, the column with the header EXTERNAL-IP shows the load balancer’s IP address.
However, in this case, it’s showing as
3.2. Using the Minikube Tunnel
In the previous section, we saw that the Redis service shows the external IP address as pending. Let’s fix this using the minikube tunnel command.
First, let’s execute the tunnel command in the terminal:
$ minikube tunnel
Status:
machine: minikube
pid: 9325
route: 10.96.0.0/12 -> 192.168.49.2
minikube: Running
services: [redis]
errors:
minikube: no errors
router: no errors
loadbalancer emulator: no errors
Here, we can see that the command sets up the network routes using the load balancer emulator.
Next, let’s open another terminal and check the IP address of the LoadBalancer service:
$ kubectl get service -n service-demo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
redis LoadBalancer 10.103.33.106 10.103.33.106 6379:31794/TCP 53s
In the output, we can see the newly allocated external IP address. Now, let’s use the same IP address from outside to access the Redis server:
$ redis-cli -h 10.103.33.106 PING
PONG
Here, we can see that the Redis server responds with the PONG message.
3.3. Cleaning Up
Now, let’s clean up from the service-demo namespace before moving to the next section.
First, switch back to the first terminal and press the Ctrl + C key combination. This operation terminates the tunnel process and cleans up the network routes.
Next, let’s use the delete command to remove the Redis service:
$ kubectl delete svc redis -n service-demo
service "redis" deleted
4. Assigning the External IP Using MetalLB
Just like the tunnel protocol, we can also use the MetalLB load balancer to assign the external IP address to the LoadBalancer service.
In the case of Minikube, we can either install and configure the MetalLB from scratch or configure it via the add-ons. Minikube add-ons are extensions of minikube used for added functionality for Kubernetes.
In this section, we’ll discuss how to configure and use the MetalLB addon.
4.1. Enabling the metallb Addon
First, let’s enable the metallb addon using the addons enable command:
$ minikube addons enable metallb
Next, let’s use the addons list command to check the status of all addons:
$ minikube addons list
In the output, we can see that the metallb addon has been enabled. Now, let’s see how to configure it.
4.2. Configuring the metallb Addon
To configure the metallb addon, we need to specify the range of IP addresses the load balancer can use. So, let’s find the IP address of the minikube node using the ip command:
$ minikube ip
192.168.49.2
Next, let’s use the addons configure command to specify the IP address range for the load balancer:
$ minikube addons configure metallb
-- Enter Load Balancer Start IP: 192.168.49.10
-- Enter Load Balancer End IP: 192.168.49.20
▪ Using image quay.io/metallb/speaker:v0.9.6
▪ Using image quay.io/metallb/controller:v0.9.6
✅ metallb was successfully configured
In this example, we have specified 192.168.48.10 as the start IP address and 192.168.48.20 as the end IP address.
It’s important to note that we need to use the IP address range that matches the network range of the minikube node. In this case, the network range starts with the 192.168.48.xx
4.3. Creating a LoadBalancer Service
Now, let’s create the LoadBalancer service using the expose command:
$ kubectl expose deploy redis --port 6379 --type LoadBalancer -n service-demo
service/redis exposed
Next, let’s check the external IP address of the Redis service:
$ kubectl get service -n service-demo
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
redis LoadBalancer 10.102.24.187 192.168.49.10 6379:31569/TCP 10s
Here, we can see that the EXTERNAL-IP column shows the IP address of the LoadBalaner service, and it matches the IP address range we configured in the previous section.
Now, let’s access the Redis server from outside using the service’s external IP address:
$ redis-cli -h 192.168.49.10 PING
PONG
Here, we can see that the Redis server sends a PONG reply.
5. Cleaning Up
While setting up an example, we created a service-demo namespace and deployed a few Kubernetes objects into it. Now, let’s do the clean-up of those objects:
$ kubectl delete ns service-demo
namespace "service-demo" deleted
In this example, we deleted the namespace directly instead of deleting individual objects. This is acceptable only in the test environment, and one should never execute the same command in the production environment.
6. Conclusion
In this article, we discussed two methods to address the issue in minikube when the service shows its external IP as pending.
First, we used the tunnel command to assign an external IP address to the LoadBalancer service. Then, we used the metallb addon to achieve the same.