Theme NexT works best with JavaScript enabled
0%

Kubernetes Manual


IMPORTANT:
Some of the content here is a personal summary/abbreviation of contents on the Official Kubernetes Guide. Feel free to refer to that site if you think some of the sections written here are not clear.


Note

  • this content assumes some prior knowledge on Docker, including Docker Compose.

Installation

Please follow this link: https://kubernetes.io/docs/tasks/tools/

  • it is recommended that you install kubectl, which allows you to run commands against Kubernetes clusters.

Kubernetes Basics

Kubernetes Clusters

  • Kubernetes coordinates a highly available cluster of computers that are connected to work as a single unit.

A Kubernetes cluster consists of two types of resources:

  • The Master coordinates the cluster
  • Nodes are the workers that run applications
    • A node is a VM or a physical computer that serves as a worker machine in a Kubernetes cluster
    • Each node has a Kubelet, which is an agent for managing the node and communicating with the Kubernetes master.
https://d33wubrfki0l68.cloudfront.net/99d9808dcbf2880a996ed50d308a186b5900cec9/40b94/docs/tutorials/kubernetes-basics/public/images/module_01_cluster.svg

Starting with Minikube

This tutorial shows you how to run a sample app on Kubernetes using minikube and Katacod.

Objectives

  • Deploy a sample application to minikube.
  • Run the app.
  • View application logs.

Guide

  1. start minikube with minikube start
    • this will create and run a docker container called minikube
  2. minikube dashboard

Create a Deployment

Pod

  • A Kubernetes Pod is a group of one or more Containers, tied together for the purposes of administration and networking.
    • each container is basically based on an image

Deployment

  • A Kubernetes Deployment checks on the health of your Pod and restarts the Pod’s Container if it terminates.
  • You describe a desired state in a Deployment, and the Deployment Controller changes the actual state to the desired state at a controlled rate.
  • Deployments are the recommended way to manage the creation and scaling of Pods

Objective

  1. Create a deployment for a pod

  2. use kubectl to look around the setup

Guide

  1. Use the kubectl create command to create a Deployment that manages a Pod.

    • The Pod runs a Container based on the provided Docker image.
    • in this example, a pod has only one container
    1
    kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.4
  2. View the Deployment:

    1
    kubectl get deployments

    The output is similar to:

    1
    2
    NAME         READY   UP-TO-DATE   AVAILABLE   AGE
    hello-node 1/1 1 1 1m
  3. View the Pod:

    1
    kubectl get pods
    • which you will see the containers in the pod
  4. View cluster events:

    1
    kubectl get events
  5. View the kubectl configuration:

    1
    kubectl config view

Create a Service

Service

  • An abstract way to expose an application running on a set of Pods as a network service.

  • Kubernetes gives Pods their own IP addresses and a single DNS name for a set of Pods, and can load-balance across them

Note

  • By default, the Pod is only accessible by its internal IP address within the Kubernetes cluster. To make the hello-node Container accessible from outside the Kubernetes virtual network, you have to expose the Pod as a Kubernetes Service.
  • this is similar to docker containers

Objective

  1. Create a service from a Deployment (which contains Pods)
  2. Use the service

Guide

  1. Expose the Pod by exposing its Deployment

    1
    kubectl expose deployment hello-node --type=LoadBalancer --port=8080

    where:

    • exposing the deployment makes it a network service

    • --type=LoadBalancer. On minikube, the LoadBalancer type makes the Service accessible through the minikube service command.

      • On cloud providers that support load balancers, an external IP address would be provisioned to access the Service.
  2. View the Service you just created

    1
    kubectl get services
  3. Run the following command to use the service

    1
    minikube service hello-node

Enabling Addons

Addons

  • Add-ons extend the functionality of Kubernetes.
  • Some of them are third party projects that provide functionality required by Kubernetes.

Objective

  1. View currently available add-ons
  2. Enable an add-on
  3. Disable an add-on

