k8s_basic_deployments

This is an old revision of the document!


Deployments, finally we have reached to the last major object in Kubernetes. Deployments take everything we have being doing so far and encapusaltes it. What I mean is the following:

Of course you can have more than 1 pod in replica set. Yes, it is replica set when under Deployment, not replication controller. But the purpose is the same.

So let's create our Deployment now:

To create a deployment again we have two ways:

  • Iterative - With kubectl create and so on
  • Declarative - Using YML / JSON file, I will be using this one.

As I am bored with the iterative way, let's clean our env and create a deployment. I won't delete my service as I will use it later.

First, let's create our YML file:

Create Deployment YML file

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-deploy
spec:
  replicas: 10
  selector:
    matchLabels:
      app: hello-date
  template:
    metadata:
      labels:
        app: hello-date
    spec:
      containers:
      - name: hello-pod
        image: andonovj/httpserverdemo:latest
        ports:
        - containerPort: 1234

Bare in mind that the deployment have been moved from extensions/v1beta1 → apps/v1 and forward :) Also a little syntax changes compared to the old one, but nothing serious.

Once we have the YAML file, we can continue as follows:

Create deployment

ubuntu@k8s-master:~$ kubectl create -f deploy.yml
deployment.apps/hello-deploy created
ubuntu@k8s-master:~$ kubectl  get deploy

NAME           READY   UP-TO-DATE   AVAILABLE   AGE
hello-deploy   1/10    10           1           26s
ubuntu@k8s-master:~$ kubectl describe deploy

Name:                   hello-deploy
Namespace:              default
CreationTimestamp:      Sat, 02 May 2020 15:54:34 +0000
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=hello-date
Replicas:               10 desired | 10 updated | 10 total | 10 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=hello-date
  Containers:
   hello-pod:
    Image:        andonovj/httpserverdemo:latest
    Port:         1234/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   hello-deploy-6cd458494 (10/10 replicas created)
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  8m59s  deployment-controller  Scaled up replica set hello-deploy-6cd458494 to 10

Again, we can check if our app is working:

As already mentioned, deployments operate with Replicat Sets, NOT replication Controllers. Eventhough that is a new objects, it inherits a lot of stuff from the replication controller. You can check the Replica sets, almost the same as the replication controller and notice that we don't have Replication Controllers anymore…after I have deleted them in the past of course.

Check Replica Sets

ubuntu@k8s-master:~$ kubectl get rs
NAME                     DESIRED   CURRENT   READY   AGE
hello-deploy-6cd458494   10        10        10      11m
ubuntu@k8s-master:~$ kubectl get rc
No resources found in default namespace.
ubuntu@k8s-master:~$ kubectl describe rs
Name:           hello-deploy-6cd458494
Namespace:      default
Selector:       app=hello-date,pod-template-hash=6cd458494
Labels:         app=hello-date
                pod-template-hash=6cd458494
Annotations:    deployment.kubernetes.io/desired-replicas: 10
                deployment.kubernetes.io/max-replicas: 13
                deployment.kubernetes.io/revision: 1
Controlled By:  Deployment/hello-deploy
Replicas:       10 current / 10 desired
Pods Status:    10 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:  app=hello-date
           pod-template-hash=6cd458494
  Containers:
   hello-pod:
    Image:        andonovj/httpserverdemo:latest
    Port:         1234/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age   From                   Message
  ----    ------            ----  ----                   -------
  Normal  SuccessfulCreate  16m   replicaset-controller  Created pod: hello-deploy-6cd458494-mjtw9
  Normal  SuccessfulCreate  16m   replicaset-controller  Created pod: hello-deploy-6cd458494-m9bgx
  Normal  SuccessfulCreate  16m   replicaset-controller  Created pod: hello-deploy-6cd458494-44jvs
  Normal  SuccessfulCreate  16m   replicaset-controller  Created pod: hello-deploy-6cd458494-6v8lt
  Normal  SuccessfulCreate  16m   replicaset-controller  Created pod: hello-deploy-6cd458494-zwh4l
  Normal  SuccessfulCreate  16m   replicaset-controller  Created pod: hello-deploy-6cd458494-jf594
  Normal  SuccessfulCreate  16m   replicaset-controller  Created pod: hello-deploy-6cd458494-vd7mt
  Normal  SuccessfulCreate  16m   replicaset-controller  Created pod: hello-deploy-6cd458494-nq2wx
  Normal  SuccessfulCreate  16m   replicaset-controller  Created pod: hello-deploy-6cd458494-f8j5f
  Normal  SuccessfulCreate  16m   replicaset-controller  (combined from similar events): Created pod: hello-deploy-6cd458494-dxqh7
 
ubuntu@k8s-master:~$ kubectl get rc
No resources found in default namespace.                     <- We don't have Replication Controllers anymore.

