Sign In
Sign In

Nginx Ingress

Updated on 25 March 2025

Ingress is a Kubernetes resource that enables access to services within a cluster via HTTP and HTTPS. It provides routing based on URLs, domains, and other parameters. This article explores the use of Nginx Ingress with three Nginx deployments simulating three different services. We will also configure an SSL certificate to secure the connection.

Installing Nginx Ingress

First, Nginx Ingress needs to be installed in the cluster. In the cluster management panel, go to the Addons tab, click on the three dots next to Nginx Ingress, and select Install.

After installation, verify that Ingress is functioning correctly by running the command:

kubectl get pods -n ingress-nginx

Ensure that all pods have the Running status.

Configuring Deployments and Services

For convenience, create a separate namespace where all manifests will be located:

kubectl create namespace ingress-example

We will deploy three Deployments with Nginx images, each simulating a separate service. For each Deployment, we will create a Service of type ClusterIP—a service type in Kubernetes that assigns an internal IP address within the cluster. Such a service is not directly accessible from the outside but can be linked to Ingress for external exposure.

service1-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service1
  namespace: ingress-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: service1
  template:
    metadata:
      labels:
        app: service1
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-volume
          mountPath: /usr/share/nginx/html
      volumes:
      - name: config-volume
        configMap:
          name: service-config
          items:
          - key: service1.html
            path: index.html
---
apiVersion: v1
kind: Service
metadata:
  name: service1
  namespace: ingress-example
spec:
  selector:
    app: service1
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP

Manifest explanation:

  • Deployment
    • replicas: 2 specifies that two replicas of Nginx pods will be running.
    • The selector and template.metadata.labels section defines how the service will locate the pods.
    • volumeMounts and volumes are used to mount the service1.html file from a ConfigMap into the directory from which Nginx serves content by default.
  • Service
    • ClusterIP means the service will be accessible only within the cluster via an assigned IP address. For external access, we will use Ingress.

service2-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service2
  namespace: ingress-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: service2
  template:
    metadata:
      labels:
        app: service2
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-volume
          mountPath: /usr/share/nginx/html
      volumes:
      - name: config-volume
        configMap:
          name: service-config
          items:
          - key: service2.html
            path: index.html
---
apiVersion: v1
kind: Service
metadata:
  name: service2
  namespace: ingress-example
spec:
  selector:
    app: service2
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP

service3-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: service3
  namespace: ingress-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: service3
  template:
    metadata:
      labels:
        app: service3
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-volume
          mountPath: /usr/share/nginx/html
      volumes:
      - name: config-volume
        configMap:
          name: service-config
          items:
          - key: service3.html
            path: index.html
---
apiVersion: v1
kind: Service
metadata:
  name: service3
  namespace: ingress-example
spec:
  selector:
    app: service3
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP

To differentiate our services, we will create a ConfigMap with three different HTML pages.

configmap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: service-config
  namespace: ingress-example
data:
  service1.html: |
    <html>
    <head><title>Service 1</title></head>
    <body><h1>Welcome to Service 1!</h1></body>
    </html>
  service2.html: |
    <html>
    <head><title>Service 2</title></head>
    <body><h1>Welcome to Service 2!</h1></body>
    </html>
  service3.html: |
    <html>
    <head><title>Service 3</title></head>
    <body><h1>Welcome to Service 3!</h1></body>
    </html>

Apply the maniests:

kubectl apply -f configmap.yaml
kubectl apply -f service1-deployment.yaml
kubectl apply -f service2-deployment.yaml
kubectl apply -f service3-deployment.yaml

Check the pods statuses:

kubectl get pods -n ingress-example

All pods should have the Running status. 

Creating Ingress

With Ingress, we will define which traffic (based on domains and paths) should be redirected to the corresponding services. We will create the ingress.yaml manifest.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  namespace: ingress-example
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: ingress1.example.com
    http:
      paths:
      - path: /service1
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 80
      - path: /service2
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 80
  - host: ingress2.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service3
            port:
              number: 80

