Skip to content

Intro to Kubernetes

  • Originally Written : July, 2021

Kubernetes, often referred to as K8s, is an open-source platform designed to automate the deployment, scaling, and management of containerized applications. It groups containers that make up an application into logical units for easy management and discovery. Initially developed by Google based on their experience of running applications at scale, Kubernetes is now maintained by the Cloud Native Computing Foundation. It provides the flexibility of running applications on public cloud platforms, private clouds, or on-premise servers, making it a popular choice for organizations implementing a multi-cloud strategy. It's built to work with a range of container tools, including Docker.

Kubernetes is often referred to as K8s as a form of abbreviation where numbers are used to shorten a word. In this case, the number 8 stands for the eight letters between the "K" and "s" in Kubernetes. You might also see i18n for Internationalization, l10n for Localization, and o11y for Observability.

Kubernetes Overview

In the next few exercises we will explore some of the key concepts behind Kubernetes, starting with building a cluster. This lab starts with the basics and often overlooked topics in the order I wish I started with. e.g. how to access a cluster

Pre-requisities

If you intend to run this lab on your own machine you should have the following installed

  • Git
  • Minikube
  • Docker Desktop
  • kubectl

Labs

  1. Starting Minikube
  2. Introduction to kubectl
  3. Starting a Pod - kubectl run
  4. Self-healing Kubernetes (not a lab)
  5. Outsourcing (not a lab)
  6. Kubernetes Resources (not a lab)
  7. Deploying an app - kubectl apply
  8. Stateless vs Stateful Apps
  9. Kubernetes Storage (not a lab)
  10. Troubleshooting
  11. Stopping Minikube

Getting Started

If you are using Killercoda you will not need to use the minikube tunnel command. Make sure to look at the instructions for the Killercoda kubectl port-forward command

  • Clone the lab repository to your local machine
git clone https://github.com/conmurphy/kubernetes-hands-on

Setting up minikube

Minikube is an open-source tool that makes it easy to run Kubernetes locally on your machine. It runs a single-node Kubernetes cluster inside a virtual machine on compute, making it ideal for you to try out Kubernetes or develop and test containerized applications.

cd kubernetes-hands-on
  • If you haven't already, follow the instructions from the Minikube website to install and start Minikube

https://minikube.sigs.k8s.io/docs/start/

Info

Remember to start Docker Desktop if using docker as driver

  • Start Minikube and set the CNI flag to Calico
minikube start --driver=docker --network-plugin=cni --cni=calico --nodes=2
  • Wait for all system pods to be in the Running 1/1 state
kubectl get pods -n kube-system

Introduction to kubectl

You can interact with Kubernetes via CLI tool, Kubectl which would be installed on your local machine. Kubectl talks to the Kubernetes API. When starting Minikube, kubectl will automatically be configured to connect to the minikube cluster using the kubeconfig file.

The kubectl command-line tool uses kubeconfig files to find the information it needs to choose a cluster and communicate with the API server of a cluster

https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/

The default local for kubeconfig is ~/.kube/config

A Kubernetes cluster is made up of a number of control plane and worker nodes.

Kubernetes Nodes

  • View the Kubernetes nodes that make up the cluster
kubectl get nodes
  • View more details using the -o wide flag
kubectl get nodes -o wide
  • Describe the nodes to see more details
kubectl describe nodes
  • You can also describe an individual node (or other Kubernetes resource) using the node name found in the kubectl get nodes command.
kubectl describe node <node-name>

Info

Namespaces are a logical way to group resources in a cluster into separate spaces

  • Take a look at which namespaces exist by default in a Minikube cluster
kubectl get namespaces

Info

Pods are the smallest deployable units of computing that you can create and manage in Kubernetes. They contain one or more containers.

  • View the pods in the default namespace by using the -n <namespace name> flag
kubectl get pods -n default
  • If you don't specify a namespace, the kubectl comma will apply to the default namespace
kubectl get pods
  • If you want to search all namespaces you can use the -A flag
kubectl get pods -A
  • View all the Kubernetes system pods which implement the Kubernetes functionality
kubectl get pods -n kube-system -o wide

Starting a Pod - kubectl run

  • You can start a pod using the kubectl run command and the format kubectl run NAME --image=image where NAME is what you want to call your pod and image is the name of the image you want to run
kubectl run firstpod --image=oguzpastirmaci/hostname
  • Confirm the pod is running
kubectl get pods

Killercoda

To make this pod accessible from outside the cluster, you need to port-forward.

kubectl port-forward firstpod 8000:8000 --address 0.0.0.0

Minikube

To make this pod accessible from outside the cluster, you need to create a service.

kubectl expose pod firstpod --port=8000 --type=LoadBalancer
  • Check the Kubernetes service has been created. You should see the EXTERNAL-IP is in <pending> status
