We've created this Kubectl Cheatsheet as a quick reference guide for you. It contains the most commonly used commands for working with Kubernetes. This cheatsheet is a work in progress, and we'll be adding more commands as we go along. If you have any suggestions, feel free to open an issue or submit a pull request.
- What is Kubectl
- How The Communication Works
- How to Install Kubectl
- Cluster Information
- Resource Management
- Inspecting Resources
- Creating and Updating Resources
- Deleting Resources
- Run Command
- Scaling Deployments
- Exposing Deployments
- Managing Rollouts
- Working with Logs
- Executing Commands in Containers
- Port Forwarding
- Labeling and Annotating Resources
- Configuring Kubectl
- Dry Run
- Looping Through Resources
- Create Resourses with
cat
command - Flattening Kubeconfig
- Getting API Resources
- Use Custom Columns --custom-columns
- Use kubectl auth can-i
- Troubleshooting
- Resources
This is the tool that most Kubernetes engineers primarily use when interacting with a Kubernetes cluster.
Behind the scenes, kubectl interacts directly with the Kubernetes API, converting the commands you type into API requests, which are then executed on the Kubernetes cluster.
With kubectl, you can perform a wide range of operations on the cluster, such as creating, deleting, and updating deployments, exposing your application, checking the logs of your running pods, and monitoring the health and capacity of your nodes and the overall cluster health.
To begin using kubectl, you must first install it on your local machine. Please refer to the next section for installation instructions.
The communication between kubectl and the Kubernetes cluster is based on RESTful HTTP requests and responses. The following diagram illustrates how kubectl interacts with Kubernetes resources:
Me
+--------------------------+
x x | Kubernetes cluster |
x x | |
x x | +---------+ |
x +---------+ | | | |
x commands | | GET, POST, PUT etc. | | api | |
x -------------->| kubectl +---------------------+------+ server | |
x x | <---------------------+------+ | |
x x x <-------- +---------+ Response | +---------+ |
x x x displays | |
x x x commands | |
x | |
x | |
x +--------------------------+
x
When you issue a command using kubectl, the tool reads the kubeconfig file on your local machine and obtains all the necessary information to authenticate with the Kubernetes API server. This file includes details about the Kubernetes server's address, your credentials, and context information.
The connection between kubectl and the API server is usually secured by TLS encryption to ensure that no tampering or eavesdropping occurs.
Authentication and authorization occur before the API server processes your request. The API server validates your credentials. There are various ways Kubernetes can authenticate you, which are covered in detail in the following article: Kubernetes - RBAC And Admission Controllers
Once you have been authenticated and authorized, the kubectl command is translated into an API request that conforms to the Kubernetes API specification.
The request is typically a RESTful HTTP request, containing a specific method (GET, POST, PUT, DELETE, etc.). It also targets the relevant API endpoint (e.g., /api/v1/namespaces/default/pods) and includes the necessary data in JSON format (if applicable). The request is then sent over the secure connection to the Kubernetes API server, along with the required headers and your credentials.
Upon receiving the API request, the API server processes it and performs the necessary operations, such as creating or updating resources.
Kubectl receives the API response from the Kubernetes API server, which typically includes data in JSON format, log messages, and more.
Finally, kubectl displays the message to the user in the terminal.
Download the latest version:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl"
Download a specific version:
curl -LO "https://dl.k8s.io/release/v1.24.0/bin/darwin/amd64/kubectl"
To make the kubectl binary executable:
chmod +x ./kubectl
To be able to run kubectl without specifying the path, move the kubectl binaries to a file location on your system PATH:
sudo mv ./kubectl /usr/local/bin/kubectl
sudo chown root: /usr/local/bin/kubectl
to check the version
kubectl version --client
## Output
Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.7", GitCommit:"1dd5338295409edcfff11505e7bb246f0d325d15", GitTreeState:"clean", BuildDate:"2021-01-13T13:23:52Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"darwin/amd64"}
With the following command, we can get information about the cluster, like the version of Kubernetes that is running, the IP address of the master, and the names of the nodes in the cluster.
kubectl cluster-info
The following commands are used to manage resources in the cluster
kubectl get nodes # list all nodes in the cluster
kubectl get pods # list all pods in the namespace or with --all-namespaces flag
kubectl get services
kubectl get deployments
kubectl get secrets
kubectl edit <resource-type> <resource-name> # edit a resource in the default editor
watch -n 2 kubectl get pods # Continuously monitor pod status every X seconds
Flags:
--all-namespaces # list the requested object(s) across all namespaces
--watch # after listing/getting the requested object, watch for changes
-o # output format example -o yaml or -o json
--show-labels # show labels in the last column
--selector # filter results by label selector example --selector env=prod
--sort-by # sort list types using a jsonpath expression example --sort-by='{.metadata.name}'
--field-selector # filter results by a field selector example --field-selector metadata.name=nginx
--no-headers # when using the default or custom-column output format, don't print headers (default print headers)
--output-watch-events # output watch event objects when --watch or --watch-only is used example kube get pods --watch --output-watch-events
kubectl get pods --sort-by=.metadata.creationTimestamp
kubectl get pods --sort-by=.status.phase
kubectl get pods --sort-by=.spec.nodeName
kubectl get pv --sort-by=.spec.capacity.storage
The following commands are used to inspect resources in the cluster.
Also we have included the kubectl explain
command which is used to get the documentation of a resource type.
kubectl describe nodes <node-name>
kubectl describe pods <pod-name>
kubectl describe services <service-name>
kubectl describe deployments <deployment-name>
kubectl explain <resource-type> # get the documentation of a resource type example kubectl explain pods
With the following commands, we can create and update resources in the cluster.
kubectl create -f <file-name> # This command is used to create resources in the cluster
kubectl apply -f <file-name> # This command is used to create or update resources in the cluster
We can also create resources directly from the command line:
kubectl create deployment <deployment-name> --image=<image-name> # create a deployment
kubectl create service <service-name> --tcp=<port>:<target-port> # create a service
kubectl create role <role-name> --verb=<verb> --resource=<resource> --resource-name=<resource-name> # create a role
kubectl create rolebinding <role-binding-name> --role=<role-name> --user=<user> # create a rolebinding
With the following commands, we can delete resources in the cluster.
kubectl delete pods <pod-name> # delete a pod
kubectl delete pods --all # delete all pods in the namespace
kubectl delete services <service-name>
kubectl delete -f <file-name>
kubectl delete deployment <deployment-name> # delete a deployment
kubectl delete namespace <namespace-name> # delete a namespace
With the run
command, we can run a container in a pod. It is a quick way to create a pod with a container in it.
kubectl run <pod-name> --image=<image-name> # run a container in a pod
kubectl run <pod-name> --image=<image-name> --restart=Never # run a container in a pod with a specific restart policy
kubectl run <pod-name> --image=<image-name> --restart=Never --dry-run=client -o yaml # generate a pod manifest without creating it
kubectl run <pod-name> --image=<image-name> --restart=Never --dry-run=client -o yaml > pod.yaml # save the pod manifest to a file
kubectl run <pod-name> --image=<image-name> --restart=Never --dry-run=client -o yaml | kubectl apply -f - # create a pod from a generated manifest
Example of using overrides:
kubectl run <pod-name> --image=<image-name> --overrides='{"apiVersion":"v1","spec":{"containers":[{"name":"<container-name>","image":"<image-name>"}]}}'
kubectl run nginx --image=nginx --overrides='{ "apiVersion": "v1", "spec": { "containers": [ { "name": "nginx", "image": "nginx:1.7.9", "ports": [ { "containerPort": 80 } ] } ] } }'
official documentation: https://kubernetes.io/docs/reference/kubectl/generated/kubectl_run/
With the following command, we can scale your deployments:
kubectl scale deployment <deployment-name> --replicas=<number-of-replicas>
In this section, we'll learn how to expose Kubernetes deployments using kubectl with different service types: ClusterIP, NodePort, and LoadBalancer. Exposing a deployment allows us to make the application accessible to users or other services, either within the cluster or externally.
kubectl expose deployment <deployment-name> --type=ClusterIP --port=<port> # Exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster.
kubectl expose deployment <deployment-name> --type=NodePort --port=<port>
kubectl expose deployment <deployment-name> --type=LoadBalancer --port=<port> # In cloud providers that support load balancers, an external IP address would be provisioned to access the service.
The loadbalancer service type is only supported in cloud providers that support load balancers.
With the following commands, we can manage the rollouts of our deployments. Rollouts are an essential part of the deployment process, as they allow you to update your applications while minimizing downtime and ensuring transitions between versions.
kubectl rollout status deployment <deployment-name> # Check the status of a rollout
kubectl rollout history deployment <deployment-name> # Check the history of a rollout
kubectl rollout undo deployment <deployment-name> # Rollback to the previous revision
kubectl rollout undo deployment <deployment-name> --to-revision=<revision-number> # Rollback to a specific revision
Set the image on a deployment:
kubectl set image deployment/<deployment-name> <container-name>=<new-image>
or when having only one container in the pod:
kubectl set image deployment/<deployment-name> <new-image>
Using json patch:
kubectl patch deployment <deployment-name> -p '{"spec":{"template":{"spec":{"containers":[{"name":"<container-name>","image":"<new-image>"}]}}}}'
With the following commands, we can work with the logs of our pods:
kubectl logs <pod-name> -n <namespace> # print the logs for a pod in a namespace
kubectl logs -f <pod-name> # follow the logs
kubectl logs -p <pod-name> # print the logs for the previous instance of the container in a pod if it exists
For a more streamlined approach, you can retrieve logs based on deployments or labels:
kubectl logs -f deployment/<deployment-name> # follow logs from a pod associated with a deployment
kubectl logs -f -l app=<app-name> # follow logs from all pods with a specific label
Using these methods, you can easily monitor logs from all pods associated with a deployment or from all pods with a specific label, saving you time and effort.
Sometimes we need to execute commands in a container:
kubectl exec <pod-name> -- <command> # execute a command in a container
kubectl exec -it <pod-name> -- <command> # execute a command in a container interactively
# enter the container's shell
kubectl exec -it <pod-name> -- /bin/bash # bash shell, very common to get into a container
# copy files to and from a container
kubectl cp <pod-name>:<path-to-file> <path-to-local-file> -c <container-name>
kubectl cp <path-to-local-file> <pod-name>:<path-to-file> -c <container-name>
With the following command, we can forward a local port to a port on a pod or service. This is very handy if the application is not exposed to the outside world, but you still want to access it.
kubectl port-forward <pod-name> <local-port>:<container-port>
kubectl port-forward <service-name> <local-port>:<container-port>
With the following commands, we can add labels and annotations to resources in the cluster. This is useful for organizing and grouping resources, as well as for attaching metadata to resources.
kubectl label pods <pod-name> <label-key>=<label-value>
kubectl annotate pods <pod-name> <annotation-key>=<annotation-value>
Taints and tolerations are a way to control how pods are scheduled on nodes. For example, we can use taints to prevent pods from being scheduled on nodes that have sensitive data.
kubectl taint nodes <node-name> <key>=<value>:<effect> # taint a node
kubectl taint nodes <node-name> <key>:<effect> # remove a taint from a node
kubectl taint nodes <node-name> <key>:NoSchedule # prevent pods from being scheduled on the node
kubectl taint nodes <node-name> <key>:NoExecute # prevent pods from being scheduled on the node and evict existing pods
kubectl taint nodes <node-name> <key>:PreferNoSchedule # prefer not to schedule pods on the node
Tolerations are applied to pods, and allow (but do not require) the pods to schedule onto nodes with matching taints.
Example pod spec with tolerations:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
kubectl config view # display merged kubeconfig settings or a specified kubeconfig file
kubectl config view --minify --output 'jsonpath={..namespace}' # display the namespace within the context
kubectl config current-context # display the current-context
kubectl config use-context <context-name> # set the current-context in a kubeconfig file
kubectl config set-context <context-name> # set a context entry in kubeconfig
kubectl config set-cluster <cluster-name> # set a cluster entry in kubeconfig
kubectl config set-credentials <user-name> # set a user entry in kubeconfig
kubectl config unset users.<name> # unset a user entry in kubeconfig
kubectl config set-context --current --namespace=<namespace> # set the default namespace for the current context
kubectl config set-cluster <cluster-name> \
--certificate-authority=<path-to-ca-file> \
--embed-certs=<true|false> \
--server=<address-and-port-of-api-server> \
--kubeconfig=<path-to-kubeconfig-file>
Dry run allows you to preview the changes that will be made to the cluster without actually making them. This is useful for debugging and testing.
kubectl apply --dry-run=client -f <file-name>
Sometimes you need to loop through resources. For example, you might want to delete all pods in a namespace or get data for all secrets.
kubectl get pods -o name | cut -d/ -f2
- -o name - get the name of the resource
- cut utility - cut out selected portions of each line of a file
- -d/ - use / as the delimiter
- -f2 - get the second field
Example Output:
hostpath-provisioner-58694c9f4b-snv67
coredns-7745f9f87f-5nzv7
calico-kube-controllers-649854c487-pk4dv
calico-node-mjc66
metrics-server-56ffd4f94b-ngzc2
calico-node-t7tgg
calico-node-4wndg
Another way is using the jq utility. jq is a lightweight and flexible command-line JSON processor.
kubectl get pods -o json | jq -r '.items[].metadata.name'
- -o json - get the output in json format since jq works with json
- items[] - get all items in the array
- metadata.name - get the name of the metadata object
kubectl get pods -o name | xargs -I {} kubectl delete {}
- xargs - build and execute command lines from standard input
- -I {} - replace {} with the input
Now we can combine the two commands to delete all pods in a namespace (this is more to show how to combine commands, as there is a better way to delete all pods in a namespace)
kubectl get pods -o name | cut -d/ -f2 | xargs -I {} kubectl delete pod {}
for pod in $(kubectl get pods -o name | cut -d/ -f2); do kubectl delete pod $pod; done
Easy way to delete all pods in a namespace
kubectl delete pods --all
On MacOS we use base64 -D to decode the data
kubectl get secret <secret-name> -o json | jq -r '.data' | base64 -D
or if Linux, we use base64 -d
kube get secret <secret-name> -o json | jq -r '.data' | base64 -d
With cat
we can create resources from stdin
cat <<EOF | kubectl create -f -
# create a n nginx pod
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
EOF
kubectl api-resources
kubectl api-resources --namespaced=true # namespaced resources
# how to get curl call from kubectl with log level 9
kubectl get pods -v=9 2>&1 | grep curl # get curl call for a specific resource
kubectl get pods -v=9 2>&1 | grep curl | sed 's/.*curl -k -v -XGET/https/' | sed 's/ -H .*//' # get curl call for a specific resource
Assume that you have multiple kubeconfig files and you want to merge them into one file. You can use the following command to do that.
KUBECONFIG=~/.kube/config:~/.kube/config2:~/.kube/config3 kubectl config view --flatten > ~/.kube/merged-config
then you can run the following command to use the merged kubeconfig file:
export KUBECONFIG=~/.kube/merged-config
--custom-columns
is not very known to many people, at least from my experience.
When managing Kubernetes pods, having the ability to customize your command line output can be incredibly powerful. kubectl provides the --custom-columns
option to do just that, enabling you to specify and format your own columns for a more tailored display of resources.
kubectl get pods -o custom-columns=NAME:.metadata.name
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase # get multiple columns and status of the pod
You can have multiple columns separated by comma.
- custom-columns - output in custom columns format
- NAME: create a column with the header NAME
With the above command, you're not only fetching the pod names but also their current phase, neatly organized into the NAME and STATUS columns.
Remember, the --custom-columns option takes a comma-separated list, allowing you to define multiple columns. Each column in the list is defined by a HEADER:JSON_PATH_EXPRESSION pair:
In the following example, we will set some odd (custom) header:
kubectl get pods -o custom-columns=MY_SUPER_PODS:.metadata.name,STATUS:.status.phase
Output example:
MY_SUPER_PODS STATUS
keda-operator-metrics-apiserver-5bb87b6cc5-hqmrb Running
devoriales-rabbitmq-0 Running
keda-admission-webhooks-6b4b4b64fc-4wc8b Running
keda-operator-7fdd98c445-9ljhj Running
consumer-deployment-58f8855bb7-hr7px Running
This command is used to check if subjects can perform an action on a resource. The way how you specify this is by using the following syntax:
kubectl auth can-i <VERB> <RESOURCE> --namespace <NAMESPACE> --as <USER>
You can also set --all-namespaces flag to check if the user can perform an action on a resource in all namespaces.
Here is an practical example how we can check if the user can create pods in the default namespace:
kubectl auth can-i create pods --namespace default
The command kubectl auth can-i
can be very handy when you want to check what a specific service account can do.
For example, you can check if the default service account in the default namespace can create pods:
kubectl auth can-i create pods --namespace default --as=system:serviceaccount:default:default
--as flag is used to specify the service account. system: is a prefix for service accounts. serviceaccount:default:default is the name of the service account in the default namespace.
Please Note! auth can-i
assumes that your current user has the permissions to impersonate a service account. If not, you may need to adjust your RBAC policies accordingly.
Full tutorial can be found on https://devoriales.com/post/332/resolve-stuck-namespaces-in-kubernetes-a-step-by-step-tutorial
First, you need to get the list of namespaces in the Terminating state:
kubectl get namespaces --field-selector status.phase=Terminating
Then you should check why the namespace is stuck in the Terminating state:
kubectl describe namespace <namespace-name>
Many times, the namespace is stuck in the Terminating state because of the finalizers. You can remove the finalizers from the namespace to force delete it:
Export the namespace to a file:
kubectl get namespace <namespace-name> -o json > namespace.json
Edit the namespace.json file and remove the finalizers section:
example finalizers section, remove "kubernetes" from the list:
"finalizers": [
"kubernetes"
]
Start the kube proxy:
kubectl proxy &
Then run the following command to delete the namespace:
curl -X PUT http://127.0.0.1:8001/api/v1/namespaces/<namespace-name>/finalize -H "Content-Type: application/json" --data-binary "@namespace.json"
Stop the kube proxy:
killall kubectl
Verify that the namespace is deleted:
kubectl get namespaces