Kubernetes - Container as a Service

Quick Reference

Kubernetes
Containers
Published

December 4, 2024

Modified

January 2, 2025

Overview

Kubernetes aka K8s …manage containerized workloads and services

  • …supports declarative configuration …automates deployment
  • …runs on virtual and physical environments …on-premise & public clouds
  • …reference infrastructure for cloud-native1˒2 applications
  • Benefits of the Kubernetes architecture…
    • service discovery …networks, devices, service, metadata, etc
    • storage orchestration …decouple storage allocation from back-ends
    • …container run-time agnostic …use any OCI compliant container engine
    • …provider agnostic …no vendor lock-in to a specific IaaS
    • …productivity …enables fast deployment CI/CD & DevOps

What can be difficult with Kubernetes?

  • Hard multi-tenancy…
    • …options for cluster-level sharing are available
    • …however difficult where the tenants do not trust each other
    • …typically each tenant is hosted a dedicated cluster instance
  • Most deployments are virtual …and run on a cloud infrastructure
    • …many use-cases & examples specific to cloud providers
    • …bare-metal deployment not widely used …hence more challenging to build

Architecture

Control plane …manages worker nodes & pods in the cluster…

  • …usually runs distributed over multiple nodes (fault-tolerance, highly-available)
  • Control plane components …global decisions about the cluster:
    • API server
      • …core component server …exposes the Kubernetes API
      • …runs several instances of kube-apiserver to scale horizontally
    • Cluster Storage
      • …consistent and highly-available key value store
      • etcd3 …uses Raft consensus algorithm
      • …data is consistently replicated across multiple nodes
      • …supports built-in snapshots for backup
    • Scheduler
      • kube-scheduler …basically assigns pods to nodes
      • …monitors cluster resources …uses various policies for placement
    • Controllers …manage the cluster state
      • kube-controller-manager …runs individual controller processes
      • …different controllers for nodes, jobs, services, etc.

Worker nodes host pods that house containerized applications…

  • …provide the Kubernetes run-time environment
  • Components that run on every node:
    • kubelet4 …primary “node agent”
      • …works in terms of a PodSpec …YAML/JSON object describing a pod
      • …ensures that pods are running and healthy
    • kube-proxy (optional) …connects pods with a network
      • …uses the OS packet filter …otherwise forwards the traffic itself
      • …other network plugins implement CNI (Container Network Interface)
    • Container run-time …Kubernetes CRI (Container Runtime Interface)

Pods

Smallest deployable compute object in Kubernetes…

  • …workloads run inside a pod …pods represents a set of running containers
  • Pod life-cycle in multiple phases…
    • Pending ready for scheduling …not started yet
    • Running pod bound to a node …containers created
    • Succeeded pod containers terminated in success (no restart)
    • Failed container terminated in failure (non-zero status)
    • Unknown pod state could not be obtained
  • Container states inside a pod…
    • Waiting …running operations to complete startup
    • Running …container is executing without issues
    • Terminated …container ran to completion or failed for some reason

Create and manage pods with kubectl run5:

# Create and run a particular image in a pod...
kubeclt run #...

# ...list pods in the cluster
kubectl get pods

# …remove a pod after exit
kubectl delete pods $pod_name

Interactive

Start an interactive container…

kubectl run busybox --image=busybox --restart=Never --stdin --tty
# ...clean up
kubectl delete pods busybox
  • --image …container image to use
  • --stdin & --tty …or -it for short
    • …allocate a terminal for each container
    • …keep stdin open (even if empty)
  • --restart=Never …pod should never be restarted
kubectl run ubuntu-bash --image=ubuntu --restart=Never -it --rm -- /bin/bash
  • --rm automatically remove pod after exit
  • -- command to execute in the container (include options & arguments)

Execute Program

Execute a program in the container…

pod_name=perl-pi
kubectl run $pod_name --image=perl --restart=OnFailure \
        -- perl -Mbignum=bpi -wle 'print bpi(2000)'

# check state of a pods containers
kubectl describe pod $pod_name

# check logs
kubectl logs $pod_name

Objects

Kubernetes objects

  • …are persistent entities in the Kubernetes system
  • After an object is created…
    • …system will constantly work to ensure that the object exists
    • …effectively tells Kubernetes the desired state
  • An object includes two nested object fields:
    • …object spec describes the desired state for the object
    • …object status describes the actual state of the object

The spec format is described in the Kubernetes API6

kubectl api-resources                 # list supported resources
kubectl explain $object               # describe associated fields
kubectl explain $object --recursive   # list all possible fields and subfields
kubectl explain $object.metadata      # get details on fields