kubectl get svc

Minikube has built-in functionality to allow you to access this traffic from the local machine.

  • Open a new terminal/cmd instance
minikube tunnel
  • You might have to wait a few seconds before the tunnel is established. There will be no dynamic output.

  • You should see Starting tunnel for service firstpod which indicates the tunnel was established.

  • Confirm that the service was created and and an EXTERNAL-IP was assigned. You may see 127.0.0.1 as the IP address

kubectl get service


This simple app displays the hostname of the container you are connected to. Since you only have one right now, this won't change when refreshing the page.

  • You can now observe the resources
kubectl get pods
kubectl describe pod firstpod
kubectl get services
kubectl describe service firstpod
  • Clean up the app resources
kubectl delete service firstpod
kubectl delete pod firstpod
  • Confirm that the resources have been removed
kubectl get all

Self-healing Kubernetes

Kubernetes possesses a self-healing property that always tries to ensure that the required number of pods are always running and available. Traffic will only be sent to those resources that are available. This applies not only to pods but many other resources including nodes.

This is known as a control loop and the functionality is implemented by the relevant controller (e.g. node controller). Scroll up to the system pods and notice again there exists a kube-controller-manager pod which embeds the core control loops.

You may have seen the Ready and Restarts fields when viewing the output of a pod. This is Kubernetes watching the state of a cluster, and attempting to move the current state closer to the desired state (i.e. the number of pods required vs the number in a ready state).

Outsourcing

Kubernetes orchestrates pods running across multiple nodes, however it doesn't do this alone. Some functionality such as networking, storage, and actually running a container is outsourced to third party applications. It achieves this through:

  • Container Networking Interface or CNI plugin for networking
  • Container Storage Interface or CSI plugin for provisioning underlying storage
  • Container Runtime Interface or CRI interface for creating pods

You have already seen two of these when starting Minikube. The CNI Calico and CRI Docker. Calico configures the routing table, IP Address Management, and any tunnels or bridges to permit forwarding.

When you deploy a new pod, Kubernetes tells Docker to start a new container matching the specifications you desire. Docker then manages the lifecycle (start, stop, delete) of those containers.

There are many CRI, CSI, and CNIs available, each with their own advantages and disadvantages

Kubernetes Resources

So far you've seen the Kubernetes Pod however Kubernetes also provides many more resources. Here are a few examples.

You've also seen the concept of a namespace which allows you to segment resources. You can apply security policies to namespaces to achieve Role Based Access Control.

Deploying an app - kubectl apply

Although you can create and manage resources such as pods through the kubectl command directly, in a real world environment you may want to store this configuration in a file. You can then apply the configuration to the cluster using the kubectl apply -f <my-configuration>.yaml command.

The resources that you require can be defined in one or more YAML files. YAML, which stands for "YAML Ain't Markup Language," is another human-friendly data serialization standard that is often used in configuration files and in applications where data is being stored or transmitted.

When you first see a Kubernetes YAML configuration file it can be overwhelming, however there is a common structure.

Tip

You can use the -o yaml flag to output in YAML so you don't need to create these files by hand.

Alternatively you can find an example on https://kubernetes.io and use it as a starting point.

This section will again deploy the hostname application (with 2 replicas) but the settings will be stored in a configuration file rather than from the command line.

  • Change the directory into the demo04 folder
cd demo04
  • Look through the files in the folder hostname-namespace.yaml hostname-deployment.yaml hostname-service.yaml

  • Apply the configuration

kubectl apply -f hostname-namespace.yaml
kubectl apply -f hostname-deployment.yaml
kubectl apply -f hostname-service.yaml
  • You can look at individual resources or all resources together
kubectl get all -n hostname
  • Confirm that two pods are running
kubectl get pods -n hostname

Info

Your minikube tunnel session should still be open for this. Start a new one if it is closed, or if it is not working within a few seconds.

In a separate terminal window run minikube tunnel

  • Take note of the address and port the app is running on.
kubectl get services -n hostname
  • In your browser open localhost on the port you see in the service we just created

  • Refresh the page on your browser (ctrl/cmd + shift + r) to show change between pods.

Info

Every now and then the hostname should change to show that the LoadBalancer is directing traffic to a new Pod. Caching mechanisms might prevent the page from refreshing properly to see the hostname change.

  • If you don't see the hostname change and both hostname pods are running, try curl http://localhost:port in your Terminal to see the LoadBalancing mechanism switch between the pods.
curl http://localhost:port
  • Edit the hostname-deployment.yaml file to have 3 replicas

  • Change the number next to replicas: to 3 and save the file

  • Update the configuration on your cluster

kubectl apply -f hostname-deployment.yaml

You should see an output: deployment.apps/hostname configured

  • Confirm that three pods are now running
