Detailed Explanation of Pod Controller – Introduction to Deployment

Learning Kubernetes from Scratch

Deployment (Deploy)

To better address the issue of service orchestration, Kubernetes introduced the Deployment controller starting from version 1.2. It is worth mentioning that this controller does not directly manage Pods but instead manages ReplicaSets to indirectly manage Pods. In other words, the Deployment manages ReplicaSets, and ReplicaSets manage Pods, making Deployment more powerful than ReplicaSet.

Detailed Explanation of Pod Controller - Introduction to Deployment

The Deployment is essentially a two-layer controller. First, the Deployment describes the version of the application through the number of ReplicaSets. Then, the Deployment ensures the number of Pod replicas through the attributes of the ReplicaSet (such as the value of replicas).

The main functions of Deployment include the following:

1. Supports all functions of ReplicaSet

2. Supports stopping and resuming releases

3. Supports rolling updates and version rollbacks

Resource manifest file for Deployment:

apiVersion: apps/v1 # Version
kind: Deployment # Type
metadata: # Metadata
  name: # Deployment Name
  namespace: # Namespace
  labels: # Labels
    controller: deploy
spec: # Specification
  replicas: 3 # Number of replicas
  revisionHistoryLimit: 3 # Retain historical versions, default is 10
  paused: false # Pause deployment, default is false
  progressDeadlineSeconds: 600 # Deployment timeout (s), default is 600
  strategy: # Strategy
    type: RollingUpdate # Rolling update strategy
    rollingUpdate: # Rolling update
      maxSurge: 30% # Maximum additional replicas allowed, can be a percentage or an integer
      maxUnavailable: 30% # Maximum number of Pods that can be unavailable, can be a percentage or an integer
  selector: # Selector, specifies which Pods this controller manages
    matchLabels: # Labels matching rules
      app: nginx-pod
    matchExpressions: # Expressions matching rules
      - {key: app, operator: In, values: [nginx-pod]}
  template: # Template, when the number of replicas is insufficient, Pods will be created based on this template
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.20.2-alpine
        ports:
        - containerPort: 80

Detailed Explanation of Pod Controller - Introduction to Deployment

Creation:

# Create pc-deployment.yaml
cat > pc-deployment.yaml < EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pc-deployment
  namespace: dev
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1-alpine
EOF
# Create deployment
# kubectl create -f pc-deployment.yaml --record=true
kubectl create -f pc-deployment.yaml

# View deployment
# READY Expected number of Pod replicas
# UP-TO-DATE Number of latest version Pods
# AVAILABLE Number of currently available Pods
kubectl get deploy pc-deployment -n dev
NAME           READY UP-TO-DATE AVAILABLE  AGE
pc-deployment  3/3       3          3      8s

# View rs
# After creating the Deployment object, a ReplicaSet with 3 Pod replicas will be created immediately, with a name composed of the Deployment name and a random string
kubectl get rs -n dev
NAME                     DESIRED CURRENT READY AGE
pc-deployment-7d9bdf9475    3       3      3   16s

# View pod
# The name of the pod has a 5-digit random string appended to the name of the rs
kubectl get pods -n dev
NAME                           READY  STATUS   RESTARTS  AGE
pc-deployment-7d9bdf9475-5fjrd  1/1    Running    0      23s
pc-deployment-7d9bdf9475-fhcb7  1/1    Running    0      23s
pc-deployment-7d9bdf9475-fxqdp  1/1    Running    0      23s

Scaling:

# Change the number of replicas to 5
kubectl scale deploy pc-deployment --replicas=5 -n dev

# View deployment
kubectl get deploy pc-deployment -n dev
NAME           READY  UP-TO-DATE AVAILABLE AGE
pc-deployment  5/5        5          5     98s

# View pod
kubectl get pods -n dev
NAME                           READY  STATUS  RESTARTS  AGE
pc-deployment-7d9bdf9475-5fjrd  1/1   Running    0      109s
pc-deployment-7d9bdf9475-ccmhz  1/1   Running    0      19s
pc-deployment-7d9bdf9475-dfq2m  1/1   Running    0      19s
pc-deployment-7d9bdf9475-fhcb7  1/1   Running    0      109s
pc-deployment-7d9bdf9475-fxqdp  1/1   Running    0      109s

# Edit the number of replicas in the deployment, modify spec:replicas: 3
kubectl edit deploy pc-deployment -n dev