Now, we have deployed application, which is totally scalable and redundancy is provided as Hell :) But what if want to fix couple bugs, or present new version.

What we do then ? Well, let's edit our application, let's add “v2” into our awesome app:

Edit Source

namespace HttpServerDemo
{
    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading.Tasks;
    using System.IO;
    using System.Threading;
    class Program
    {
        public async static Task Main(string[] args)
        {
            TcpListener tcpListener = new TcpListener(IPAddress.Any, 1234);
            tcpListener.Start();
            while (true)
            {
                TcpClient tcpClient = await tcpListener.AcceptTcpClientAsync();
                await ProcessClientAsync(tcpClient);
            }
        }

        public static async Task ProcessClientAsync(TcpClient tcpClient)
        {
            const string NewLine = "\r\n";
            using (var networkStream = tcpClient.GetStream())
            {
                byte[] requestBytes = new byte[1000000];   //TODO USE Buffer
                int bytesRead = await networkStream.ReadAsync(requestBytes, 0, requestBytes.Length);
                string request = Encoding.UTF8.GetString(requestBytes, 0, bytesRead);
                string responseText = @"<h1>Working... v2</h1>" +                      <- Updated this line with "v2" :)
                                          $"<form> <h1> Time is: {System.DateTime.Now} </h1> </form>";
                string response = "HTTP/1.1 200 OK" + NewLine
                                 + "Server: SoftuniServer/1.0 " + NewLine
                                 + "Content-Type: text/html" + NewLine
                                 + "Content-Length: " + responseText.Length + NewLine + NewLine
                                 + responseText;

                byte[] responseBytes = Encoding.UTF8.GetBytes(response);
                await networkStream.WriteAsync(responseBytes, 0, responseBytes.Length);
                Console.WriteLine(request);
                Console.WriteLine(new string('=', 60));
            }
        }
    }
}

You see that “v2” after “Working”, yes, I just added it now. Let's rebuild via docker, upload it and edit our edition to v2 :) The Rebuild part you can see in the Docker section, but I will put the output here as well:

Dockerize, Tag & Push

[root@postgresqlmaster httpserverdemo]# ls -lart
total 16
-rw-r--r--. 1 root root  178 Jan 15 11:29 HttpServerDemo.csproj
-rw-r--r--. 1 root root  405 Jan 24 07:20 Dockerfile
-rw-r--r--. 1 root root 1904 May  2 12:19 Program.cs
dr-xr-x---. 7 root root 4096 May  2 12:39 ..
drwxr-xr-x. 2 root root   71 May  2 12:45 .
root@k8s-master:/home/vagrant/HttpServerDemo# docker build -t httpserverdemo .
Sending build context to Docker daemon  6.144kB
Step 1/11 : FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
 ---> 4aa6a74611ff
Step 2/11 : WORKDIR /app
 ---> Using cache
 ---> e6fb8470c359
Step 3/11 : COPY *.csproj ./
 ---> Using cache
 ---> c6e7e3257ccd
Step 4/11 : RUN dotnet restore
 ---> Using cache
 ---> 073b0e6dcfac
Step 5/11 : COPY . ./
 ---> dbb416239305
Step 6/11 : RUN dotnet publish -c Release -o out
 ---> Running in cdccacf739ec
Microsoft (R) Build Engine version 16.5.0+d4cbfca49 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 38.37 ms for /app/HttpServerDemo.csproj.
  HttpServerDemo -> /app/bin/Release/netcoreapp3.1/HttpServerDemo.dll
  HttpServerDemo -> /app/out/
Removing intermediate container cdccacf739ec
 ---> 29d5a30972d4
Step 7/11 : FROM mcr.microsoft.com/dotnet/core/sdk:3.1
 ---> 4aa6a74611ff
Step 8/11 : WORKDIR /app
 ---> Using cache
 ---> e6fb8470c359
Step 9/11 : COPY --from=build-env /app/out .
 ---> ff034e158a2e
Step 10/11 : RUN find -type d -name bin -prune -exec rm -rf {} \; && find -type d -name obj -prune -exec rm -rf {} \;
 ---> Running in e217c60056a6
Removing intermediate container e217c60056a6
 ---> f3755f21e57e
Step 11/11 : ENTRYPOINT ["dotnet", "HttpServerDemo.dll"]
 ---> Running in e49283dde769
Removing intermediate container e49283dde769
 ---> 9f2f48860257
Successfully built 9f2f48860257

aaaaand….we are done :) We have edited our awesome software and uploaded it to docker hub.

Let's now update the containers in the pods :)

For that purpose, we have to edit the YAML file with couple more values like:

  • Strategy: RollingUpdate(default)
  • maxUnavailable: 1 - Never have more than 1 unavailable
  • maxSurge: 1 - Never have more than 1 additional. In our case, never have more than 11 pods

