Kubernetes

[Cloud] 7. Deployment strategies

트리스탄1234 2023. 2. 5. 13:28
728x90
반응형

There are several ways to update an application in a kubernetes environment. Distribution in the actual Kubernetes environment is distributed in connection with CI/CD. There are four deployment strategies:

Recreate

The first method is called Recreate. This method deletes the existing version of the Pod and deploys the updated Pod. In the picture above, from the top left, first, the existing V1 Pod is deleted and the V2 Pod is created. In this method, service downtime occurs until V2 Pod is created after V1 Pod is deleted.

This is recommended for low cost and mainly development systems.

Then, let's create a Yaml file to deploy V1 Pods and deploy V2 Pods again. After creating a directory to save the app-v1.yaml file as shown in the log below, use vi to enter the following contents in the app-v1.yaml file and save it.

root@master-VirtualBox:~/test# mkdir deploystrategy
root@master-VirtualBox:~/test# cd deploystrategy/
root@master-VirtualBox:~/test/deploystrategy# mkdir recreate
root@master-VirtualBox:~/test/deploystrategy# cd recreate/
root@master-VirtualBox:~/test/deploystrategy/recreate# vi app-v1.yaml
apiVersion: v1
kind: Service
metadata:
name: my-app
labels:
app: my-app
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: http
selector:
app: my-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
strategy:
type: Recreate ==> define typf of update
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
version: v1.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9101"
spec:
containers:
- name: my-app
image: containersol/k8s-deployment-strategies
ports:
- name: http
containerPort: 8080
- name: probe
containerPort: 8086
env:
- name: VERSION
value: v1.0.0 ==> define value of version
livenessProbe:
httpGet:
path: /live
port: probe
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: probe
periodSeconds: 5

After saving is complete, let's distribute and inquire about the distributed information.

root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl apply -f app-v1.yaml
service/my-app created
deployment.apps/my-app created
oot@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-app-9bb6fb8db-44rlm 1/1 Running 0 4m24s
my-app-9bb6fb8db-5zcnq 1/1 Running 0 4m24s
my-app-9bb6fb8db-swc8x 1/1 Running 0 4m24s
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d1h
my-nginx-svc NodePort 10.96.95.232 <none> 8080:31793/TCP 19h

As shown in the log above, 3 Pods are deployed, 1 Service object is Nodeport Type, and the Service Port is opened as 31793. Now, let's use the curl command to send a request message and check if it works normally.

root@master-VirtualBox:~/test/deploystrategy/recreate# curl localhost:31793
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org.
Commercial support is available at
<a href="http://nginx.com/">nginx.com.

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@master-VirtualBox:~/test/deploystrategy/recreate#

반응형

The response to the above request was normally received. Now, let's create app-v2.yaml and deploy it and see how it works. First, create a--v2.yaml file as shown below, enter the following contents into the file and save it..

 

root@master-VirtualBox:~/test/deploystrategy/recreate# vi app-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
strategy:
type: Recreate ==>define type of update
# The selector field tell the deployment which pod to update with
# the new version. This field is optional, but if you have labels
# uniquely defined for the pod, in this case the "version" label,
# then we need to redefine the matchLabels and eliminate the version
# field from there.
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
version: v2.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9101"
spec:
containers:
- name: my-app
image: containersol/k8s-deployment-strategies
ports:
- name: http
containerPort: 8080
- name: probe
containerPort: 8086
env:
- name: VERSION
value: v2.0.0 ==> define value of version
livenessProbe:
httpGet:
path: /live
port: probe
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: probe
periodSeconds: 5

Now, let's deploy app-v2.yaml and check the distribution.

root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl apply -f app-v2.yaml
deployment.apps/my-app configured
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod -o wide​​
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-app-69c46bcf4d-j22t5 1/1 Running 0 41s 172.16.168.215 worknode1-virtualbox <none> <none>
my-app-69c46bcf4d-qmpss 1/1 Running 0 41s 172.16.168.214 worknode1-virtualbox <none> <none>
my-app-69c46bcf4d-vrdr4 1/1 Running 0 41s 172.16.7.142 worknode2-virtualbox <none> <none>

You can see that the Pod Name part is different from the Pod after deploying the app-v1.yaml file. That is, you can see that a new Pod has been created.

Ramped(Rolling Update)

