Skip to main content

Certified Kubernetes Application Developer (CKAD)

Course

Intro Video

Photo of Will Boyd

Will Boyd

DevOps Team Lead in Content

Length

18:51:06

Difficulty

Intermediate

Videos

31

Hands-on Labs

13

Course Details

Kubernetes provides many powerful tools to help manage complex applications. In order to fully utilize all that Kubernetes has to offer, you need some understanding of its features and how to design application to run on Kubernetes. The Certified Kubernetes Application Developer (CKAD) certification focuses on these topics.

This course will help you prepare for the exam, so that you can earn your certification. Even if you are not interested in becoming certified, this course can help you learn how to design and build applications for Kubernetes!

Syllabus

Certified Kubernetes Application Developer (CKAD)

Introduction

Course Introduction

00:01:11

Lesson Description:

Welcome to the Certified Kubernetes Application Developer (CKAD) course! This video will introduce the course, briefly discuss the course layout, and show the videos and hands-on labs that are associated with the exam objectives.

About the Course Author

00:00:27

Lesson Description:

This video introduces William Boyd, the author of this course!

Course Features and Tools

00:02:32

Lesson Description:

In this video, we will discuss some of the features and tools which Linux Academy offers to help you succeed in the course. There is a lot more to the course than just videos, so be sure to take advantage of everything the course has to offer!

Core Concepts

Build Your Practice Cluster

00:09:39

Lesson Description:

Although installing and configuring a Kubernetes cluster is not one of the objectives for the CKAD exam, it is important to get some hand-on experirnce with the concepts covered in this course. Therefore, it is useful to have a Kubernetes cluster with which you can experiment and try out the things that will be covered throughout the course. This lesson will guide you through the process of building a basic cluster that you can experiment with as you proceed. Lesson Reference If you want to follow along, there is a reference for the commands used in this lesson below. On all 3 servers First, set up the Docker and Kubernetes repositories:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo add-apt-repository    "deb [arch=amd64] https://download.docker.com/linux/ubuntu 
   $(lsb_release -cs) 
   stable"

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

cat << EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
Install Docker and Kubernetes packages: Note that if you want to use a newer version of Kubernetes, change the version installed for kubelet, kubeadm, and kubectl. Make sure all three use the same version. Note: There is currently a bug in Kubernetes 1.13.4 (and earlier) that can cause problems installaing the packages. Use 1.13.5-00 to avoid this issue.
sudo apt-get update

sudo apt-get install -y docker-ce=18.06.1~ce~3-0~ubuntu kubelet=1.13.5-00 kubeadm=1.13.5-00 kubectl=1.13.5-00

sudo apt-mark hold docker-ce kubelet kubeadm kubectl
Enable iptables bridge call:
echo "net.bridge.bridge-nf-call-iptables=1" | sudo tee -a /etc/sysctl.conf

sudo sysctl -p
On the Kube master server Initialize the cluster:
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
Set up local kubeconfig:
mkdir -p $HOME/.kube

sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

sudo chown $(id -u):$(id -g) $HOME/.kube/config
Install Flannel networking:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml
On each Kube node server Join the node to the cluster:
sudo kubeadm join $controller_private_ip:6443 --token $token --discovery-token-ca-cert-hash $hash
On the Kube master server Verify that all nodes are joined and ready:
kubectl get nodes
You should see all three servers with a status of Ready:
NAME                      STATUS   ROLES    AGE   VERSION
wboyd1c.mylabserver.com   Ready    master   54m   v1.13.4
wboyd2c.mylabserver.com   Ready    <none>   49m   v1.13.4
wboyd3c.mylabserver.com   Ready    <none>   49m   v1.13.4

Kubernetes API Primitives

00:09:43

Lesson Description:

Kubernetes API primitive, also known as Kubernetes objects, are the basic building blocks of any application running in Kubernetes. Building and managing Kubernetes applications means working with objects. It is essential to be familiar with Kubernetes objects in order to develop applications for Kubernetes. In this lesson, we will discuss what Kubernetes objects are, and how to find information about objects in a cluster. Relevant Documentationhttps://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/ Lesson Reference

