Getting started with Kubectl

Overview

Teaching: 10 min
Exercises: 0 min
Questions
  • What is Kubectl?

  • How to use Kubectl commands?

Objectives
  • Learn what the kubectl command can do

  • Learn how to set up different services/resources to get the most of your cluster

K8s - Imperative vs Declarative programming

In the context of Kubernetes, imperative and declarative are two different paradigms used to define and manage the desired state of resources within a cluster. While imperative commands are useful for ad-hoc tasks or interactive exploration, the declarative approach is more suitable for managing and maintaining resources in a Kubernetes cluster efficiently. Let’s explore each approach! But first, we need a tool to interact with our cluster.

Kubectl

The kubectl command-line tool is a powerful utility provided by Kubernetes that allows you to interact with and manage Kubernetes clusters. Both Minikube and K8s on Docker Desktop come with a built-in kubectl installation. Use the following syntax to run kubectl commands from your terminal window:

kubectl [command] [TYPE] [NAME] [flags]

Where:

Do not forget to go through the setup episode to get your environment up and running. Also, check out the kubectl cheat sheet.

Windows Users - Reminder

To enable Kubernetes on WSL2, you have two options: activating Kubernetes in Docker Desktop or installing Minikube following the Linux option on WSL2 Ubuntu. It’s important to note that the Windows instructions for the Minikube installation guide users to PowerShell, but running the CMSSW container there will cause issues. Therefore, it is necessary to execute those commands within the Ubuntu shell.

Docker desktop needs to be running in the background in order for Minikube to start. From a terminal with administrator access (but not logged in as root), run:

minikube start
If you have already installed kubectl and it is pointing to some other environment, such as docker-desktop or a GKE cluster, ensure you change the context so that kubectl is pointing to minikube:
kubectl config use-context minikube

If minikube fails to start, see the drivers page for help setting up a compatible container or virtual-machine manager.

Congratulations! You have successfully activated Minikube. You can now use Kubernetes to deploy and manage containerized applications on your local machine. Remember to familiarize yourself with Kubernetes concepts and commands to make the most of its capabilities.

To enable Kubernetes in Docker Desktop, in support to the documentation follow these steps:
  1. From the Docker Dashboard, select the Settings.
  2. Select Kubernetes from the left sidebar.
  3. Next to Enable Kubernetes, select the checkbox.
  4. Select Apply & Restart to save the settings and then click Install to confirm. This instantiates images required to run the Kubernetes server as containers, and installs the /usr/local/bin/kubectl command on your machine.
If you have already installed kubectl and it is pointing to some other environment, such as minikube or a GKE cluster, ensure you change the context so that kubectl is pointing to docker-desktop:
kubectl config use-context docker-desktop
You can test the command by listing the available nodes:
kubectl get nodes

Congratulations! You have successfully activated Docker Desktop Kubernetes. You can now use Kubernetes to deploy and manage containerized applications on your local machine. Remember to familiarize yourself with Kubernetes concepts and commands to make the most of its capabilities.

Imperative Approach

In the imperative approach, you specify the exact sequence of commands or actions to be performed to create or modify Kubernetes resources. You interact with the Kubernetes API by issuing explicit instructions.

Let’s first create a node running Nginx by using the imperative way.

Create the pod using the Imperative way
kubectl run mynginx --image=nginx
Get a list of pods and their status
kubectl get pods

Output

The status of the pod is “ContainerCreating,” which means that Kubernetes is currently in the process of creating the container for the pod. The “0/1” under the “READY” column indicates that the pod has not yet reached a ready state.

NAME      READY   STATUS              RESTARTS   AGE
mynginx   0/1     ContainerCreating   0          5s

Once the pod is successfully created and the container is running, the status will change to “Running” or a similar value, and the “READY” column will reflect that the pod is ready.

NAME      READY   STATUS              RESTARTS   AGE
mynginx   1/1     Running             0          70s
Get more info
kubectl get pods -o wide

Output

The updated output indicates that the pod named “mynginx” is now successfully running and ready to serve requests.

NAME      READY   STATUS    RESTARTS   AGE     IP             NODE       NOMINATED NODE   READINESS GATES
mynginx   1/1     Running   0          4m23s   10.244.0.122   minikube   <none>           <none>
kubectl describe pod mynginx

Output

The status of the pod is “ContainerCreating,” which means that Kubernetes is currently in the process of creating the container for the pod. The “0/1” under the “READY” column indicates that the pod has not yet reached a ready state.

