Today, Kubernetes is the de facto container orchestration solution. Together with the devops culture, developers have to get familiarised to its tools, such as kubectl
.
After some point though, using kubectl
for everything can get quite verbose, especially if you use many namespaces and contexts. The following tips try to minimise the pain of doing operations solely through it, sometimes even using other tools beside it.
Kubectx: context and namespaces management
Operations done in kubectl
usually require two params: context and namespace. Any operation will result in something as kubectl --context dev --namespace hello-world exec -it hello-world-app-0 sh
. It is fine for a one-time operation, but after some point, it can get quite cumbersome. One way to avoid these long command strings is by using kubectx
.
After installing it, the context can be set by simply using kubectx dev
and the namespace as kubens hello-world
. To list the available contexts and namespaces, just run it without arguments. The above operation can be run by only using kubectl exec -it hello-world-app-0 sh
.
Terminal aliases
Seasoned Unix developers are quite used to terminal aliases. Some are quite popular that are even grouped in packs, such as oh-my-zsh git aliases. With Kubernetes is not that different.
Usually, having alias k="kubectl"
already make operations shorter. Using the same example, it would result in k exec -it hello-world-app-0 sh
. But, most likely, one alias will not be enough. There are some options for this.
The first one can be set-up in any terminal emulator (zsh
, bash
…). Get the .kubectl_aliases
file from ahmetb/kubectl-aliases
and place it in your home directory. After sourcing it on .zshrc
or .bashrc
, 600 aliases will be available out-of-box, including the aforementioned k
.
[ -f ~/.kubectl_aliases ] && source ~/.kubectl_aliases
If zsh
and oh-my-zsh
are already set-up, an easier option would be to use the pre-installed kubectl
plugin. To enable it, edit your .zshrc
and add kubectl
to the plugins
variable (more details about oh-my-zsh plugins here).
plugins=(git kubectl ...)
There are fewer aliases compared to ahmetb/kubectl-aliases
, making it easier to learn and faster to load. The list of oh-my-zsh/kubectl
aliases is available here
kubectx
and kubens
do not have aliases by default. To allow shorter calls for it, place the following on .zshrc
or .bashrc
.
alias kns="kubens"
alias kcx="kubectx"
After all these aliases been set-up, the hello-world-app-0 sh
can be accessed using a simple keti hello-world-app-0 sh
. As games, it will be as learning combat combos, although it will not be as close as a Hadouken combo.
Terminal namespace and context indicator
Developers are humans (in case you did not know) and humans do not have bulletproof memory. One can forget that kubernetes context is set to production and then run kubectl apply
there, instead of dev.
To avoid this, an indicator can be used in the terminal to show what is the actual context and namespace. The easiest way to do it is by using kube-ps1
. It already comes with oh-my-zsh
, requiring kube-ps1
to be added to .zshrc
plugins variable.
After installing or enabling it, the PS1 needs to be changed to include the kubectl context and namespace information. This can be easily done by adding export PS1='$(kube_ps1) '$PS1
to your .bashrc/.zshrc
file. The final result will be something like the following.
The only issue with kube-ps1
is, when used with git
plugin in zsh, it can generate really long PS1 strings. If tmux
is used, it can be actually set-up in the status bar through kube-tmux
plugin, avoiding PS1 cluttering.
Investigating logs: the sane way
Failures can happen, debugs are required and check-ups are sometimes necessary. For all of these, application logs are needed. The standard way to open them is:
kubectl --namespace dev --context labs get pods
# get the pod id
kubectl --namespace dev --context labs logs <pod-id> -f
If the pod is killed and restarted, the process has to be repeated as the pod id will change. Besides, the kubectl
logs tool is quite simple in terms of features. stern
is meant to be more powerful and allows to tail multiple pods and containers at once (even the whole namespace, if required).
To tail pods, such as the hello-world example, stern hello-world
will do. It would tail everything using the *hello-world*
as an expression. If multiple pods were been run, it would log all hello-world pods.
stern hello-world # tail all pods containing "hello-world" in its name
stern . # tail all pods in current namespace
stern --since 1h . # tail logs from last one hour
Shorter calls can be done setting up an alias, such as alias s='stern'
. If set, it uses the kubectx
and kubens
settings, while accepting --namespace
and --context
args as well.
Automatic deployments
A way to avoid touching prod environment using kubectl
is by setting up kube-applier
. This service auto-deploy changes on infrastructure changes, based on a git repository.
It runs as a separate pod, watching and comparing kubernetes manifest repository with deployed services. If there is a difference between manifests, it will automatically apply what is in the git repository, making it the source of truth for kube manifests.
After installing kube-applier
, no deploys should be done through kubectl
, as it will always revert to git manifests. This avoids confusions around deployments made in a rush, not merged and then rollbacked by a mistake.
Add safety against wrong kubectl apply
If kube-applier
is not an option, perhaps it would be good to have a protection before kubectl apply
operations. There are many ways to do this, the following considers overwriting kaf
from oh-my-zsh
plugin. It adds a confirmation prompt and shows which context it will be applied to.
# Confirm command to be executed
confirm() {
echo -n "\e[33mDo you want to run $*? [N/yes] \e[m"
read REPLY
# if test "$REPLY" = "y" -o "$REPLY" = "Y"; then
if test "$REPLY" = "yes"; then
"$@"
else
echo "Cancelled by user"
fi
}
safe_kubectlapply() {
context=$(kubectl config current-context)
echo "\n"
echo "BECAREFUL!!! APPLYING TO \e[31m$context\e[m"
confirm kubectl apply -f "$@"
}
alias kaf='safe_kubectlapply'
This can pottentially save lifes. It can be modified to be used with other operations, such as kdel
and kdelf
(aliases for kubectl delete
).
Conclusion
These are just some tricks I use in my daily kubernetes life. Have a good coding week! 😉