Lab Exercises for Workloads & Scheduling

Exercise 0 - Setup

Exercise 1 - Understand deployments and how to perform rolling update and rollbacks

  1. Create a deployment object consisting of 6 pods, each containing a single nginx:1.19.5 container
  2. Identify the update strategy adopted by this deployment
  3. Modify the update strategy so maxSurge is equal to 50% and maxUnavailable is equal to 50%
  4. Perform a rolling update to this deployment so that the image gets updated to nginx1.19.6
  5. Undo the most recent change
Answer - Imperative
kubectl create deployment nginx --image=nginx:1.19.5 --replicas=6
kubectl describe deployment nginx | grep StrategyType
kubectl patch deployment nginx -p "{\"spec\": {\"strategy\": {\"rollingUpdate\": { \"maxSurge\":\"50%\"}}}}" --record=true
kubectl patch deployment nginx -p "{\"spec\": {\"strategy\": {\"rollingUpdate\": { \"maxUnavailable\":\"50%\"}}}}" --record=true
kubectl set image deployment nginx nginx=nginx:1.19.6 --record=true
kubectl rollout undo deployment/nginx
Answer - Declarative
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  replicas: 6
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.19.5
        ports:
        - containerPort: 80
kubectl describe deployment nginx (unless specified, will be listed as "UpdateStrategy")

patch.yaml contents:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  strategy:
      rollingUpdate:
        maxSurge: 50%
        maxUnavailable: 50%
  template:
      spec:
        containers:
            - name: nginx
              image: nginx:1.19.6
kubectl patch deployment nginx --patch-file=patch.yaml
kubectl rollout undo deployment/nginx

Exercise 2 - Use ConfigMaps to configure applications

  1. Create a configmap named mycm that has the following key=value pair
    1. key = owner
    2. value = yourname
  2. Create a pod of your choice, such as nginx. Configure this Pod so that the underlying container has the environent varibale OWNER set to the value of this configmap
Answer

Create configmap:

kubectl create configmap mycm --from-literal=owner=david

Define Pod:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-configmap
spec:
  containers:
    - name: nginx-configmap
      image: nginx
      command: [ "/bin/sh", "-c", "env" ]
      env:
        # Define the environment variable
        - name: OWNER
          valueFrom:
            configMapKeyRef:
              # The ConfigMap containing the value you want to assign to SPECIAL_LEVEL_KEY
              name: mycm
              # Specify the key associated with the value
              key: owner

Validate:

kubectl logs nginx-configmap | grep OWNER
OWNER=david

Exercise 3 - Use Secrets to configure applications

  1. Create a secret named mysecret that has the following key=value pair
  2. dbuser = MyDatabaseUser
  3. dbpassword = MyDatabasePassword
  4. Create a pod of your choice, such as nginx. Configure this Pod so that the underlying container has the the following environment variables set:
  5. DBUSER from secret key dbuser
  6. DBPASS from secret key dbpassword
Answer
kubectl create secret generic mysecret --from-literal=dbuser="MyDatabaseUser" --from-literal=dbpassword="MyDatabasePassword"

Apply the following manifest:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-secret
spec:
  containers:
  - name: nginx-secret
    image: nginx
    command: [ "/bin/sh", "-c", "env" ]
    env:
      - name: dbuser
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: dbuser
      - name: dbpassword
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: dbpassword
  restartPolicy: Never

Which can be validated with:

kubectl logs nginx-secret | grep db                                                  
dbuser=MyDatabaseUser
dbpassword=MyDatabasePassword

Exercise 4 - Know how to scale applications

  1. Create a deployment object consisting of 3 pods containing a single nginx container
  2. Increase this deployment size by adding two additional pods.
  3. Decrease this deployment back to the original size of 3 pods
Answer - Imperative
kubectl create deployment nginx --image=nginx --replicas=3
kubectl scale --replicas=5 deployment nginx
kubectl scale --replicas=3 deployment nginx
Answer - Declarative

Apply initial YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
      app: nginx
spec:
  replicas: 3
  selector:
      matchLabels:
        app: nginx
  template:
      metadata:
        labels:
            app: nginx
      spec:
        containers:
            - name: nginx
              image: nginx
              ports:
                - containerPort: 80

Apply modified YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1
        ports:
        - containerPort: 80

Apply original YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

Excerise 5 - Understand how resource limits can affect Pod scheduling

  1. Create a new namespace called "tenant-b-100mi"
  2. Create a memory limit of 100Mi for this namespace
  3. Create a pod with a memory request of 150Mi, ensure the limit has been set by verifying you get a error message.
Answer
kubectl create ns tenant-b-100mi

Deploy the manifest:

apiVersion: v1
kind: LimitRange
metadata:
  name: tenant-b-memlimit
  namespace: tenant-b-100mi
spec:
  limits:
  - max:
      memory: 100Mi
    type: Container

Test with deploying:

apiVersion: v1
kind: Pod
metadata:
  name: default-mem-demo
  namespace: tenant-b-100mi
spec:
  containers:
  - name: default-mem-demo
    image: nginx
    resources:
      requests:
        memory: 150Mi

Which should return:

The Pod "default-mem-demo" is invalid: spec.containers[0].resources.requests: Invalid value: "150Mi": must be less than or equal to memory limit