KIA CH02 First Steps with Docker and Kubernetes
Ch 2 notes for Kubernetes in Action. Key topics include: creating and sharing Docker container images, running a local single-node cluster via Minikube, configuring the kubectl CLI, and deploying/horizontally scaling a Kubernetes application.
Hi there.
Today, let us read the Chapter 02: First Steps with Docker and Kubernetes (Part I: Overview) of Kubernetes in Action
- Creating, running, and sharing a container image with Docker
- Running a single-node Kubernetes cluster locally, with Minikube
- Setting up and using the kubectl command-line client
- Deploying an app on Kubernetes and scaling it horizontally
busybox is a single executable that combines many of the
standard UNIX command-line tools, such as echo, ls, gzip, etc.
docker run command will download and run the container.
# docker run <image>:<tag>docker run busybox echo "Hello world"- Docker checks the presence of image
busybox:latestin local machine. (image = busybox, tag islatestby default)- If yes, continue to step 2
- If no, Docker pulls it from Docker Hub registry (locally stored layer will NOT be pulled)
- Docker creates a container from that image
- Docker runs the
echo "Hello world"command inside container
Then the app was executed inside a container, completely isolated from all the other processes running on your machine.
-
write the app Use the following code to start an HTTP server on port 8080, and then to reply with
"You've hit " + ${actual hostname of a server}and status code200 OK:// app.js - a demo Node.js appconst http = require('http');const os = require('os');console.log('kubia server starting...');var handler = function (request, response) {console.log('Received request from ' + request.connection.remoteAddress);response.writeHead(200);response.end("You've hit " + os.hostname() + '\n');};var www = http.createServer(handler);www.listen(8080); -
write Dockerfile
A Dockerfile is a text file that contains all the commands to build a given image. And in the Dockerfile, each individual command creates a new layer. The topmost layer a Dockerfile created will be tagged as latest.
Use the following Dockerfile to package the app into an image:
FROM node:7ADD app.js /app.jsENTRYPOINT ["node", "app.js"]- the
FROMto define the base image(image as a starting point) - the
ADDto add yourapp.jsfile from your local directory into the root directory in the image, creating a new layer on top of the base image - the
ENTRYPOINTcommand denotes that commandnode app.jswill be executed upon starting the image, thereby creating an additional layer on top of the newly created layer, which will then be tagged as latest.
- the
-
build the container image
use “
docker build” command to build the container image out of Dockerfile by pulling/creating layers:Terminal window docker build -t kubia .- image name:
kubia - where is the Dockerfile located: ‘
.’ (the current working directory)
Use “
docker images” to list the newly built Docker image:REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE kubia latest d30ecc7419e7 1 minute ago 637.1 MB - image name:
-
run the container
Use “
docker run” to run the imageTerminal window docker run --name kubia-container -p 80:8080 -d kubia- name of container is
kubia-container, started from image namedkubia -d: container is detached from console-p 80:8080: the container’s internal port8080is mapped to port80on the host- the ‘kubia’ app can thus be accessed by
http://localhost:80
Use “
docker ps” to list running containersCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 44d76963e8e1 kubia:latest ”/bin/sh -c ‘node app.js’ 6 minutes ago Up 6 minutes 0.0.0.0:80->8080/tcp kubia-container Use “
docker inspect” to see detailed info about the docker container in JSONUse “
docker exec” to run the shell inside the containerTerminal window docker exec -it kubia-container /bin/bash-i: makes sure STDIN is kept open-t: allocates a pseudo terminal (TTY)
Now that the app is running inside the container
44d76963e8e1, we can find it by runningps aux.- isolated process tree
- PID Linux namespace
- processes running in the container are running in the host OS, but with different process ID (PID)
- isolated filesystem
- name of container is
-
stops and removes a container Use “
docker stop” to stop a dockerTerminal window docker stop kubia-containerUse “
docker rm” to remove the container that still exists in “docker ps -a” commandTerminal window docker rm kubia-container
To make the local image (e.g., the image built in section 2.1.4) available to others, we need to push the image to an external image registry.
- private Docker Registry
- Docker Hub Registry
- Google Artifact Registry
- Red Hat Quay.io
There are 3 steps to push image to registry
-
Tag an image
Use “
docker tag” to create an additional tag for the same imageTerminal window docker tag kubia ${yourDockerRegistryID}/kubia -
Log into Docker Registry
Use “
docker login” to log into the Docker Hub Registry, or other Registries by:Terminal window docker login -u username ${DockerRegistryURL} -
Push the image Use “
docker push” to push image to RegistryTerminal window docker push ${yourDockerRegistryID}/kubia
Minikube is a tool that sets up a single-node cluster for both testing Kubernetes and developing apps locally.
The minikube documentation provides detailed installation guide. For example, I will use Debian package in x64-based Ubuntu Linux:
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube_latest_amd64.debsudo dpkg -i minikube_latest_amd64.deb-
start a Kubernetes cluster with Minikube
Terminal window minikube start -
display cluster info
Terminal window minikube kubectl -- cluster-infoto explore inside cluster, use
minikube sshto log into the Minikube VM with SSH
kubectl is a command line tool for communicating with control plane of a Kubernetes cluster, using the Kubernetes API.
Use kubectl to list all nodes in the cluster
- “
kubectl cluster-info”: to show basic information about a Kubernetes cluster - “
kubectl get nodes”: to show the most basic information for the listed objects - “
kubectl describe node ${nameOfNode}”: to show the status of a specific node, including CPU and memory data, system information, containers running on the node, etc.
Kubernetes uses Pod to deal with a group of containers (rather than dealing with individual containers directly)
- same pod: containers running on the same logical machine
- different pod: containers running on the different logical machines, even these containers are running on the same worker node
Each pod behaves like a separate independent machine with its own IP address and hostname.
Use “kubectl get pods” to show basic info about pods, and use “kubectl describe pod”.
This section require experiments on cloud platform, and the minikube may not fit this section, because the minikube does not support “LoadBalancer” service.
Use “kubectl create deployment” to create a deployment
kubectl create deployment kubia --image=${YourDockerRegistryId}/kubia --port=8080# (deprecated): kubectl run kubia --image=${YourDockerRegistryId}/kubia --port=8080 --generator=run/v1The diagram shown below is about how a container runs in Kubernetes:
- what happens behind the scene:
- kubectl will create a new ReplicationController object in the cluster, by sending a REST HTTP request to the Kubernetes API server
- ReplicationController then creates a new pod
- Scheduler schedules the new pod to one of the worker nodes
- kubelet of the scheduled worker node instructs Docker to pull image from registry if the specified image is not available locally
- Docker creates and runs the container
There are 4 types of services:
- ClusterIP: A regular service, just like the pod, is only accessible from inside the cluster.
- NodePort
- LoadBalancer: creating an external load balancer, and allowing external access to the pod via the public IP
- Note: Minikube does NOT support LoadBalance service
- ExternalName
And this section mainly covers how to use LoadBalancer service to allow external access of the Node.js app:
- Use “
kubectl create” to create a LoadBalancer service
kubectl expose deployment kubia --type=LoadBalancer --name kubia-http# (deprecated): kubectl expose rc kubia --type=LoadBalancer --name kubia-http- minikube does NOT support LoadBalance service, so the “EXTERNAL-IP” of command “
kubectl get services” will always bepending. "Replication Controller"has been deprecated in newer version of kubectl
-
Use “
kubectl get services” command to see the newly created Service object- cluster IP
- external IP
- port
- age
-
Access the service via external IP
There are 2 views of the system:
- Physical view
- Worker nodes (or nodes)
- Control Plane (Master) node(s)
- Logical View
- Pods
- each pod has its unique private IP address
- ReplicationControllers
- replicate pods to the exactly number of replicas(by default: 1 replica).
- monitor and keep pods running
- creating a new pod to replace the missing one
- Services
- expose multiple pods at a single constant
<IP, port>pair - offer a static IP to forward user requests to pods, regardless of IP addresses of pods
- expose multiple pods at a single constant
- Pods
To scale up the number of pods:
-
use “
kubectl get rc” or “kubectl get replicationcontrollers” to get the number of replicasNAME DESIRED CURRENT AGE kubia 1 1 17m DESIRED: the number of pod replicas you want the ReplicationController to keepCURRENT: the actual number of pods currently running
-
use “
kubectl scale rc kubia --replicas=3” command to increase theDESIREDreplica count ofkubiato 3- inspect with “
kubectl get rc”NAME DESIRED CURRENT READY AGE kubia 1 1 2 17m - inspect with “
kubectl get pods”NAME READY STATUS RESTARTS AGE kubia-hczji 1/1 Running 0 7s kubia-iq9y6 0/1 Pending 0 7s kubia-4jfyf 1/1 Running 0 18m
- inspect with “
In general, there is no need to care about which worker node a pod is scheduled to, yet there is still a way to find out:
-
use “
kubectl get pods -o wide” command to show list pods with IP and worker node-o wideoption is used to display additional columns based on “kubectl get pods” command
-
use “
kubectl describe pod kubia-hczji” command to check which worker node the podkubia-hczjiis scheduled to.
Kubernetes dashboard allows you to list all the Pods, ReplicationControllers, Services, and other objects deployed in your cluster, as well as to create, modify, and delete them.
Use “minikube dashboard” to open Kubernetes Dashboard in browser.
# 1) start Minikube Dashboardminikube dashboard
# 2) add proxy to allow external access (outside VM where Minikube is installed)kubectl proxy --port=8001 --address='0.0.0.0' --accept-hosts='^.*' &Then dashboard can be accessed by:
http://${YourVmAddress}:8001/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/In this chapter, there are mainly two topics:
- how to run a app in Docker, and then package it into a Docker Image
- how to use Kubernetes with Minikube and kubectl
- single node Kubernetes cluster
- scaling the Kubernetes cluster
- one control plane node
- three worker nodes
| Original | Abbreviation |
|---|---|
| pods | po |
| replication controller(deprecated) | rc |
| services | svc |
best practice about alias in Linux terminal:
# use `k` instead of `kubectl`alias k=kubectlNote: if you use k instead of kubectl, you should execute the following commands to enable command autocompletion:
# 1) allow command completion for `kubectl`source <(kubectl completion bash)
# 2) allow command completion for `k`source <(kubectl completion bash | sed s/kubectl/k/g)