Kubernetes is the dominant technology for infrastructure today, and that means sysadmins need to be familiar with administering it. I have been managing Kubernetes clusters every day for years now, and I picked up a few tricks that I highly recommend for others looking to simplify their admin experience.
I created this cheat sheet to share the key notes about kubectl and the commands I use daily to keep clusters up and running. It's broken up into sections to help you gauge whether or not you should use them for certain tasks. I also included some flags in both long-form and shorthand to help get you fluent with them more quickly.
Get, create, edit, and delete resources with kubectl
The safest place to start with a command-line utility is to ask questions (read operations) rather than give commands (write operations). The helpful get commands can get you rolling.
Kubectl get
Use get to pull a list of resources you have currently on your cluster. The types of resources you can get include:
- Namespace
- Pod
- Node
- Deployment
- Service
- ReplicaSets
Each of these provides details about the available resources in the cluster. As an example, here's the output of the get nodes command, which provides a version of Kubernetes in usage and status.
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready master 9d v1.18.0
Most of these commands have shortened versions. To get the namespaces, you can run kubectl get namespaces or kubectl get ns (see the cheat sheet for the full list):
$ kubectl get ns
NAME STATUS AGE
charts Active 8d
default Active 9d
kube-node-lease Active 9d
kube-public Active 9d
kube-system Active 9d
Each get command can focus in on a given namespace with the –namespace or -n flag. I use especially help when you want to review the pods in kube-system, which are the services needed to run Kubernetes itself.
$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-66bff467f8-mjptx 1/1 Running 2 9d
coredns-66bff467f8-t2xcz 1/1 Running 2 9d
etcd-minikube 1/1 Running 1 9d
kube-apiserver-minikube 1/1 Running 1 9d
kube-controller-manager-minikube 1/1 Running 2 9d
kube-proxy-rpc9d 1/1 Running 1 9d
kube-scheduler-minikube 1/1 Running 2 9d
storage-provisioner 1/1 Running 1 9d
Kubectl create
Now that we've gathered some resources, let's create some more. With kubectl, you can create nearly any type of resource in a cluster. Some of these resources do require configuration files and namespaces to set the resource to, as well as names. Resources you can create include:
- service
- cronjob
- deployment
- job
- namespace (ns)
So, for example, create namespace requires another parameter to name the namespace.
$ kubectl create ns hello-there
namespace/hello-there created
We can also create continuously running jobs with cron like many Linux friends will be familiar with. Here we use cronjob to echoes "hello" every five seconds.
$ kubectl create cronjob my-cron --image=busybox --schedule="*/5 * * * *" -- echo hello
cronjob.batch/my-namespaced-cron created
You can also use the shortened version, cj, rather than cronjob.
$ kubectl create cj my-existing-cron --image=busybox --schedule="*/15 * * * *" -- echo hello
cronjob.batch/my-existing-cron created
Kubectl edit
So, what happens when we've created something, and we want to update? That's where kubectl edit comes in.
You can edit any resource in your cluster when you run this command. It will open your default text editor. So we'll edit our existing cron job, can we run:
$ kubectl edit cronjob/my-existing-cron
This shows our configuration to edit.
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: batch/v1beta1
kind: CronJob
metadata:
creationTimestamp: "2020-04-19T16:06:06Z"
managedFields:
- apiVersion: batch/v1beta1
fieldsType: FieldsV1
fieldsV1:
f:spec:
f:concurrencyPolicy: {}
f:failedJobsHistoryLimit: {}
f:jobTemplate:
f:metadata:
f:name: {}
f:spec:
f:template:
f:spec:
f:containers:
k:{"name":"my-new-cron"}:
.: {}
f:command: {}
f:image: {}
f:imagePullPolicy: {}
The schedule is set to every 15 seconds:
We will change it to every 25 seconds and write to the resource:
Once we write it, we can see it was changed.
$ kubectl edit cronjob/my-existing-cron
cronjob.batch/my-existing-cron edited
If we want to use a different editor, we can override that by adding by using this KUBE_EDITOR syntax.
$ KUBE_EDITOR="nano" kubectl edit cronjob/my-existing-cron
Kubectl delete
So far, we have done everything short of removing it altogether, so that is what we are going to do next. The cronjob we just edited was one of two cronjobs, so now we're just going to delete the whole resource.
$ kubectl delete cronjob my-existing-cron
cronjob.batch "my-existing-cron" deleted
As a warning, you should never just delete something you don't know all the information about. Once the resource is deleted, there's no recovering it; you will have to recreate it, so think twice before you run this command.
Kubectl apply
Earlier, I mentioned that some commands will require configuration files. The apply command allows you to apply configurations via files for resources within your cluster. This can also be done through standard in (STDIN) on the command line, but the suggestion is always by file.
I consider this command to be a little more advanced, as you need to know how to use your cluster and what kind of configuration file to apply to it. For this example, I am using the role-based access control (RBAC) config from Helm for a service account.
$ kubectl apply -f commands.yaml
serviceaccount/tiller created
clusterrolebinding.rbac.authorization.k8s.io/tiller created
You can apply just about any configuration you want, but you will always need to know for sure what it is you're applying, or you may see unintended outcomes.
Troubleshooting Kubernetes with kubectl
Kubectl describe
Describe shows the details of the resource you're looking at. The most common use case is describing a pod or node to check if there's an error in the events, or if resources are too limited to use.
Resources you can describe include:
- Nodes
- Pods
- Services
- Deployments
- Replica sets
- Cronjobs
In this example, we can describe the cronjob currently in the cluster from our previous examples.
$ kubectl describe cronjob my-cron
Snippet:
Name: my-cron
Namespace: default
Labels: <none>
Annotations: <none>
Schedule: */5 * * * *
Concurrency Policy: Allow
Suspend: False
Successful Job History Limit: 3
Failed Job History Limit: 1
Starting Deadline Seconds: <unset>
Selector: <unset>
Parallelism: <unset>
Completions: <unset>
Pod Template:
Labels: <none>
Containers:
my-cron:
Image: busybox
Port: <none>
Host Port: <none>
Kubectl logs
While the describe command gives you the events occurring for the applications inside a pod, logs offer detailed insights into what's happening inside Kubernetes in relation to the pod. Understanding this distinction allows you to troubleshoot issues happening inside the application and inside Kubernetes because they are not always the same problem.
$ kubectl logs cherry-chart-88d49478c-dmcfv -n charts
Snippet:
172.17.0.1 - - [19/Apr/2020:16:01:15 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-"
172.17.0.1 - - [19/Apr/2020:16:01:20 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-"
172.17.0.1 - - [19/Apr/2020:16:01:25 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-"
172.17.0.1 - - [19/Apr/2020:16:01:30 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-"
172.17.0.1 - - [19/Apr/2020:16:01:35 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-"
172.17.0.1 - - [19/Apr/2020:16:01:40 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-"
172.17.0.1 - - [19/Apr/2020:16:01:45 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-"
172.17.0.1 - - [19/Apr/2020:16:01:50 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-"
172.17.0.1 - - [19/Apr/2020:16:01:55 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-"
You can also remove extra noise or look for another event by using grep with this command. The kube-probe can be noisy, so let's filter it out with grep.
$ kubectl logs cherry-chart-88d49478c-dmcfv -n charts | grep -vie kube-probe
127.0.0.1 - - [10/Apr /2020:23:01:55 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0" “-”
Since some deployments have multiple containers within a pod, you can also use the -c <container name> with your logs to only look in one specific container for logs.
Kubectl exec
Much like the docker exec command, you can also exec into a container to troubleshoot an application directly. This is useful when the logs from the pod haven't provided you an answer to the issues you may be debugging. When using the exec command, the end of the line must always provide which shell you are using within the pod.
$ kubectl exec -it cherry-chart-88d49478c-dmcfv -n charts -- /bin/bash
root@cherry-chart-88d49478c-dmcfv:/#
Kubectl cp
This command is for copying files and directories to and from containers, much like the Linux cp command. It is not something you will use every day, but it is my personal favorite for pulling or restoring backups in an emergency when automation is failing.
Here's an example of copying a local file to a container. The syntax follows a kubectl cp <filename> <namespace/podname:/path/tofile> format:
$ kubectl cp commands_copy.txt charts/cherry-chart-88d49478c-dmcfv:commands.txt
$ kubectl exec -it cherry-chart-88d49478c-dmcfv -n charts -- /bin/bash
root@cherry-chart-88d49478c-dmcfv:/# ls
bin boot commands.txt dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
Here is another example, but this time pulling a file to our local machine from a container. The syntax is kubectl cp <namespace/podname:/path/tofile> format:
$ kubectl cp charts/cherry-chart-88d49478c-dmcfv:commands.txt commands_copy.txt
$ ls
commands_copy.txt
Download the kubectl cheat sheet
There are a lot of little commands that are helpful to have around as a Kubernetes administrator. I hope this cheat sheet comes in handy for you!
6 Comments