View on GitHub

Containers & Kubernetes Tutorial

Lab 07 - Managing services

On this lab you’ll create deployments and services to deploy an Echo App.

On this lab

Create deployments

First step to get your app (or services) running on a kubernetes cluster you need to have a deployment for each component: webapp and api.

Let’s try to create deployment manifests on your own.

For echo-api-depdeployment:

If you want to get full content for this deployment, navigate to this link.

For echo-webapp-depdeployment:

If you want to get full content for this deployment, navigate to this link.

Now you can apply your manifests on your cluster. To better manage these deployments, let’s create a namespace.

kubectl create ns echo-app-ns

Then create the deployments.

kubectl apply -f echo-api-dep.yaml -n echo-app-ns
kubectl apply -f echo-webapp-dep.yaml -n echo-app-ns

Check if your deployments are running properly.

kubectl get deploy -n echo-app-ns

And you should get an output like this.

NAME              READY   UP-TO-DATE   AVAILABLE   AGE
echo-api-dep      3/3     3            3           19s
echo-webapp-dep   3/3     3            3           18s

Create services

Now you should create the services to get access to your Echo App.

To have external access to LoadBalancer services on minikube you need to create a tunnel between cluster and your machine.

Open a new terminal and run the following command. This terminal needs to be open until the end of this lab.

minikube tunnel

First, create a file called echo-api-svc.yaml and add the following content.

apiVersion: v1
kind: Service
metadata:
  name: echo-api-svc
spec:
  ports:
    - port: 8080
      targetPort: 80
      name: api
  selector:
    app: echo-app
    tier: back
  type: LoadBalancer

This is a Load Balancer type service to grant you access directly from outside of your cluster (on this lab, using localhost).

The selector block will make the match with the labels you added on the pods on your deployment.

On ports block you define your service port to be 8080 and any request to it will forward to port 80 on the container.

Let’s create the service on the cluster.

kubectl apply -f echo-api-svc.yaml -n echo-app-ns

To check if everything is working properly navigate to http://localhost:8080/echo/message.

This service have another endpoint that you can call several time to check that you’re being served by different pods.

Navigate (or use curl command on command line) to http://localhost:8080/hostname and check the output to change (not on every call since your cluster uses a random algorithm as balancing algorithm).

Now let’s create Echo Webapp service. Create a file called echo-webapp-svc.yaml and add the following content.

apiVersion: v1
kind: Service
metadata:
  name: echo-webapp-svc
spec:
  ports:
    - port: 9000
      targetPort: 80
      name: web
  selector:
    app: echo-app
    tier: front
  type: LoadBalancer

Let’s create the service on the cluster.

kubectl apply -f echo-webapp-svc.yaml -n echo-app-ns

To check if everything is working properly navigate to http://localhost:9000.

Now your already have your frontend and backend available from outside of your cluster.

Define ingress

Regarding production environment you don’t want to have services accessed directly on different port.

To better handle external communication with your cluster, let’s create an ingress controller.

First you need to turn off minikube tunnel. Go to terminal where you run that command and press Ctrl-c.

Then create your first ingress, you need to install an ingress controller on your cluster.

minikube addons enable ingress

You need to check if ingress controller is already available on your cluster.

To do that, run the following command to check the status of the pod that implements the ingress controller.

kubectl get pods --namespace=ingress-nginx

You should get an output similar like this.

NAME                                        READY   STATUS      RESTARTS       AGE
ingress-nginx-admission-create--1-mzkx6     0/1     Completed   0              5h11m
ingress-nginx-admission-patch--1-4hzxw      0/1     Completed   0              5h11m
ingress-nginx-controller-54d8b558d4-jbnwx   1/1     Running     1 (103m ago)   5h11m

Your ingress controller is ready to be used when you see Running as the status of the pod with the name starting with ingress-nginx-controller.

Now your cluster is ready to receive and handle an ingress object.

Before you need to change the service of your already created services.

To do that you need only to change the line type: LoadBalancer on both services files to type: ClusterIP

After that, apply again the services to the cluster. Since we are using a declarative configuration, the cluster will make the change about service type.

kubectl apply -f echo-webapp-svc.yaml -n echo-app-ns
kubectl apply -f echo-api-svc.yaml -n echo-app-ns

Let’s check that services type have changed to ClusterIP.

NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
echo-api-svc      ClusterIP   10.97.110.110   <none>        8080/TCP   8m33s
echo-webapp-svc   ClusterIP   10.96.27.91     <none>        9000/TCP   7m12s

Let’s create the ingress. Create a file called echo-app-ingress.yaml and add the following content.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echo-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  ingressClassName: nginx
  rules:
  - host: echo-app.ingress.test
    http:
      paths:
      - path: /(.*)
        pathType: Prefix
        backend:
          service:
            name: echo-webapp-svc
            port:
              number: 9000
      - path: /api/(.*)
        pathType: Prefix
        backend:
          service:
            name: echo-api-svc
            port:
              number: 8080

With this ingress you will get:

Let’s dive on the ingress file.

You have set an URL on host property.

- host: echo-app.ingress.test

This means that the requests for this URL will be handle by this ingress.

On API path you have this definition.

- path: /api/(.*)

This means that ingress will use a regex to match everything on the URL after /api/. This allow to send this text to the service that will serve this request.

The way for your to send this to the service is defined on the following lines.

annotations:
  nginx.ingress.kubernetes.io/rewrite-target: /$1

$1 means the first matching by regex on the URL. Knowing this, you may have several matches on URL and send them to the service.

Now it’s time to apply the ingress on your cluster.

kubectl apply -f echo-app-ingress.yaml -n echo-app-ns

Now you need to restart the tunnel to get an IP on your ingress.

Run minikube command to start the tunnel.

minikube tunnel

Notice if the tunnel ask to enter sudopassword since you’re using reserved 80 port.

You can check if you ingress is properly configured running this command.

kubectl describe ingress echo-app-ingress -n echo-app-ns

You need an additional step to make everything working. First, let’s get the ingress IP.

kubectl get ingress echo-app-ingress -n echo-app-ns

You should get an output like this.

NAME               CLASS   HOSTS                   ADDRESS        PORTS   AGE
echo-app-ingress   nginx   echo-app.ingress.test   192.168.49.2   80      6m

The IP you need is on ADDRESS column.

You need to change hosts file on your machine to have a match between URL defined on the ingress and this IP.

sudo sh -c 'echo "192.168.49.2\techo-app.ingress.test\n" >> /etc/hosts'

Finally, let’s test if everything is working properly.

Navigate to http://echo-app.ingress.test/ and you should see Echo App Webapp.

Then navigate to http://echo-app.ingress.test/api/echo/message and you should receive "message" as output.

On webapp, if you fill the input box with same text and click on Make Echo! button, you should see an error.

Let’s check next lab to fix this!

Next Lab: Persistence in Kubernetes >

Return home >