Guide

  1. List the currently supported addons:

    1
    minikube addons list

    The output is similar to:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    addon-manager: enabled
    dashboard: enabled
    default-storageclass: enabled
    efk: disabled
    freshpod: disabled
    gvisor: disabled
    helm-tiller: disabled
    ingress: disabled
    ingress-dns: disabled
    logviewer: disabled
    metrics-server: disabled
    nvidia-driver-installer: disabled
    nvidia-gpu-device-plugin: disabled
    registry: disabled
    registry-creds: disabled
    storage-provisioner: enabled
    storage-provisioner-gluster: disabled
  2. Enable an addon, for example, metrics-server:

    1
    minikube addons enable metrics-server

    The output is similar to:

    1
    metrics-server was successfully enabled
  3. View the Pod and Service you just created:

    1
    kubectl get pod,svc -n kube-system
  4. Disable metrics-server:

    1
    minikube addons disable metrics-server

    The output is similar to:

    1
    metrics-server was successfully disabled

Clean Up

Objective

  1. remove the Service you created

  2. remove the Deployment you created

    • this will also remove the Pods under that deployment
  3. optionally, stop and remove minikube VM

Guide

  1. Clean up the resources you created in your cluster:

    1
    2
    kubectl delete service hello-node
    kubectl delete deployment hello-node
  2. Optionally, stop the Minikube virtual machine (docker container)

    1
    minikube stop

    Optionally, delete the Minikube VM (docker container):

    1
    minikube delete

Minikube to Kubernetes

Reminder

  • Recall that a cluster contains the following:

    https://d33wubrfki0l68.cloudfront.net/99d9808dcbf2880a996ed50d308a186b5900cec9/40b94/docs/tutorials/kubernetes-basics/public/images/module_01_cluster.svg

    where:

    • The Master is responsible for managing the cluster.
    • A Node is a VM or a physical computer that serves as a worker machine in a Kubernetes cluster (e.g. a running docker container)
      • The nodes communicate with the master using the Kubernetes API

Pod vs Node

  • where:

    • A Pod always runs on a Node.
    • Pods are the atomic unit on the Kubernetes platform
    • A Node can have multiple pods, and the Kubernetes master automatically handles scheduling the pods across the Nodes in the cluster.

Create a Cluster

Basically, we have done this with the minikube part - minikube itself is a node (since it is a docker container)!

For Example

  1. Start minikube:

    1
    minikube start
  2. View it as a node:

    1
    kubectl get nodes

    gives you:

    1
    2
    NAME       STATUS   ROLES                  AGE    VERSION
    minikube Ready control-plane,master 3m1s v1.20.2

Deploy an App

Once you have a running Kubernetes cluster (at least one node), you can deploy your containerized applications on top of it.

To do so, you create a Kubernetes Deployment configuration.

Reminder

  • The Deployment instructs Kubernetes how to create and update instances of your application.
  • You can create and manage a Deployment by using the Kubernetes command line interface, kubectl
  • When you created a Deployment, Kubernetes created a automatically Pod to host your application instance.

Deploying an App Basically does this

https://d33wubrfki0l68.cloudfront.net/152c845f25df8e69dd24dd7b0836a289747e258a/4a1d2/docs/tutorials/kubernetes-basics/public/images/module_02_first_app.svg

where:

  • when you create a Deployment, you’ll need to specify the container image for your application and the number of replicas that you want to run.

Objective

  • Deploy an app based on the minikube node
    • the app is created using a container image

Guide

  1. .Make sure you have at least one node running. For example,

    1
    minikube start
  2. Deploy the app with the image gcr.io/google-samples/kubernetes-bootcamp:v1 into the cluster

    1
    kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1

    where:

    • if it is a docker image, you can just specify the name without the URL
    • When you created a Deployment, Kubernetes created a Pod to host your application instance.
  3. To see the state of the deployment, use

    1
    kubectl get deployments
  4. Reminder

    • Pods that are running inside Kubernetes are running on a private, isolated network. By default they are visible from other pods and services within the same kubernetes cluster, but not outside that network.
    • When we use kubectl, we’re interacting through an API endpoint to communicate with our application.

    Therefore, to interact with Pods through kubectl API, one way to do it will be:

    1. Create a Proxy with kubectl proxy
  • this will basically start listening on port 8001
  1. Use Http request to use/interact the service listening on 8001:

    1
    curl http://localhost:8001/version

Note

  • In order for the new deployment to be accessible without using the Proxy, a Service is required which will be explained in the next modules.

Exploring Your App

First, get the main concepts out of the way. The main picture in mind will be:

The picture in mind will be:

Kubernetes Pods

  • A Pod is a Kubernetes abstraction that represents a group of one or more application containers (such as Docker), and some shared resources for those containers.

    • For example, a Pod might include both the container with your Node.js app as well as a different container that feeds the data to be published by the Node.js webserver.
  • Pods are the atomic unit on the Kubernetes platform. When we create a Deployment on Kubernetes, that Deployment:

    1. creates Pods
    2. create containers inside Pods

    (as opposed to creating containers directly).

  • Each Pod is tied to the Node where it is scheduled, and remains there until termination (according to restart policy) or deletion. In case of a Node failure, identical Pods are scheduled on other available Nodes in the cluster.

Node

  • A Pod always runs on a Node.
  • A Node is a worker machine in Kubernetes and may be either a virtual or a physical machine.
  • Each Node is managed by the Master.
    • the Kubernetes master automatically handles scheduling the pods across the Nodes in the cluster
  • Every Kubernetes Node runs at least:
    • Kubelet, a process responsible for communication between the Kubernetes Master and the Node.
    • A container runtime (like Docker) responsible for pulling the container image from a registry (for Pods), unpacking the container, and running the application.

Objective

  1. Look at the configuration of pods
  2. Interact with containers inside a pod

Guide

  1. We’ll use the kubectl get command and look for existing Pods

  2. view what containers are inside that Pod with kubectl describe pods

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Name:         kubernetes-bootcamp-57978f5f5d-5j5rg
    Namespace: default
    Priority: 0
    Node: minikube/192.168.49.2
    Start Time: Sat, 13 Feb 2021 19:25:10 +0800
    Labels: app=kubernetes-bootcamp
    pod-template-hash=57978f5f5d
    Annotations: <none>
    Status: Running
    IP: 172.17.0.2
    IPs:
    IP: 172.17.0.2
    Controlled By: ReplicaSet/kubernetes-bootcamp-57978f5f5d
    Containers:
    kubernetes-bootcamp:
    Container ID: docker://72b74c5cfa8e21a4cf996c8c6caa4a32b27d2749adc4a66f803d2d0af99163ea
    Image: gcr.io/google-samples/kubernetes-bootcamp:v1
    Image ID: docker-pullable://gcr.io/google-samples/kubernetes-
    // other logs omitted

    we see that it shows information such as:

    • address, the ports used
    • a list of events related to the lifecycle of the Pod.
    • etc.

    Note

    • the describe command can be used to get detailed information about most of the kubernetes primitives: node, pods, deployments.

    • for example: kubectl describe deployments

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      Name:                   kubernetes-bootcamp
      Namespace: default
      CreationTimestamp: Sat, 13 Feb 2021 19:25:10 +0800
      Labels: app=kubernetes-bootcamp
      Annotations: deployment.kubernetes.io/revision: 1
      Selector: app=kubernetes-bootcamp
      Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable
      StrategyType: RollingUpdate
      MinReadySeconds: 0
      RollingUpdateStrategy: 25% max unavailable, 25% max surge
      Pod Template:
      Labels: app=kubernetes-bootcamp
      Containers:
      kubernetes-bootcamp:
      Image: gcr.io/google-samples/kubernetes-bootcamp:v1
      Port: <none>
      Host Port: <none>
      Environment: <none>
      Mounts: <none>
      Volumes: <none>
      Conditions:
      Type Status Reason
      ---- ------ ------
      Available True MinimumReplicasAvailable
      Progressing True NewReplicaSetAvailable
      OldReplicaSets: <none>
      NewReplicaSet: kubernetes-bootcamp-57978f5f5d (1/1 replicas created)
      Events: <none>
  3. Now, to expose the container/app, you need to create a proxy, since Pods are isolated:

    1
    kubectl proxy
    • which will start listening on 8001

    then, in a new terminal, use kubectl as the interface to communicate with the Pod:

    1. first, you need to get the name of pod:

      1
      export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
    2. then, you can use it:

      1
      curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/proxy/
  4. Anything that the application would normally send to STDOUT becomes logs for the container within the Pod.

    1
    kubectl logs $POD_NAME
  5. Lastly, we can execute commands directly on the container once the Pod is up and running with the exec command with name of the Pod as a parameter.

    1
    kubectl exec $POD_NAME -- env

    to do this interactively, use:

    1
    kubectl exec -ti $POD_NAME -- bash

    and now we are inside the container/Pod!

    Note

    • this step does not technically need a proxy running
  6. To exit, use exit

Expose Your App