kubectl api-resources -o name

kubectl get pods -n kube-system

kubectl get nodes

kubectl get nodes $node_name

kubectl get nodes $node_name -o yaml

kubectl describe node $node_name

Creating Pods

00:09:51

Lesson Description:

Pods are one of the most essential Kubernetes object types. Most of the orchestration features of Kubernetes are centered around the management of Pods. In this lesson, we will discuss what Pods are and demonstrate how to create a pod. We will also talk about how to edit and delete pods after they are created. The principles discussed in this lesson for managing pods apply to the management of other types of Kubernetes objects as well. Relevant Documentation https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/ Lesson Reference Create a new yaml file to contain the pod definition. Use whatever editor you like, but we used vi:

vi my-pod.yml
my-pod.yml:
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
Create a pod from the yaml definition file:
kubectl create -f my-pod.yml
Edit a pod by updating the yaml definiton and re-applying it:
kubectl apply -f my-pod.yml
You can also edit a pod like this:
kubectl edit pod my-pod
You can delete a pod like this:
kubectl delete pod my-pod

Namespaces

00:04:51

Lesson Description:

Although namespaces are not on the objectives list for the CKAD exam, they play an important role in many of the tasks that the exam may cover. An understanding of namespaces is necessary in order to avoid confusion in many scenarios that may arise when working with Kubernetes. In this lesson, we will briefly discuss namespaces, how to assign objects to namespaces, and how to browse objects within namespaces. Relevant Documentation https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ Lesson Reference You can get a list of the namespaces in the cluster like this:

kubectl get namespaces
You can also create your own namespaces.
kubectl create ns my-ns
To assign an object to a custom namespace, simply specify its metadata.namespace attribute.
apiVersion: v1
kind: Pod
metadata:
  name: my-ns-pod
  namespace: my-ns
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
Create the pod with the created yaml file.
kubectl create -f my-ns.yml
Use the -n flag to specify a namespace when using commands like kubectl get.
kubectl get pods -n my-ns
You can also use -n to specify a namespace when using kubectl describe.
kubectl describe pod my-ns-pod -n my-ns

Basic Container Configuration

00:05:58

Lesson Description:

When building applications in Kubernetes, it is often necessary to provide some configuration for your containers. In this lesson we will discuss some frequently-used container configuration options: command, args, and containerPort. After completing this lesson, you will have a basic understanding of some the ways in which Kubernetes allows you to customize how your containers are run within a pod. Relevant Documentationhttps://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/ Lesson Reference You can specify custom commands for your containers.

apiVersion: v1
kind: Pod
metadata:
  name: my-command-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['echo']
  restartPolicy: Never
You can also add custom arguments like so:
apiVersion: v1
kind: Pod
metadata:
  name: my-args-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['echo']
    args: ['This is my custom argument']
  restartPolicy: Never
Here is a pod with a containerPort:
apiVersion: v1
kind: Pod
metadata:
  name: my-containerport-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: nginx
    ports:
    - containerPort: 80
You can check the status of your pods at any time with kubectl get pods.

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

00:15:00

Configuration

ConfigMaps

00:12:30

Lesson Description:

Management of configuration data is one of the challenges involved in building and maintaining complex application infrastructures. Luckily, Kubernetes offers functionality that helps to maintain application configurations in the form of ConfigMaps. In this lesson, we will discuss what ConfigMaps are, how to create them, some of the ways that ConfigMap data can be passed in to containers running within Kubernetes Pods. Relevant Documentationhttps://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/ Lesson Reference Here's an example of of a yaml descriptor for a ConfigMap containing some data:

apiVersion: v1
kind: ConfigMap
metadata:
   name: my-config-map
data:
   myKey: myValue
   anotherKey: anotherValue
Passing ConfigMap data to a container as an environment variable looks like this:
apiVersion: v1
kind: Pod
metadata:
  name: my-configmap-pod
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', "echo $(MY_VAR) && sleep 3600"]
    env:
    - name: MY_VAR
      valueFrom:
        configMapKeyRef:
          name: my-config-map
          key: myKey
