loading...
Cover image for How I expose my applications on Kubernetes with Ingress and a domain

How I expose my applications on Kubernetes with Ingress and a domain

phuonghau98 profile image Phuong Hau ・4 min read

My intention of writing this post is to share with you things that I learned today and hope that might help some guy on the Internet just like me searching for a quick way to do something rather than reading a lot of dry text.

Motivation

The demand emerges when there is a fact that I have multiple applications running on my Kubernetes cluster, I have only one domain though. That is where Kubernetes Ingress resource comes into play.

Prerequisites

For the sake of simplicity and focusing on Ingress resource, I will assume that you are familiar with Kubernetes resource objects like: Deployment, Service,... and having control over your cluster with kubectl.

Let's do it

For demonstration purpose, I am going to spin up two applications, portfolio and healthinsight respectively. To achieve that, I simply create two deployments with one replica each, and also two services in order to keep track of IP of the pods created and destroy frequently.
If not mentioned otherwise, all resources are deployed on default namespace.

Yaml file for portfolio app

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: portfolio
  namespace: default
spec:
  selector:
    matchLabels:
      run: portfolio
  template:
    metadata:
      labels:
        run: portfolio
    spec:
      containers:
      - image: gcr.io/phuong-devops/portfolio:v2
        imagePullPolicy: IfNotPresent
        name: portfolio
        ports:
        - containerPort: 3000
          protocol: TCP
      imagePullSecrets:
      - name: gcr-key
---
apiVersion: v1
kind: Service
metadata:
  name: portfolio
  namespace: default
spec:
  ports:
  - port: 3000
    protocol: TCP
    targetPort: 3000
  selector:
    run: portfolio
  type: NodePort

YAML file for healthinsight app

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: healthinsight-app
  namespace: default
spec:
  selector:
    matchLabels:
      run: healthinsight-app
  template:
    metadata:
      labels:
        run: healthinsight-app
    spec:
      containers:
        - image: gcr.io/phuong-devops/healthinsight-frontend:v1
          name: healthinsight-app
          ports:
            - containerPort: 80
              protocol: TCP
      imagePullSecrets:
        - name: gcr-key
---
apiVersion: v1
kind: Service
metadata:
  name: healthinsight-app
  namespace: default
spec:
  ports:
  - port: 3001
    protocol: TCP
    targetPort: 80
  selector:
    run: healthinsight-app
  type: NodePort

Deploying these two applications is easy as a piece of cake.

Alt Text

The problem is our application is unreachable from the external network (Internet), so I deploy an Ingress resource on our Kubernetes cluster so as to it routes the traffic from Internet to our pods (applications).
Keep in mind that you have to setup an Ingress Controller to satisfy Ingress Resource. Only creating Ingress Resource below has no effect.

There are a bunch of Controller that may fit your preferences, take a look at here. For demonstration purpose, I will pick Nginx Ingress Controller, you could easily have your Nginx controller installed on your cluster after following the official documentation here

So what exactly Ingress do?

Ingress exposed HTTP and HTTPS routes from outside the cluster to services within cluster. Traffic routing is controlled by rules defined on the Ingress resource.

An Ingress can be configured to give Services externally-reachable URL, load balance, terminate SSL/TLS, and offer name based virtual hosting.

The below diagram illustrates our implementation.

Alt Text

I am going to deploy our Ingress resource configured to satisfy above demand.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
  name: cluster-ingress
  namespace: default
spec:
  rules:
  - host: hi.phuonghau.com
    http:
      paths:
      - backend:
          serviceName: healthinsight-app
          servicePort: 3001
  - host: phuonghau.com
    http:
      paths:
      - backend:
          serviceName: portfolio
          servicePort: 3000

Check out if our Ingress resource deployment works fine.

Alt Text

DNS

It is just not enough, we need to explicitly configure our domain DNS to navigate to our server cluster IP.

Note:
When we expose our applications on cluster on a domain name, we need the external IP address of an application to be static that does not change. So that the domain can correctly navigate to our clusters.

I am using GoDaddy for example, the steps are not the same if you are using other domain broker services, but the terms is applicable.

To reiterate, I want phuonghau.com to points to portfolio service and hi.phuonghau.com to point to health insight service.

Simply add an A record pointing to cluster IP (phuonghau.com points to clusterIP), and a CName hi points to phuonghau.com. Check the brief differences between an A record and Cname at here

Alt Text
It could take couple of minutes for your DNS configuration propagate over global.

Tadaaa

Now we can access multiple services on our Kubernetes cluster with only one domain.
Alt Text

Conclusion

With Kubernetes Ingress we are able to expose many applications to outside on the Internet with ease, those above steps is basically describe practical steps. The official document still the best place which we should take a glance at. Any feedback on this article is more than welcome.Thanks for reading.

Posted on by:

phuonghau98 profile

Phuong Hau

@phuonghau98

I am a young guy with enthusiasm for computer.

Discussion

markdown guide