Kubernetes features and scalability make it a preferred choice for managing containerized applications. However, harnessing the full power of Kubernetes requires proficiency in various tools and one of the most essential among them is Kubectl.
In this guide, we will get into the heart of Kubernetes management, offering a guide to mastering Kubectl. This guide will equip you with the knowledge and skills needed to streamline your Kubernetes workflow. Let's navigate the complexities of Kubectl together and unlock the potential of seamless Kubernetes administration.
Prerequisites:
Before we begin, ensure you have the following:
- Package manager, on macOS, you can use Homebrew, on Linux, you can use Snap, and on Windows, you can use a package manager like Chocolatey.
- A Kubernetes Cluster: You need a working Kubernetes cluster. If you don't have one, you can set up a local cluster using tools like Minikube, Kind or use a cloud-based Kubernetes service like Google Kubernetes Engine (GKE) or Amazon EKS. In this article, I will be using Minikube.
Notes:
-Due to lengthy outputs, some screenshots may be cut off.
-If you are using Minikube,kubectl comes bundled with it.
I will be working from a folder I created on my desktop called kubectl_practice.
What is Kubectl?
Kubectl is a command-line utility designed for communication with Kubernetes clusters. It enables users to deploy and oversee applications, inspect and manage cluster resources, and examine logs.
Kubectl Installation
We will be looking at ways of installing Kubectl on Windows, Mac, and Linux.
On Windows, open Command Prompt or PowerShell as an administrator and run:
choco install kubernetes-cli
On MacOS If you have Homebrew installed, run the following:
brew install kubectl
On Linux For uniformity of installation,I will be using Snap, a package manager that comes bundled in most Linux distributions.
First check if you have Snap installed by running:
snap --version
You should get the output below if you have Snap installed.
If you don't have Snap installed, on Ubuntu-based systems you can do so by running
sudo apt-get install snapd -y
while on Red-hat-based distribution, you will first have to install the Epel repository with:
sudo dnf install epel-release -y
Then, update dnf with:
sudo dnf upgrade
Finally, install Snap with:
sudo dnf install snap -y
When you are done with the above steps, just run:
sudo snap install kubectl --classic
And you are in!
Verifying the Installation
After installation, verify that kubectl
is working by running the command:
kubectl version
If you are using a cloud-based Kubernetes cluster, there are extra things you need to get Kubectl up and running.
Configuring Kubectl for cloud-based Kubernetes cluster
You need the cluster configuration details to connect kubectl
to your cluster. These details typically include:
- Cluster API Server: The endpoint where your cluster is running.
- Cluster Certificate Authority: The certificate authority data for your cluster.
- Authentication Token: A token for authenticating with the cluster (used in some configurations).
There are 2 ways of achieving this:
- Using
kubectl config
command - Kubeconfig File
Using kubectl config command: To set cluster configuration using the kubectl config command, open a terminal and paste the following commands
kubectl config set-cluster my-cluster-name --server=https://cluster-api-server-address --certificate-authority=path/to/certificate-authority
kubectl config set-credentials my-cluster-cred --token=your-auth-token
kubectl config set-context my-cluster-context --cluster=my-cluster-name --user=my-cluster-
Replace my-cluster-name
, https://cluster-api-server-address
, path/to/certificate-authority
, and your-auth-token
with your specific cluster details.
Using kubeconfig file: You can directly edit the kubeconfig
file (usually located at ~/.kube/config
) to add multiple clusters. Manually add your cluster details in the clusters
, users
, and contexts
sections.
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: <certificate-authority-data>
server: https://cluster-api-server-address
name: my-cluster-name
contexts:
- context:
cluster: my-cluster-name
user: my-cluster-cred
name: my-cluster-context
current-context: my-cluster-context
kind: Config
preferences: {}
users:
- name: my-cluster-cred
user:
token: your-auth-token
Once you've configured kubectl
, you can test the connection by running:
kubectl cluster-info
Getting Minikube Ready
I will use Minikube to set up a Kubernetes cluster on my local machine.
For this guide, I will be using the bash terminal on Windows but command prompt or PowerShell will work fine. Let’s start a Minikube cluster of 3 nodes. Open the terminal and type:
minikube start --nodes 3
When Minikube is done starting, you will be presented with the below output
All good, we now have our Minikube cluster running.
Now let us get into business.
In this article, we will not be looking at all the commands that are available in Kubectl.To get you up and running, we will check out Kubectl commands as they pertain to:
- Node and Cluster Management
- Application Management
- Updating and Deleting Application
- Debugging Application
For a comprehensive list of all Kubectl commands please check the Kubectl documentation.
Below is a table of commands we will be looking at in this guide.
Commands | Uses |
---|---|
kubectl get | Retrieving information about Kubernetes resources |
kubectl describe | Detailed information about a specific resource |
kubectl logs | Accessing container logs |
kubectl create | Creating resources |
kubectl apply | Updating resources |
kubectl delete | Removing resources from the cluster |
kubectl exec | Running commands inside containers |
kubectl cordon | Marks a node as unschedulable |
kubectl uncordon | Unmarks a node as unschedulable |
kubectl drain | Gracefully moves all pods off a node |
kubectl set image deployment | Updating the container image in a specific deployment |
kubectl api-versions | Lists the API groups and their versions understood by the Kubernetes API server. |
kubectl api-resources | Display the available API resources |
Node and Cluster Management
As a Kubernetes user, among the things you will be doing is working with nodes and clusters. This section will guide you on using kubectl to operate Kubernetes node and cluster.
Get Nodes
Do you still remember the cluster we created? Let’s now put it to use.
First, let’s get some information about the minikube cluster. In your terminal, type:
kubectl get nodes
This command gets information about the nodes in our minikube cluster and presents us with the below output:
Describe Nodes
Let’s go further and get detailed information about the nodes.
Type kubectl describe nodes
and you will be presented with descriptions of all the nodes on your cluster.
Let’s narrow our command and get a description of our minikube control-plane node.
Type kubectl describe node minikube
Kubernetes returns an output stating details about the minikube node.
Before we move on, let's get information about our minikube-m02 node.
In the terminal, type: kubectl describe node minikube-m02
The above command displays a description of our minikube-m02 node below:
Cordon Nodes
Imagine you have a team of workers doing their tasks in an office. Now, let's say you need to do some maintenance on a particular desk and don't want anyone to start new tasks there until you're done. In Kubernetes, kubectl cordon is like putting a Do Not Disturb sign on that desk. It tells Kubernetes not to schedule any new work on a specific worker node so you can conduct maintenance on it.
Let us demonstrate this with our minikube-m02 node.
On the terminal,type kubectl cordon minikube-m02
Now our minikube-m02 node is restricted from having new pods scheduled on it.
Use kubectl describe node minikube-m02
to check if this is true.
Pay attention to the output,unshedulable now says true.
Get it to run new pods by executing kubectl uncordon minikube-m02
Drain Nodes
Next on our lineup is kubectl drain. If you ever need to remove all pods from a node, then kubectl drain is the man for the job.
It helps you prepare a node for maintenance by moving all the tasks and applications to other nodes. Let us see it in action.
In your terminal, type kubectl drain minikube-m03 --ignore-daemonsets --force
Before we press enter, let me explain what the above command does.
- kubectl drain is the main command that tells Kubernetes to prepare a particular node for maintenance.
- minikube-m03 is our particular node for maintenance.
- --ignore-daemonsets : this tells Kubernetes not to move certain essential tasks called daemonsets to other nodes.
- --force : the force flag tells Kubernetes not to wait for resources to terminate gracefully.
From the above output, we can see that the drain command does 2 things.
- It cordons or stops the node from having new pods scheduled on it.
- It then drains the node of existing pods.
Delete Nodes
With our minikube-m03 node drained, we are now ready to delete the node. Run this command
kubectl delete node minikube-m03
The screenshot below shows us that our minikube-m03 node has been deleted.
Cluster Management
It is advisable to regularly inspect the cluster API versions, as each new release of Kubernetes introduces new API versions and may eliminate older ones. To obtain a list of available APIs, execute the following command:
kubectl api-versions
The above output returns a list of API versions available that we can make use of.
Kubectl also provides a way to check the API resource list.
To get the available API resource list run kubectl api-resources
Our command returns the accessible resources, their short names, the API group to which a resource is affiliated, whether it is namespace-specific or not, and the specific KIND type.
Application Management
In this section, we will look at application management with Kubectl. Navigate to the kubectl_practice folder.
Let’s start with creating a deployment.
Create Deployment
In the kubectl_practice
folder, create a file named practice-deployment.yaml
with the provided content.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: nginx:latest
resources:
limits:
cpu: "0.5"
memory: "512Mi"
requests:
cpu: "0.2"
memory: "256Mi"
Run kubectl apply -f practice-deployment.yaml
to deploy using the configuration in the practice-deployment.yaml file.
The above command will present you with the console output below :
Let's check the status of our deployment by running kubectl get deployments
Create A Service
Services expose Pods to the network within or outside the cluster. Let’s check out how to create services with Kubectl .
I will create a file in kubectl_practice folder and name it practice-service.yaml with the below as the content of this file:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Next, let's apply the configuration.
Type kubectl apply -f practice-service.yaml
in your terminal and hit the enter key.
The screenshot below shows that our service was created.
You may check the status of the service by running kubectl get services
which displays the output below
Nice, our service is running.
Create Pods
Creating pods directly in Kubernetes seems convenient but brings challenges in scalability, resilience, updates, and resource management. Using higher-level abstractions like Deployments and ReplicaSets ensures easier management, automatic healing, streamlined updates, and optimized resource use for a more efficient Kubernetes experience. For the above, avoid creating pods directly in Kubernetes but instead, use deployments.
In the kubectl_practice folder, create a file named practice-pod.yaml with the following content:
apiVersion: v1
kind: Pod
metadata:
name: practice-pod-1
spec:
containers:
- name: my-container
image: nginx:latest
resources:
limits:
memory: "200Mi"
cpu: "500m"
requests:
memory: "120Mi"
cpu: "250m"
---
apiVersion: v1
kind: Pod
metadata:
name: practice-pod-2
spec:
containers:
- name: container-1
image: nginx:latest
resources:
limits:
memory: "150Mi"
cpu: "300m"
requests:
memory: "100Mi"
cpu: "200m"
Now run this command kubectl apply -f practice-pod.yaml
If you follow everything correctly, the screenshot below should be the output on your terminal.
With our practice-pod.yaml file we created 2 pods. Let’s confirm this by running kubectl get pods
Get rid of these pods by running kubectl delete pods practice-pod-1 practice-pod-2
Updating And Deleting Application
Updating
There are many methods to deploy a new application version. Here, we will be focusing on two methods:
- kubectl apply
- kubectl set image
Open the practice-deployment.yaml file and change the docker image from nginx:latest
to nginx:stable-perl
.
Save the file and run the following command kubectl apply -f practice-deployment.yaml
Let’s run a quick command to get a description of our deployment.
In your terminal, type kubectl describe deployment my-deployment
In the above screenshot, did you notice that the container image changed from nginx:latest tag to nginx:stable-perl?
Let's use kubectl set image
to change the container image tag to another version. Jump back into the terminal and type: ****
kubectl set image deployment my-deployment my-container=nginx:mainline
Get the description of our deployment by running kubectl describe deployment my-deployment
Exposing Application To The Internet
To make your application available on the internet, go into the practice-service.yaml file and change the type from clusterIP to LoadBalancer.
Apply the changes by running kubectl apply -f practice-service.yaml
Then run the get service command by typing kubectl get service
The below screenshot should be similar to the output on your console.
If you are using a cloud-based Kubernetes cluster, It might take minutes for your cloud provider to set you up. If you are using Minikube, you will need to start the Minikube tunnel to expose the External-IP.
On a separate terminal, run minikube tunnel
Then get back and run kubectl get service
By now the external IP status should change from pending to showing an external IP like so.
Copy the EXTERNAL-IP, and open it in a browser.
You have successfully exposed your application to the internet. Great job.
Deleting Application
Let us get information about our deployment and our service.
Run kubectl get service
command to get our service.
Let’s delete my-service with kubectl delete service my-service
Try to get my-service with kubectl get service
and you will notice it is no longer there.
Get the name of our deployment with kubectl get deployments
and run kubectl delete deployment my-deployment
.
Try to get our deployment with kubectl get deployments
and you will get the below output:
Debugging Application
Sometimes things might not go as planned and you have to get into the pods to fix things. To demonstrate this, let’s create a fresh deployment.
In the kubectl_practice folder, create a file called myDatabase-deployment.yaml and paste the below content.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-database
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-sql
image: mysql:oracle
#env goes here
resources:
requests:
cpu: "0.4"
memory: "800Mi"
limits:
cpu: "0.8"
memory: "900Mi"
Get into the terminal and type kubectl apply -f myDatabase-deployment.yaml
The above command gives the output below.
Try to get our deployment with kubectl get deployments
and you will be presented with the output below.
For some reason,my-database deployment is not ready. Let’s get the pods in our deployment
Run kubectl get pods
From the above output, we can see that my-database— pod has the status of CrashLoopBackOff.What could this be?
Let's get a log of the pods, run kubectl logs my-database-7c44d9bcb4-h9h54
The preceding command shows a log of the pods. Line 3 of the logs is of concern to us where it displays that "Database is uninitialized and password option is not specified You need to specify one of the following as an environment variable:"
This means that we need to set a password for the database. To fix this, get into myDatabase-deployment.yaml file, under containers, add the below content:
env:
- name: MYSQL_ROOT_PASSWORD
value: secret-password
Next, get back to the terminal and run kubectl apply -f myDatabase-deployment.yaml
Confirm if our pod is running by executing kubectl get pods
Awesome our pods are running.
Finally, let's show how to use kubectl exec
to run a terminal inside a container. I will be using Windows Powershell to demonstrate this.
If you are using Windows OS, open Powershell and navigate to our kubectl_practice folder.
First I will run kubectl get pods
Second I will get the pod name and exec into the container with
kubectl exec -it my-database-7c8c774899-jdqth -- /bin/bash
Let's get a list of directories/folders inside the container by running ls
which stands for lists.
The above output shows the Linux directory structure inside our my-sql container.
Let's run mysql -p
which will prompt for the password to be entered.
Remember we set the password to secret-password. Type it in and you will be presented with an output similar to this:
You may leave the container by running exit
.
Conclusion
And there you have it, your journey into the world of Kubectl. We covered node and cluster management, application management, and updating and deleting applications, and even went as far as debugging your applications. Remember, mastering Kubectl takes practice but every command you learn brings you a step closer to becoming a Kubernetes master.
Keep this guide handy as you continue your Kubernetes exploration, and don't hesitate to experiment. The world of Kubernetes is dynamic and ever-expanding and Kubectl is your key to unlocking its full potential.
Top comments (2)
good article and definitely bookmarked for future ref. only issue i see is in the linux install instructions it says:
sudo apt-get update && sudo apt-get
which is missing an important word.
Thanks, @gbhorwood for taking the time to point out this error. I have changed the Linux install instructions to only use Snap which is more straight to the point.