So, our YAML file should look as follows:

Updated YAML file

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-deploy
spec:
  replicas: 10
  minReadySeconds: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  selector:
    matchLabels:
      app: hello-date
  template:
    metadata:
      labels:
        app: hello-date
    spec:
      containers:
      - name: hello-pod
        image: andonovj/httpserverdemo:v2
        ports:
        - containerPort: 1234

Once we have the file, you can start the process as so:

Rolling Update Status

ubuntu@k8s-master:~$ kubectl apply -f deploy.yml
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
deployment.apps/hello-deploy configured

You can see the progress of the Rolling Update as follows:

Rolling Update Status

ubuntu@k8s-master:~$ kubectl rollout status deploy hello-deploy
Waiting for deployment "hello-deploy" rollout to finish: 2 out of 10 new replicas have been updated...
^Cubuntu@k8s-master:~$ kubectl get pods
NAME                            READY   STATUS              RESTARTS   AGE
hello-deploy-6cd458494-6mvt7    1/1     Running             0          80s
hello-deploy-6cd458494-9bl7c    1/1     Running             0          80s
hello-deploy-6cd458494-fvwvz    1/1     Running             0          80s
hello-deploy-6cd458494-grp2w    1/1     Running             0          80s
hello-deploy-6cd458494-ldsxq    1/1     Running             0          80s
hello-deploy-6cd458494-lpgdj    1/1     Running             0          80s
hello-deploy-6cd458494-mjsmh    1/1     Running             0          80s
hello-deploy-6cd458494-rd58j    1/1     Running             0          80s
hello-deploy-6cd458494-rrkhq    1/1     Running             0          80s
hello-deploy-7f44bd8b96-k92sr   0/1     ContainerCreating   0          23s
hello-deploy-7f44bd8b96-lqmdx   0/1     ContainerCreating   0          23s
ubuntu@k8s-master:~$ kubectl rollout status deploy hello-deploy
Waiting for deployment "hello-deploy" rollout to finish: 4 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 4 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 6 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 6 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 6 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 6 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 6 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 8 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 8 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 8 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 8 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 8 out of 10 new replicas have been updated...
Waiting for deployment "hello-deploy" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "hello-deploy" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "hello-deploy" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "hello-deploy" rollout to finish: 1 old replicas are pending termination...

We can also check the version which is currently being used:

Rolling Update Status

ubuntu@k8s-master:~$ kubectl get deploy hello-deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
hello-deploy   10/10   10           10          5m7s
ubuntu@k8s-master:~$ kubectl describe deploy hello-deploy
Name:                   hello-deploy
Namespace:              default
CreationTimestamp:      Sun, 03 May 2020 11:28:33 +0000
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 2
Selector:               app=hello-date
Replicas:               10 desired | 10 updated | 10 total | 10 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        10
RollingUpdateStrategy:  1 max unavailable, 1 max surge
Pod Template:
  Labels:  app=hello-date
  Containers:
   hello-pod:
    Image:        andonovj/httpserverdemo:edge                        <- We are using the "edge" version, which we have just compiled.
    Port:         1234/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   hello-deploy-7f44bd8b96 (10/10 replicas created)
Events:
  Type    Reason             Age                 From                   Message
  ----    ------             ----                ----                   -------
  Normal  ScalingReplicaSet  5m11s               deployment-controller  Scaled up replica set hello-deploy-6cd458494 to 10
  Normal  ScalingReplicaSet  4m14s               deployment-controller  Scaled up replica set hello-deploy-7f44bd8b96 to 1
  Normal  ScalingReplicaSet  4m14s               deployment-controller  Scaled down replica set hello-deploy-6cd458494 to 9
  Normal  ScalingReplicaSet  4m14s               deployment-controller  Scaled up replica set hello-deploy-7f44bd8b96 to 2
  Normal  ScalingReplicaSet  2m18s               deployment-controller  Scaled down replica set hello-deploy-6cd458494 to 7
  Normal  ScalingReplicaSet  2m18s               deployment-controller  Scaled up replica set hello-deploy-7f44bd8b96 to 4
  Normal  ScalingReplicaSet  2m3s                deployment-controller  Scaled down replica set hello-deploy-6cd458494 to 5
  Normal  ScalingReplicaSet  2m3s                deployment-controller  Scaled up replica set hello-deploy-7f44bd8b96 to 6
  Normal  ScalingReplicaSet  108s                deployment-controller  Scaled down replica set hello-deploy-6cd458494 to 3
  Normal  ScalingReplicaSet  82s (x4 over 108s)  deployment-controller  (combined from similar events): Scaled down replica set hello-deploy-6cd458494 to 0

  • k8s_basic_deployments.1588507775.txt.gz
  • Last modified: 2020/05/03 12:09
  • by andonovj