Address fields with JSON path identifier <type>.<fieldName>[.<fieldName>]

Imperative Commands

Imperative commands (fail if a resource exists already)

# run an instance of the nginx container by creating a deployment object
kubectl create deployment nginx --image nginx

# create the objects defined in a configuration file
kubectl create -f nginx/deployment.yaml

# update the objects defined in a configuration file
# note: dropping all changes to the object missing from the configuration file
kubectl replace -f nginx/deployment.yaml

Declarative Commands

Declarative commands …work on existing resources…

  • …create, update, and delete operations are automatically detected per-object
  • …retains changes, even if the changes are not in the object configuration file
# apply changes
kubectl apply -f nginx/
# see what changes are going to be made
kubectl diff -f nginx/
# use option -R for recursive directory decent

Namespaces

Mechanism for isolating groups of resources within a single cluster

  • …scoping is applicable only for namespaced objects
  • …divide cluster resources between multiple users (via resource quota)
  • Namespaces default for new clusters without first creating a namespace
# list current namespaces
kubectl get namespace

# set the namespace for a current request
kubectl <...> --namespace=$name

# set namespace preference
kubectl config set-context --current --namespace=$name
# ...to unset
kubectl config set-context --current --namespace='' 

Labels & Annotations

Labels are key/value pairs to specify identifying attributes of objects

  • …used to organize and to select subsets of objects
  • …each key must be unique for a given object
  • …common set of labels allows tools to work interoperable
  • …labels without a prefix are private to users

Labels are defined in the metadata.labels object:

apiVersion: v1
kind: Pod
metadata:
  # ...
  labels:
    environment: prod
    name: mariadb
    component: database
    part-of: slurm
#...
# list objects with a given label
kubectl get <...> -l 'component=database,part-of=slurm'
kubectl get <...> -l 'environment in (prod,dev)'

# list all labels of an object
kubectl get <...> -o json | jq .metadata.labels

Shared labels/annotations have a common prefix <prefix>/<name>

  • <prefix> (optional) needs to be a valid DNS subdomain
  • <name> arbitrary property name of the label

Annotations attach arbitrary non-identifying metadata to objects

Workloads

Workload objects represents a higher abstraction level than a Pod

  • Job …one-off tasks that run to completion and then stop
  • CronJob …one-time Jobs on a repeating schedule
  • Deployment …manage stateless application workload
  • StatefulSet …persistent storage & unique network identity
  • DaemonSet …local to a specific node
    • …performs a role similar to a system daemon
    • …facilities to enhance the container platform

Jobs

job_name=hello
cat > $job_name.yml <<EOF
apiVersion: batch/v1
kind: Job
metadata:
  name: $job_name
spec:
  template:
    spec:
      containers:
      - name: hello
        image: busybox
        command: ["echo", "Hello, World!"]
      restartPolicy: OnFailure
EOF

# create job (if not existing)
kubectl create -f $job_name.yml

# inspect job state
kubectl get jobs $job_name
kubectl describe jobs $job_name

# print the logs
kubectl logs job/$job_name

# clean up
kubectl delete job $job_name

Run the parallel job example:

job_name=sleep-parallel
cat > $job_name.yml <<EOF 
apiVersion: batch/v1
kind: Job
metadata:
  name: $job_name
spec:
  completions: 6
  parallelism: 2
  template:
    spec:
      containers:
      - name: sleep
        image: busybox
        command: ["sleep",  "60"]
      restartPolicy: Never
EOF
kubectl create -f $job_name.yml

# watch the status of pods created
kubectl get -w pods -l job-name=$job_name

# clean up
kubectl delete -f $job_name.yml
  • completions number of pods to complete
  • parallelism number of pods to run in parallel

Cronjob

job_name=hello
cat > $job_name.yml <<EOF
apiVersion: batch/v1
kind: CronJob
metadata:
  name: $job_name
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            command: ["echo", "Hello, World!"]
          restartPolicy: OnFailure
EOF

# start & inspect
kubectl create -f $job_name.yml
kubectl get cronjob $job_name

# list periodically created pods
kubectl get pods | grep ^$job_name

# clean up
kubectl delete cronjob $job_name

Deployment

A deployment7 is a higher-level concept that manages ReplicaSets

  • ReplicaSets manage a number of Pod replicas and their life-cycle
  • It provide rollback functionality and update control

Download nginx-deployment.yaml Kubernetes example:

kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
# inspect the deployment
kubectl get deployments

