9 kubectl commands sysadmins need to know

Download our new kubectl cheat sheet to learn helpful commands for the Kubernetes command-line utility.
220 readers like this.
Blender Hotkey Cheat Sheet


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
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
  creationTimestamp: "2020-04-19T16:06:06Z"
  - apiVersion: batch/v1beta1
    fieldsType: FieldsV1
        f:concurrencyPolicy: {}
        f:failedJobsHistoryLimit: {}
            f:name: {}
                    .: {}
                    f:command: {}
                    f:image: {}
                    f:imagePullPolicy: {}

The schedule is set to every 15 seconds:

kubectl schedule

We will change it to every 25 seconds and write to the resource:

kubectl schedule

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


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>
    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: - - [19/Apr/2020:16:01:15 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-" - - [19/Apr/2020:16:01:20 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-" - - [19/Apr/2020:16:01:25 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-" - - [19/Apr/2020:16:01:30 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-" - - [19/Apr/2020:16:01:35 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-" - - [19/Apr/2020:16:01:40 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-" - - [19/Apr/2020:16:01:45 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-" - - [19/Apr/2020:16:01:50 +0000] "GET / HTTP/1.1" 200 612 "-" "kube-probe/1.18" "-" - - [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 - - [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

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

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!

What to read next
User profile image.
Tech nomad, working in about anything I can find. Evangelist of silo prevention in the IT space, the importance of information sharing with all teams. Believer in educating all and open source development. Lover of all things tech. All about K8s, chaos and anything new and shiny I can find! Mastodon ID


Nice information

Excellent article!

One (small) nit pick: the exec command isn't _only_ to open a shell, you can one-off execute any command that pod/container has access to. In your example you're just executing `/bin/bash` in order to poke around and run other commands, but if you have some other program installed or script installed you can call just that, instead.

So let's say you have a command that runs a specific ops task that you haven't fully automated yet, your command might be:

kubectl exec -it cherry-chart-88d49478c-dmcfv -n charts -- /etc/path/to/script.sh

Which would just run the /etc/path/to/script.sh, putting all stdin/stdout to your terminal, and then it would exit when it's complete, instead of leaving open the terminal within the container.

Nice article! Isn’t your cronjob example ‘*/15 * * * *’ running every every 15 minutes rather than seconds or is cron different in Kubernetes?

This is a great article, but if I may make a suggestion, it would be awsome to be able to share links to specific parts of the content.

This can be achieved easily in HTML and is a great feature!

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.