Manifest explanation:

  • rules.host specifies the domain to which Ingress will be bound.
  • paths defines the routing rules:
    • Requests to ingress1.example.com/service1 will be redirected to service1.
    • Requests to ingress1.example.com/service2 will be redirected to service2.
    • Requests to ingress2.example.com/ will be redirected to service3.

Apply the manifest:

kubectl apply -f ingress.yaml

Creating a LoadBalancer

To access Nginx Ingress from an external network, we will create a Service of type LoadBalancer, which will handle load balancing and provide an external IP address. We will prepare the loadbalancer.yaml manifest for this.

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
spec:
  selector:
    app.kubernetes.io/name: ingress-nginx
  ports:
    - name: http
      port: 80
      targetPort: 80
    - name: https
      port: 443
      targetPort: 443
  type: LoadBalancer

Apply the manifest:

kubectl apply -f loadbalancer.yaml

Wait until the load balancer is created and verify that it has an external IP address:

kubectl get services -n ingress-nginx

The external IP will be displayed in the EXTERNAL-IP column.

Add the external IP to the domain’s DNS settings as A records for the domains ingress1.example.com and ingress2.example.com. Once the DNS updates, your domains will point to this load balancer, and you will be able to access the services via external URLs:

  • http://ingress1.example.com/service1 — will display the header "Welcome to Service 1!".
  • http://ingress1.example.com/service2 — will display the header "Welcome to Service 2!".
  • http://ingress2.example.com/ — will display the header "Welcome to Service 3!".

Configuring an SSL Certificate

To ensure a secure connection in Nginx Ingress, you need to add an existing SSL certificate as a Kubernetes Secret and specify this secret in the Ingress manifest.

If you want to automate certificate issuance and renewal (e.g., using Let’s Encrypt), use cert-manager.

Preparing Certificate and Key Files

Save the tls.key (private key) and tls.crt (certificate) files locally. Ensure that the certificate is not expired and matches the domains you want to secure.

Creating a Kubernetes Secret

To add the certificate to the cluster, encode the files in Base64 and create a Secret manifest. Run the following commands in the terminal:

base64 -w 0 ./tls.crt
base64 -w 0 ./tls.key

Then, create the tls-secret.yaml file with the following content:

apiVersion: v1
kind: Secret
metadata:
  name: ingress-example-tls
  namespace: ingress-example
type: kubernetes.io/tls
data:
  tls.crt: |-
    <BASE64_ENCODED_CERTIFICATE>
  tls.key: |-
    <BASE64_ENCODED_KEY>

Save the file and apply the manifest:

kubectl apply -f tls-secret.yaml

Verify that the key and certificate values are not empty by running:

kubectl describe secret ingress-example-tls -n ingress-example

Updating the Ingress Manifest

Update your ingress.yaml manifest by adding the tls section and specifying the created secret.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  namespace: ingress-example
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
  - hosts:
    - ingress1.example.com
    - ingress2.example.com
    secretName: ingress-example-tls
  rules:
  - host: ingress1.example.com
    http:
      paths:
      - path: /service1
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 80
      - path: /service2
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 80
  - host: ingress2.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service3
            port:
              number: 80

Apply the updated manifest:

kubectl apply -f ingress.yaml

Now, when accessing ingress1.example.com or ingress2.example.com over HTTPS, the browser will use the certificate stored in the ingress-example-tls secret. This ensures that traffic to your services is secured.

If you have multiple certificates for different domains, create a Secret for each of them. For example, for example.com and example.org, create two separate secrets.

Then, update the Ingress manifest by adding a tls section for each domain.

spec:
  tls:
  - hosts:
    - example.com
    secretName: example-com-tls
  - hosts:
    - example.org
    secretName: example-org-tls

Each domain will then use its respective certificate as specified in the corresponding secret.

Was this page helpful?
Updated on 25 March 2025

Do you have questions,
comments, or concerns?

Our professionals are available to assist you at any moment,
whether you need help or are just unsure of where to start.
Email us
Hostman's Support