Kubectl Commands: Efficient Kubernetes Cluster Administration

Oct 11, 2023 • 9 min

In this article, we’ll explore how to manage Kubernetes clusters with the official command-line tool, kubectl.

We’ll delve into the primary commands and also touch upon some advanced kubectl commands that might be unfamiliar!

To start, kubectl is a blend of the words Kubernetes and control. It’s a tool that allows communication with the Kubernetes API to create, modify, read, or even delete resources from our Kubernetes cluster.

For those needing a refresher, I suggest revisiting our introductory article on Kubernetes.

ℹ️ Fun fact before we get started, there are many ways to pronounce “kubectl”. Some say “cube control”, others “kube cuddle”, and yet others might prefer “kube ktl”. There’s no consensus, but at Enix, we lean towards the first version. Pick your favorite!

Installing Kubectl

Kubectl is compatible with Linux, Mac, and Windows platforms. Each OS has its distinct installation method, detailed in the Kubernetes documentation.

Enabling Auto-Completion

Once kubectl is installed, just follow these steps (the same for all supported OS). Ensure the bash-completion package is installed.

source <(kubectl completion bash) # set up auto-completion in the current bash shell.
echo "source <(kubectl completion bash)" >> ~/.bashrc # set up auto-completion in your bash shells permanently.

You can also use an alias that works with auto-completion.

alias k=kubectl
complete -F __start_kubectl k

With that set up, let’s dive in! 🎉

Kubectl Config and Kubeconfig File

Before accessing a cluster’s resources, it’s essential to set up the context and ensure proper access to the desired cluster. The first step is to create a configuration file ~/.kube/config containing the connection information for your various clusters. This file can be manually edited or via the kubectl commands outlined in the aforementioned documentation.

Multiple contexts can be created within a single kubeconfig file.

To activate a context, use the command kubectl config use-context <CONTEXT_NAME>.

ℹ️ Some tools like kubie simplify contexte management, especially with the easy use of multiple kubeconfig files. It makes adding a new entry much easier, especially when the ~/.kube/config file is already dense.

Kubectl Command Format

Kubectl Syntax

kubectl [command] [TYPE] [NAME] [flags]

The kubectl command blueprint is intuitive:

  • The first argument is the action to be executed on a resource.
  • The TYPE argument corresponds to the resource type targeted by the action. The name can be singular, plural, or uabbreviated (e.g. sts for statefulset). The kubectl api-resources command can list available resource types in a cluster.
  • The NAME argument corresponds to the name of the Kubernetes resource targeted by the desired action
  • Various flags can be appended.

Some commands don’t target explicitly resources, like the kubectl version command, which doesn’t take any additional parameters.

Kubectl Output and Formatting

Kubectl provides various output formatting options. The -o flag, for example, allows you to choose the output format from several options, including json, yaml, or a more detailed column display than the default using the wide format.

Advanced options such as custom-columns or jsonpath are available but won’t be covered in this introductory article.

kubectl [command] [TYPE] [NAME] -o <output_format>

It’s common to use the jq utility to rework the json format output. For example, you can list all our Kubernetes pods and the number of volumes on these pods with this very handy, albeit long, command:

$ kubectl get pods -A -o json | \
jq -r '.items[] | [.metadata.name, (.spec.volumes | length)] | @tsv' | \
column -t -s $'\t'
cattle-node-agent-z9df5 6
kube-api-auth-xcwc5 2
cert-manager-6d6bb4f487-q25lp 1

A bit tricky to read/write, right? 🥵 Fortunately, in many cases, you can simplify by using the -o custom-columns flag, for example, to display the owner of a resource in addition to the base columns:

$ kubectl get pod -o custom-columns=\
NAME:.metadata.name,\
OWNER-KIND:.metadata.ownerReferences[0].kind,\
OWNER-NAME:.metadata.ownerReferences[0].name
NAME                     OWNER-KIND   OWNER-NAME
my-rs-6fb78fd4c8-pql9f   ReplicaSet   my-rs-6fb78fd4c8

Kubectl Commands

Essential kubectl commands

Let’s now delve into some frequently used commands. Starting with this very basic set of kubectl commands:

kubectl apply

kubectl apply -f ./deployment.yaml # create or update resources from a file

Remember, you can use multiple files simultaneously. For example, to create a group of resources: kubectl apply -f foo.yaml -f bar.yaml, or to apply a whole directory recursively: kubectl apply -f ./foobar. You can also apply resources directly from standard input with kubectl apply -f-.

kubectl create

kubectl create -f ./deployment.yaml # create resources from a file (the command fails if the resource already exists)

kubectl get pods

kubectl get pods [...pod_name] # list a type of resource; you can specify an arbitrary number of resource names or leave the argument empty to list everything

kubectl delete pod

kubectl delete pod <pod_name> # destroy a resource

kubectl describe

Use kubectl describe to get detailed information about a resource, especially events related to it.

kubectl describe <TYPE> [...NAME] # displays essential information about a resource

kubectl logs

kubectl logs <pod_name> <container_name> # displays logs from a container

Kubectl and namespaces

