Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:
How to Get a Kubernetes Ingress Endpoint/IP Address
Last updated: September 29, 2024
1. Introduction
Kubernetes ingress is a powerful resource that allows us to manage external access to services within our Kubernetes cluster. By defining rules for routing HTTP and HTTPS traffic, ingress provides a single entry point for multiple services, reducing the complexity of managing multiple NodePorts or LoadBalancers. This becomes especially useful in production environments, where simplicity and efficiency are key.
In this tutorial, we’ll walk through setting up an ingress controller in a Kubernetes cluster and configuring ingress resources to route traffic to our services. We’ll also explore obtaining a Kubernetes ingress endpoint or IP address, which we’ll need to access our services externally.
Whether we’re running a bare-metal cluster or using a cloud provider, we’ll discuss why this is important and how it fits into the broader picture of Kubernetes networking. Let’s get started!
2. Setting up Kubernetes Ingress Controller
Ingress is an API object that manages external access to services in a Kubernetes cluster. It acts as a layer 7 (application layer) load balancer, providing HTTP and HTTPS routing from outside the cluster to services within.
Using ingress offers several advantages:
- URL-based routing: We can route traffic to different services based on the URL path.
- SSL/TLS termination: Ingress can handle SSL/TLS encryption, offloading this task from our services.
- Name-based virtual hosting: We can host multiple domains on a single IP address.
- Load balancing: Ingress can distribute incoming traffic across multiple backend services.
Unlike services, which typically expose a single service on a specific port, an ingress controller allows us to define complex routing rules. These rules might route traffic based on the URL path, the host, or even SSL/TLS settings.
There are several ingress controllers available, with the most popular ones being:
- NGINX ingress controller: Widely used and well-documented, NGINX is a solid choice for most use cases
- GCE ingress controller: Specifically designed for Google Kubernetes Engine (GKE), this controller integrates tightly with Google Cloud
- Traefik ingress controller: Another popular choice, especially for those who prefer a dynamic configuration
For this tutorial, we’ll continue with the NGINX ingress controller, which is commonly used across many Kubernetes environments. This is due to its mature and stable performance, extensive documentation, and strong community support.
Moreover, NGINX offers high performance, especially under heavy traffic loads, and is feature-rich. It supports SSL/TLS termination, load balancing, and various other capabilities, making it a versatile choice for different Kubernetes setups.
2.1. Installing NGINX Ingress Controller
To install the NGINX ingress controller, first, we need to deploy the NGINX ingress controller using the mandatory YAML file provided by the NGINX ingress project:
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
configmap/ingress-nginx-controller created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
...
deployment.apps/ingress-nginx-controller created
Here, we set up the necessary resources in our cluster, such as Deployments, Services, and ConfigMaps. The command will create a new namespace, ingress-nginx, and deploy the ingress controller within it. Then, the controller will start watching for ingress resources across all namespaces in our cluster.
After applying the configuration, let’s verify that the ingress controller has been deployed successfully by checking the status of the pods in the ingress-nginx namespace:
$ kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
ingress-nginx-controller-7f9bcb7ccf-hjksm 1/1 Running 0 2m
The STATUS column should show Running, indicating that the controller is up and running.
2.2. Configuring LoadBalancer for Ingress on Bare Metal
In most cloud environments, the NGINX ingress controller automatically provisions a LoadBalancer to handle external traffic. However, when running Kubernetes on bare metal, we need to manually configure this setup.
To expose the ingress controller externally, we first need to create a Service of the type LoadBalancer. This service will route external traffic to the ingress controller, which will then forward it to the appropriate services based on the ingress rules.
We start by downloading a NodePort service template that we’ll modify to act as a LoadBalancer:
$ curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/baremetal/service-nodeport.yaml -o svc-ingress-nginx-lb.yaml
Here, we download a NodePort service template (service-nodeport.yaml) from the NGINX ingress GitHub repository and save it as svc-ingress-nginx-lb.yaml on our local machine.
Now, let’s modify this file to set up our LoadBalancer. To do this, we’ll edit the downloaded file to change the service type to LoadBalancer and add the externalIPs field with the IP addresses of our nodes. The modified spec section of the file should now look something like:
spec:
type: LoadBalancer
externalIPs:
- 192.168.121.110
- 192.168.121.111
- 192.168.121.112
externalTrafficPolicy: Local
Here, externalIPs specifies the external IP addresses assigned to the nodes in the cluster. Traffic to these IPs will be routed to the ingress controller. Also, externalTrafficPolicy: Local ensures that traffic is only routed to local pods on the node receiving the request, reducing unnecessary network hops and preserving the source IP address.
2.3. Applying the Configuration
After saving the file, we need to apply the configuration to our cluster with kubectl:
$ kubectl apply -f svc-ingress-nginx-lb.yaml
service/ingress-nginx-lb created
This will create a LoadBalancer service that routes external traffic to the NGINX ingress controller.
Finally, we can now verify the creation of the LoadBalancer service with the correct external IPs:
$ kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-lb LoadBalancer 10.96.105.34 192.168.121.110,... 80:31213/TCP,443:31813/TCP 1m
Our output shows the creation of ingress-nginx-lb service as a LoadBalancer type, with the EXTERNAL-IP field listing the IPs we configured. These IPs are now accessible externally, allowing traffic to reach the NGINX ingress controller, which will then distribute it according to the ingress rules.
3. Configuring Ingress Resources
With the ingress controller up and running, our next step is to configure ingress resources. These resources define the route of external requests to appropriate services within our cluster. This configuration allows us to consolidate multiple services under a single IP address or hostname, making our services more accessible and easier to manage.
3.1. Setting up Sample Applications
To demonstrate how ingress works and retrieve the IP address later, we’ll set up two simple applications: an NGINX web server and an EchoServer. EchoServer is a simple server that responds with the details of the request it receives, making it useful for testing. We’ll create Deployments for both applications and then expose them as Services.
Let’s start by creating our Deployments.
First, let’s deploy the nginx web server:
$ kubectl create deployment nginx --image=nginx --port=80
deployment.apps/nginx created
Here, we create a new Deployment nginx using the official NGINX image from Docker Hub. The –port=80 flag specifies that the container will listen on port 80.
Next, let’s deploy the EchoServer:
$ kubectl create deployment echoserver --image=gcr.io/google_containers/echoserver:1.4 --port=8080
deployment.apps/echoserver created
Similarly, we create a Deployment echoserver using the EchoServer image from Google’s container registry. The server listens on port 8080, which is specified by the –port=8080 flag.
Now, we need to expose these Deployments as Services to be accessible within the cluster with kubectl expose.
For the nginx service, let’s run:
$ kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed
The service will now route traffic to port 80 of the nginx pod.
Similarly, let’s expose the EchoServer Deployment as a Service:
$ kubectl expose deployment echoserver --port=8080 --type=NodePort
service/echoserver exposed
Finally, let’s verify the creation of both Services and that they are running correctly:
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echoserver NodePort 10.100.200.45 <none> 8080:31250/TCP 30s
nginx NodePort 10.100.200.75 <none> 80:32018/TCP 45s
With our sample applications now running and exposed as services, we’re ready to set up ingress to route external traffic to these services and retrieve the ingress endpoint or IP address.
3.2. Creating an Ingress Resource
Now that our applications and the NGINX ingress controller are up and running, we can create an ingress resource to define the route of external traffic to our services.
We start by creating a YAML configuration for the ingress resource. This configuration will specify that requests to /nginx should be routed to the nginx service, and requests to /echo should be routed to the echoserver service.
Let’s see the YAML configuration:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: fanout-nginx-ingress
namespace: default
spec:
rules:
- http:
paths:
- path: /nginx
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80
- path: /echo
pathType: Prefix
backend:
service:
name: echoserver
port:
number: 8080
Our YAML defines an ingress resource fanout-nginx-ingress in the default namespace. It specifies two paths /nginx and /echo and associates them with the respective services. The pathType is set to Prefix, meaning any request that starts with the specified path will be routed to the corresponding backend service.
Let’s now apply the ingress configuration file to our cluster:
$ kubectl apply -f ingress.yaml
ingress.networking.k8s.io/fanout-nginx-ingress created
To ensure we have the correct configuration for our ingress resource, let’s check it with kubectl describe:
$ kubectl describe ing fanout-nginx-ingress
Name: fanout-nginx-ingress
Namespace: default
Address: 192.168.121.110
Rules:
Host Path Backends
---- ---- --------
* /nginx nginx:80 (10.244.1.5:80)
/echo echoserver:8080 (10.244.1.6:8080)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Sync 1m nginx-ingress-controller Scheduled for sync
With this setup, the ingress resource now directs traffic based on the specified paths to the appropriate services within the cluster. Requests to /nginx are routed to the nginx service, and requests to /echo are routed to the EchoServer service.
This configuration will also allow us to retrieve the ingress endpoint or IP address later to access these services externally.
4. Retrieving the Ingress Endpoint or IP Address
After configuring our ingress resource, we can now retrieve the ingress endpoint or IP address. This is the external address that clients will use to access the services defined in our ingress resource.
4.1. Using kubectl to Get the Ingress Address
The simplest way to retrieve the ingress IP address is by using the kubectl command:
$ kubectl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
fanout-nginx-ingress <none> * 192.168.121.110 80 5m
As we can see, an IP address in the ADDRESS column is the external IP address assigned to the ingress. Clients will use this IP address to access the services. In our example above, the IP is 192.168.121.110. We now have the endpoint that external clients can use to access the nginx and EchoServer services via the defined paths.
4.2. Verifying Access to Services via Ingress
After obtaining the ingress IP address, we should verify that the services are accessible through the ingress. We can do this by sending HTTP requests to the ingress paths using tools like curl or by accessing them via a web browser.
For example, let’s use curl to test if the NGINX service is accessible via the ingress:
$ curl http://192.168.121.110/nginx
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; }
...
</body>
</html>
Our output confirms that the nginx service is successfully accessible via the ingress at the /nginx path. The response is the default NGINX welcome page.
Similarly, we can also test if the EchoServer service is accessible:
$ curl http://192.168.121.110/echo
{
"host": "echoserver-6df5b57bdc-b2msl",
"uri": "/echo",
"headers": {
"host": "192.168.121.110",
"user-agent": "curl/7.68.0",
"accept": "*/*"
}
}
Our output is a JSON response generated by the EchoServer. It includes details about the request, such as the request URI (/echo), headers, and the pod that processed the request (host). This confirms that the EchoServer service is also accessible via the ingress at the /echo path.
5. Conclusion
In this article, we’ve explored the process of obtaining a Kubernetes ingress endpoint/IP address. Ingress offers powerful tools for managing incoming traffic in our clusters. We started with the basics of Kubernetes ingress and set up sample applications, including the installation of an ingress controller. We then created an ingress resource and discussed how to retrieve its endpoint.
We’ve seen how ingress plays a crucial role in Kubernetes networking, providing a flexible way to route external traffic to our services.