Also at Deasil Works · txn2 · Plexara
Profiles GitHub · X · LinkedIn
Theme Light · Auto · Dark
Professional notes by Craig Johnston
long-form, short-form, working drafts · since 2008
VOL. XIX · MMXXVI
85 NOTES IN PRINT
FOLIO II 01 MAR 2018 · 6 MIN · SHORT-FORM

Kubernetes Overview

Container Orchestration & Microservices

Diagram · folio ii
mindmap
  root((Kubernetes basics))
    Workloads
      Pod
      Deployment
      StatefulSet
      DaemonSet
      Job
      CronJob
    Networking
      Service
      Ingress
      NetworkPolicy
      DNS
    Storage
      Volume
      PersistentVolume
      PersistentVolumeClaim
      StorageClass
    Config
      ConfigMap
      Secret
    Access
      Namespace
      RBAC
      ServiceAccount
    Tools
      kubectl
      kubeadm
      minikube
      helm

Getting started with Kubernetes for local development. I develop on a Mac, but most of this translates cleanly to Windows and Linux.

This started as my personal development notes, written to get co-workers up to speed quickly. If you spot an error, open an issue or a pull request.


§2026 Update

This post is from 2018, when a local cluster meant minikube on top of VirtualBox and Kubernetes was at v1.9. The mental model below has held up well: a cluster has nodes, a node runs pods, a pod runs containers. The core kubectl verbs still work the way they did. But the toolchain underneath moved enough that a few of the original commands will either fail or behave differently today. Here is what changed and what I run now.

The big one: kubectl run no longer creates a Deployment. As of Kubernetes 1.18 it creates a single Pod and nothing more. The generator flags that used to spin up a Deployment were removed. If you want something managed and replicated, use kubectl create deployment (shown below) or a YAML manifest. kubectl run is now for one-off pods, like a quick debug shell.

heapster is gone and metrics-server replaced it. The old minikube addons enable heapster no longer exists. For kubectl top and autoscaling metrics, enable metrics-server instead.

CoreDNS replaced kube-dns. Cluster DNS is served by CoreDNS now and has been the default for years. You will not see a kube-dns addon on a current minikube.

You no longer need VirtualBox. minikube defaults to the Docker driver on most machines, so a container runtime is usually all you need. You can still pick a driver explicitly with --driver (docker, podman, qemu, and others). The old VirtualBox path works but is no longer the default.

The sample images moved. Google retired gcr.io/google_containers. Images live under registry.k8s.io now, and the official hello-world tutorial uses agnhost instead of echoserver.

minikube is also no longer the only easy option. It is still a great choice and the most batteries-included. But the local-cluster field filled out: kind (built by the Kubernetes project to test Kubernetes itself), k3d (Rancher’s lightweight k3s wrapped in Docker, noticeably faster to start), Docker Desktop’s built-in Kubernetes, and Rancher Desktop (k3s with a GUI). If startup speed matters to you, k3d is hard to beat. If you want maximum fidelity to a “real” cluster, kind. For a guided, addon-rich experience, minikube. I still reach for minikube when I want the dashboard and addons without thinking about it.

The walkthrough below is updated to current commands. The original 2018 session is preserved at the end as a snapshot.


The article continues below. The 2026 Update above summarizes what changed; the walkthrough that follows has been updated to current commands.

§Deeper Reading and Resources

The Lynda courses I originally linked here are gone; Lynda became LinkedIn Learning. If you are paying for a course, check the publication date and the Kubernetes version it targets before you commit, the platform churns fast enough that a three-year-old course is mostly history.

§Prerequisites

VirtualBox is optional now and only needed if you specifically want the virtualbox driver.

§Spin Up a Local Cluster

# start a cluster using the default driver (Docker on most machines)
minikube start

# or name the driver explicitly
minikube start --driver=docker

# enable metrics so kubectl top works (heapster's replacement)
minikube addons enable metrics-server

# open the dashboard in a browser
minikube dashboard

§Check Cluster Status

These commands are unchanged from 2018 and still the first things I run:

# are we running a cluster?
kubectl cluster-info

# we should have a minikube node
kubectl get nodes

# resource usage (needs the metrics-server addon enabled)
kubectl top nodes

§Architecture

Read Kubernetes Basics for a fuller picture, but the short version still holds:

  • A Cluster has Nodes
  • A Node runs Pods
  • A Pod runs containers and mounts volumes

§Create a Deployment

Run a “hello world” using the current sample image. Note kubectl create deployment, not kubectl run, since we want a managed Deployment:

# create a Deployment from the official sample image
kubectl create deployment hello-node \
  --image=registry.k8s.io/e2e-test-images/agnhost:2.53 \
  -- /agnhost netexec --http-port=8080

# expose it as a NodePort service
kubectl expose deployment hello-node --type=NodePort --port=8080

# get a reachable URL
minikube service hello-node --url

Open the URL it prints. To tear it down:

kubectl delete service hello-node
kubectl delete deployment hello-node

§Useful Commands

CommandDescription
kubectl get pods -o wideGet information about all running pods in the default namespace
kubectl get pods -o wide --namespace=testGet information about all running pods in the test namespace
kubectl describe pod <pod>Describe one pod
kubectl expose pod <pod> --port=2701 --name=apiExpose the port of a pod (creates a new service)
kubectl attach <pod> -iAttach to a pod
kubectl exec <pod> -- commandExecute a command in the pod
kubectl label pods <pod> mylabel=funAdd a new label to a pod
kubectl run -i --tty alpine --image=alpine --restart=Never -- shRun a throwaway shell in a one-off pod

§Port Forwarding / Local Development

Check out kubefwd for a command line utility that bulk forwards services of one or more namespaces to your local workstation, so your local code can talk to in-cluster services by their real names.

§Original 2018 Walkthrough

Preserved as a snapshot. The versions and addon list below are historical, minikube was at v0.25 and Kubernetes at v1.9, the Docker driver did not exist yet, and heapster and kube-dns were still the defaults.

$ minikube version
minikube version: v0.25.0

$ minikube start
Starting local Kubernetes v1.9.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.
Loading cached images from config file.

$ minikube addons list
- addon-manager: enabled
- coredns: disabled
- dashboard: enabled
- default-storageclass: enabled
- efk: disabled
- freshpod: disabled
- heapster: disabled
- ingress: disabled
- kube-dns: enabled
- registry: disabled
- registry-creds: disabled
- storage-provisioner: enabled

# enable heapster for CPU and mem
$ minikube addons enable heapster
heapster was successfully enabled

# the original hello world, using the now-retired image registry
$ kubectl run hello-minikube --image=gcr.io/google_containers/echoserver:1.4 --port=8080
deployment "hello-minikube" created

$ kubectl expose deployment hello-minikube --type=NodePort
service "hello-minikube" exposed

$ minikube service hello-minikube --url
http://192.168.99.100:31923
← back to all notes