- 10:00 - 10:30: Introduction and Environment Setup
- 10:30 - 12:00: Containers Recap & Kubernetes Overview
- 12:00 - 12:15: Break
- 12:15 - 13:30: Kubernetes Objects & kubectl
- 13:30 - 14:30: Lunch Break
- 14:30 - 16:00: YAML, Namespaces, and Pods
- 16:00 - 16:15: Break
- 16:15 - 18:00: Events and Services
- I go (quickly) over the theory
- I solve an exercise
- you solve the exercise
- we go over and solve any encountered issue together so that everyone finishes the exercise
Hello, I'm Olimpiu!
- I've been programming and doing some sysadmining for the past ~20 years
- backend - python
- dev&ops @Eau we Web
- sysadmin & networking
- Kubernetes instructor @JSLeague
What about you?
- Technical background?
- Experience with Linux, terminal, Docker / containers, Kubernetes?
- Expectations from the workshop?
But first, a bit of history! The History of Virtualization and Containerization
A container is a sandboxed process running on a host machine that is isolated from all other processes running on that host machine. That isolation leverages kernel namespaces and cgroups, features that have been in Linux for a long time. Docker makes these capabilities approachable and easy to use. - Images and containers
A container runs natively on Linux and shares the kernel of the host machine with other containers. It runs a discrete process, taking no more memory than any other executable, making it lightweight. - [Containers and (vs.) virtual machines](https://docs.docker.com/guides/docker-concepts/the-basics/what-is-a-container/ #containers-versus-virtual-machines-vms)
To achieve isolation, (Docker) containers use the following Linux kernel features:
- namespaces: PID, MNT, NET, UTS (hostname), IPC
- control groups (
cgroups
): share available hardware resources and, if required, set up limits and constraints - memory, CPU, disk I/O - secure computing mode (
seccomp
): restrict the actions available within a container down to the granularity of a single system callDocker's default seccomp profile is a whitelist of calls that are allowed and blocks over 50 different syscalls. [...] The default bounding set of capabilities inside a Docker container is less than half the total capabilities assigned to a Linux process.
root
inside a container is different thanroot
on the host"
Kubernetes is a portable, extensible, open-source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation. It has a large, rapidly growing ecosystem. [...] The name Kubernetes originates from Greek, meaning helmsman or pilot. Google open-sourced the Kubernetes project in 2014. [...] Kubernetes provides the building blocks for building developer platforms, but preserves user choice and flexibility where it is important. - What is Kubernetes?
Kubernetes distributions:
- minikube, kind - development
- kubeadm, kubespray, rke, k3s - bare-metal clusters
- Rancher, Red Hat OpenShift - enterprise
- GKE, EKS, AKS - infrastructure provider-managed
- many others
Kubernetes components - drawing board time!
Kubernetes objects are persistent entities in the Kubernetes system. Kubernetes uses these entities to represent the state of your cluster. Specifically, they can describe:
- What containerized applications are running (and on which nodes)
- The resources available to those applications
- The policies around how those applications behave, such as restart policies, upgrades, and fault-tolerance - Understanding Kubernetes Objects
Object fields:
apiVersion
- Which version of the Kubernetes API you're using to create this objectkind
- What kind of object you want to createmetadata
- Data that helps uniquely identify the object, including aname
string,UID
, and optionalnamespace
spec
- What state you desire for the objectstatus
- Used by Kubernetes to report back the resource status
3. kubectl (Documentation)
kubectl
is a tool to interact with the Kubernetes API server from the command line.
Useful commands:
# get cluster info (not that useful)
kubectl cluster-info
# show all available resource types / API versions in the cluster
kubectl api-resources
kubectl api-versions
# get the list of resources
# available options:
# -A: get resources from all namespaces
# -n $name: get resources from namespace $name
# -o wide: show more details
# -w: watch for changes
# -l foo=bar: list resources which have label foo with value bar
# for more options run kubectl get --help
# replace $kind with the resource type, e.g. pod
kubectl get $kind
# get a single resource
# available options:
# -o yaml: show detailed yaml resource definition
kubectl get $kind $name
# get more details about a resource
kubectl describe $kind $name
# show resource fields documentation
# available options:
# --recursive: show the full field hierarchy
kubectl explain $kind[.$field[.$subfield[...]]]
# show kubectl config
kubectl config view
Explore the cluster using the commands above. Specifically, look for:
- Kubernetes version
- available resource types and API versions
- how many nodes, node details (Linux distro, CPU, memory etc.)
- namespaces, pods
- what fields does a
pod
'sspec
field have?
# control plane components versions
kubectl -n kube-system describe pod kube-apiserver-jsl-cp-0 | grep -i image
kubectl -n kube-system describe pod kube-controller-manager-jsl-cp-0 | grep -i image
kubectl -n kube-system describe pod kube-scheduler-jsl-cp-0 | grep -i image
kubectl -n kube-system describe pod etcd-jsl-cp-0 | grep -i image
# kubelet versions
kubectl get nodes -o wide
# resources and api versions
kubectl api-resources
kubectl api-versions
# node details
kubectl describe node jsl-cp-0
kubectl get namespaces
kubectl get pods -A -o wide
kubectl explain pod.spec [--recursive]
key: value
list:
- 'item 1'
- "item 2"
altIndentList:
- foo
- bar
number: 123
bool: true
listOfObjects:
- id: 1
name: foo
- id: 2
name: bar
multilineString: |
a very very very
very very very
long multiline string
Kubernetes supports multiple virtual clusters backed by the same physical cluster. These virtual clusters are called namespaces. - Namespaces
- provide a scope for names: names of resources need to be unique within a namespace, but not across namespaces
- Kubernetes starts with four initial namespaces:
default
,kube-system
,kube-public
,kube-node-lease
- if no namespace is set in the
kubectl
config,default
is used - some resource types are not namespaced (which is an obvious one? how can we find out which resources are namespaced and which are not?)
- they are not a security boundary by default (workloads in one namespace can access services in another)
Pods are the smallest deployable units of computing that can be created and managed in Kubernetes.
A Pod (as in a pod of whales or pea pod) is a group of one or more containers, with shared storage and network resources, and a specification for how to run the containers. A Pod's contents are always co-located and co-scheduled, and run in a shared context. A Pod models an application-specific "logical host" - it contains one or more application containers which are relatively tightly coupled. In non-cloud contexts, applications executed on the same physical or virtual machine are analogous to cloud applications executed on the same logical host. - Pods
For practical reasons we'll use one container per pod, but be aware that a pod can contain more than one containers.
-
Create a simple pod named
webserver
with one container using thenginx:1.28.0
image. -
Check that it's running, get its IP address and use
wget
to test that it's working. -
Check the pod logs.
Hints:
- to output a simple pod blueprint
(see
kubectl run $podName --image $imageSpec --dry-run=client -o yaml
kubectl run --help
) - to redirect the output of a command to a file use
command >filename
- to send resources from a YAML file to Kubernetes use
kubectl apply -f filename.yaml
- to get the pod IP use
kubectl get pods -o wide
- to get the pod logs use
kubectl logs $podName # follow logs kubectl logs -f $podName
- to output the
wget
response use# run this from a cluster node wget -qO- http://$ipAddress
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: webserver
name: webserver
spec:
containers:
- image: nginx:1.23.4
name: nginx
Create a new pod named debug
using the busybox:1.36.0
image, exec into it, and use wget
to access the nginx
pod.
Hints:
- use
command: ["sleep", "86400"]
to keep the pod running (seekubectl explain pod.spec.containers.command
) - to delete a pod use
kubectl delete pod $podName --grace-period 1
- to exec (run a shell) into a pod use
kubectl exec -it $podName -- /bin/sh
- to see a diff between Kubernetes state and an YAML file use
kubectl diff -f filename.yaml [ | cdiff]
# append to pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
labels:
run: debug
name: debug
spec:
containers:
- image: busybox:1.36.0
command: ["sleep", "86400"]
name: busybox
kubectl exec debug -- wget -qO- http://$webserverIP
Kubernetes events are objects that show you what is happening inside a cluster, such as what decisions were made by the scheduler or why some pods were evicted from the node. All core components and extensions (operators) may create events through the API Server. - Understanding Kubernetes cluster events
- are only kept for 1h by default
kubectl get events [-A] [-w] [--watch-only]
- related events are shown at the end of
kubectl describe
output
An abstract way to expose an application running on a set of Pods as a network service.
With Kubernetes you don't need to modify your application to use an unfamiliar service discovery mechanism. Kubernetes gives Pods their own IP addresses and a single DNS name for a set of Pods, and can load-balance across them. - Service
-
Expose the
webserver
pod using a service namedwebserver-svc
. -
Get its IP address and test that it works using
wget
(from thedebug
pod). -
Create another
webserver-2
pod similar towebserver
(use the same labels, so that it's selected by the service) and test that the service load-balances the requests by looking at the pods logs. -
Test that you can access the service using its DNS name (
webserver-svc
/webserver-svc.$username
). -
Make the service
NodePort
and try to access it from your computer:http://65.109.43.242.nip.io:$nodePort/
.
Hints:
- to get the blueprint for a service use
kubectl expose pod $podName --port $port --dry-run=client -o yaml
- to check the endpoints the service balances the traffic to use
kubectl describe service $serviceName
- to show the logs of multiple pods that match a label use
kail
kail -l $label=$value -n $username
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: webserver-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
run: webserver
# append to pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
labels:
run: webserver
name: webserver-2
spec:
containers:
- image: nginx:1.23.4
name: webserver-2
kubectl describe service webserver-svc
kubectl exec debug -- wget -qO- http://webserver-svc