Services and Labels

  • A Service routes traffic across a set of Pods. Services are the abstraction that allow pods to die and replicate in Kubernetes without impacting your application.
    • remember, each Pod in a Kubernetes cluster has a unique IP address. So this Service abstraction can be used to reconcile that
  • A Service is defined using YAML or JSON, and it targets a set of Pods by matching them using labels and selectors, a grouping primitive that allows logical operation on objects in Kubernetes.

Overview of Services/Replica Set

  • When a worker node dies, the Pods running on the Node are also lost. A ReplicaSet might then dynamically drive the cluster back to desired state via creation of new Pods to keep your application running.
  • In genera; Services allow your applications to receive traffic. Services can be exposed in different ways by specifying a type in the ServiceSpec:
    • ClusterIP (default) - Exposes the Service on an internal IP in the cluster. This type makes the Service only reachable from within the cluster.
    • NodePort - Exposes the Service on the same port of each selected Node in the cluster using NAT. Makes a Service accessible from outside the cluster using <NodeIP>:<NodePort>. Superset of ClusterIP.
    • LoadBalancer - Creates an external load balancer in the current cloud (if supported) and assigns a fixed, external IP to the Service. Superset of NodePort.
    • ExternalName - Exposes the Service using an arbitrary name (specified by externalName in the spec) by returning a CNAME record with the name. No proxy is used. This type requires v1.7 or higher of kube-dns.

Objectives

  1. Expose a deployment to become a Service
  2. View and change the labels of a Pod
  3. Delete a Service