The second deployment strategy is Ramped Type. This type is a service non-disruptive deployment strategy that updates N Pods at once, not in the order of deletion and deployment after a complete service interruption like recreate. Let's take a look at the picture below.

As shown in the figure above, it is a structure in which N V2 Pods are created and then N V1s are deleted without deleting the existing v1 first. That is, the service is not interrupted. ​

Then, create the app-v1.yaml file as shown below, enter the following contents and save it.

root@master-VirtualBox:~/test/deploystrategy/recreate# vi app-v1.yaml
apiVersion: v1
kind: Service
metadata:
name: my-app
labels:
app: my-app
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: http
selector:
app: my-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
version: v1.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9101"
spec:
containers:
- name: my-app
image: containersol/k8s-deployment-strategies
ports:
- name: http
containerPort: 8080
- name: probe
containerPort: 8086
env:
- name: VERSION
value: v1.0.0
livenessProbe:
httpGet:
path: /live
port: probe
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: probe
periodSeconds: 5

Now, let's distribute APP-V1.yaml and look up information.

root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl apply -f app-v1.yaml
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-app-9bb6fb8db-bl76q 1/1 Running 0 7s
my-app-9bb6fb8db-dbw4k 1/1 Running 0 7s
my-app-9bb6fb8db-j4wwk 1/1 Running 0 7s
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d2h
my-app NodePort 10.100.224.187 <none> 80:32486/TCP 16s

Now, let's create the app-v2.yaml file as shown below, then deploy it and check it.

root@master-VirtualBox:~/test/deploystrategy/recreate# vi app-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 3
# Here we define the rolling update strategy
# - maxSurge define how many pod we can add at a time
# - maxUnavailable define how many pod can be unavailable
# during the rolling update
#
# Setting maxUnavailable to 0 would make sure we have the appropriate
# capacity during the rolling update.
# You can also use percentage based value instead of integer.
strategy:
type: rollingUpdate ==> 배포 전략을 RollingUpdate로 정의
maxSurge: 1
maxUnavailable: 0
# The selector field tell the deployment which pod to update with
# the new version. This field is optional, but if you have labels
# uniquely defined for the pod, in this case the "version" label,
# then we need to redefine the matchLabels and eliminate the version
# field from there.
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
version: v2.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9101"
spec:
containers:
- name: my-app
image: containersol/k8s-deployment-strategies
ports:
- name: http
containerPort: 8080
- name: probe
containerPort: 8086
env:
- name: VERSION
value: v2.0.0
livenessProbe:
httpGet:
path: /live
port: probe
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: probe
# Intial delay is set to a high value to have a better
# visibility of the ramped deployment
initialDelaySeconds: 15
periodSeconds: 5

Now, let's deploy the created app-v2.yaml file and check the status of the Pod.

root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl apply -f app-v2.yaml
deployment.apps/my-app configured
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-app-5b75d6ddbd-jmn88 0/1 Running 0 11s
my-app-9bb6fb8db-bl76q 1/1 Running 0 3m21s
my-app-9bb6fb8db-dbw4k 1/1 Running 0 3m21s
my-app-9bb6fb8db-j4wwk 1/1 Running 0 3m21s
root@master-VirtualBox:~/test/deploystrategy/recreate#
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-app-5b75d6ddbd-jmn88 0/1 Running 0 20s
my-app-9bb6fb8db-bl76q 1/1 Running 0 3m30s
my-app-9bb6fb8db-dbw4k 1/1 Running 0 3m30s
my-app-9bb6fb8db-j4wwk 1/1 Running 0 3m30s
root@master-VirtualBox:~/test/deploystrategy/recreate#
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-app-5b75d6ddbd-62kgv 0/1 ContainerCreating 0 5s
my-app-5b75d6ddbd-jmn88 1/1 Running 0 25s
my-app-9bb6fb8db-bl76q 1/1 Running 0 3m35s
my-app-9bb6fb8db-dbw4k 1/1 Running 0 3m35s

As you can see in the log above, you can see that the Pod with the last digit of the Pod ID, jimn88, is newly created and the Pod called j4wwk is deleted after it is converted to Running.

Blue/Green deployments

