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!