kubectl get pods -n hostname
  • Cleanup the resources
kubectl delete -f hostname-namespace.yaml

Warning

Deleting a namespace will delete all resources within it (it might take some time as the pods terminate)

  • Confirm that the resources have been removed
kubectl get all -n hostname

Kubernetes Networking

Since this lab doesn't cover Kubernetes networking concepts in details here are two additional resources on how Kubernetes networking is implemented.

Kubernetes Storage

There are a few important storage related points to be aware of when working Kubernetes

  • On-disk files in a container are ephemeral
  • Container state is not saved
  • When a container crashes or is stopped all files that were created or modified during the lifetime of the container are lost
  • During a crash, Kubernetes restarts the container with a clean state

Warning

Don’t forget your to save your work by using persistent volumes!

Stateless vs Stateful Apps

Stateful Sets are like a deployment but:

  • Provides guarantees about the ordering and uniqueness of Pods.
  • Maintains a sticky identity for each of its Pods
  • Each has a persistent identifier that it maintains across any rescheduling.
  • Identifiers make it easier to match existing volumes to new Pods that replace any that have failed

Let's now deploy a stateful application and observe what happens when pods are deleted

  • Change directory into demo05
cd demo05
  • Look at message-board-all-in-one.yaml

  • Apply the configuration

kubectl apply -f message-board-all-in-one.yaml
  • Check the resources were created
kubectl get all -n message-board
  • Watch the resources as they're created by using the -w flag
kubectl get pods -n message-board -w
  • Wait for the pod to be running

  • Once the pods are running, press ctrl + c to go back.

Killercoda

First update the message-board-all-in-one.yaml. Change the from storageClassName: standard to storageClassName: local-path

To make this pod accessible from outside the cluster, you need to port-forward.

kubectl port-forward -n message-board deployment/message-board 5000:5000 --address 0.0.0.0

Info

Your minikube tunnel session should still be open for this. Start a new one if it is closed, or if it is not working within a few seconds.

In a separate terminal window run minikube tunnel

  • Open localhost:5000

  • Sign up to the message board, log in, and write a message

  • Refresh the page and confirm that the message still remains

  • Delete the pod, confirm it was deleted and that a new one is starting

kubectl delete pod -l name=message-board -n message-board
kubectl get pods -n message-board
  • Reload the page

  • Confirm that the message is still there.

Info

This is because the message was saved in a Persistent Volume, which gets attached to the pod.

  • Cleanup the resources
kubectl delete -f message-board-all-in-one.yaml
  • Confirm that the resources have been removed
kubectl get all -n message-board

Troubleshooting

This last section will provide and introduction into some common errors you may see when deploying applications to a Kubernetes cluster. It is by no means and extensive list of errors or troubleshooting steps.

Following Pod Logs

  • If the minikube tunnel from previous sections was closed then open a new one
minikube tunnel
  • Create a new Nginx pods
kubectl create deployment --image nginx my-nginx
  • Confirm the pod is running
kubectl get pods

Killercoda

To make this pod accessible from outside the cluster, you need to port-forward.

kubectl port-forward firstpod 30001:80 --address 0.0.0.0

Minikube

To make this pod accessible from outside the cluster, you need to create a service.

kubectl expose deployment my-nginx --port=30001 --target-port=80 --type=LoadBalancer

Access a browser on http://localhost:30001 and refresh the page a couple of times. You should see the Nginx welcome page

  • Watch the Nginx logs as you access a browser
kubectl logs deployment/my-nginx --follow`
  • Go back to your terminal and confirm you can see the logs updating as you refresh the page

  • Cleanup the resources

kubectl delete deployment my-nginx
  • Confirm that the resources have been removed
kubectl get all

Troubleshooting Image and Storage Errors

  • Change directory into demo06
cd demo06
  • Look at message-board-all-in-one-troubleshooting.yaml

  • Apply the configuration

kubectl apply -f message-board-all-in-one-troubleshooting.yaml
  • Check if the pods have started
kubectl get pods -n message-board

Question

If the pod is not in running status check the events for any errors. What do you find?

kubectl describe pods -n message-board
  • Check the storage has been provisioned
kubectl get persistentvolumeclaim -n message-board

Question

If the status is pending check the events for errors. What do you find?

kubectl describe pvc -n message-board
  • Cleanup the resources
kubectl delete -f  message-board-all-in-one-troubleshooting.yaml -n message-board
  • Confirm that the resources have been removed
kubectl get all -n message-board

Stopping Minikube

  • If you are finished with the lab you can stop the cluster
minikube stop
  • This stops the minikube cluster, but retains the state for when you start the cluster again via minikube start.

  • To completely delete the cluster you can run minikube delete

Resources

Official Kubernetes.io CheatSheet Page


Last update: February 12, 2024