It's also possible to pass ConfigMap data to containers, in the form of file using a mounted volume, like so:
apiVersion: v1
kind: Pod
metadata:
  name: my-configmap-volume-pod
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', "echo $(cat /etc/config/myKey) && sleep 3600"]
    volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: my-config-map
In the lesson, we'll also use the following commands to explore how the ConfigMap data interacts with pods and containers:
kubectl logs my-configmap-pod

kubectl logs my-configmap-volume-pod

kubectl exec my-configmap-volume-pod -- ls /etc/config

kubectl exec my-configmap-volume-pod -- cat /etc/config/myKey

SecurityContexts

00:11:48

Lesson Description:

Occasionally, it's necessary to customize how containers interact with the underlying security mechanisms present on the operating systems of Kubernetes nodes. The securityContext attribute in a pod specification allows for making these customizations. In this lesson, we will briefly discuss what the securityContext is, and demonstrate how to use it to implement some common functionality. Relevant Documentation https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ Lesson Reference First, create some users, groups, and files on both worker nodes which we can use for testing.

sudo useradd -u 2000 container-user-0
sudo groupadd -g 3000 container-group-0
sudo useradd -u 2001 container-user-1
sudo groupadd -g 3001 container-group-1
sudo mkdir -p /etc/message/
echo "Hello, World!" | sudo tee -a /etc/message/message.txt
sudo chown 2000:3000 /etc/message/message.txt
sudo chmod 640 /etc/message/message.txt
On the controller, create a pod to read the message.txt file and print the message to the log.
vi my-securitycontext-pod.yml
Content of the YAML File
apiVersion: v1
kind: Pod
metadata:
  name: my-securitycontext-pod
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', "cat /message/message.txt && sleep 3600"]
    volumeMounts:
    - name: message-volume
      mountPath: /message
  volumes:
  - name: message-volume
    hostPath:
      path: /etc/message
Check the pod's log to see the message from the file:
kubectl logs my-securitycontext-pod
Delete the pod and re-create it, this time with a securityContext set to use a user and group that do not have access to the file.
kubectl delete pod my-securitycontext-pod --now
apiVersion: v1
kind: Pod
metadata:
  name: my-securitycontext-pod
spec:
  securityContext:
    runAsUser: 2001
    fsGroup: 3001
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', "cat /message/message.txt && sleep 3600"]
    volumeMounts:
    - name: message-volume
      mountPath: /message
  volumes:
  - name: message-volume
    hostPath:
      path: /etc/message
Check the log again. You should see a "permission denied" message.
kubectl logs my-securitycontext-pod
Delete the pod and re-create it again, this time with a user and group that are able to access the file.
kubectl delete pod my-securitycontext-pod --now
apiVersion: v1
kind: Pod
metadata:
  name: my-securitycontext-pod
spec:
  securityContext:
    runAsUser: 2000
    fsGroup: 3000
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', "cat /message/message.txt && sleep 3600"]
    volumeMounts:
    - name: message-volume
      mountPath: /message
  volumes:
  - name: message-volume
    hostPath:
      path: /etc/message
Check the log once more. You should see the message from the file.
kubectl logs my-securitycontext-pod

Resource Requirements

00:05:41

Lesson Description:

Kubernetes is a powerful tool for managing and utilizing available resources to run containers. Resource requests and limits provide a great deal of control over how resources will be allocated. In this lesson, we will talk about what resource requests and limits do, and also demonstrate how to set resource requests and limits for a container. Relevant Documentationhttps://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#resource-requests-and-limits-of-pod-and-container Lesson Reference Specify resource requests and resource limits in the container spec like this:

apiVersion: v1
kind: Pod
metadata:
  name: my-resource-pod
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

Secrets

00:04:53

Lesson Description:

