Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
k8s_basic_deployments [2020/05/02 16:08] – andonovj | k8s_basic_deployments [2020/05/03 12:16] (current) – andonovj | ||
---|---|---|---|
Line 96: | Line 96: | ||
Again, we can check if our app is working: | Again, we can check if our app is working: | ||
- | {{ : | + | {{: |
Line 108: | Line 108: | ||
ubuntu@k8s-master: | ubuntu@k8s-master: | ||
No resources found in default namespace. | No resources found in default namespace. | ||
+ | ubuntu@k8s-master: | ||
+ | Name: | ||
+ | Namespace: | ||
+ | Selector: | ||
+ | Labels: | ||
+ | pod-template-hash=6cd458494 | ||
+ | Annotations: | ||
+ | deployment.kubernetes.io/ | ||
+ | deployment.kubernetes.io/ | ||
+ | Controlled By: Deployment/ | ||
+ | Replicas: | ||
+ | Pods Status: | ||
+ | Pod Template: | ||
+ | Labels: | ||
+ | | ||
+ | Containers: | ||
+ | | ||
+ | Image: | ||
+ | Port: | ||
+ | Host Port: 0/TCP | ||
+ | Environment: | ||
+ | Mounts: | ||
+ | Volumes: | ||
+ | Events: | ||
+ | Type Reason | ||
+ | ---- ------ | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | |||
+ | ubuntu@k8s-master: | ||
+ | No resources found in default namespace. | ||
+ | </ | ||
+ | |||
+ | =====Rolling-Updates===== | ||
+ | Now, we have deployed application, | ||
+ | |||
+ | What we do then ? | ||
+ | Well, let's edit our application, | ||
+ | |||
+ | ====Edit Software==== | ||
+ | <Code: C#|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, | ||
+ | tcpListener.Start(); | ||
+ | while (true) | ||
+ | { | ||
+ | TcpClient tcpClient = await tcpListener.AcceptTcpClientAsync(); | ||
+ | await ProcessClientAsync(tcpClient); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public static async Task ProcessClientAsync(TcpClient tcpClient) | ||
+ | { | ||
+ | const string NewLine = " | ||
+ | using (var networkStream = tcpClient.GetStream()) | ||
+ | { | ||
+ | byte[] requestBytes = new byte[1000000]; | ||
+ | int bytesRead = await networkStream.ReadAsync(requestBytes, | ||
+ | string request = Encoding.UTF8.GetString(requestBytes, | ||
+ | string responseText = @"< | ||
+ | $"< | ||
+ | string response = " | ||
+ | + " | ||
+ | + " | ||
+ | + " | ||
+ | + responseText; | ||
+ | |||
+ | byte[] responseBytes = Encoding.UTF8.GetBytes(response); | ||
+ | await networkStream.WriteAsync(responseBytes, | ||
+ | Console.WriteLine(request); | ||
+ | Console.WriteLine(new string(' | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | You see that " | ||
+ | The Rebuild part you can see in the Docker section, but I will put the output here as well: | ||
+ | |||
+ | ====Dockerize, | ||
+ | <Code: bash|Dockerize, | ||
+ | [root@postgresqlmaster httpserverdemo]# | ||
+ | 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:/ | ||
+ | Sending build context to Docker daemon | ||
+ | Step 1/11 : FROM mcr.microsoft.com/ | ||
+ | | ||
+ | Step 2/11 : WORKDIR /app | ||
+ | | ||
+ | | ||
+ | Step 3/11 : COPY *.csproj ./ | ||
+ | | ||
+ | | ||
+ | Step 4/11 : RUN dotnet restore | ||
+ | | ||
+ | | ||
+ | Step 5/11 : COPY . ./ | ||
+ | | ||
+ | Step 6/11 : RUN dotnet publish -c Release -o out | ||
+ | | ||
+ | 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 / | ||
+ | HttpServerDemo -> / | ||
+ | HttpServerDemo -> /app/out/ | ||
+ | Removing intermediate container cdccacf739ec | ||
+ | | ||
+ | Step 7/11 : FROM mcr.microsoft.com/ | ||
+ | | ||
+ | Step 8/11 : WORKDIR /app | ||
+ | | ||
+ | | ||
+ | Step 9/11 : COPY --from=build-env /app/out . | ||
+ | | ||
+ | Step 10/11 : RUN find -type d -name bin -prune -exec rm -rf {} \; && find -type d -name obj -prune -exec rm -rf {} \; | ||
+ | | ||
+ | Removing intermediate container e217c60056a6 | ||
+ | | ||
+ | Step 11/11 : ENTRYPOINT [" | ||
+ | | ||
+ | Removing intermediate container e49283dde769 | ||
+ | | ||
+ | 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 :) | ||
+ | |||
+ | ====Perform the Update==== | ||
+ | For that purpose, we have to edit the YAML file with couple more values like: | ||
+ | |||
+ | * Strategy: RollingUpdate(default) | ||
+ | * maxUnavailable: | ||
+ | * 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: | ||
+ | |||
+ | <Code: bash| Updated YAML file> | ||
+ | apiVersion: apps/v1 | ||
+ | kind: Deployment | ||
+ | metadata: | ||
+ | name: hello-deploy | ||
+ | spec: | ||
+ | replicas: 10 | ||
+ | minReadySeconds: | ||
+ | strategy: | ||
+ | type: RollingUpdate | ||
+ | rollingUpdate: | ||
+ | maxUnavailable: | ||
+ | maxSurge: 1 | ||
+ | selector: | ||
+ | matchLabels: | ||
+ | app: hello-date | ||
+ | template: | ||
+ | metadata: | ||
+ | labels: | ||
+ | app: hello-date | ||
+ | spec: | ||
+ | containers: | ||
+ | - name: hello-pod | ||
+ | image: andonovj/ | ||
+ | ports: | ||
+ | - containerPort: | ||
+ | </ | ||
+ | |||
+ | Once we have the file, you can start the process as so: | ||
+ | |||
+ | <Code: bash|Rolling Update Status> | ||
+ | ubuntu@k8s-master: | ||
+ | Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply | ||
+ | deployment.apps/ | ||
+ | </ | ||
+ | |||
+ | |||
+ | You can see the progress of the Rolling Update as follows: | ||
+ | <Code: bash|Rolling Update Status> | ||
+ | ubuntu@k8s-master: | ||
+ | Waiting for deployment " | ||
+ | ^Cubuntu@k8s-master: | ||
+ | NAME READY | ||
+ | hello-deploy-6cd458494-6mvt7 | ||
+ | hello-deploy-6cd458494-9bl7c | ||
+ | hello-deploy-6cd458494-fvwvz | ||
+ | hello-deploy-6cd458494-grp2w | ||
+ | hello-deploy-6cd458494-ldsxq | ||
+ | hello-deploy-6cd458494-lpgdj | ||
+ | hello-deploy-6cd458494-mjsmh | ||
+ | hello-deploy-6cd458494-rd58j | ||
+ | hello-deploy-6cd458494-rrkhq | ||
+ | hello-deploy-7f44bd8b96-k92sr | ||
+ | hello-deploy-7f44bd8b96-lqmdx | ||
+ | ubuntu@k8s-master: | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | </ | ||
+ | |||
+ | We can also check the version which is currently being used: | ||
+ | |||
+ | <Code: bash|Rolling Update Status> | ||
+ | ubuntu@k8s-master: | ||
+ | NAME | ||
+ | hello-deploy | ||
+ | ubuntu@k8s-master: | ||
+ | Name: | ||
+ | Namespace: | ||
+ | CreationTimestamp: | ||
+ | Labels: | ||
+ | Annotations: | ||
+ | Selector: | ||
+ | Replicas: | ||
+ | StrategyType: | ||
+ | MinReadySeconds: | ||
+ | RollingUpdateStrategy: | ||
+ | Pod Template: | ||
+ | Labels: | ||
+ | Containers: | ||
+ | | ||
+ | Image: | ||
+ | Port: | ||
+ | Host Port: 0/TCP | ||
+ | Environment: | ||
+ | Mounts: | ||
+ | Volumes: | ||
+ | Conditions: | ||
+ | Type | ||
+ | ---- | ||
+ | Available | ||
+ | Progressing | ||
+ | OldReplicaSets: | ||
+ | NewReplicaSet: | ||
+ | Events: | ||
+ | Type Reason | ||
+ | ---- ------ | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | |||
+ | </ | ||
+ | |||
+ | =====Rolling Back===== | ||
+ | Now, before we continue, let's speak a little bit about Change History. We can check the history of all changes as follows: | ||
+ | |||
+ | <Code: bash| Check Change History> | ||
+ | ubuntu@k8s-master: | ||
+ | deployment.apps/ | ||
+ | REVISION | ||
+ | 1 < | ||
+ | 2 < | ||
+ | </ | ||
+ | |||
+ | The reason why you don't see anything in the " | ||
+ | |||
+ | <Code: bash| Rollback> | ||
+ | ubuntu@k8s-master: | ||
+ | deployment.apps/ | ||
ubuntu@k8s-master: | ubuntu@k8s-master: | ||
</ | </ | ||
+ | |||
+ | Of course we can monitor it with the same command as before: | ||
+ | |||
+ | <Code: bash| Rollback> | ||
+ | ubuntu@k8s-master: | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | Waiting for deployment " | ||
+ | deployment " | ||
+ | ubuntu@k8s-master: | ||
+ | Name: | ||
+ | Namespace: | ||
+ | CreationTimestamp: | ||
+ | Labels: | ||
+ | Annotations: | ||
+ | Selector: | ||
+ | Replicas: | ||
+ | StrategyType: | ||
+ | MinReadySeconds: | ||
+ | RollingUpdateStrategy: | ||
+ | Pod Template: | ||
+ | Labels: | ||
+ | Containers: | ||
+ | | ||
+ | Image: | ||
+ | Port: | ||
+ | Host Port: 0/TCP | ||
+ | Environment: | ||
+ | Mounts: | ||
+ | Volumes: | ||
+ | Conditions: | ||
+ | Type | ||
+ | ---- | ||
+ | Available | ||
+ | Progressing | ||
+ | OldReplicaSets: | ||
+ | NewReplicaSet: | ||
+ | Events: | ||
+ | Type Reason | ||
+ | ---- ------ | ||
+ | Normal | ||
+ | Normal | ||
+ | Normal | ||
+ | </ | ||
+ | |||
+ | ====Rollupdate with Record==== | ||
+ | Let's again apply the RollUpdate WITH the record this time: | ||
+ | |||
+ | <Code: bash|Rollupdate with Record> | ||
+ | ubuntu@k8s-master: | ||
+ | deployment.apps/ | ||
+ | ubuntu@k8s-master: | ||
+ | ubuntu@k8s-master: | ||
+ | deployment.apps/ | ||
+ | REVISION | ||
+ | 3 < | ||
+ | 4 | ||
+ | </ | ||
+ | |||
+ | Now, we can see that, the record is there and we can see the history of changes. |