Blue/green deployment: Blue is the existing version and Green is the new version with new functions. After testing the Green version in the production environment with both versions present in the production environment, if there is no problem, the traffic connected to Green is transferred to Green It is a strategy to change and deploy. The advantage is that the deployed version (Green) can quickly switch traffic to Blue if there is a problem, while the disadvantage is that it takes twice as many resources for deployment and handling of stateful applications. The downside is that it's difficult to do.

As we looked at the Service resource earlier, we saw that the process of finding a Pod in a Service uses the Label Selector. Traffic diversion in blue/green deployment has the effect of changing the traffic by changing the specifications described in the Label Selector from V1 to V2.

If you look at the picture, the structure is as follows. After deploying the new version to Green and completing the test, if there is no test result, the traffic is switched to Blue with the kubectl patch service command.

Now, edit app-ve.yaml as below and save it.

root@master-VirtualBox:~/test/deploystrategy/recreate# vi app-v1.yaml
apiVersion: v1
kind: Service
metadata:
name: my-app
labels:
app: my-app
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: http
# Note here that we match both the app and the version
selector:
app: my-app
version: v1.0.0
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-v1
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
version: v1.0.0
template:
metadata:
labels:
app: my-app
version: v1.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9101"
spec:
containers:
- name: my-app
image: containersol/k8s-deployment-strategies
ports:
- name: http
containerPort: 8080
- name: probe
containerPort: 8086
env:
- name: VERSION
value: v1.0.0
livenessProbe:
httpGet:
path: /live
port: probe
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: probe
periodSeconds: 5

Now, let's deploy the app-v.yaml file and check the status of Pods and SVCs.

root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl apply -f app-v1.yaml
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-app-v1-9bb6fb8db-5ms25 1/1 Running 0 8s
my-app-v1-9bb6fb8db-hlqnm 1/1 Running 0 8s
my-app-v1-9bb6fb8db-szxkp 1/1 Running 0 8s
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d3h
my-app NodePort 10.111.157.220 <none> 80:30717/TCP 13s

Then, create a new version app-v2.yaml file, enter the following information and save it.

root@master-VirtualBox:~/test/deploystrategy/recreate# vi app-v2.yaml
apiVersion: v1
kind: Service
metadata:
name: my-app-v2
labels:
app: my-app
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: http
# Note here that we match both the app and the version
selector:
app: my-app
version: v2.0.0
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-v2
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
version: v2.0.0
template:
metadata:
labels:
app: my-app
version: v2.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9101"
spec:
containers:
- name: my-app
image: containersol/k8s-deployment-strategies
ports:
- name: http
containerPort: 8080
- name: probe
containerPort: 8086
env:
- name: VERSION
value: v2.0.0
livenessProbe:
httpGet:
path: /live
port: probe
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: probe
periodSeconds: 5

So now let's deploy app-v2.yaml and see how the Pods change.

root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl apply -f app-v2.yaml
oot@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-app-v1-9bb6fb8db-5ms25 1/1 Running 0 9m30s
my-app-v1-9bb6fb8db-hlqnm 1/1 Running 0 9m30s
my-app-v1-9bb6fb8db-szxkp 1/1 Running 0 9m30s
my-app-v2-69c46bcf4d-tsnr6 1/1 Running 0 12s
my-app-v2-69c46bcf4d-wvsm9 1/1 Running 0 12s
my-app-v2-69c46bcf4d-z8ndf 1/1 Running 0 12s
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d3h
my-app NodePort 10.111.157.220 <none> 80:30717/TCP 9m39s
my-app-v2 NodePort 10.111.8.220 <none> 80:30166/TCP 21s

As shown in the log above, you can see that 3 Pods V1 and 3 V2 are created, and V1 and V2 Services are also created. In this situation, test the application in v2 and if the result is normal, you can switch the traffic to V2 with the command below.

root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl patch service my-app -p '{"spec":{"selector":{"version":"v2.0.0"}}}'
service/my-app patched

Then, all traffic will be forwarded only to Pods with VERSION 2.0.0.

Canary Deployment

Canary deployment is a method of gradually moving traffic from applications deployed to V1 in production to V2. For example, a strategy to direct user requests for the same application 90% to V1 and the remaining 10% to the newly deployed V2. This deployment method is used when there is insufficient testing of the application to be deployed or when there is no confirmation of its stability.

Initially, it operates with 2 V1.2.3 Pods and 1 V1.3.0 Pod, and then increases to 2 and finally 3 as shown in the figure below.