# View pod
kubectl get deploy pc-deployment -n dev
NAME         READY UP-TO-DATE AVAILABLE AGE
pc-deployment 3/3      3          3     2m26s
kubectl get pods -n dev
NAME READY STATUS RESTARTS AGE
pc-deployment-7d9bdf9475-5fjrd 1/1 Running 0 2m35s
pc-deployment-7d9bdf9475-fhcb7 1/1 Running 0 2m35s
pc-deployment-7d9bdf9475-fxqdp 1/1 Running 0 2m35s

Image Update:

The deployment supports two update strategies:Recreate and RollingUpdate (default), which can be specified through strategy to indicate the type of strategy, supporting two properties:

strategy: Specifies the strategy for replacing old Pods with new Pods, supporting two properties:
  type: Specifies the type of strategy, supporting two strategies
    Recreate: All existing Pods will be killed before creating new Pods
    RollingUpdate: Rolling update, which kills some and starts some, during the update process, there are two versions of Pods
  rollingUpdate: Effective when type is RollingUpdate, used to set parameters for RollingUpdate, supporting two properties:
    maxUnavailable: Specifies the maximum number of unavailable Pods during the upgrade process, default is 25%
    maxSurge: Specifies the maximum number of Pods that can exceed the expected number during the upgrade process, default is 25%

Recreate Update:

Edit pc-deployment.yaml, add update strategy under the spec node

spec:
  strategy: # Strategy
    type: Recreate # Recreate update
cat > pc-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pc-deployment
  namespace: dev
spec:
  strategy:
    type: Recreate
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1-alpine
EOF

Create deploy for verification:

# Update pc-deployment's yaml file
kubectl apply -f pc-deployment.yaml

# View deployment version
kubectl get deploy pc-deployment -n dev -o wide
NAME           READY UP-TO-DATE AVAILABLE  AGE   CONTAINERS       IMAGES            SELECTOR
pc-deployment  3/3       3          3     3m39s     nginx    nginx:1.17.1-alpine app=nginx-pod

# Observe the upgrade process, then open a new shell to execute the update, all pods start updating simultaneously
kubectl get pods -n dev -w
NAME                           READY  STATUS          RESTARTS  AGE
pc-deployment-7d9bdf9475-5fjrd  1/1   Running            0      3m56s
pc-deployment-7d9bdf9475-fhcb7  1/1   Running            0      3m56s
pc-deployment-7d9bdf9475-fxqdp  1/1   Running            0      3m56s
pc-deployment-7d9bdf9475-fxqdp  1/1   Terminating        0      4m21s
pc-deployment-7d9bdf9475-5fjrd  1/1   Terminating        0      4m21s
pc-deployment-7d9bdf9475-fhcb7  1/1   Terminating        0      4m21s
pc-deployment-9d4dbb5bd-68zms   0/1   Pending            0      0
pc-deployment-9d4dbb5bd-7mxpv   0/1   Pending            0      0
pc-deployment-9d4dbb5bd-nkdn2   0/1   Pending            0      0
pc-deployment-9d4dbb5bd-68zms   0/1   ContainerCreating  0      0
pc-deployment-9d4dbb5bd-7mxpv   0/1   ContainerCreating  0      0
pc-deployment-9d4dbb5bd-nkdn2   0/1   ContainerCreating  0      0
pc-deployment-9d4dbb5bd-7mxpv   1/1   Running            0      1
pc-deployment-9d4dbb5bd-nkdn2   1/1   Running            0      20
pc-deployment-9d4dbb5bd-68zms   1/1   Running            0      36s

# Change image
kubectl set image deployment pc-deployment nginx=nginx:1.17.2-alpine -n dev

Rolling Update:

Edit pc-deployment.yaml, add update strategy under the spec node

spec:
  strategy: # Strategy
    type: RollingUpdate # Rolling update strategy
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
cat > pc-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pc-deployment
  namespace: dev
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1-alpine
EOF
# Update pc-deployment's yaml file
kubectl apply -f pc-deployment.yaml

# View deployment version
kubectl get deploy pc-deployment -n dev -o wide
NAME           READY UP-TO-DATE AVAILABLE  AGE   CONTAINERS        IMAGES          SELECTOR
pc-deployment  3/3       3          3      11m     nginx    nginx:1.17.1-alpine  app=nginx-pod

