Deploy containers from a to z

This practical work will consist of creating Kubernetes objects to deploy an example stack: monster_stack. It is composed of:

You can use either your Cloud environment or Minikube.

Reminder: Install Lens

Lens is a nice graphical interface for Kubernetes.

It connects using the default ~/.kube/config configuration and allows us to access a much more pleasant dashboard.

You can install it by running these commands:

sudo apt-get update; sudo apt-get install -y libxss-dev
curl -fSL https://github.com/lensapp/lens/releases/download/v4.0.6/Lens-4.0.6.AppImage -o ~/Lens.AppImage
chmod +x ~/Lens.AppImage
~/Lens.AppImage &

Deploying the monsterstack stack

Pods are sets of containers always kept together.

We would like to deploy our monster_app stack. We will start by creating a pod with only our monstericon container.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: monstericon 
  labels:
    <labels>

This file expresses an empty deployment object.

Add the label app: monsterstack to this Deployment object.

For now, our deployment is not defined because it does not have a spec: section.

The first step is to propose a ReplicaSet template for our deployment. Add the following (spec: should be at the same level as kind: and metadata:)

spec:
  template:
    spec:

Fill in the spec section of our monstericon pod from a pod template launching an Nginx container:

        containers:
        - name: nginx
          image: nginx:1.7.9
          ports:
            - containerPort: 80
    metadata:
      labels:
        app: monsterstack
        partie: monstericon

At this stage, we have described the pods of our deployment with their labels (a common label to all objects of the app, a more specific label to the sub-part of the app).

Now it is a matter of adding some options to configure our deployment (at the level of template:):

  selector:
    matchLabels:
      app: monsterstack
      partie: monstericon
  strategy:
    type: Recreate

This section indicates the labels to use to identify the pods of this deployment among others.

Then the update strategy (rollout) of the pods for the deployment is specified: Recreate designates the most brutal strategy of complete pod deletion and redeployment.

Finally, just before the line selector: and at the level of the strategy: keyword, add replicas: 3. Kubernetes will create 3 identical pods during the monstericon deployment.

The monstericon.yaml file so far:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: monstericon
  labels:
    app: monsterstack
spec:
  template:
    spec:
      containers:
      - name: monstericon
        image: tecpi/monster_icon:0.1
        ports:
        - containerPort: 9090
    metadata:
      labels:
        app: monsterstack
        partie: monstericon
  selector:
    matchLabels:
      app: monsterstack
      partie: monstericon
  strategy:
    type: Recreate
  replicas: 3
Apply our deployment
        readinessProbe:
          failureThreshold: 5 # Retry 5 times
          httpGet:
            path: /
            port: 9090
            scheme: HTTP
          initialDelaySeconds: 30 # Wait 30s before testing
          periodSeconds: 10 # Wait 10s between each try
          timeoutSeconds: 5 # Wait 5s for response

This way, k8s will be able to know if the container is working well by calling the /. route. This is a good practice for Kubernetes to know when to restart a pod.

      resources:
        requests:
          cpu: "100m"
          memory: "50Mi"

Our pods will then be guaranteed to have one-tenth of a CPU and 50 megabytes of RAM.

Final monstericon.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: monstericon
  labels:
    app: monsterstack
spec:
  template:
    spec:
      containers:
      - name: monstericon
        image: tecpi/monster_icon:0.1
        ports:
        - containerPort: 9090
        readinessProbe:
          failureThreshold: 5 # Retry 5 times
          httpGet:
            path: /
            port: 9090
            scheme: HTTP
          initialDelaySeconds: 30 # Wait 30s before testing
          periodSeconds: 10 # Wait 10s between each try
          timeoutSeconds: 5 # Wait 5s for response
        resources:
          requests:
            cpu: "100m"
            memory: "50Mi"
    metadata:
      labels:
        app: monsterstack
        partie: monstericon
  selector:
    matchLabels:
      app: monsterstack
      partie: monstericon
  strategy:
    type: Recreate
  replicas: 5

Similar deployment for dnmonster. Now we will also create a deployment for dnmonster:

apiVersion: apps/v1
kind: Deployment
metadata:
  name:

 dnmonster 
  labels:
    app: monsterstack
spec:
  selector:
    matchLabels:
      app: monsterstack
      partie: dnmonster
  strategy:
    type: Recreate
  replicas: 5
  template:
    metadata:
      labels:
        app: monsterstack
        partie: dnmonster
    spec:
      containers:
      - image: amouat/dnmonster:1.0
        name: dnmonster
        ports:
        - containerPort: 8080

Finally, configure a third deployment redis:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis 
  labels:
    app: monsterstack
spec:
  selector:
    matchLabels:
      app: monsterstack
      partie: redis
  strategy:
    type: Recreate
  replicas: 1
  template:
    metadata:
      labels:
        app: monsterstack
        partie: redis
    spec:
      containers:
      - image: redis:latest
        name: redis
        ports:
        - containerPort: 6379

Expose our stack with services

K8s services are network endpoints that automatically balance traffic to a set of pods designated by certain labels.

To create a Service object, use the following code, to be completed:

apiVersion: v1
kind: Service
metadata:
  name: <service_name>
  labels:
    app: monsterstack
spec:
  ports:
    - port: <port>
  selector:
    app: <app_selector> 
    partie: <tier_selector>
  type: <type>

Add the following code at the beginning of each deployment file. Complete for each part of our application:

The type will be: ClusterIP for dnmonster and redis because these are services that only need to be accessed internally, and LoadBalancer for monstericon.

Apply your three files.

Let's gather the three objects with a kustomization.

A kustomization allows summarizing an object contained in multiple files in one place to be able to launch it easily:

Also create a kustomization.yaml file inside with:

resources:
    - monstericon.yaml
    - dnmonster.yaml
    - redis.yaml

Add an Ingress load balancer to expose our application on the standard port

Let's install the Nginx Ingress controller with minikube addons enable ingress.

This is an implementation of a dynamic load balancer based on nginx configured to interface with a k8s cluster.

Also, add the following load balancer configuration object in the monster-ingress.yaml file:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: monster-ingress 
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
        - path: /monstericon
          backend:
            serviceName: monstericon
            servicePort: 9090

You should be able to access the application by running minikube service monstericon –url and adding /monstericon to access it.