Getting Started With Kubectl: A Guide To Kubernetes
Tags: devops, kubernetes, cloud, tutorial
Published: 2023-12-12 15:56:12



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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nh8v0ha0evkxxjcnslp7.png)
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](https://docs.fedoraproject.org/en-US/epel/epel-about/) 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!
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7cv0sr2ttpn1w48d3l3v.png)

## Verifying the Installation

After installation, verify that **`kubectl`** is working by running the command:

`kubectl version`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2j64pjim0z2nqb5vi301.png)

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.

```yaml
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: 

```yaml
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:

```yaml
minikube start --nodes 3
```

 When Minikube is done starting, you will be presented with the below output

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gbvwn9e4xdecrtpm7um.png)
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](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands).

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:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6lnjympimensj1dlkyt4.png)
### 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.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nyflpwkfe8y7yfd0mt22.png)
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:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mh0y5j25dnmkkxwn7yas.png)
### 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`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mt2aiwaqenci2cizrqqq.png)

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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gk559svq49nhetmqvbkp.png)

Pay attention to the output,unshedulable now says true.

Get it to run new pods by executing `kubectl uncordon minikube-m02`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/85mcmcpus1pkzxdxq5ra.png)

### 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.

1. kubectl drain is the main command that tells Kubernetes to prepare a particular node for maintenance.
2. minikube-m03 is our particular node for maintenance.
3. --ignore-daemonsets : this tells Kubernetes not to move certain essential tasks called daemonsets to other nodes.
4. --force : the force flag tells Kubernetes not to wait for resources to terminate gracefully.

Now hit enter.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w4kdqv8oq1fvjr68hieg.png)

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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zro9y551ad34mvoti41.png)

### 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`
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ke2n0f7cc27py8mpxwt.png)
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`
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs9g5ccadp3ky9uuj1d5.png)

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.

```yaml
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 :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p95wq2wulmdtvwssaohm.png)

Let's check the status of our deployment by running `kubectl get deployments`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lbybglral4haigui9ohr.png)

### 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:

```yaml
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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i43180hjj9x9tj163pub.png)
You may check the status of the service by running `kubectl get services`  which displays the output below 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y8bzzeyx3b7c6wgmelg1.png)

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:

```yaml
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.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/23v89abav4vrt66iwer2.png)

With our practice-pod.yaml file we created 2 pods. Let’s confirm this by running `kubectl get pods` 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/usevua63wjmteyfpssd5.png)

Get rid of these pods by running  `kubectl delete pods practice-pod-1 practice-pod-2`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzkcjcmlu81wg0v7aaq0.png)

## 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`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s2aspxsrncx1wa9xq7te.png)

Let’s run a quick command to get a description of our deployment. 

In your terminal, type `kubectl describe deployment my-deployment`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nyf9qeyyepi6t6b0pfjx.png)

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`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dqzkbk4vv62oq2zdm5a3.png)

Get the description of our deployment by running `kubectl describe deployment my-deployment`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87iw58wafmuvwauq7h7l.png)

### 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.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/97rh564vhdtjcxgrfgl9.png)

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.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dzi6tmu7ryoru8hajj0f.png)

Copy the EXTERNAL-IP, and open it in a browser.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/axx9gb511x6p9gk10zeh.png)

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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vmnco2kezgwmkrlaaubf.png)
Let’s delete my-service with  `kubectl delete service my-service` 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2khzr694ymr0nem7zbso.png)

Try to get my-service with `kubectl get service` and you will notice it is no longer there.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jil6d0d1jag5ao2g44nx.png)

Get the name of our deployment with `kubectl get deployments` and run `kubectl delete deployment my-deployment`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x9lvrkllkubhouvu1dcs.png)

Try to get our deployment with `kubectl get deployments` and you will get the below output:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gm0ctdi2e6cvcwvr87br.png)

## 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.

```yaml
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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7pgw2zlwcqrvlszwpgzi.png)

Try to get our deployment with `kubectl get deployments` and you will be presented with the output below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsbx6xwcaqydo64hjoz0.png)

For some reason,my-database deployment is not ready. Let’s get the pods in our deployment

Run `kubectl get pods`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vi67us5n7jdpg0n0ttih.png)

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`
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hrlticiiaboquaq9jmn7.png)

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:
```yaml
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`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jhm3ejrfokowjn5gntqr.png)

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`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gthez1m0nozae2akiyiw.png)
Second  I will get the pod name and exec into the container with 
`kubectl exec -it my-database-7c8c774899-jdqth -- /bin/bash`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xqfexg5z2hzfayid204n.png)
Let's get a list of directories/folders inside the container by running `ls` which stands for lists.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/moce8no7eegtp269ilev.png)
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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tnswkpesl5swmkb0ogqy.png)
Remember we set the password to secret-password. Type it in and you will be presented with an output similar to this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/02yy2emllbktdlq66g3q.png)

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.