# see the ReplicaSet created by the Deployment
kubectl get kubectl get replicaset

# list the pods (using a label)
kubectl get pods -l app=nginx

Rolling update incremental replacement of multiple pods

  • …no downtime …network traffic load-balanced to available pods
  • …facilitates CI/CD deployments …support rollback to previous version
# update pods to a new container version
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1

# check the revisions of this Deployment
kubectl rollout history deployment/nginx-deployment

# undo the current rollout and rollback to the previous revision
kubectl rollout undo deployment/nginx-deployment

Scaling an application on demand…

  • …increase the number of pods to a desired state
  • …supports (horizontal) autoscaling depending to load
# scale a deployment
kubectl scale deployment/nginx-deployment --replicas=5

# remove a deployment
kubectl delete deployment nginx-deployment

Storage

Long-term & temporary storage for pods…

  • Container storage is ephemeral (aka temporary)…
    • …data created/modified during lifetime is lost
    • …restart boots a container with clean state
  • Volumes8 (directory accessible to the container)
    • …many types of volumes …pods can use multiple types simultaneously
    • …mount at the specified paths within the container
    • Ephemeral volumes …have the lifetime of a pod
    • Persistent volumes …exist beyond the lifetime of a pod

Example

An emptyDir volume is created when a pod is assigned to a node…

  • …deleted when the pod is removed
  • …user for temporary scratch space
  • safe across container crashes
  • …on storage local to the worker node
pod_name=emptydir-example
cat > $pod_name.yml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: $pod_name
spec:
  volumes:
    - name: opt
      emptyDir: {}
  containers:
    - name: container-one
      volumeMounts:
        - name: opt
          mountPath: /opt
      image: alpine
      command: ["/bin/sh"]
      args: ["-c", "sleep 10000"]
    - name: container-two
      volumeMounts:
        - name: opt
          mountPath: /opt
      image: alpine
      command: ["/bin/sh"]
      args: ["-c", "sleep 10000"]
EOF

Create a pod with containers sharing /opt

kubectl create -f $pod_name.yml

# write a file into the mounted volume from the first container
kubectl exec $pod_name -c container-one -- cp /etc/hostname /opt

# read the file from the second container
kubectl exec $pod_name -c container-two -- cat /opt/hostname

kubectl delete pod $pod_name

Storage Classes

Storage Classes are an abstraction layer over the underlying storage infrastructure

  • Define properties/behavior of PVs, quality-of-service levels, (backup) policies
  • Enable automatic provisioning of storage characteristics…
    • …type of the storage (for example SSD, HDD)
    • …access modes (read-only, read-write, etc.)
kubectl get sc

CSI (Container Storage Interface) volume plugins…

  • …enable storage vendors to create custom storage plugins
  • …uses the csi volume type to attach or mount the volumes

Persistent Volumes

Persistent Volumes9 (PV) are a way to abstract and represent physical or networked storage resources

Why use persistent volumes?

  1. Data persistence vital to stateful applications and databases
  2. Abstraction of the back-end storage
    • …allows to manage storage resources independently
    • …enables admins control utilization and optimization of storage hardware
  3. Access control to ensure data integrity and security

Persistent Volume Claims (PVC) request storage resources for pods

  • Used to specific requirements to the storage resource
  • …independent of the internals of the storage provider
  • Ensures a volume ‘claim’ to be portable across numerous back-ends
  • Isolates storage-related concerns from the workload
example.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-storage
spec:
  capacity:
    storage: 500Mi 
  # Indicating that this PV is intended for file-based storage
  volumeMode: Filesystem
  # Can be mounted as read-write by a single node at a time
  accessModes:
    - ReadWriteOnce
  # Data is retained even if the associated PVC is deleted
  # …requires to be removed manual for cleanup
  persistentVolumeReclaimPolicy: Retain
  # Associates to a particular StorageClass
  storageClassName: local-storage
  # Specify the actual location on the host machine
  hostPath:
    path: /srv

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: example-claim
spec:
  # can be mounted as read-write by a single node at a time
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      #  request minimum storage capacity
      storage: 200Mi 
  # associates with a StorageClass
  storageClassName: local-storage

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
        # mount volumes to the container
        volumeMounts:
        # which volume to mount
        - name: example-nginx-storage
          # where to mount the volume inside the container
          mountPath: /usr/share/nginx/html
      # define volumes available to the pod
      volumes:
      - name: example-nginx-storage
        persistentVolumeClaim:
          claimName: example-claim
kubectl apply -f example.yml
# check ...clean up
kubectl get -f example.yml
kubectl delete -f example.yml