Guides

  1. First,we can see what services we have already:

    1
    2
    3
    jasonyux@XY-Laptop /code $ kubectl get services
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d
  2. Then, we want to create a Service and expose it to traffic with kubectl expose:

    1
    2
    3
    4
    5
    6
    jasonyux@XY-Laptop /code $ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
    service/kubernetes-bootcamp exposed
    jasonyux@XY-Laptop /code $ kubectl get services
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 9d
    kubernetes-bootcamp NodePort 10.105.181.115 <none> 8080:31364/TCP 6s

    where:

    • external-IP of the node would be the IP of the Node itself. (which you can find out with kubectl describe nodes)
    • the Deployment also created automatically a label for our Pod.
  3. Now, to see the labels of the Pod, use describe:

    1
    2
    3
    4
    5
    6
    jasonyux@XY-Laptop /code :( $ kubectl describe deployment
    Name: kubernetes-bootcamp
    Namespace: default
    CreationTimestamp: Sat, 13 Feb 2021 19:25:10 +0800
    Labels: app=kubernetes-bootcamp
    // other logs omitted

    then, we can get the Pod by its label

    1
    kubectl get pods -l run=kubernetes-bootcamp

    and get the selected Pods of a service by label:

    1
    kubectl get services -l run=kubernetes-bootcamp
  4. To change the label of a pod, use label pod.

    1. first, get the Pod’s name:

      1
      2
      3
      jasonyux@XY-Laptop /code :( $ export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
      jasonyux@XY-Laptop /code $ echo Name of the Pod: $POD_NAME
      Name of the Pod: kubernetes-bootcamp-57978f5f5d-5j5rg
    2. change the Pod‘s name

      1
      2
      3
      4
      5
      6
      7
      8
      9
      jasonyux@XY-Laptop /code $ kubectl describe pods
      Name: kubernetes-bootcamp-57978f5f5d-5j5rg
      Namespace: default
      Priority: 0
      Node: minikube/192.168.49.2
      Start Time: Sat, 13 Feb 2021 19:25:10 +0800
      Labels: app=v1
      pod-template-hash=57978f5f5d
      // other logs omitted
    3. Now, you can get the information by the new label:

      1
      2
      3
      jasonyux@XY-Laptop /code $ kubectl get pods -l app=v1
      NAME READY STATUS RESTARTS AGE
      kubernetes-bootcamp-57978f5f5d-5j5rg 1/1 Running 1 9d
  5. To delete services, you can also use its label/selector:

    1
    kubectl delete service -l run=kubernetes-bootcamp

    then, it is no longer exposed, but it is still running. This means you can still do:

    1
    kubectl exec -ti $POD_NAME curl localhost:8080

Scaling an Application

Scaling

  • Scaling is accomplished by changing the number of replicas in a Deployment.

  • Scaling out a Deployment will:

    1. ensure new Pods are created and scheduled to Nodes with available resources.
    2. increase the number of Pods to the new desired state.

Reminder: Replica Set

  • When a worker node dies, the Pods running on the Node are also lost. A ReplicaSet might then dynamically drive the cluster back to desired state via creation of new Pods to keep your application running.
  • A ReplicaSet is defined with fields, including a selector that specifies how to identify Pods it can acquire, a number of replicas indicating how many Pods it should be maintaining, and a pod template specifying the data of new Pods it should create to meet the number of replicas criteria.
    • then, a ReplicaSet then fulfills its purpose by creating and deleting Pods as needed to reach the desired number.

Note

  • Running multiple instances of an application will require a way to distribute the traffic to all of them. Services have an integrated load-balancer that will distribute network traffic to all Pods of an exposed Deployment.

Objective

  1. Scale your application/deployment using kubectl scale
  2. Verify that the load-balancer is working automatically by communicating with the Service

Guide

  1. First, inspect the current state (deployments/replica set). You will see that:

    1
    2
    3
    4
    5
    6
    jasonyux@XY-Laptop /code $ kubectl get deployments
    NAME READY UP-TO-DATE AVAILABLE AGE
    kubernetes-bootcamp 1/1 1 1 15d
    jasonyux@XY-Laptop /code $ kubectl get rs
    NAME DESIRED CURRENT READY AGE
    kubernetes-bootcamp-57978f5f5d 1 1 1 15d

    where, for deployments:

    • NAME lists the names of the Deployments in the cluster.
    • READY shows the ratio of CURRENT/DESIRED replicas
    • UP-TO-DATE displays the number of replicas that have been updated to achieve the desired state.
    • AVAILABLE displays how many replicas of the application are available to your users.
    • AGE displays the amount of time that the application has been running.

    for replica-set:

    • DESIRED displays the desired number of replicas of the application, which you define when you create the Deployment. This is the desired state.
    • CURRENT displays how many replicas are currently running.
  2. Now, you can scale your deployment to 4 replicas:

    1
    2
    3
    4
    5
    jasonyux@XY-Laptop /code $ kubectl scale deployment/kubernetes-bootcamp --replicas=4
    deployment.apps/kubernetes-bootcamp scaled
    jasonyux@XY-Laptop /code $ kubectl get deployments
    NAME READY UP-TO-DATE AVAILABLE AGE
    kubernetes-bootcamp 4/4 4 4 15d
  3. Inspect the scaled Pods in your deployment:

    1
    2
    3
    4
    5
    6
    jasonyux@XY-Laptop /code $ kubectl get pods
    NAME READY STATUS RESTARTS AGE
    kubernetes-bootcamp-57978f5f5d-9vtkx 1/1 Running 0 2m37s
    kubernetes-bootcamp-57978f5f5d-jgqnt 1/1 Running 0 2m37s
    kubernetes-bootcamp-57978f5f5d-lcg4t 1/1 Running 0 2m38s
    kubernetes-bootcamp-57978f5f5d-tg497 1/1 Running 1 6d1h

    where you see that there are 4 Pods now, with different IP addresses.

    You can also see all changes in the deployment log

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    jasonyux@XY-Laptop /code $ kubectl describe deployments/kubernetes-bootcamp
    Name: kubernetes-bootcamp
    Namespace: default
    CreationTimestamp: Sat, 13 Feb 2021 19:25:10 +0800
    Labels: app=kubernetes-bootcamp
    Annotations: deployment.kubernetes.io/revision: 1
    Selector: app=kubernetes-bootcamp
    Replicas: 4 desired | 4 updated | 4 total | 4 available | 0 unavailable
    // some log omitted here
    Events:
    Type Reason Age From Message
    ---- ------ ---- ---- -------
    Normal ScalingReplicaSet 3m5s deployment-controller Scaled up replica set kubernetes-bootcamp-57978f5f5d to 4
    Normal ScalingReplicaSet 2m17s deployment-controller Scaled up replica set kubernetes-bootcamp-57978f5f5d to 6
    Normal ScalingReplicaSet 2m13s deployment-controller Scaled down replica set kubernetes-bootcamp-57978f5f5d to 4
  4. To find out the exposed IP and Port we can use the describe service, and then communicate with the deployments using the IP/Port.

    • first, we look at the Service:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      jasonyux@XY-Laptop /code $ kubectl describe services/kubernetes-bootcamp
      Name: kubernetes-bootcamp
      Namespace: default
      Labels: app=kubernetes-bootcamp
      Annotations: <none>
      Selector: app=kubernetes-bootcamp
      Type: NodePort
      IP Families: <none>
      IP: 10.105.181.115
      IPs: 10.105.181.115
      Port: <unset> 8080/TCP
      TargetPort: 8080/TCP
      NodePort: <unset> 31364/TCP
      Endpoints: 172.17.0.3:8080,172.17.0.5:8080,172.17.0.6:8080 + 1 more...
      Session Affinity: None
      External Traffic Policy: Cluster
      Events: <none>

      which is specified the IP and (Node) Port

    • now, again some handy renaming to environment variable

      1
      2
      export NODE_PORT=$(kubectl get services/kubernetes-bootcamp -o go-template='{{(index .spec.ports 0).nodePort}}')
      echo NODE_PORT=$NODE_PORT
    • lastly, communicate:

      1
      curl $(minikube ip):$NODE_PORT

      where:

      • We hit a different Pod with every request. This demonstrates that the load-balancing is working.
  5. To scale down, use the same command:

    1
    kubectl scale deployments/kubernetes-bootcamp --replicas=2

Performing a Rolling Update

Users expect applications to be available all the time and developers are expected to deploy new versions of them several times a day. In Kubernetes this is done with rolling updates.

Rolling Update

  • Rolling updates allow Deployments’ update to take place with zero downtime by incrementally updating Pods instances with new ones. The new Pods will be scheduled on Nodes with available resources.
  • By default, the maximum number of Pods that can be unavailable during the update and the maximum number of new Pods that can be created, is one.
    • Both options can be configured to either numbers or percentages (of Pods).

Note

  • In Kubernetes, updates are versioned and any Deployment update can be reverted to a previous (stable) version.
  • Of course, in order to ensure high availability, you need more than one running Pods.

Objective

  1. Perform an update to your deployment by changing the application image
  2. Check the rolling update status
  3. Revert back to previous update

Goal

  1. Let’s begin with a deployment of 4 Pods

    1
    2
    3
    4
    5
    6
    7
    8
    9
    jasonyux@XY-Laptop /code $ kubectl get deployments
    NAME READY UP-TO-DATE AVAILABLE AGE
    kubernetes-bootcamp 4/4 4 4 15d
    jasonyux@XY-Laptop /code $ kubectl get pods
    NAME READY STATUS RESTARTS AGE
    kubernetes-bootcamp-57978f5f5d-9vtkx 1/1 Running 0 25m
    kubernetes-bootcamp-57978f5f5d-jgqnt 1/1 Running 0 25m
    kubernetes-bootcamp-57978f5f5d-lcg4t 1/1 Running 0 25m
    kubernetes-bootcamp-57978f5f5d-vg7dt 1/1 Running 0 41s
  2. To update the image of the application to version 2, use the set image command, followed by the kubectl set image <deployment_name> <container_name>:<image_name>:

    • first to see current image:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      jasonyux@XY-Laptop /code $ kubectl describe pods
      Name: kubernetes-bootcamp-57978f5f5d-vg7dt
      Namespace: default
      Priority: 0
      Node: minikube/192.168.49.2
      Start Time: Sun, 28 Feb 2021 23:21:05 +0800
      Labels: app=kubernetes-bootcamp
      pod-template-hash=57978f5f5d
      // some logs omitted
      Image: gcr.io/google-samples/kubernetes-bootcamp:v1
    • then, to set the new state:

      1
      2
      3
      4
      jasonyux@XY-Laptop /code $ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp
      :v2
      deployment.apps/kubernetes-bootcamp image updated
      jasonyux@XY-Laptop /code $
  3. Now, as an intermediate state, you might see:

    1
    2
    3
    4
    5
    6
    7
    jasonyux@XY-Laptop /code $ kubectl get pods
    NAME READY STATUS RESTARTS AGE
    kubernetes-bootcamp-57978f5f5d-lcg4t 0/1 Terminating 0 31m
    kubernetes-bootcamp-769746fd4-bgt2r 1/1 Running 0 50s
    kubernetes-bootcamp-769746fd4-dggf8 1/1 Running 0 49s
    kubernetes-bootcamp-769746fd4-g4k4f 1/1 Running 0 64s
    kubernetes-bootcamp-769746fd4-l5mb4 1/1 Running 0 64s
  4. Again, to verify that it is working, you can find out the exposed IP and Port we can use describe service, then get the node-port and ip and try to communicate using curl

    • this is basically the same procedure as previous section
  5. Additionally, updates can be confirmed with

    1
    2
    jasonyux@XY-Laptop /code $ kubectl rollout status deployments/kubernetes-bootcamp
    deployment "kubernetes-bootcamp" successfully rolled out

    so that now, the image field will be updated:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    jasonyux@XY-Laptop /code $ kubectl describe pods
    Name: kubernetes-bootcamp-769746fd4-bgt2r
    Namespace: default
    Priority: 0
    Node: minikube/192.168.49.2
    Start Time: Sun, 28 Feb 2021 23:27:35 +0800
    Labels: app=kubernetes-bootcamp
    pod-template-hash=769746fd4
    Annotations: <none>
    Status: Running
    IP: 172.17.0.9
    IPs:
    IP: 172.17.0.9
    Controlled By: ReplicaSet/kubernetes-bootcamp-769746fd4
    Containers:
    // some logs omitted
    Image: jocatalin/kubernetes-bootcamp:v2
  6. However, if we have performed a wrong update, for example setting the image version to v10 which does not exist

    1
    2
    jasonyux@XY-Laptop /code $ kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10
    deployment.apps/kubernetes-bootcamp image updated

    then:

    1
    2
    3
    jasonyux@XY-Laptop /code $ kubectl get deployments
    NAME READY UP-TO-DATE AVAILABLE AGE
    kubernetes-bootcamp 3/4 2 3 15d

    where:

    • basically one Pod is down because it has the wrong image/update

    A describe command on the Pods should give more insights:

    1
    kubectl describe pods

    in this case:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    jasonyux@XY-Laptop /code $ kubectl describe pods
    Name: kubernetes-bootcamp-597654dbd-b7p2c
    Namespace: default
    Priority: 0
    Node: minikube/192.168.49.2
    Start Time: Sun, 28 Feb 2021 23:32:52 +0800
    Labels: app=kubernetes-bootcamp
    pod-template-hash=597654dbd
    Annotations: <none>
    Status: Pending
    IP: 172.17.0.5
    IPs:
    IP: 172.17.0.5
    Controlled By: ReplicaSet/kubernetes-bootcamp-597654dbd
    Containers:
    kubernetes-bootcamp:
    Container ID:
    Image: gcr.io/google-samples/kubernetes-bootcamp:v10
    // some logs omitted
    Events:
    Type Reason Age From Message
    ---- ------ ---- ---- -------
    Normal Scheduled 82s default-scheduler Successfully assigned default/kubernetes-bootcamp-597654dbd-b7p2c to minikube
    Warning Failed 36s (x2 over 66s) kubelet Failed to pull image "gcr.io/google-samples/kubernetes-bootcamp:v10": rpc error: code = Unknown desc = Error response from daemon: Get https://gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
    Warning Failed 36s (x2 over 66s) kubelet Error: ErrImagePull
    Normal BackOff 21s (x2 over 66s) kubelet Back-off pulling image "gcr.io/google-samples/kubernetes-bootcamp:v10"
    Warning Failed 21s (x2 over 66s) kubelet Error: ImagePullBackOff
    Normal Pulling 8s (x3 over 81s) kubelet Pulling image "gcr.io/google-samples/kubernetes-bootcamp:v10"

    where we see that error in the Events: tag:

    • Failed to pull image "gcr.io/google-samples/kubernetes-bootcamp:v10": rpc error: code = Unknown desc = Error response from daemon: Get https://gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
      
      1
      2
      3
      4
      5
      6

      7. To **revert/undo** the last update, you can do:

      ```bash
      jasonyux@XY-Laptop /code $ kubectl rollout undo deployments/kubernetes-bootcamp
      deployment.apps/kubernetes-bootcamp rolled back

    where:

    • technically, updates are versioned and you can revert to any previously know state of a Deployment.

    List again the Pods to confirm:

    1
    2
    3
    4
    5
    6
    jasonyux@XY-Laptop /code $ kubectl get pods
    NAME READY STATUS RESTARTS AGE
    kubernetes-bootcamp-769746fd4-4sllf 1/1 Running 0 89s
    kubernetes-bootcamp-769746fd4-bgt2r 1/1 Running 0 10m
    kubernetes-bootcamp-769746fd4-dggf8 1/1 Running 0 10m
    kubernetes-bootcamp-769746fd4-l5mb4 1/1 Running 0 11m