Why set up speed on day one
You will type kubectl thousands of times, and in the Kubernetes admin exam in your plan (15.1) you get 2 hours for 15-20 practical tasks. It does not test whether you know Kubernetes; it tests how fast you can make it do things. So you set up a small "speed kit" now, and every lab from here on becomes practice. This lesson also teaches the one shape almost every kubectl command has, so new commands stop looking like noise.
What you need to know already: the cluster and kubectl (15.1), aliases and type (1.9), environment variables (2.21), ~/.bashrc, heredocs and process substitution <( ) (6.8, 6.18), YAML (11.31).
The speed kit: five lines
$ alias k=kubectl
$ export do="--dry-run=client -o yaml"
$ export now="--force --grace-period=0"
$ source <(kubectl completion bash)
$ complete -o default -F __start_kubectl k
Line by line:
alias k=kubectl-know meanskubectl. Everyk ...in this course is akubectl ....export do=...- a variable holding two flags, so$doexpands to--dry-run=client -o yaml.--dry-run=client= "build the object but do not send it to the cluster";-o yaml= "print it as YAML". Together: generate a file instead of creating the thing. More on this below.export now=...-$now=--force --grace-period=0: delete without waiting for the program inside to shut down cleanly (the SIGTERM grace period from 3.18). Saves 30 seconds per delete in the exam; dangerous in production.source <(kubectl completion bash)-kubectl completion bashprints a bash script that teaches Tab how to complete kubectl commands (typek get pothen Tab).<( )is process substitution: bash runs the command and hands its output tosourceas if it were a file (6.8).complete -o default -F __start_kubectl k- completion is tied to the command word. The script above registered its function (__start_kubectl) only for the wordkubectl. This line registers the same function fork. Forget it and Tab does nothing afterk.
To make them survive new shells, append them to ~/.bashrc and run source ~/.bashrc. Check them with:
$ type k
k is aliased to `kubectl' # (bash's own `quoting' style)
$ complete -p k
complete -o default -F __start_kubectl k
(type says what a word means to bash; complete -p k prints the completion rule for k.)
Objects, kinds and resource types
Before the grammar, three words you will see everywhere:
- An object is one record stored in the cluster, describing one thing: one pod, one node.
kubectl getlists objects;kubectl applycreates or changes them. - Its kind is what sort of object it is:
Pod,Node,Deployment... (capitalised, singular - it is thekind:line in YAML). - The resource type is the plural lowercase name you type on the command line for that kind:
pods,nodes,deployments.
You will meet many kinds in this chapter. You don't need to know them yet, but so the examples below make sense:
| kind | in one line | taught in |
|---|---|---|
| Pod | a running container (or a few that belong together) | 15.14 |
| Deployment | "keep N identical pods running, and update them one by one" | 15.16 |
| ReplicaSet | the helper a Deployment uses to keep the count at N | 15.16 |
| StatefulSet | like a Deployment, for databases: stable names and disks | 15.19 |
| DaemonSet | one pod on every node | 15.22 |
| Job / CronJob | run to completion / run on a schedule | 15.24 |
| ConfigMap / Secret | settings and passwords handed to pods | 15.29, 15.33 |
| Namespace | a named folder that groups objects | 15.26 |
| Service | a stable address in front of pods | Ch 16 |
The grammar
Almost every kubectl command is:
kubectl <verb> <type> [<name>] [flags]
k get pods web-7d9f -n shop -o wide
- verb - what to do:
get(list),describe(show details),create,apply,delete,logs,exec... - type - which resource type:
pods,nodes,deployments... - name - one object by name; leave it out to mean "all of that type".
- flags - options. The two you use most:
-n shop= in namespaceshop(without it: the namespace calleddefault);-o wide= output with extra columns.
Type and name can also be written as one word, type/name, which is what kubectl itself prints. k create deployment web --image=nginx:1.27 --replicas=3 creates a Deployment called web running 3 copies of the nginx:1.27 image:
$ k create deployment web --image=nginx:1.27 --replicas=3
deployment.apps/web created
$ k get deploy web # same as
$ k get deploy/web # same as
$ k get deployments.apps web
deploy is a short name for deployments; .apps is its API group (below).
Several types at once, comma-separated, no spaces:
$ k get deploy,rs,pods
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/web 3/3 3 3 8s
NAME DESIRED CURRENT READY AGE
replicaset.apps/web-vf2s9shm74 3 3 3 7s
NAME READY STATUS RESTARTS AGE
pod/web-vf2s9shm74-65fv5 1/1 Running 0 7s
...
One Deployment made one ReplicaSet, which made three pods (you will read every column of these tables in 15.14 and 15.16; for now: 3/3 = 3 of 3 wanted are ready, AGE = how long ago it was created).
Types, short names, groups: api-resources
kubectl api-resources lists every resource type this API server knows:
$ k api-resources
NAME SHORTNAMES APIVERSION NAMESPACED KIND
configmaps cm v1 true ConfigMap
namespaces ns v1 false Namespace
nodes no v1 false Node
pods po v1 true Pod
services svc v1 true Service
daemonsets ds apps/v1 true DaemonSet
deployments deploy apps/v1 true Deployment
replicasets rs apps/v1 true ReplicaSet
statefulsets sts apps/v1 true StatefulSet
cronjobs cj batch/v1 true CronJob
jobs batch/v1 true Job
...
| column | means |
|---|---|
| NAME | the resource type you type in full |
| SHORTNAMES | the abbreviation: po, deploy, svc, cm, ns, no, sts, ds, cj |
| APIVERSION | the API group and version, written in a manifest's apiVersion: line. Core types are just v1; the rest are group/version: Deployments are apps/v1, never v1 |
| NAMESPACED | true = the object lives inside a namespace. false = cluster-wide (nodes, namespaces themselves...); -n is ignored for those |
| KIND | the kind: you write in a manifest |
An API group is just a family of related types (apps for workloads, batch for Jobs); it lets the API grow without name clashes.
$ k api-resources --namespaced=false # only the cluster-wide types
$ k api-resources --api-group=apps # only one group
Field docs without leaving the terminal: explain
Every object in YAML has fields (spec.replicas, spec.template...). kubectl explain prints the built-in documentation for any field path. The exam allows the official docs, but finding a field in a browser costs a minute; explain costs five seconds:
$ k explain deployment.spec.strategy
GROUP: apps
KIND: Deployment
VERSION: v1
FIELD: strategy <DeploymentStrategy>
DESCRIPTION:
The deployment strategy to use to replace existing pods with new ones.
FIELDS:
rollingUpdate <RollingUpdateDeployment>
Rolling update config params. Present only if DeploymentStrategyType =
RollingUpdate.
type <string>
Type of deployment. Can be "Recreate" or "RollingUpdate". Default is
RollingUpdate.
The path is the kind, then the fields separated by dots. The word in angle brackets tells you the YAML shape of the value:
| shape | in YAML |
|---|---|
<string>, <integer>, <boolean> | a single value: name: web, replicas: 3, paused: true |
<Object> or a named type like <DeploymentStrategy> | a nested block of more fields |
<[]Container> | a list (lines starting with - ) of objects |
<map[string]string> | free key: value pairs |
-required- marks mandatory fields. --recursive prints the whole subtree as an indented outline - the fastest way to recall a deep path.
Manifests: generate them, don't write them
A manifest is a YAML file describing one or more objects - what you give to kubectl apply -f file.yaml. Every manifest has the same four top-level parts:
apiVersion: v1 # API group/version (from api-resources)
kind: Pod # what sort of object
metadata: # its name, labels, namespace...
name: nginx
spec: # what you want it to be
...
Writing one from memory under time pressure is how typos happen. kubectl has generators - k run (a Pod) and k create <kind> - that build a correct object from flags. Add $do and they print YAML instead of creating anything:
$ k run nginx --image=nginx:1.27 $do
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
name: nginx
spec:
containers:
- image: nginx:1.27
name: nginx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
k run nginx --image=nginx:1.27 = "a pod named nginx running image nginx:1.27". The generator added a label run: nginx (a name tag, 15.26), named the container after the pod, and some harmless noise (creationTimestamp: null, resources: {}, status: {}) you can leave in or delete. The generators you will use most:
k run NAME --image=IMG $do # Pod
k create deployment NAME --image=IMG --replicas=3 $do # Deployment
k create job NAME --image=IMG $do -- CMD ARGS # Job
k create cronjob NAME --image=IMG --schedule='*/5 * * * *' $do -- CMD
k create configmap NAME --from-literal=K=V $do
k create secret generic NAME --from-literal=K=V $do
k expose deployment NAME --port=80 --target-port=8080 $do # Service
Everything after a lone -- is the command the container runs. Then > file.yaml, edit the file, and k apply -f file.yaml.
Output formats you will use every day
-o wide more columns (IP and NODE for pods)
-o yaml | -o json the full object as the API stores it
-o name pod/web-7d9f..., for piping into other commands
-o jsonpath='{...}' extract single fields (15.38)
-o custom-columns=A:.x,B:.y your own table (15.38)
--show-labels add a LABELS column
-l app=web only objects with label app=web
-A all namespaces (short for --all-namespaces)
-w keep watching and print a line on every change (Ctrl+C stops)
A mistake to make once and remember: -o yaml on a command that returns several objects gives you a wrapper, kind: List, with the objects under items:; on one named object it gives the object itself. That matters when you extract fields later (15.38).
What you can now do:
- set up
k,$do,$nowand Tab completion fork - read any kubectl command as verb / type / name / flags
- find a type's short name, group and scope, look up any field with
explain, and generate a manifest instead of typing it