Installing NGINX Ingress Controller#
This tutorial covers the installation of Ingress NGINX Controller, which is an open source project made by the Kubernetes community. k0s doesn't come with a built-in ingress controller, but it's easy to deploy Ingress NGINX Controller as shown in this document. Other ingress solutions can be used as well (see the links at the end of the page).
NodePort vs. LoadBalancer vs. Ingress#
Kubernetes offers multiple options for exposing services to external networks. The main options are NodePort, LoadBalancer and Ingress.
NodePort, as the name says, means that a port on a node is configured to route incoming requests to a certain service. The port range is limited to 30000-32767, so you cannot expose commonly used ports like 80 or 443 via NodePort.
LoadBalancer is a service, which is typically implemented by the cloud provider as an external service (with additional cost). Load balancers can also be installed internally in the Kubernetes cluster with MetalLB, which is typically used for bare-metal deployments. Load balancer provides a single IP address to access your services, which can run on multiple nodes.
Ingress controller helps to consolidate routing rules of multiple applications into one entity. Ingress controller is exposed to an external network with the help of NodePort, LoadBalancer or host network. You can also use Ingress controller to terminate TLS for your domain in one place, instead of terminating TLS for each application separately.
Ingress NGINX Controller#
Ingress NGINX Controller is a very popular ingress for Kubernetes. In many cloud environments, it can be exposed to an external network by using the load balancer offered by the cloud provider. However, cloud load balancers are not necessary. Load balancer can also be implemented with MetalLB, which can be deployed in the same Kubernetes cluster. Another option to expose the Ingress controller to an external network is to use NodePort. The third option is to use host network. All of these alternatives are described in more detail on below, with separate examples.

Installation using NodePort#
Installing using NodePort is the most simple example for Ingress NGINX Controller as we can avoid the load balancer dependency. NodePort is used for exposing the controller to the external network.
-
Install Ingress NGINX Controller (using the official manifests from the official
ingress-nginxKubernetes git repository)kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.3/deploy/static/provider/baremetal/deploy.yaml -
Check that the Ingress controller pods have started
kubectl get pods -n ingress-nginx -
Check that you can see the NodePort service
kubectl get services -n ingress-nginx -
From version
v1.0.0of the Ingress NGINX Controller, a ingressclass object is required.In the default installation, an ingressclass object named
nginxhas already been created.$ kubectl -n ingress-nginx get ingressclasses NAME CONTROLLER PARAMETERS AGE nginx k8s.io/ingress-nginx <none> 162mIf this is only instance of the Ingress NGINX Controller, you should add the annotation
ingressclass.kubernetes.io/is-default-classin your ingress class:kubectl -n ingress-nginx annotate ingressclasses nginx ingressclass.kubernetes.io/is-default-class="true" -
Try connecting the controller using the
NodePortfrom the previous step (in the range of 30000-32767)curl <worker-external-ip>:<node-port>If you don't yet have any backend service configured, you should see "404 Not Found" from nginx. This is okay for now. If you see a response from nginx, the ingress controller is running and you can reach it.
-
Deploy a small test application (Apache HTTP Server) to verify your ingress controller.
Create the following YAML file and name it
simple-web-server-with-ingress.yaml:apiVersion: v1 kind: Namespace metadata: name: web --- apiVersion: apps/v1 kind: Deployment metadata: name: web-server namespace: web spec: selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: httpd image: httpd:2.4.53-alpine ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: web-server-service namespace: web spec: selector: app: web ports: - protocol: TCP port: 5000 targetPort: 80 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: web-server-ingress namespace: web spec: ingressClassName: nginx rules: - host: web.example.com http: paths: - path: / pathType: Prefix backend: service: name: web-server-service port: number: 5000Deploy the app:
kubectl apply -f simple-web-server-with-ingress.yaml -
Verify that you can access your application using the
NodePortfrom step 3.curl <worker-external-ip>:<node-port> -H 'Host: web.example.com'If you are successful, you should see
<html><body><h1>It works!</h1></body></html>.
Install using LoadBalancer#
In this example you'll install Ingress NGINX Controller using LoadBalancer on k0s.
-
Install a
LoadBalancerThere are two alternatives to install
LoadBalanceron k0s. Follow the links in order to installLoadBalancer.- MetalLB as a pure software solution running internally in the k0s cluster - Cloud provider's load balancer running outside of the k0s cluster
-
Verify
LoadBalancerIn order to proceed you need to have a load balancer available for the Kubernetes cluster. To verify that it's available, deploy a simple Service of type
LoadBalancer.apiVersion: v1 kind: Service metadata: name: example-load-balancer spec: selector: app: web ports: - protocol: TCP port: 80 targetPort: 80 type: LoadBalancerkubectl apply -f example-load-balancer.yamlThen run the following command to see your
LoadBalancerwith an external IP address.kubectl get service example-load-balancerIf the
LoadBalanceris not available, you won't get an IP address for EXTERNAL-IP. Instead, it's<pending>. In this case you should go back to the previous step and check your load balancer availability.If you are successful, you'll see a real IP address and you can proceed further.
You can delete the example-load-balancer:
kubectl delete -f example-load-balancer.yaml -
Install Ingress NGINX Controller by following the steps in the previous chapter (step 1 to step 4).
-
Edit the Ingress NGINX Controller to use
LoadBalancerinstead ofNodePortkubectl edit service ingress-nginx-controller -n ingress-nginxFind the spec.type field and change it from
NodePorttoLoadBalancer. -
Check that you can see the
ingress-nginxservice with typeLoadBalancer.kubectl get services -n ingress-nginx -
Try connecting to the ingress controller
If you used private IP addresses for MetalLB in step 2, you should run the following command from the local network. Use the IP address from the previous step, column EXTERNAL-IP.
curl <EXTERNAL-IP>If you don't yet have any backend service configured, you should see "404 Not Found" from nginx. This is okay for now. If you see a response from nginx, the Ingress Controller is running and you can reach it using
LoadBalancer. -
Deploy a small test application (Apache HTTP Server) to verify your
Ingress.Create the YAML file
simple-web-server-with-ingress.yamlas described in the previous chapter (step 6) and deploy it.kubectl apply -f simple-web-server-with-ingress.yaml -
Verify that you can access your application through the
LoadBalancerand ingress controller.curl <worker-external-ip> -H 'Host: web.example.com'If you are successful, you should see
<html><body><h1>It works!</h1></body></html>.
Install using host network#
The host network option exposes Ingress directly using the worker nodes' IP addresses. It also allows you to use ports 80 and 443. This option doesn't use any Service objects (ClusterIP, NodePort, LoadBalancer) and it has the limitation that only one Ingress controller Pod may be scheduled on each cluster node.
-
Install Ingress NGINX Controller manifests:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.3/deploy/static/provider/baremetal/deploy.yaml -
Edit
deploy.yaml. Find the Deployment ingress-nginx-controller and enable the host network option by adding thehostNetworkline:spec: template: spec: hostNetwork: trueYou can also remove the Service ingress-nginx-controller completely, because it won't be needed.
-
Install Ingress
kubectl apply -f deploy.yaml -
Try to connect to the ingress controller, deploy a test application and verify the access. These steps are similar to the previous install methods.
Additional information#
For more information about Ingress NGINX Controller installation, take a look at the official installation guide and bare-metal considerations.