# Observe the upgrade process, then open a new shell to execute the update
kubectl get pods -n dev -w
pc-deployment-7d9bdf9475-9xvnj 1/1 Running 0 49s
pc-deployment-7d9bdf9475-mkqhj 1/1 Running 0 48s
pc-deployment-7d9bdf9475-n7fj v 1/1 Running 0 51s
pc-deployment-545fbd7bb5-vkv8k 0/1 Pending 0 0
pc-deployment-545fbd7bb5-vkv8k 0/1 Pending 0 0
pc-deployment-545fbd7bb5-vkv8k 0/1 ContainerCreating 0 0
pc-deployment-545fbd7bb5-vkv8k 0/1 ContainerCreating 0 0
pc-deployment-545fbd7bb5-vkv8k 1/1 Running 0 20s
pc-deployment-7d9bdf9475-mkqhj 1/1 Terminating 0 3m2s
pc-deployment-545fbd7bb5-ss7pk 0/1 Pending 0 0
pc-deployment-545fbd7bb5-ss7pk 0/1 Pending 0 0
pc-deployment-545fbd7bb5-ss7pk 0/1 ContainerCreating 0 0
pc-deployment-545fbd7bb5-ss7pk 0/1 ContainerCreating 0 0
pc-deployment-7d9bdf9475-mkqhj 0/1 Terminating 0 3m3s
pc-deployment-545fbd7bb5-ss7pk 0/1 ContainerCreating 0 0
# Change image
kubectl set image deployment pc-deployment nginx=nginx:1.17.3-alpine -n dev

Rolling update process:

Detailed Explanation of Pod Controller - Introduction to Deployment

Changes in rs during image update

# View rs, the original rs still exists, but the number of pods has become 0, and then a new rs is generated with 3 pods
# This is actually the secret behind the deployment's ability to perform version rollbacks, which will be explained in detail later
kubectl get rs -n dev
NAME                     DESIRED CURRENT READY  AGE
pc-deployment-545fbd7bb5    3       3      3   2m20s
pc-deployment-7d9bdf9475    0       0      0   14m
pc-deployment-9d4dbb5bd     0       0      0   10m

Version Rollback:

The deployment supports various functions such as pausing, resuming, and rolling back during the version upgrade process.

kubectl rollout: Version upgrade related functions, supporting the following options:

1. status Displays the current upgrade status

2. history Displays the upgrade history

3. pause Pauses the version upgrade process

4. resume Resumes the already paused version upgrade process

5. restart Restarts the version upgrade process

6. undo Rolls back to the previous version (can use –to-revision to roll back to a specified version)

# Delete deployment
kubectl delete -f pc-deployment.yaml

# Edit pc-deployment.yaml
cat > pc-deployment.yaml < EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pc-deployment
  namespace: dev
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
  replicas: 3
  selector:
    matchLabels:
      app: nginx-pod
  template:
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.1-alpine
EOF
# Create deployment, --record records the deployment operation process
# kubectl create -f pc-deployment.yaml --record=true
kubectl create -f pc-deployment.yaml --record

# View deploy, rs, pod
kubectl get deploy,rs,pod -n dev
NAME                          READY  UP-TO-DATE AVAILABLE  AGE
deployment.apps/pc-deployment  3/3       3          3      25s
NAME                                     DESIRED  CURRENT  READY  AGE
replicaset.apps/pc-deployment-7d9bdf9475    3        3       3    25s
NAME                               READY  STATUS   RESTARTS  AGE
pod/pc-deployment-7d9bdf9475-g95pv  1/1   Running     0      25s
pod/pc-deployment-7d9bdf9475-ghhlx  1/1   Running     0      25s
pod/pc-deployment-7d9bdf9475-twgw8  1/1   Running     0      25s

# Open 2 new shells to observe the process, the update will create a new rs, and the pods under the old rs will be 0
kubectl get rs -n dev -w
NAME                       DESIRED  CURRENT  READY   AGE
pc-deployment-7d9bdf9475     3        3       3    3m13s
pc-deployment-9d4dbb5bd      1        0       0      0
pc-deployment-9d4dbb5bd      1        0       0      0
pc-deployment-9d4dbb5bd      1        1       0      0
pc-deployment-9d4dbb5bd      1        1       1      2
pc-deployment-7d9bdf9475     2        3       3    4m21s
pc-deployment-9d4dbb5bd      2        1       1       2
pc-deployment-7d9bdf9475     2        3       3    4m21s
pc-deployment-9d4dbb5bd      2        1       1     2
pc-deployment-7d9bdf9475     2        2       2    4m21s
pc-deployment-9d4dbb5bd      2        2       1     2
pc-deployment-9d4dbb5bd      2        2       2     4
pc-deployment-7d9bdf9475     1        2       2    4m23s
pc-deployment-9d4dbb5bd      3        2       2     4