Now, after creating app-v1.yaml as shown below, enter the following contents and save it.

root@master-VirtualBox:~/test/deploystrategy/recreate# vi app-v1.yaml
apiVersion: v1
kind: Service
metadata:
name: my-app
labels:
app: my-app
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: http
selector:
app: my-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-v1
labels:
app: my-app
spec:
replicas: 4
selector:
matchLabels:
app: my-app
version: v1.0.0
template:
metadata:
labels:
app: my-app
version: v1.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9101"
spec:
containers:
- name: my-app
image: containersol/k8s-deployment-strategies
ports:
- name: http
containerPort: 8080
- name: probe
containerPort: 8086
env:
- name: VERSION
value: v1.0.0
livenessProbe:
httpGet:
path: /live
port: probe
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: probe
periodSeconds: 5

Now, let's deploy app-v1.yaml and check Pod and Service information.

root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl apply -f app-v1.yaml
service/my-app created
deployment.apps/my-app-v1 created
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-app-v1-9bb6fb8db-mv6xj 1/1 Running 0 9s
my-app-v1-9bb6fb8db-qfmpz 1/1 Running 0 9s
my-app-v1-9bb6fb8db-tb9fw 1/1 Running 0 9s
my-app-v1-9bb6fb8db-v746q 1/1 Running 0 9s
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6d4h
my-app NodePort 10.96.124.3 <none> 80:31060/TCP 12s

Now, after creating the app-v2.yaml file, enter the following information into the file and save it. As you can see below, the value of replicas of V2 is set to 1. That is, only one v2 Pod is deployed.

root@master-VirtualBox:~/test/deploystrategy/recreate# vi app-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-v2
labels:
app: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
version: v2.0.0
template:
metadata:
labels:
app: my-app
version: v2.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9101"
spec:
containers:
- name: my-app
image: containersol/k8s-deployment-strategies
ports:
- name: http
containerPort: 8080
- name: probe
containerPort: 8086
env:
- name: VERSION
value: v2.0.0
livenessProbe:
httpGet:
path: /live
port: probe
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: probe
periodSeconds: 5

Now, let's deploy the created app-v2.yaml and check the Pod status.

root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl apply -f app-v2.yaml
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-app-v1-9bb6fb8db-mv6xj 1/1 Running 0 5m46s
my-app-v1-9bb6fb8db-qfmpz 1/1 Running 0 5m46s
my-app-v1-9bb6fb8db-tb9fw 1/1 Running 0 5m46s
my-app-v1-9bb6fb8db-v746q 1/1 Running 0 5m46s
my-app-v2-69c46bcf4d-7xc4k 1/1 Running 0 5s

Assuming that there is no problem with the newly deployed V2 Pod, you can use the command below to create a new V2 Pod and delete the V1 Pod.

root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl scale --replicas=4 deploy my-app-v2
deployment.apps/my-app-v2 scaled
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-app-v1-9bb6fb8db-mv6xj 1/1 Running 0 9m54s
my-app-v1-9bb6fb8db-qfmpz 1/1 Running 0 9m54s
my-app-v1-9bb6fb8db-tb9fw 1/1 Running 0 9m54s
my-app-v1-9bb6fb8db-v746q 1/1 Running 0 9m54s
my-app-v2-69c46bcf4d-5vlgk 1/1 Running 0 7s
my-app-v2-69c46bcf4d-7xc4k 1/1 Running 0 4m13s
my-app-v2-69c46bcf4d-d8nnh 1/1 Running 0 7s
my-app-v2-69c46bcf4d-zxk28 1/1 Running 0 7s
root@master-VirtualBox:~/test/deploystrategy/recreate#
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl delete deployments my-app-v1
deployment.apps "my-app-v1" deleted
root@master-VirtualBox:~/test/deploystrategy/recreate# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-app-v2-69c46bcf4d-5vlgk 1/1 Running 0 41s
my-app-v2-69c46bcf4d-7xc4k 1/1 Running 0 4m47s
my-app-v2-69c46bcf4d-d8nnh 1/1 Running 0 41s
my-app-v2-69c46bcf4d-zxk28 1/1 Running 0 41s
root@master-VirtualBox:~/test/deploystrategy/recreate#

Now, we have looked at all the deployment strategies supported for Kubernetes.

728x90
반응형