Now, we know how to seamlessly interact with our Kubernetes resources. However, by default, these commands run in the current namespace.

To select another namespace, add to your kubectl command the --namespace flag or its abbreviation -n, followed by the namespace name. You can also use the kubie tool I mentioned earlier with the kubie ns <NAMESPACE> command, which sets your context to execute all subsequent commands in a given namespace.

And to perform your action across all namespaces (usually used to quickly list all resources of the same type), use the --all-namespaces flag or its abbreviation -A.

kubectl port-forward

This kubectl command can be particularly useful for debugging.

kubectl port-forward <pod_name> [LOCAL_PORT:]REMOTE_PORT # exposes the REMOTE_PORT of the pod on our LOCAL_PORT

Advanced kubectl commands

Now, let’s explore some more advanced kubectl operations.

kubectl --watch

Let’s begin with Kubectl commands tailored for resource observation. We’ll use the --watch flag:

kubectl get pods --watch # "watches" a resource

kubectl get pods --watch --output-watch-events # "watches" a resource and additionally displays the type of event received (ADDED, MODIFIED, DELETED…)

Using both the --watch and --output-watch-events flags lets you observe in real-time all changes made to a resource type and the type of change made. Surprisingly, these two flags, in addition to the -o json flag, allow you to write a Kubernetes operator in bash 🤯. Yes, it sounds crazy, but it’s true. This technique is notably used in Jérôme Petazzoni’s nsplease project.

kubectl explain

A very useful command when you’re writing a new resource you’re not familiar with is the explain command. It displays documentation for a resource type and its various fields.

For example, kubectl explain pods will explain the pod type, letting us know it consists of an apiVersion, a kind, metadata, spec, and finally a status. But we can delve deeper, for instance, by asking to explain an initContainer in a pod: kubectl explain pods.spec.initContainer. With this command, you won’t even need to search online for how to configure this custom resource defined by that complex, poorly documented operator you can’t do without 🥳 (provided the Custom Resource Definition in question is at least minimally documented). More info on operators and CRDs in our blogpost on Kubernetes (link given at the beginning of the article).

Generating templates with kubectl

Starting with a basic template can be helpful when creating a new resource. Fortunately, kubectl lets you generate pre-filled templates for various resource types.

For example, to create a deployment, you’d use kubectl create deployment my-nginx --image=nginx:1.21 --dry-run=client -o yaml. This performs a local dry-run and displays the result in yaml (i.e., the yaml that would have been applied if we hadn’t done a dry-run).

Each type is slightly different to configure, so you can consult the help to know the available and/or required flags and options (kubectl create <TYPE> –help or kubectl create --help to see the list of types available via this command).

kubectl wait

Lastly, I recommend this short article on the kubectl wait command, which is particularly useful, written by my cheerful colleague Antoine Millet 😉

Kubectl Plugins

Kubectl also offers a plugin interface. These plugins are created by the community and can vary widely. In this section, we’ll look at an example plugin with kubectl neat, then learn how to install a new plugin.

Kubectl Neat

A plugin I frequently use is kubectl neat. As the name suggests, its purpose is to produce a neat and clear output. The plugin filter out non-essential data when retrieving a resource’s configuration. The status, for example, is removed, and only the essential data needed to recreate the resource identically is retained. All temporary and redundant information is thus removed.

To use it, it’s straightforward: kubectl get pods -o yaml | kubectl neat. The plugin works on all resource types and both yaml and json formats.

Installing a Kubectl Plugin

Now that we understand the concept, let’s try installing this plugin! There are multiple methods, but the recommended method is to use the krew package manager. Interestingly, krew is a kubectl plugin in itself!

Let’s start by installing krew. I’d suggest following the steps described in the krew documentation.

Now that we have krew on our machine, all we have to do is update the plugin list (equivalent to an apt update) and then get the plugin installed.

kubectl krew update
kubectl krew install neat

Kubectl neat is now installed and can be used via the kubectl command-line or independently via the kubectl-neat binary.

kubectl get pods -o yaml | kubectl neat # via kubectl
kubectl get pods -o yaml | kubectl-neat # standalone (note the hyphen between kubectl and neat)

You can also get a list of available plugins: kubectl krew search (only those referenced via krew; some may not have been packaged). An exhaustive list, complemented by descriptions, is accessible on the official website.

Conclusion

There you have it! You’re now equipped to engage with your Kubernetes cluster directly via your CLI. We’ve seen that you can use kubectl to perform all basic administrative tasks on a cluster, as well as some more advanced operations.

Kubectl is very handy in many cases because it’s relatively simple and quick to use. However, if you manage k8s clusters all day long, a GUI tool might be more pleasant to use. In that case, tools like Lens or K9s are often preferred, offering roughly the same features as kubectl but through a GUI executable directly from your terminal or a web GUI. Of course, these tools will never completely overshadow kubectl, which remains the go-to tool for simple tasks and quick access.

It’s now time for you to masterfully navigate your Kubernetes clusters using kubectl commands. Wishing you smooth sailing! 😉


Do not miss our latest DevOps and Cloud Native blogposts! Follow Enix on Twitter!