# Open 2 new shells to observe the process, the updated pods will be under the new rs
kubectl get pods -n dev -w
NAME                            READY  STATUS      RESTARTS    AGE
pc-deployment-7d9bdf9475-g95pv   1/1   Running            0    3m19s
pc-deployment-7d9bdf9475-ghhlx   1/1   Running            0    3m19s
pc-deployment-7d9bdf9475-twgw8   1/1   Running            0    3m19s
pc-deployment-9d4dbb5bd-p79xr   0/1   Pending            0    0
pc-deployment-9d4dbb5bd-p79xr   0/1   Pending            0    0
pc-deployment-9d4dbb5bd-p79xr   0/1   ContainerCreating  0    0
pc-deployment-9d4dbb5bd-p79xr   0/1   ContainerCreating  0    0
pc-deployment-9d4dbb5bd-p79xr   1/1   Running            0    2
pc-deployment-7d9bdf9475-twgw8   1/1   Terminating        0    4m21s
pc-deployment-9d4dbb5bd-l5qpv   0/1   Pending            0    0
pc-deployment-9d4dbb5bd-l5qpv   0/1   Pending            0    0
pc-deployment-9d4dbb5bd-l5qpv   0/1   ContainerCreating  0    0
pc-deployment-9d4dbb5bd-l5qpv   0/1   ContainerCreating  0    0
pc-deployment-7d9bdf9475-ghhlx   0/1   Terminating        0    4m24s
pc-deployment-9d4dbb5bd-l5qpv   1/1   Running            0    1

# Change image
kubectl set image deploy pc-deployment nginx=nginx:1.17.2-alpine -n dev
# -record indicates that this command is recorded in the operation history
kubectl set image deploy pc-deployment nginx=nginx:1.17.2-alpine -n dev --record
# View rs, the rs has been updated along with the deployment, the old rs is used for version rollback
kubectl get rs -n dev
NAME                       DESIRED CURRENT  READY   AGE
pc-deployment-7d9bdf9475      0       0      0     7m20s
pc-deployment-9d4dbb5bd       3       3      3     3m1s
# View the status of the current upgrade version
kubectl rollout status deploy pc-deployment -n dev
deployment "pc-deployment" successfully rolled out

# View upgrade history
kubectl rollout history deploy pc-deployment -n dev
deployment.apps/pc-deployment REVISION CHANGE-CAUSE
kubectl create -f pc-deployment.yaml --record=true
kubectl create -f pc-deployment.yaml --record=true

# Again, change image
kubectl set image deploy pc-deployment nginx=nginx:1.17.3-alpine -n dev
# -record indicates that this command is recorded in the operation history
kubectl set image deploy pc-deployment nginx=nginx:1.17.3-alpine -n dev --record

# Again, view upgrade history
kubectl rollout history deploy pc-deployment -n dev
deployment.apps/pc-deployment REVISION CHANGE-CAUSE
kubectl create -f pc-deployment.yaml --record=true
kubectl create -f pc-deployment.yaml --record=true
kubectl create -f pc-deployment.yaml --record=true
# It can be seen that there are three version records, indicating that two upgrades have been completed
# View deployment version
kubectl get deploy -n dev -o wide
NAME          READY UP-TO-DATE  AVAILABLE AGE  CONTAINERS     IMAGES            SELECTOR
pc-deployment  3/3       3          3     18m    nginx    nginx:1.17.3-alpine  app=nginx-pod

# Version rollback
# Here directly use --to-revision=1 to roll back to version 1, if this option is omitted, it will roll back to the previous version, which is version 2
kubectl rollout undo deployment pc-deployment --to-revision=1 -n dev
deployment.apps/pc-deployment rolled back

# View shows that the nginx image version has returned to the first version
kubectl get deploy -n dev -o wide
NAME         READY UP-TO-DATE AVAILABLE AGE CONTAINERS   IMAGES               SELECTOR
pc-deployment 3/3      3         3      18m   nginx    nginx:1.17.1-alpine  app=nginx-pod

# View rs, find that there are 3 pods running in the first rs, while the pods in the updated two versions of rs are 0
# The reason why deployment can achieve version rollback is that it records the historical rs
# Once you want to roll back to a certain version, you just need to reduce the current version pod count to 0, and then increase the pod count of the rollback version to the target count
kubectl get rs -n dev
NAME                     DESIRED CURRENT  READY  AGE
pc-deployment-545fbd7bb5    0       0       0    3m4s
pc-deployment-7d9bdf9475    3       3       3    19m
pc-deployment-9d4dbb5bd     0       0       0    14m

# Again, view upgrade history, find that version 1 is gone, because it has now rolled back to version 4 which is version 1
kubectl rollout history deploy pc-deployment -n dev
deployment.apps/pc-deployment REVISION CHANGE-CAUSE
kubectl create -f pc-deployment.yaml --record=true
kubectl create -f pc-deployment.yaml --record=true
kubectl create -f pc-deployment.yaml --record=true

Leave a Comment