One of the challenges in managing a complex application infrastructure is ensuring that sensitive data remains secure. It is always important to store sensitive data, such as tokens, passwords, and keys, in a secure, encrypted form. In this lesson, we will talk about Kubernetes secrets, a way of securely storing data and providing it to containers. We will also walk through the process of creating a simple secret, and passing the sensitive data to a container as an environment variable. Relevant Documentationhttps://kubernetes.io/docs/concepts/configuration/secret/ Lesson Reference Create a secret using a yaml definition like this. It is a good idea to delete the yaml file containing the sensitive data after the secret object has been created in the cluster.

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
stringData:
  myKey: myPassword
Once a secret is created, pass the sensitive data to containers as an environment variable:
apiVersion: v1
kind: Pod
metadata:
  name: my-secret-pod
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', "echo Hello, Kubernetes! && sleep 3600"]
    env:
    - name: MY_PASSWORD
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: myKey

ServiceAccounts

00:02:57

Lesson Description:

Kubernetes allows containers running within the cluster to interact with the Kubernetes API. This opens the door to some powerful forms of automation. But in order to ensure that this gets done securely, it is a good idea to use specialized ServiceAccounts with restricted permissions to allow containers to access the API. In this lesson, we will discuss ServiceAccounts as they pertain to pod configuration, and we will walk through the process of specifying which ServiceAccount a pod will use to connect to the Kubernetes API. Relevant Documentationhttps://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ Lesson Reference Creating a ServiceAccount looks like this:

kubectl create serviceaccount my-serviceaccount
Use the serviceAccountName attribute in the pod spec to specify which ServiceAccount the pod should use:
apiVersion: v1
kind: Pod
metadata:
  name: my-serviceaccount-pod
spec:
  serviceAccountName: my-serviceaccount
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', "echo Hello, Kubernetes! && sleep 3600"]

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:30:00

Multi-Container Pods

Understanding Multi-Container Pods

00:09:38

Lesson Description:

Multi-container pods provide an opportunity to enhance containers with helper containers that provide additional functionality. This lesson covers the basics of what multi-container pods are and how they are created. It also discusses the primary ways that containers can interact with each other within the same pod, as well as the three main multi-container pod design patterns: sidecar, ambassador, and adapter. Be sure to check out the hands-on labs for this course (including the practice exam) to get some hands-on experience with implementing multi-container pods. Relevant Documentation https://kubernetes.io/docs/concepts/cluster-administration/logging/#using-a-sidecar-container-with-the-logging-agenthttps://kubernetes.io/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/https://kubernetes.io/blog/2015/06/the-distributed-system-toolkit-patterns/ Lesson Reference Here is the YAML used to create a simple multi-container pod in the video:

apiVersion: v1
kind: Pod
metadata:
  name: multi-container-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.15.8
    ports:
    - containerPort: 80
  - name: busybox-sidecar
    image: busybox
    command: ['sh', '-c', 'while true; do sleep 30; done;']

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:30:00

Observability

Liveness and Readiness Probes

00:07:20

Lesson Description:

Kubernetes is often able to detect problems with containers and respond appropriately without the need for specialized configuration. But sometimes we need additional control over how Kubernetes determines container status. Kubernetes probes provide the ability to customize how Kubernetes detects the status of containers, allowing us to build more sophisticated mechanisms for managing container health. In this lesson, we discuss liveness and readiness probes in Kubernetes, and demonstrate how to create and configure them. Relevant Documentationhttps://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probeshttps://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/ Lesson Reference Here is a pod with a liveness probe that uses a command: my-liveness-pod.yml:

apiVersion: v1
kind: Pod
metadata:
  name: my-liveness-pod
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', "echo Hello, Kubernetes! && sleep 3600"]
    livenessProbe:
      exec:
        command:
        - echo
        - testing
      initialDelaySeconds: 5
      periodSeconds: 5
Here is a pod with a readiness probe that uses an http request: my-readiness-pod.yml:
apiVersion: v1
kind: Pod
metadata:
  name: my-readiness-pod
spec:
  containers:
  - name: myapp-container
    image: nginx
    readinessProbe:
      httpGet:
        path: /
        port: 80
      initialDelaySeconds: 5
      periodSeconds: 5

Container Logging

00:04:15

Lesson Description:

