How to use Kubernetes Ingress on an ASP.NET Core app

How to use Kubernetes Ingress on an ASP.NET Core app

In this tutorial you will learn about Kubernetes Ingress and how to apply Ingress on an ASP.NET Core app which is running inside a Pod. Ingress is a Kubernetes object whose work is to expose the Kubernetes Service to HTTP and HTTPS routes.

In the last tutorial I had created an ASP.NET Core app and hosted it on a Pod. I also exposed that Pod with a Service and the service was accessible with an IP address. If you want to check this tutorial then visit – What are Services in Kubernetes.

What is Ingress and how it is different than a Service

When you want to expose your service to outside world i.e. with http and https protocols then you create an ingress and it expose a service. The service is connected to the pods.

The ingress is exposed to the outside world using http and https. So this means Ingress will serve your app when the Ingress IP is called on the browser.

Check the below image where I tried to explain this working.

kubernetes ingress working

A question arises why use Ingress when the Service is exposing the Pod to HTTP and HTTPS routes? The answer is that Ingress sits in front of multiple services and act as a “smart router” or entrypoint into your cluster. So, an Ingress can control multiple services and this reduces complexities. In production you should use Ingress for exposing your app to HTTP and HTTPS routes, you should not expose your service like what I did in the previous tutorial.

Ingress Controller

In order for the Ingress to work your kubernetes cluster must have an Ingress Controller running. The work of the Ingress Controller is to see the incoming request and pass them on to the respective Ingress. There are lots of Ingress Controllers, see this link for various types of Ingress Controllers. I will be using ingress-nginx. There are number of reasons to do it:

  • 1. It is developed by the Kubernetes core team and is most popular.
  • 2. It is a complete package and works perfectly.

Check it’s page for the Installation procedure on AWS, Azure, Google Cloud. In minikube the installation is very simple, just run the following command on your command prompt or terminal.

minikube addons enable ingress
minikube addons enable ingress

Creating Ingress for your ASP.NET Core app

Let us create an Ingress for my ASP.NET Core app. Note that I have already created a deployment and service for my app in my previous tutorial. Kindly check that tutorial if you haven’t done so, link is here.

Now I will create an Ingress which will expose the HTTP and HTTPS routes from outside the cluster to the service. So once the Ingress is created then I will be able to access my ASP.NET Core app by opening the Ingress IP address on the browser.

So, add the below Ingress on a yaml file. I named the file as myingress.yaml.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: first-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: first-service
            port:
              number: 8080

The Ingress code is very simple so let us go through them.

If you want to store data for the Pods then use Kubernetes Volumes. Check my tutorial on it – Kubernetes Volume emptyDir and SSL Mount to volume.
apiVersion & kind

The api version of the Ingress should be networking.k8s.io/v1 and kind should be specified as Ingress.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata & annotations

Next there is a metadata field where the name of the Ingress is given as first-ingress. You can name this Ingress anything which you like.

metadata:
  name: first-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /

Next, there is an annotations field which controls the URL rewriting. The field nginx.ingress.kubernetes.io/rewrite-target targets the URI where the traffic must be redirected. I have given it the value of forward slash (“/”) so this means for a URI match the URI will be rewritten to /. I will tell how the URI match is done in just a moment.

Take 3 example given below:

/apple
/jack/proper
/wave/sea/ocean

Suppose there is a URI match for all of these 3 then they will be rewritten as:

/
/
/

If I change it to /api:

nginx.ingress.kubernetes.io/rewrite-target: /api

Then these 3 URI will be rewritten as:

/api
/api
/api
spec, rules and paths

Then comes the spec section which has all the information needed to configure the Ingress. I have shown it below.

spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: first-service
            port:
              number: 8080

It defines rules for matching URI. See the paths fields that defines “path” to be matched. In the annotations section above I did not told you how the matching of URI is done. Now you can easily understand how this matching is performed.

I have given – path: / field, the “/” specifies all paths will be matched. If I would have given “apple” then all paths starting with apple will be matched, some of them are:

/apple
/apple/jack
/apple/jones/cricket?pg=4
etc..

To match more than one paths you can add a new path section like shown highlighted in the below code:

spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: first-service
            port:
              number: 8080
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: second-service
            port:
              number: 8080

Notice when the path is /api then I am targeting it with another service which is second-service. I will come to the service section in a moment.

pathType

There is a pathType field, each path is required to have a path type. The pathType can have 2 main values:

  • 1. Exact : Matches the URL path exactly and with case sensitivity.
  • 2. Prefix : Matching is done so that the URL should start with the value specified in the path field i.e. the URL should be prefixed with the value specified in the path field

Some examples of Prefix path type are:

Path value URL Match result
/ all paths Yes
/foo /foo Yes
/foo /foo/bar Yes
/foo /bar No
/foo /foo/ No
/foo /foos No
/foo/apple /foo/apple Yes
/foo/apple /foo/bar No
/foo/apple /foo/apple/jack Yes

Dynamic Annotations and Path

I did not define how to make dynamic annotations before as it require you to understand the working of path field.

Now I will explain how annotations and paths can be made dynamic using regular expression. See the below Ingress yaml file and note the highlighted lines:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: first-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - http:
      paths:
      - path: /aspnetcore(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: first-service
            port:
              number: 8080

Here $2 in nginx.ingress.kubernetes.io/rewrite-target means any characters captured by (.*) given on the path field – path: /something(/|$)(.*) will be assigned to the placeholder $2.

This means (.*) forms the 2nd segment or 2nd position in the URI. Let us understand how it happens.

The URI segments given by the “path” field are as follows.

  • a. /aspnetcore forms the 0th segment.
  • b. (/|$) forms the 1st segment.
  • c. (.*) forms the 2nd segment.

See some examples that help you to understand the result:

  • /aspnetcore rewrites to / as no segment is there on 2nd position.
  • /aspnetcore/ rewrites to / as no segment is there on 2nd position. The last “/” on the “/aspnetcore/” is 1st segment.
  • >/aspnetcore/yogihosting rewrites to /yogihosting as “yogihosting” is 2nd segment of the URI.
backend

The backend field specifies the K8S Service and the service port number to be targeted. This means HTTP (and HTTPS) requests to the Ingress are sent to the listed backend. So the service called first-service is targeted by the Ingress.

backend:
  service:
    name: first-service
    port:
      number: 8080

The Port number, here 8080, should be the same port given on the service yaml file.

On my last tutorial I created the Service with the YAML file which is given below. I have highlighted it’s port no which is 8080 and this is the one which the Ingress is targeting.

apiVersion: v1
kind: Service
metadata:
  name: first-service
spec:
  type: NodePort
  selector:
    component: web
  ports:
    - port: 8080
      targetPort: 80

Ingress ”host” field

The host field is an options field. If present it requires that the HTTP host header matches the host field value.

If not specified then the matching rules specified in the Ingress will be applied to all inbound HTTP traffic.

Take for example in the below YAML file of the Ingress I have applied the – host: “yogihosting.com”. So the Ingress will only match requests where the host is yogihosting.com. In simple terms it means the domain should be yogihosting.com.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: first-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: "yogihosting.com"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: first-service
            port:
              number: 8080

In the same way more and one host field can be applied. Check the highlighted below code which has another host field targeting another domain.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: first-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: "yogihosting.com"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: first-service
            port:
              number: 8080
  - host: "api-yogi.com"
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: second-service
            port:
              number: 8080

Hostname wildcards

You can apply wildcard i.e. (* character) for matching. It requires 2 things:

  • 1. “host” should be equal to the suffix of the wildcard rule.
  • 2. wildcard only covers a single DNS label.
Host Value Request for Match result
*.example.com bar.example.com Yes
*.example.com roo.bar.example.com No, wildcard covers only single DNS label
*.example.com example.com No, wildcard covers only single DNS label.
*.example.com somedomain.com No, host is not same as the suffix of the wildcard rule

A simple example is given below.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: first-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: "*.yogihosting.com"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: first-service
            port:
              number: 8080

Applying Ingress

So now I will apply the Ingress Yaml file on my local k8s cluster. First in my command prompt, I go to the directory containing this YAML file and run the kubectl apply.

kubectl apply -f myingress.yaml
k8s ingress created

Next run the kubectl get ingress command which will show all the Ingress on my cluster. I have shown the output of this command in the given image. The ingress first-ingress is shown with an Address which in my case is 192.168.49.2.

kubectl get ingress command

Now if you are in Linux OS or macOS then you can copy this address and paste it on your browser. This will open your app.

opening ingress ip address on browser

If you are in windows then unfortunately this won’t open the app. You have to do curl on this IP address and the curl response will be the HTML of the page which shows the IP address is indeed opening the app. This is the procedure to perform curl.

  • 1. Open another command prompt window and enter minikube tunnel command on it. This will open the tunnel.
  • 2. In the command prompt (where you just ran the kubectl get pods) run the ssh command:
minikube ssh

This will SSH to minikube vm.

Then curl the IP of the Ingress. The command is given below:

curl 192.168.49.2

I have shown this in the below image:

ingress ip curl windows

DefaultBackend

You can specify a DefaultBackend field which will be applied if none of the hosts or paths match the HTTP request in the Ingress objects. See the below Ingress yaml file of an Ingress called some-ingress which has a DefaultBackend. This default backend exposes a service called some-service in case of no match for the HTTP request.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: some-ingress
spec:
  defaultBackend:
    service:
      name: some-service
      port:
        number: 80

Types of Ingress

There are 4 types of Ingress:

  • 1. Ingress backed by a single Service
  • 2. Simple fanout
  • 3. Name based virtual hosting
  • 4. TLS

Ingress backed by a single Service

In this type of Ingress only a single Service is exposed by the Ingress. The Ingress which we just created for our ASP.NET Core app is an example of this type.

Also, the example of the ingress given in the DefaultBackend section is also the example of this type of Ingress.

Simple fanout

In Simple fanout Ingress there is one host in the Ingress and the Ingress exposes multiple services. In the example of the Ingress shown below there is one host called yogihosting.com, the ingress exposes 2 services based on different paths. These 2 services are:

  • a. news-service
  • b. api-service

I have highlighted the fields of the Ingress which makes it a Simple Fanout type.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: fanout-example
spec:
  rules:
  - host: yogihosting.com
    http:
      paths:
      - path: /news
        pathType: Prefix
        backend:
          service:
            name: news-service
            port:
              number: 4200
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

Name based virtual hosting

In this Ingress there can be multiple hosts but the condition is that their IP address should be same. Check the below example where the Ingress has 2 hosts – example1.com and example2.com.

Both example1.com and example2.com should have the same IP address. So in this type of Ingress there are more than one host fields.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: name-virtual-host-example
spec:
  rules:
  - host: example1.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service1
            port:
              number: 80
  - host: example2.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: service2
            port:
              number: 80

TLS

Ingress which are secured by TLS certificates comes under the TLS Ingress types. Kubernetes Secrets let you store and manage sensitive information, such as passwords, OAuth tokens, and ssh keys.

I defined a Secret by the name of mysecret in a YAML configuration file given below.

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
data:
  tls.crt: base64 encoded cert
  tls.key: base64 encoded key
type: kubernetes.io/tls

Now I can secure my Ingress by applying tls section. In this section I provide secretName field with the value mysecret.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-example-ingress
spec:
  tls:
  - hosts:
      - yogihosting.com
    secretName: mysecret
  rules:
  - host: yogihosting.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 80

Updating & Deleting Ingress

To update an Ingress change it’s YAML configuration file then apply the new changes with the kubectl apply -f command.

The name of my ingress file is myingress.yaml so the command would be:

kubectl apply -f myingress.yaml

To delete the ingress the command is:

Kubectl delete -f myingress.yaml 

Download the source codes.

Download

Conclusion

I hoped you liked this tutorial on Kubernetes Ingress. You are now ready to deploy your ASP.NET Core app on Kubernetes and expose it on HTTP with Ingress. If you like this tutorial then please share it with your friends on social community websites. Thank you.

SHARE THIS ARTICLE

  • linkedin
  • reddit
yogihosting

ABOUT THE AUTHOR

I hope you enjoyed reading this tutorial. If it helped you then consider buying a cup of coffee for me. This will help me in writing more such good tutorials for the readers. Thank you. Buy Me A Coffee donate

Leave a Reply

Your email address will not be published. Required fields are marked *