Name:             mynginx                                     # Pod name
Namespace:        default                                     # Namespace of the Pod
Priority:         0                                           # Priority assigned to the Pod
Service Account:  default                                     # Service account used by the Pod
Node:             minikube/192.168.49.2                       # Node where the Pod is running
Start Time:       Thu, 01 Jun 2023 18:46:23 -0500             # Time when the Pod started
Labels:           run=mynginx                                 # Labels assigned to the Pod
Annotations:      <none>                                      # Annotations associated with the Pod
Status:           Running                                     # Current status of the Pod
IP:               10.244.0.122                                # IP address assigned to the Pod
IPs:
  IP:  10.244.0.122                                           
Containers:
  mynginx:
    Container ID:   docker://c22dce8c953394...               # ID of the container
    Image:          nginx                                    # Image used by the container
    Image ID:       docker-pullable://nginx@sha256:af296b... # ID of the container image
    Port:           <none>                                   # Port configuration for the container
    Host Port:      <none>                                   # Host port configuration for the container
    State:          Running                                  # Current state of the container
      Started:      Thu, 01 Jun 2023 18:46:50 -0500          # Time when the container started
    Ready:          True                                     # Indicates if the container is ready
    Restart Count:  0                                        # Number of times the container has been restarted
    Environment:    <none>                                   # Environment variables set for the container
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from...  # Mount points for the container
Conditions:
  Type              Status                                    # Various conditions related to the Pod's status
  Initialized       True                                      # Pod has been initialized
  Ready             True                                      # Pod is ready
  ContainersReady   True                                      # Containers are ready
  PodScheduled      True                                      # Pod has been scheduled
Volumes:
  kube-api-access-hvg8b:                                      # Volumes used by the Pod
    Type:                    Projected
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort                         # Quality of service class for the Pod
Node-Selectors:              <none>                             # Node selectors for the Pod
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age    From               Message         # Events related to the Pod
  ----    ------     ----   ----               -------
  Normal  Scheduled  7m32s  default-scheduler  Successfully assigned default/mynginx to minikube
  Normal  Pulling    7m32s  kubelet            Pulling image "nginx"
  Normal  Pulled     7m5s   kubelet            Successfully pulled image "nginx" in 26.486269096s (26.486276637s including waiting)
  Normal  Created    7m5s   kubelet            Created container mynginx
  Normal  Started    7m5s   kubelet            Started container mynginx
Delete the pod
kubectl delete pod mynginx

Declarative Approach

In the declarative approach, you define the desired state of Kubernetes resources in a declarative configuration file (e.g., YAML or JSON). Rather than specifying the steps to achieve that state, you describe the desired outcome and let Kubernetes handle the internal details.

Create a pod using the declarative way

Download the file:

wget https://cms-opendata-workshop.github.io/workshop2023-lesson-introcloud/files/kubectl/myapp.yaml

YAML File

This YAML file describes a Pod with an nginx web server container that listens on port 80 and has an environment variable set. The specific behavior and functionality of the nginx web server will depend on the configuration of the nginx image used.

# myapp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80
    env:
    - name: DBCON
      value: myconnectionstring

Now, let’s create a pod using the YAML file

kubectl create -f myapp.yaml

Get some info

kubectl get pods -o wide
kubectl describe pod myapp-pod

Open a shell in the running pod

kubectl exec -it myapp-pod -- bash

Output

We used the command to execute an interactive shell session within the “myapp-pod” pod. After executing this command, you are now inside the pod and running commands as the “root” user. The prompt “root@myapp-pod:/#” indicates that you are currently in the pod’s shell environment and can run commands.

root@myapp-pod:/#

Print the DBCON environment variable that was set in the YAML file.

echo $DBCON

Output

The command “echo $DBCON” is used to print the value of the environment variable “DBCON”.

root@myapp-pod:/# echo $DBCON
myconnectionstring

Exit from the container

exit

Delete the pod

kubectl delete -f myapp.yaml

The declarative approach is the recommended way to manage resources in Kubernetes. It promotes consistency, reproducibility, and automation. You can easily version control the configuration files, track changes over time, and collaborate with team members more effectively.

Let’s run a few examples.

Kubernetes namespaces partition resources in a cluster, creating isolated virtual clusters. They allow multiple teams or applications to coexist while maintaining separation and preventing conflicts.

Get the currently configured namespaces:

kubectl get namespaces
kubectl get ns

Both commands are equivalent and will retrieve the list of namespaces in your Kubernetes cluster.

Get the pods list:

Get a list of all the installed pods.

kubectl get pods

You get the pods from the default namespace. Try getting the pods from the docker namespace. You will get a different list.

kubectl get pods -n kube-system

Output

The command “kubectl get pods –namespace=kube-system” is used to retrieve information about the pods running in the “kube-system” namespace.