When managing containers, obtaining container logs is sometimes necessary in order to gain insight into what is going on inside a container. Kubernetes offers an easy way to view and interact with container logs using the kubectl logs command. In this lesson, we discuss container logs and demonstrate how to access them using kubectl logs. Relevant Documentationhttps://kubernetes.io/docs/concepts/cluster-administration/logging/ Lesson Reference A sample pod that generates log output every second:

apiVersion: v1
kind: Pod
metadata:
  name: counter
spec:
  containers:
  - name: count
    image: busybox
    args: [/bin/sh, -c, 'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
Get the container's logs:
kubectl logs counter
For a multi-container pod, specify which container to get logs for using the -c flag:
kubectl logs <pod name> -c <container name>
Save container logs to a file:
kubectl logs counter > counter.log

Installing Metrics Server

00:03:50

Lesson Description:

In order to practice using some of the monitoring features in Kubernetes, you will need a running metrics server in your cluster. It is not necessary to know how to install the metrics server in order to pass the exam, but you will need to install it in your practice cluster if you are following along. In this lesson, we will go over to quickly and easily install the metrics server in your practice cluster. Lesson Reference Clone the metrics server repo and install the server using kubectl apply:

cd ~/
git clone https://github.com/linuxacademy/metrics-server
kubectl apply -f ~/metrics-server/deploy/1.8+/
Once you have installed the metrics server, you can use this command to verify that it is responsive:
kubectl get --raw /apis/metrics.k8s.io/

Monitoring Applications

00:03:43

Lesson Description:

Monitoring is an important part of managing any application infrastructure. In this lesson, we will discuss how to view the resource usage of pods and nodes using the kubectl top command. Relevant Documentationhttps://kubernetes.io/docs/tasks/debug-application-cluster/resource-usage-monitoring/ Lesson Reference Here are some sample pods that can be used to test kubectl top. They are designed to use approximately 300m and 100m CPU, respectively.

apiVersion: v1
kind: Pod
metadata:
  name: resource-consumer-big
spec:
  containers:
  - name: resource-consumer
    image: gcr.io/kubernetes-e2e-test-images/resource-consumer:1.4
    resources:
      requests:
        cpu: 500m
        memory: 128Mi
  - name: busybox-sidecar
    image: radial/busyboxplus:curl
    command: [/bin/sh, -c, 'until curl localhost:8080/ConsumeCPU -d "millicores=300&durationSec=3600"; do sleep 5; done && sleep 3700']
apiVersion: v1
kind: Pod
metadata:
  name: resource-consumer-small
spec:
  containers:
  - name: resource-consumer
    image: gcr.io/kubernetes-e2e-test-images/resource-consumer:1.4
    resources:
      requests:
        cpu: 500m
        memory: 128Mi
  - name: busybox-sidecar
    image: radial/busyboxplus:curl
    command: [/bin/sh, -c, 'until curl localhost:8080/ConsumeCPU -d "millicores=100&durationSec=3600"; do sleep 5; done && sleep 3700']
Here are the commands used in the lesson to view resource usage data in the cluster:
kubectl top pods
kubectl top pod resource-consumer-big
kubectl top pods -n kube-system
kubectl top nodes

Debugging

00:10:19

Lesson Description:

Problems will occur in any system, and Kubernetes provides some great tools to help locate and fix problems when they occur within a cluster. In this lesson, we will go through the process of debugging an issue in Kubernetes. We will use our knowledge of kubectl get and kubectl describe to locate a broken pod, and then explore various ways of editing Kubernetes objects to fix issues. Relevant Documentationhttps://kubernetes.io/docs/tasks/debug-application-cluster/debug-application/https://kubernetes.io/docs/tasks/debug-application-cluster/debug-pod-replication-controller/https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/ Lesson Reference I prepared my cluster before the video by creating a broken pod in the nginx-ns namespace:

kubectl create namespace nginx-ns
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: nginx-ns
spec:
  containers:
  - name: nginx
    image: nginx:1.158
Exploring the cluster to locate the problem
kubectl get pods

kubectl get namespace

kubectl get pods --all-namespaces

kubectl describe pod nginx -n nginx-ns
Fixing the broken image name Edit the pod:
kubectl edit pod nginx -n nginx-ns
Change the container image to nginx:1.15.8. Exporting a descriptor to edit and re-create the pod. Export the pod descriptor and save it to a file:
kubectl get pod nginx -n nginx-ns -o yaml --export > nginx-pod.yml
Add this liveness probe to the container spec:
livenessProbe:
  httpGet:
    path: /
    port: 80
Delete the pod and recreate it using the descriptor file. Be sure to specify the namespace:
kubectl delete pod nginx -n nginx-ns

kubectl apply -f nginx-pod.yml -n nginx-ns

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:00:00

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:30:00

Pod Design

Labels, Selectors, and Annotations

00:09:40

Lesson Description:

Kubernetes labels provide a way to attach custom, identifying information to your objects. Selectors can then be used to filter objects using label data as criteria. Annotations, on the other hand, offer a more freeform way to attach useful but non-identifying metadata. In this lesson, we will discuss labels, selectors, and annotations. We will also demonstrate how to use them in a cluster. Relevant Documentationhttps://kubernetes.io/docs/concepts/overview/working-with-objects/labels/https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ Lesson Reference Here is a pod with some labels.

apiVersion: v1
kind: Pod
metadata:
  name: my-production-label-pod
  labels:
    app: my-app
    environment: production
spec:
  containers:
  - name: nginx
    image: nginx
You can view existing labels with kubectl describe.
kubectl describe pod my-production-label-pod
Here is another pod with different labels.
apiVersion: v1
kind: Pod
metadata:
  name: my-development-label-pod
  labels:
    app: my-app
    environment: development
spec:
  containers:
  - name: nginx
    image: nginx
You can use various selectors to select different subsets of objects.
kubectl get pods -l app=my-app

kubectl get pods -l environment=production

kubectl get pods -l environment=development

kubectl get pods -l environment!=production

kubectl get pods -l 'environment in (development,production)'

kubectl get pods -l app=my-app,environment=production
Here is a simple pod with some annotations.
apiVersion: v1
kind: Pod
metadata:
  name: my-annotation-pod
  annotations:
    owner: terry@linuxacademy.com
    git-commit: bdab0c6
spec:
  containers:
  - name: nginx
    image: nginx
Like labels, existing annotations can also be viewed using kubectl describe.
kubectl describe pod my-annotation-pod

Deployments

00:07:21

Lesson Description:

Deployments provide a variety of features to help you automatically manage groups of replica pods. In this lesson, we will discuss what deployments are. We will also create a simple deployment and go through the process of scaling the deployment up and down by changing the number of desired replicas. Relevant Documentationhttps://kubernetes.io/docs/concepts/workloads/controllers/deployment/ Lesson Reference Here is a simple deployment for three replica pods running nginx.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
You can explore and manage deployments using the same kubectl commands you would use for other object types.
kubectl get deployments

kubectl get deployment <deployment name>

kubectl describe deployment <deployment name>

kubectl edit deployment <deployment name>

kubectl delete deployment <deployment name>

Rolling Updates and Rollbacks

00:10:48

Lesson Description:

One powerful feature of Kubernetes deployments is the ability to perform rolling updates and rollbacks. These allow you to push out new versions without incurring downtime, and they allow you to quickly return to a previous state in order to recover from problems that may arise when deploying changes. In this lesson, we will discuss rolling updates and rollback, and we will demonstrate the process of performing them on a deployment in the cluster. Relevant Documentationhttps://v1-12.docs.kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deploymenthttps://v1-12.docs.kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-back-a-deployment Lesson Reference Here is a sample deployment you can use to practice rolling updates and rollbacks.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rolling-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.1
        ports:
        - containerPort: 80
Perform a rolling update.
kubectl set image deployment/rolling-deployment nginx=nginx:1.7.9 --record
Explore the rollout history of the deployment.
kubectl rollout history deployment/rolling-deployment

kubectl rollout history deployment/rolling-deployment --revision=2
You can roll back to the previous revision like so.
kubectl rollout undo deployment/rolling-deployment
You can also roll back to a specific earlier revision by providing the revision number.
kubectl rollout undo deployment/rolling-deployment --to-revision=1
You can also control how rolling updates are performed by setting maxSurge and maxUnavailable in the deployment spec:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rolling-deployment
spec:
  strategy:
    rollingUpdate:
      maxSurge: 3
      maxUnavailable: 2
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.1
        ports:
        - containerPort: 80

Jobs and CronJobs

00:10:14

Lesson Description:

Kubernetes provides the ability to easily run container workloads in a distributed cluster, but not all workloads need to run constantly. With jobs, we can run container workloads until they complete, then shut down the container. CronJobs allow us to do the same, but re-run the workload regularly according to a schedule. In this lesson, we will discuss Jobs and CronJobs and explore how to create and manage them. Relevant Documentationhttps://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/https://kubernetes.io/docs/tasks/job/automated-tasks-with-cron-jobs/ Lesson Reference This Job calculates the first 2000 digits of pi.

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
      restartPolicy: Never
  backoffLimit: 4
You can use kubectl get to list and check the status of Jobs.
kubectl get jobs
Here is a CronJob that prints some text to the console every minute.
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
You can use kubectl get to list and check the status of CronJobs.
kubectl get cronjobs

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:00:00

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:00:00

Services and Networking

Services

00:09:45

Lesson Description:

Deployments make it easy to create a set of replica pods that can be dynamically scaled, updated, and replaced. However, providing network access to those pods for other components is difficult. Services provide a layer of abstraction that solves this problem. Clients can simply access the service, which dynamically proxies traffic to the current set of replicas. In this lesson, we will discuss services and demonstrate how to create one that exposes a deployment's replica pods. Relevant Documentationhttps://kubernetes.io/docs/concepts/services-networking/service/https://kubernetes.io/docs/tutorials/kubernetes-basics/expose/expose-intro/ Lesson Reference Create a deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
Expose the deployment's replica pods with a service:
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type: ClusterIP
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 80
You can get more information about the service with these commands:
kubectl get svc
kubectl get endpoints my-service

NetworkPolicies

00:15:36

Lesson Description:

From a security perspective, it is often a good idea to place network-level restrictions on any communication between different parts of your infrastructure. NetworkPolicies allow you to restrict and control the network traffic going to and from your pods. In this lesson, we will discuss NetworkPolicies and demonstrate how to create a simple policy to restrict access to a pod. Relevant Documentationhttps://kubernetes.io/docs/concepts/services-networking/network-policies/ Lesson Reference In order to use NetworkPolicies in the cluster, we need to have a network plugin that supports them. We can accomplish this alongside an existing flannel setup using canal:

wget -O canal.yaml https://docs.projectcalico.org/v3.5/getting-started/kubernetes/installation/hosted/canal/canal.yaml

kubectl apply -f canal.yaml
Create a sample nginx pod:
apiVersion: v1
kind: Pod
metadata:
  name: network-policy-secure-pod
  labels:
    app: secure-app
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
Create a client pod which can be used to test network access to the Nginx pod:
apiVersion: v1
kind: Pod
metadata:
  name: network-policy-client-pod
spec:
  containers:
  - name: busybox
    image: radial/busyboxplus:curl
    command: ["/bin/sh", "-c", "while true; do sleep 3600; done"]
Use this command to get the cluster IP address of the Nginx pod:
kubectl get pod network-policy-secure-pod -o wide
Use the secure pod's IP address to test network access from the client pod to the secure Nginx pod:
kubectl exec network-policy-client-pod -- curl <secure pod cluster ip address>
Create a network policy that restricts all access to the secure pod, except to and from pods which bear the allow-access: "true" label:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-network-policy
spec:
  podSelector:
    matchLabels:
      app: secure-app
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          allow-access: "true"
    ports:
    - protocol: TCP
      port: 80
  egress:
  - to:
    - podSelector:
        matchLabels:
          allow-access: "true"
    ports:
    - protocol: TCP
      port: 80
Get information about NetworkPolicies in the cluster:
kubectl get networkpolicies
kubectl describe networkpolicy my-network-policy

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:00:00

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:00:00

State Persistence

Volumes

00:04:16

Lesson Description:

Container storage is designed to be as temporary as the containers themselves. However, sometimes we need storage that is able to survive beyond the short life of a container. Kubernetes volumes allow us to mount storage to a container that isn't in the container itself. In this lesson, we will discuss volumes and demonstrate how to mount a simple volume to a container in a pod. Relevant Documentationhttps://kubernetes.io/docs/concepts/storage/volumes/ Lesson Reference This pod mounts a simple emptyDir volume, my-volume, to the container at the path /tmp/storage.

apiVersion: v1
kind: Pod
metadata:
  name: volume-pod
spec:
  containers:
  - image: busybox
    name: busybox
    command: ["/bin/sh", "-c", "while true; do sleep 3600; done"]
    volumeMounts:
    - mountPath: /tmp/storage
      name: my-volume
  volumes:
  - name: my-volume
    emptyDir: {}

PersistentVolumes and PersistentVolumeClaims

00:12:02

Lesson Description:

PersistentVolumes (PVs) and PersistentVolumeClaims (PVCs) provide a way to easily consume storage resources, especially in the context of a complex production environment that uses multiple storage solutions. In this lesson, we will talk about implementing persistent storage using PersistentVolumes and PersistentVolumeClaims, and we will demonstrate how to set up a PV and PVC to consume storage resources in a pod. Relevant Documentation https://kubernetes.io/docs/concepts/storage/persistent-volumes/https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/ Lesson Reference Create the PersistentVolume:

kind: PersistentVolume
apiVersion: v1
metadata:
  name: my-pv
spec:
  storageClassName: local-storage
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
Create the PersistentVolumeClaim:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  storageClassName: local-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 512Mi
We can use kubectl to check the status of existing PVs and PVCs:
kubectl get pv
kubectl get pvc
Create a pod to consume storage resources using a PVC:
kind: Pod
apiVersion: v1
metadata:
  name: my-pvc-pod
spec:
  containers:
  - name: busybox
    image: busybox
    command: ["/bin/sh", "-c", "while true; do sleep 3600; done"]
    volumeMounts:
    - mountPath: "/mnt/storage"
      name: my-storage
  volumes:
  - name: my-storage
    persistentVolumeClaim:
      claimName: my-pvc

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:00:00

Practice Exam
Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:30:00

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:30:00

Hands-on Labs are real live environments that put you in a real scenario to practice what you have learned without any other extra charge or account to manage.

01:30:00

Wrap-Up

Preparing for the Exam

00:03:55

Lesson Description:

In order to pass the CKAD exam, being well-prepared is important. In this video, I will provide some recommendations on how to use the course material to finish studying for the exam. I will point you toward some resources you may not have checked out yet, and I will offer some insight on what to focus on, in order to maximize the effectiveness of your study time. Be sure to read over all of the material on the official CKAD site, so that you are aware of everything you need to know before taking the exam.

Signing Up for and Taking the Exam

00:02:59

Lesson Description:

In his video, we will briefly discuss the process of signing up for and taking the exam. I will give you an idea of what to expect when going through the process, so that you will be prepared for success in earning your certification. You can find the CKAD exam site here: https://www.cncf.io/certification/ckad/ Using the official Kubernetes documentation while taking the exam is allowed: https://kubernetes.io/docs/

Exam Tips

00:06:43

Lesson Description:

In this video, I will share some tips to help you succeed while taking the CKAD exam. These are all things that I found useful when taking the exam myself! You can set up kubectl autocomplete like so:

source <(kubectl completion bash)

echo "source <(kubectl completion bash)" >> ~/.bashrc
The documentation for kubectl autocomplete can be found here: https://kubernetes.io/docs/reference/kubectl/cheatsheet/#kubectl-autocomplete

Next Steps

00:01:25

Lesson Description:

This is the end of the CKAD course, but your learning journey does not have to end here! In this video, we will discuss some other Linux Academy courses which you may be interested in if you want to learn more about Kubernetes and containers.