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-nginx
Kubernetes 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.0
of the Ingress NGINX Controller, a ingressclass object is required.In the default installation, an ingressclass object named
nginx
has already been created.$ kubectl -n ingress-nginx get ingressclasses NAME CONTROLLER PARAMETERS AGE nginx k8s.io/ingress-nginx <none> 162m
If this is only instance of the Ingress NGINX Controller, you should add the annotation
ingressclass.kubernetes.io/is-default-class
in your ingress class:kubectl -n ingress-nginx annotate ingressclasses nginx ingressclass.kubernetes.io/is-default-class="true"
-
Try connecting the controller using the
NodePort
from 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: 5000
Deploy the app:
kubectl apply -f simple-web-server-with-ingress.yaml
-
Verify that you can access your application using the
NodePort
from 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
LoadBalancer
There are two alternatives to install
LoadBalancer
on 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
LoadBalancer
In 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: LoadBalancer
kubectl apply -f example-load-balancer.yaml
Then run the following command to see your
LoadBalancer
with an external IP address.kubectl get service example-load-balancer
If the
LoadBalancer
is 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
LoadBalancer
instead ofNodePort
kubectl edit service ingress-nginx-controller -n ingress-nginx
Find the spec.type field and change it from
NodePort
toLoadBalancer
. -
Check that you can see the
ingress-nginx
service 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.yaml
as 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
LoadBalancer
and 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 thehostNetwork
line:spec: template: spec: hostNetwork: true
You 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.