NAME                               READY   STATUS    RESTARTS        AGE
coredns-787d4945fb-62wpc           1/1     Running   9 (4d19h ago)   34d
etcd-minikube                      1/1     Running   8 (4d19h ago)   34d
kube-apiserver-minikube            1/1     Running   9 (4d19h ago)   34d
kube-controller-manager-minikube   1/1     Running   9 (4d19h ago)   34d
kube-proxy-hm78n                   1/1     Running   8 (4d19h ago)   34d
kube-scheduler-minikube            1/1     Running   8 (4d19h ago)   34d
storage-provisioner                1/1     Running   16 (18m ago)    34d

Get nodes information:

Get a list of all the installed nodes. Using Docker Desktop or Minikube, there should be only one.

kubectl get nodes

Get some info about the node.

kubectl describe node

Output

The output provides details about each node, including its name, status, roles, age, and version.

NAME       STATUS   ROLES           AGE   VERSION
minikube   Ready    control-plane   34d   v1.26.3

Run your first deployment

A Deployment is a higher-level resource that provides declarative updates and manages the deployment of Pods. It allows you to define the desired state of your application, including the number of replicas, container images, and resource requirements.
Download the file:

wget https://cms-opendata-workshop.github.io/workshop2023-lesson-introcloud/files/kubectl/deploy-example.yaml

YAML File

This Deployment will create and manage three replicas of an nginx container based on the nginx:alpine image. The Pods will have resource requests and limits defined, and the container will expose port 80. The Deployment ensures that the desired state of the replicas is maintained, managing scaling and updating as needed.

# deploy-example.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-example
spec:
  replicas: 3
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: nginx
      env: prod
  template:
    metadata:
      labels:
        app: nginx
        env: prod
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 250m
            memory: 256Mi        
        ports:
        - containerPort: 80

Create the Deployment:

kubectl apply -f deploy-example.yaml

Get the pods list

kubectl get pods -o wide

Output

Deployments are Kubernetes resources that manage the lifecycle of replicated pods, ensuring high availability, scalability, and automated healing, while ReplicaSets are used by deployments to maintain a desired number of pod replicas, enabling rolling updates and fault tolerance.

NAME                             READY   STATUS              RESTARTS   AGE   IP       NODE       NOMINATED NODE   READINESS GATES
deploy-example-54fbc9897-56s28   0/1     ContainerCreating   0          4s    <none>   minikube   <none>           <none>
deploy-example-54fbc9897-9twh8   0/1     ContainerCreating   0          4s    <none>   minikube   <none>           <none>
deploy-example-54fbc9897-lng78   0/1     ContainerCreating   0          4s    <none>   minikube   <none>           <none>

All three pods are currently in the “ContainerCreating” state, indicating that the containers are being created for these pods. After some time you will get:

NAME                             READY   STATUS    RESTARTS   AGE   IP             NODE       NOMINATED NODE   READINESS GATES
deploy-example-54fbc9897-56s28   1/1     Running   0          42s   10.244.0.126   minikube   <none>           <none>
deploy-example-54fbc9897-9twh8   1/1     Running   0          42s   10.244.0.124   minikube   <none>           <none>
deploy-example-54fbc9897-lng78   1/1     Running   0          42s   10.244.0.125   minikube   <none>           <none>

Get more details about the pod

kubectl describe pod deploy-example

Output

The output shows three running pods named “deploy-example-54fbc9897-56s28”, “deploy-example-54fbc9897-9twh8”, and “deploy-example-54fbc9897-lng78” in the “default” namespace. These pods are controlled by the ReplicaSet “deploy-example-54fbc9897” and are running the “nginx:alpine” image. They have successfully pulled the image, created the container, and started running. Each pod has an IP assigned, and they are running on the “minikube” node.

Get the Deployment info

kubectl get deploy

Output

All 3 replicas are ready, up-to-date, and available, indicating that the deployment is successfully running.

NAME             READY   UP-TO-DATE   AVAILABLE   AGE
deploy-example   3/3     3            3           4m57s

Get the ReplicaSet name:

A ReplicaSet is a lower-level resource that ensures a specified number of replicas of a Pod are running at all times.

kubectl get rs

Output

The current replica count matches the desired count, indicating that the ReplicaSet has successfully created and maintained 3 replicas. All 3 replicas are ready and available.

NAME                       DESIRED   CURRENT   READY   AGE
deploy-example-54fbc9897   3         3         3       6m12s

In summary, a Deployment provides a higher-level abstraction for managing and updating the desired state of Pods, while a ReplicaSet is a lower-level resource that ensures the specified number of Pod replicas are maintained. Deployments use ReplicaSets under the hood to achieve the desired state and handle scaling and rolling updates.

Cleanup

Delete the pod

kubectl delete -f deploy-example.yaml

Key Points

  • kubectl is the ruler of GKE