Over the years, I have learned a lot of kubectl commands and used a lot of tools to help me naviagate through the Kubernetes ecosystem. While tools like kubens and kubectx are great for switching between namespaces and contexts, I have found that most of the time, I just use bare kubectl commands. Here are some of the most common commands that I use on a daily basis and some extras that have helped me out in the past. For faster typing and less mistakes, I have aliased kubectl to k.
# add this to your shell profile to alias kubectl to k
alias k="kubectl"
Over the years, I have bounced around a lot between different namespaces and contexts and never really found a lot of use
for setting kube config to point to a specific namespace. If you wanted to go that route, you just need to do something similar
to kubectl config set-context <clusterName> --namespace=<nameSpace>
. Here is a general list of commands I use to navigate around each
cluster. While there are a lot of tools and GUI's for this, most of my time is spent in the terminal so all of these commands
are for the terminal.
# showing the available clusters:
$ k config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
docker-desktop docker-desktop docker-desktop
k3s k3s-cluster k3s-admin
minikube minikube minikube default
* raspberry raspberry raspberry
ubuntupi ubuntupi ubuntupi
# Selecting a cluster:
$ k config use-context k3s
# Display the context you are currently using:
$ k config current-context
k3s
# Show all available namespaces (ns is short for namespace):
$ k get ns
NAME STATUS AGE
...
argo-events Active 148d
argo Active 141d
default Active 236d
sean-home Active 136d
go-site-gin Active 236d
# list resources in a namespace (note all doesn't mean everything)
$ k get all -n go-site-gin
NAME READY STATUS RESTARTS AGE
pod/go-site-gin-76869976cd-klvhj 1/1 Running 0 4h40m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/go-site-gin-svc NodePort 10.43.3.39 <none> 8080:30090/TCP 236d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/go-site-gin 1/1 1 1 128d
NAME DESIRED CURRENT READY AGE
replicaset.apps/go-site-gin-86df6c949f 0 0 0 128d
replicaset.apps/go-site-gin-799fdb896c 0 0 0 128d
replicaset.apps/go-site-gin-77b846d5bb 0 0 0 48d
...
# show api version in k8s (really helpfull for building manifests):
$ k api-versions
admissionregistration.k8s.io/v1
apiextensions.k8s.io/v1
apiregistration.k8s.io/v1
apps/v1
argoproj.io/v1alpha1
authentication.k8s.io/v1
...
# Show the resources for the apis (great for finding shortcodes):
$ k api-resources -o wide
NAME SHORTNAMES APIGROUP NAMESPACED KIND VERBS
bindings true Binding [create]
componentstatuses cs false ComponentStatus [get list]
configmaps cm true ConfigMap [create delete deletecollection get list patch update watch]
endpoints ep true Endpoints [create delete deletecollection get list patch update watch]
events ev true Event [create delete deletecollection get list patch update watch]
...
# Explain a resource and its fields (drill in with dot notation):
$ k explain pod
KIND: Pod
VERSION: v1
DESCRIPTION:
Pod is a collection of containers that can run on a host. This resource is
created by clients and scheduled onto hosts.
...
# Dig further:
$ k explain pod.spec.serviceAccountName
KIND: Pod
VERSION: v1
FIELD: serviceAccountName <string>
DESCRIPTION:
ServiceAccountName is the name of the ServiceAccount to use to run this
pod. More info:
https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
These commands are great for testing and debugging, but when using tools like ArgoCD to manager your deployments, you will rarely use these commands. If you run these commands against a managed resource, you will likely find yourself fighting the reconciler and your changes will be reverted. In that cause you'll need to temporarily disable the reconciler or use the ArgoCD CLI to make changes.
# Scale a deployment:
$ k scale --replicas=2 deployment/<deployment-name> -n <namespace>
# edit a running resource (usually a deployment, configmap, or secret):
# it's also worth noting that you can use kubectl edit to edit a resource in your default editor
$ k edit deployment <deployment-name> -n <namespace>
# apply a localy stored manifest to the cluster:
$ k apply -f <path-to-manifest> -n <namespace>
# delete a resource:
$ k delete <resource> <resource-name> -n <namespace>
# if it was generated from a local file:
$ k delete -f <path-to-manifest> -n <namespace>
# removing pods with a grace period:
$ k delete pod <podName> --grace-period=10
# restarting a deployment
$ k rollout restart deployment <deployment-name> -n <namespace>
# get the status of a rollout
$ k rollout status deployment/<deployment-name> -n <namespace>
# copy files from a container to your local machine:
$ k cp <pod-name>:<path-to-file> <path-to-destination> -n <namespace>
# copy files from your local machine to a container:
$ k cp <path-to-file> <pod-name>:<path-to-destination> -n <namespace>
# exec into a pod (if tty is enabled, you can use bash or sh to get a shell):
$ k exec -it <pod-name> -n <namespace> -- /bin/bash
# connect to a specific container in a pod:
$ k exec -it <pod-name> -c <container-name> -n <namespace> -- /bin/bash
# get values of a kubernetes secret using jsonpath:
$ k get secret <secret-name> -n <namespace> -o jsonpath='{.data.<key>}' | base64 --decode
# get a list of nodes:
$ k get nodes
NAME STATUS ROLES AGE VERSION
nd1-4gb Ready <none> 235d v1.27.3+k3s1
nd2-8gb Ready control-plane,master 236d v1.27.3+k3s1
# describe a specific node:
$ k describe node <node-name>
# taint a node (for maintinance or to prevent workloads from being scheduled):
$ k taint <node-name> <taint-key>:<taint-value>:<taint-effect>
ex:
$ k taint nd1-4gb app:app:NoSchedule
# cordon off a node (prevent new workloads from being scheduled):
$ k cordon <node-name>
# drain a node (move workloads off of a node):
$ k drain <node-name>
# uncordon a node (allow workloads to be scheduled on a node):
$ k uncordon </node-name>
# remove a taint from a node (yes you will need that trailing dash):
$ k taint <node-name> <taint-key>:<taint-value>-
# get a list of pods and their node assignments using custom-columns:
$ k get pod -o=custom-columns=NAME:.metadata.name,STATUS:.status.phase,NODE:.spec.nodeName,WORKLOAD:.spec.nodeSelector.workload -n chime01|grep compute
# get a list of nodes and the zone they are in (useful for draining a zone):
$ kk get nodes --no-headers -l failure-domain.beta.kubernetes.io/zone=us-east-1c | awk '{print $1}' | while read k8sNode
Argocd app of apps definition.
Argo Workflows up and running
Automating workflows with github actions.
Simple Api using gin-gonic.
Building K8s manifests with Helm3
A collection of kubectl commands that have helped me a ton.
Configuring Role Based Access Control in Kubernetes.
Making images smaller with multi stage builds.
Keeping secrets out of your container images even while using private modules