Welcome to the first part of my guide to using Kubernetes CLI commands to manage your cluster. In this part, I will focus on providing a complete overview of how to work with pods, deployments, services, and more using the Kubernetes CLI. This guide is the first part of a three-part series, so make sure to follow along for the next two parts, where we will dive deeper into other Kubernetes resources and advanced techniques. Whether you’re new to Kubernetes or a seasoned user, this guide will equip you with the knowledge and skills to manage your cluster efficiently using the CLI.
The examples provided here are just a portion of the many imperative commands available.
My intention is to introduce you to this type of command so that you can effectively communicate with Kubernetes in a fast manner.
So, let’s get started and explore the power of Kubernetes CLI together!
Remember this:
By default, the kubectl edit command would launch either vi for Linux or notepad on Windows when editing a resource.
However, you have the option to modify this behavior by updating the KUBE_EDITOR variable’s value. For instance, if you prefer using the nano editor to edit your resources, you can execute a similar command:
KUBE_EDITOR="nano" kubectl edit -f nginx.yaml
Pods
Create a Pod named my-pod with a container running nginx:
kubectl run my-pod --image=nginx
Delete a Pod named my-pod:
kubectl delete pod my-pod
Get the logs from a Pod named my-pod:
kubectl logs my-pod
Get information about a Pod named my-pod:
kubectl describe pod my-pod
Create a Pod from a YAML file named my-pod.yaml:
kubectl create -f my-pod.yaml
Update the image of the container in a Pod named my-pod:
kubectl set image pod my-pod nginx=nginx:latest
Restart a Pod named my-pod:
kubectl rollout restart pod my-pod
Get the IP address of a Pod named my-pod:
kubectl get pod my-pod -o=jsonpath='{.status.podIP}'
Scale a deployment named my-deployment to 3 replicas:
kubectl scale deployment my-deployment --replicas=3
Check the status of a Pod named my-pod:
kubectl get pod my-pod
Forward traffic from a local port 8080 to a container port 80 in a Pod named my-pod:
kubectl port-forward my-pod 8080:80
Update the environment variables in a Pod named my-pod:
kubectl set env pod my-pod MY_ENV_VAR=my-value
Of course, you will replace my-pod with the desired Pod name. Also, these commands assume that you have the necessary permissions to perform these actions.
Be careful when deleting Pods as it may cause disruption to the application running in the Pod.
Some of these commands also assume the existence of certain Kubernetes objects like a deployment or a container.
Always ensure that the necessary objects have been created before using these commands.
Deployment
Create a Deployment:
kubectl create deployment nginx --image=nginx:latest --replicas=3
Update the image of a Deployment:
kubectl set image deployment/nginx nginx=nginx:1.23.3
Scale a Deployment:
kubectl scale deployment nginx --replicas=5
Rollback to the previous version of a Deployment:
kubectl rollout undo deployment/nginx
Check the status of a Deployment:
kubectl rollout status deployment/nginx
Pause a Deployment:
kubectl rollout pause deployment/nginx
Resume a paused Deployment:
kubectl rollout resume deployment/nginx
Expose a Deployment as a Service:
kubectl expose deployment nginx --port=80 --target-port=80 --type=LoadBalancer
Delete a Deployment:
kubectl delete deployment nginx
Edit a Deployment:
kubectl edit deployment nginx
This command will open the deployment definition in your default text editor (vim or nano), allowing you to make any necessary changes to the deployment’s specifications.
Once you’ve made your changes, save and close the file to apply the changes to the deployment.
Note that when you edit a deployment, the existing pods will be terminated and replaced with new ones that match the updated deployment specification.
Therefore, it’s important to carefully consider the impact of any changes you make to a deployment before applying them.
Services
Create a Service with NodePort type:
kubectl create service nodeport my-service --tcp=80:8080
Update a Service to use a different port:
kubectl edit service my-service
Update the spec.ports field to use a different port number.
Scale a Service:
kubectl scale deployment/my-deployment --replicas=3
Expose a Service:
kubectl expose deployment/my-deployment --type=LoadBalancer --port=80 --target-port=8080
Delete a Service:
kubectl delete service my-service
Annotate a Service:
kubectl annotate service my-service description="My service description"
Set the selector for a Service:
kubectl patch service my-service -p '{"spec":{"selector":{"app":"my-app"}}}'
Change the Service type to ClusterIP:
kubectl patch service my-service -p '{"spec":{"type":"ClusterIP"}}'
Change the Service type to LoadBalancer:
kubectl patch service my-service -p '{"spec":{"type":"LoadBalancer"}}'
Update the Service IP address:
kubectl patch service my-service -p '{"spec":{"clusterIP":"10.0.0.1"}}'
ConfigMaps
Create a ConfigMap from a file:
kubectl create configmap my-configmap --from-file=my-file.properties
Create a ConfigMap from a literal value:
kubectl create configmap my-configmap --from-literal=key1=value1 --from-literal=key2=value2
Edit a ConfigMap:
kubectl edit configmap my-configmap
Delete a ConfigMap:
kubectl delete configmap my-configmap
View the details of a ConfigMap:
kubectl describe configmap my-configmap
View the contents of a ConfigMap:
kubectl get configmap my-configmap -o yaml
Create a Pod that uses a ConfigMap:
kubectl run my-pod --image=my-image --env-file=my-configmap.properties
In the above example, the ConfigMap is mounted as a file and the environment variables are read from that file.
Update the data in a ConfigMap:
kubectl create configmap my-configmap --from-file=my-file.properties --dry-run=client -o yaml | kubectl apply -f -
So in this example, the ConfigMap is updated using the dry-run flag and the YAML output is piped to the apply command.
Rollback to a previous version of a ConfigMap:
kubectl rollout undo configmap/my-configmap
Here we have a ConfigMap rolled back to the previous version.
Roles
Create a Role named my-role in namespace my-namespace with permission to list pods:
kubectl create role my-role --verb=list --resource=pods -n my-namespace
Create a Role named my-role in namespace my-namespace with permission to get deployments:
kubectl create role my-role --verb=get --resource=deployments -n my-namespace
Update a Role named my-role in namespace my-namespace to include the permission to delete services:
kubectl patch role my-role -n my-namespace --type='json' -p='[{"op": "add", "path": "/rules/-", "value": {"verbs":["delete"],"apiGroups":[""],"resources":["services"]}}]'
Delete a Role named my-role in namespace my-namespace:
kubectl delete role my-role -n my-namespace
Create a Role named my-role in namespace my-namespace with permissions to list and get pods:
kubectl create role my-role --verb=list,get --resource=pods -n my-namespace
Update a Role named my-role in namespace my-namespace to include the permission to update deployments:
kubectl patch role my-role -n my-namespace --type='json' -p='[{"op": "add", "path": "/rules/-", "value": {"verbs":["update"],"apiGroups":["apps"],"resources":["deployments"],"resourceNames":["my-deployment"]}}]'
Create a Role named my-role in namespace my-namespace with permission to create and delete config maps:
kubectl create role my-role --verb=create,delete --resource=configmaps -n my-namespace
Update a Role named my-role in namespace my-namespace to remove permission to delete pods:
kubectl patch role my-role -n my-namespace --type='json' -p='[{"op": "remove", "path": "/rules/0/verbs/1"}]'
Please note that the above commands assume that there are no existing policies in place that may conflict with the permissions granted by the Roles.
Always review your cluster’s security policies before creating or modifying Roles.
Role Bindings
Create a RoleBinding with the “editor” Role for the “default” ServiceAccount in the “kube-system” namespace:
kubectl create rolebinding default-editor --clusterrole=edit --serviceaccount=kube-system:default --namespace=kube-system
Update the RoleBinding named “edit-binding” in the “default” namespace to use the “admin” ClusterRole:
kubectl patch rolebinding edit-binding -p '{"roleRef": {"name": "admin"}}'
Delete the RoleBinding named “view-binding” in the “kube-system” namespace:
kubectl delete rolebinding view-binding --namespace=kube-system
Get a piece of detailed information about the RoleBinding named “admin-binding” in the “default” namespace:
kubectl describe rolebinding admin-binding --namespace=default
Create a RoleBinding with the “view” Role for the “view-user” ServiceAccount in the “my-namespace” namespace:
kubectl create rolebinding view-binding --clusterrole=view --serviceaccount=my-namespace:view-user --namespace=my-namespace
Add a user with the name “Luka” to an existing RoleBinding named “admin-binding” in the “default” namespace:
kubectl patch rolebinding admin-binding --namespace=default --type=json -p='[{"op": "add", "path": "/subjects/-", "value": {"kind": "User", "name": "luka", "apiGroup": null}}]'
To list all RoleBindings in the “kube-system” namespace:
kubectl get rolebindings --namespace=kube-system
Edit the RoleBinding named “view-binding” in the “default” namespace to add a new subject with the name “Jelena”, use the following command:
kubectl edit rolebinding view-binding --namespace=default
Create a RoleBinding with the “admin” Role for a specific User with the name “admin-user”.
kubectl create rolebinding admin-binding --clusterrole=admin --user=admin-user
Update the RoleBinding named “edit-binding” in the “default” namespace to remove a specific subject with the name “alice”:
kubectl patch rolebinding edit-binding --namespace=default --type=json -p='[{"op": "remove", "path": "/subjects/1"}]'
Network Policies
Create a new NetworkPolicy named “allow-nginx” that allows traffic to pods with the label “app=nginx” on port 80.
kubectl create networkpolicy allow-nginx --from-pod-selector=app=nginx --pod-selector= --policy-types=ingress --ingress=[{"ports": [{"port": 80, "protocol": "TCP"}]}]
Update an existing NetworkPolicy named “allow-mysql” to deny traffic to pods with the label “app=mysql” on port 3306:
kubectl patch networkpolicy allow-mysql --type=json -p='[{"op": "add", "path": "/spec/policyTypes", "value": ["ingress", "egress"]}, {"op": "add", "path": "/spec/ingress/0/from/podSelector/matchLabels", "value": {"app": "mysql"}}, {"op": "add", "path": "/spec/ingress/0/ports/0/port", "value": 3306}, {"op": "add", "path": "/spec/ingress/0/ports/0/protocol", "value": "TCP"}, {"op": "add", "path": "/spec/egress", "value": []}]'
Delete a NetworkPolicy named “deny-all” in the “default” namespace:
kubectl delete networkpolicy deny-all --namespace=default
Get detailed information about a NetworkPolicy named “allow-web” in the “frontend” namespace:
kubectl describe networkpolicy allow-web --namespace=frontend
Create a new NetworkPolicy that allows traffic from a specific IP address to pods with the label “app=api” on port 8080:
kubectl create networkpolicy allow-ip --from=[{"ipBlock": {"cidr": "192.168.0.1/32"}}] --pod-selector=app=api --policy-types=ingress --ingress=[{"ports": [{"port": 8080, "protocol": "TCP"}]}]
List all NetworkPolicies in the “backend” namespace:
kubectl get networkpolicies --namespace=backend
Edit an existing NetworkPolicy named “allow-db” to allow traffic from pods with the label “app=frontend” on port 5432:
kubectl edit networkpolicy allow-db
Update an existing NetworkPolicy named “allow-internal” in the “internal” namespace to allow traffic between pods with the label “app=backend”.
kubectl patch networkpolicy allow-internal --namespace=internal --type=json -p='[{"op": "add", "path": "/spec/podSelector/matchLabels", "value": {"app": "backend"}}, {"op": "add", "path": "/spec/ingress/0/from/podSelector/matchLabels", "value": {"app": "backend"}}]'
Create a new NetworkPolicy that allows traffic from pods with the label “app=web” to pods with the label “app=db” on port 3306.
kubectl create networkpolicy allow-db --from-pod-selector=app=web --to-pod-selector=app=db --policy-types=ingress --ingress=[{"ports": [{"port": 3306, "protocol": "TCP"}]}]
Delete all NetworkPolicies in the “kube-system” namespace.
kubectl delete networkpolicies --namespace=kube-system
Events
Get all events in the “default” namespace.
kubectl get events --namespace=default
Get all events related to a specific object, such as a Pod named “nginx”.
kubectl describe pod nginx | grep -i events
Get a summary of all events in the cluster.
kubectl get events
Filter events by a specific reason.
kubectl get events --field-selector reason=FailedScheduling
Create a new event for a specific object, such as a Pod named “api”:
kubectl annotate pod api kubernetes.io/events="{\"message\": \"Failed to start container\", \"reason\": \"ContainerFailed\"}"
Delete all events in the “kube-system” namespace:
kubectl delete events --namespace=kube-system
Watch events in real-time for the “default” namespace:
kubectl get events --namespace=default --watch
This will continuously update the terminal with any new events that occur in the namespace.
Filter events by a specific object, such as a Deployment named “web-deploy”:
kubectl get events --field-selector involvedObject.name=web-deploy
This will show only the events that are related to the “web-deploy” object.
To filter events by a specific type, such as a Warning.
kubectl get events --field-selector type=Warning
This will show only the events that have a type of Warning.
Create a new event with a custom message:
kubectl create event --namespace=default --from=api --reason=ContainerFailed --type=Warning --message="Container failed to start"
This will create a new event with the specified message and metadata.
Namespaces
Create a new namespace named “prod”:
kubectl create namespace prod
Get all namespaces in the cluster:
kubectl get namespaces
Delete a namespace named “test”:
kubectl delete namespace test
Set the “prod” namespace as the default namespace for subsequent kubectl commands:
kubectl config set-context --current --namespace=prod
Add the label “environment=dev” to the “default” namespace:
kubectl label namespace default environment=dev
Get all pods in the “prod” namespace:
kubectl get pods --namespace=prod
Update the resource quota of the “default” namespace to limit CPU usage to 2 cores:
kubectl patch namespace default --patch '{"spec":{"finalizers":null},"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"default\"},\"spec\":{\"finalizers\":[\"kubernetes\"]}}\n"},"name":"default"}}' -p '{"spec":{"resourceQuota":{"hard":{"limits.cpu":"2"}}}}'
Stateful Sets
Create a new StatefulSet named “web” from a YAML file:
kubectl apply -f web-statefulset.yaml
Get information about the “web” StatefulSet.
kubectl describe statefulset web
Scale the number of replicas of the “web” StatefulSet to 3:
kubectl scale statefulset web --replicas=3
Update the image used by the containers in the “web” StatefulSet:
kubectl set image statefulset web web-container=new-image:tag
Delete the “web” StatefulSet:
kubectl delete statefulset web
Force delete the “web” StatefulSet without waiting for the pods to gracefully terminate:
kubectl delete statefulset web --cascade=false
Update the partition for the “web” StatefulSet to update only the second and third replicas:
kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":2}}}}'
Jobs
Create a new Job named “my-job” from a YAML file:
kubectl apply -f my-job.yaml
Get information about the “my-job” Job:
kubectl describe job my-job
Get the logs for the first container in the first pod of the “my-job” Job:
kubectl logs my-job-0 -c container-1
Delete the “my-job” Job:
kubectl delete job my-job
Restart the “my-job” Job:
kubectl rollout restart job my-job
Create a new Job named “my-job” and run it immediately.
kubectl run my-job --image=my-image --restart=Never --dry-run=client -o yaml | kubectl apply -f -
Get the status of the “my-job” Job:
kubectl get job my-job -o=jsonpath='{.status.conditions[?(@.type=="Complete")].status}'
Create a Job named “my-job” and run it immediately, and then wait for it to complete:
kubectl run my-job --image=my-image --restart=Never --wait -- /bin/sh -c "echo Hello, Kubernetes!"
View the pod’s logs from a Job named “my-job”:
kubectl logs -f my-job-0
Create a Job named “my-job” with a time limit of 10 seconds and a backoff limit of 5:
kubectl run my-job --image=my-image --restart=OnFailure --backoff-limit=5 --command -- /bin/sh -c "sleep 10; echo Job complete"
Update the image used by the containers in a Job named “my-job”:
kubectl set image job my-job my-container=my-image:tag
Delete all completed Jobs:
kubectl delete jobs --field-selector=status.successful=1
Cron Jobs
Create a new Cron Job named “my-cronjob” from a YAML file:
kubectl apply -f my-cronjob.yaml
Get information about the “my-cronjob” Cron Job:
kubectl describe cronjob my-cronjob
Get the logs for the first container in the first pod of the latest run of the “my-cronjob” Cron Job:
kubectl logs $(kubectl get pods --selector=job-name=my-cronjob --output=jsonpath='{.items[-1:].metadata.name}') -c container-1
Delete the “my-cronjob” Cron Job:
kubectl delete cronjob my-cronjob
Update the image used by the containers in a Cron Job named “my-cronjob”:
kubectl set image cronjob my-cronjob my-container=my-image:tag
Create a new Cron Job named “my-cronjob” and run it immediately:
kubectl create cronjob my-cronjob --image=my-image --schedule="*/1 * * * *" --dry-run=client -o yaml | kubectl apply -f -
Update the schedule for a Cron Job named “my-cronjob” to run every hour:
kubectl patch cronjob my-cronjob -p '{"spec":{"schedule":"0 * * * *"}}'
Temporarily stop a Cron Job named “my-cronjob”:
kubectl patch cronjob my-cronjob -p '{"spec":{"suspend":true}}'
Resume a suspended Cron Job named “my-cronjob”:
kubectl patch cronjob my-cronjob -p '{"spec":{"suspend":false}}'
Run a specific Cron Job manually:
kubectl create job --from=cronjob/my-cronjob my-cronjob-manual-run