To interact with a Kubernetes cluster, what we use the most is ‘Kubectl’. Kubectl is a Command line Interface for communicating with a Kubernetes cluster’s control plane using the Kubernetes API. Therefore, it is important to know some of the basic Kubectl commands in order to work with Kubernetes.
A Kubectl command usually takes the kubectl <action> <resource> <flags>
format.
Eg: kubectl get pods -n default
Create Resources
To create Kubernetes resources we can use the kubectl create
command.
$ kubectl create deployment nginx --image=nginx:stable-alpine
deployment.apps/nginx created
Above example will create a Deployment named ‘nginx’ using the ‘nginx:stable-alpine’ from Docker Hub.
To run a pod instead of creating a deployment, we can use the kubectl run
command as below.
$ kubectl run nginx-pod --image=nginx:stable-alpine
pod/nginx-pod created
The above command will start a single instance of an Nginx pod.
However, we don’t create resources in this manner by running kubectl create
commands in Kubernetes. Instead, we use Kubernetes manifest files. Kubernetes manifest files are configuration files written in YAML that allow us to define how resources should run, connect to other resources etc.. We will discuss about Kubernetes manifest files at length in a future article.
To create or update resources using manifest files, we use kubectl apply
command as shown below.
$ kubectl apply -f mobile-app-ws.yaml
deployment.apps/mobile-app-ws created
service/mobile-app-ws-service created
In the above example, I have passed a manifest file named mobile-app-ws.yaml
with a -f
flag. And as a result, we can see that a Deployment and a Service has been created. In the next article of this Kubernetes series, we are looking into Kubernetes manifests in detail.
Edit Resources
To edit Kubernetes resources we can use the kubectl edit
command.
$ kubectl edit deployment nginx
deployment.apps/nginx edited
In the above example, I am editing the Nginx Deployment I created. Once the command is run, the default editor will open the configuration for the resource and we can do any changes in it. Once the file is saved and exited, the command line will show the output as shown above.
Alternatively, we can simply make the change in our manifest file for the resource and then use the kubectl apply command in the same manner we used it to create the resource.
For an example, if I make a small change in the manifest file for a certain resource and apply it, the output would look like below.
$ kubectl apply -f mobile-app-ws.yaml
deployment.apps/mobile-app-ws configured
service/mobile-app-ws-service unchanged
Delete Resources
To delete Kubernetes resources we can use the kubectl delete
command.
$ kubectl delete deployment nginx
deployment.apps "nginx" deleted
In the above example, I am deleting the Nginx Deployment I created. Likewise, you can delete other resources too.
Get/List Resources
To view or list resources we can use kubectl get
command.
In below example I have run kubectl get services
command to list all the services.
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d3h
mobile-app-ws-service LoadBalancer 10.102.15.204 <pending> 80:30080/TCP 6m12s
mysql-service ClusterIP 10.103.70.48 <none> 3306/TCP 6m25s
As you can see, there are 3 Services on this occasion. We can see some details like Service name, type, IP address and ports.
Likewise, we can run this command to list down other resources as well. Some more examples below.
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
mobile-app-ws 2/2 2 2 63m
mysql 1/1 1 1 63m
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mobile-app-ws-86b9d5ddcb-r6l2s 1/1 Running 0 62m
mobile-app-ws-86b9d5ddcb-wq5c2 1/1 Running 0 11s
mysql-984c75797-vqsjc 1/1 Running 0 62m
Wide Output
To get a little bit more details about the resources, we can modify the command by specifying -o wide
flag as below.
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mobile-app-ws-86b9d5ddcb-r6l2s 1/1 Running 0 63m 172.17.0.4 minikube <none> <none>
mobile-app-ws-86b9d5ddcb-wq5c2 1/1 Running 0 66s 172.17.0.5 minikube <none> <none>
mysql-984c75797-vqsjc 1/1 Running 0 63m 172.17.0.3 minikube <none> <none>
Get Details of a Specific Object
If we needed to see the details of only a specific pod, let’s say mobile-app-ws pod in the previous example, we can modify the kubectl get
command as below.
$ kubectl get pods mobile-app-ws-86b9d5ddcb-r6l2s
NAME READY STATUS RESTARTS AGE
mobile-app-ws-86b9d5ddcb-r6l2s 1/1 Running 0 20m
Notice that I have specified the pod name as a parameter to the command.
Specifying a Namespace
In Kubernetes, we use namespaces to logically organize our resources. When we run the kubectl get
command without specifying any namespace, it shows us the results for default namespace. If we need to fetch results for a specific namespace, then we can use the -n
flag with the command.
$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-64897985d-8szlb 1/1 Running 1 (47m ago) 4d3h
etcd-minikube 1/1 Running 1 (47m ago) 4d3h
kube-apiserver-minikube 1/1 Running 1 (47m ago) 4d3h
kube-controller-manager-minikube 1/1 Running 1 (47m ago) 4d3h
kube-proxy-4nk2m 1/1 Running 1 (47m ago) 4d3h
kube-scheduler-minikube 1/1 Running 1 (47m ago) 4d3h
storage-provisioner 1/1 Running 11 (46m ago) 4d3h
In above example, I am listing down the pods in kube-system namespace.
Get by Labels
In Kubernetes, we can specify labels to our resources(a label is basically a key value pair, and we will discuss these in detail later). These come in handy on many occasions.
For instance, I have specified a label as app=mobile-app-ws
for mobile-app-ws pods. If I need to get only mobile-app-ws pods, I can amend my kubectl get
command with a -l
flag as below.
$ kubectl get pods -l app=mobile-app-ws
NAME READY STATUS RESTARTS AGE
mobile-app-ws-86b9d5ddcb-r6l2s 1/1 Running 0 73m
mobile-app-ws-86b9d5ddcb-wq5c2 1/1 Running 0 11m
Notice that this time, only 2 mobile-app-ws pods have been fetched and the MySQL pod has been omitted from the output.
If you need to find out the labels assigned for certain pods or any other resource in the first place, you can run the kubectl get
command with --show-labels
flag as shown below.
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
mobile-app-ws-86b9d5ddcb-r6l2s 1/1 Running 0 77m app=mobile-app-ws,pod-template-hash=86b9d5ddcb
mobile-app-ws-86b9d5ddcb-wq5c2 1/1 Running 0 15m app=mobile-app-ws,pod-template-hash=86b9d5ddcb
mysql-984c75797-vqsjc 1/1 Running 0 78m app=mysql,pod-template-hash=984c75797
As you can see, this shows the labels assigned for each of the pods.
There are many other options available for the the get
command but these should be sufficient when getting started.
Verbose Details of Resources
To get verbose details of our resources, we can use the kubectl describe
command.
$ kubectl describe deployment mobile-app-ws
Name: mobile-app-ws
Namespace: default
CreationTimestamp: Sun, 03 Jul 2022 12:12:56 +0530
Labels: app=mobile-app-ws
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=mobile-app-ws
Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=mobile-app-ws
Containers:
mobile-app-ws:
Image: dcharith/mobile-app-ws:3.0
Port: 8080/TCP
Host Port: 0/TCP
Environment:
DB_HOST: <set to the key 'DB_HOST' of config map 'mobile-app-ws-configmap'> Optional: false
DB_USERNAME: <set to the key 'DB_USERNAME' in secret 'mobile-app-ws-secret'> Optional: false
DB_PASSWORD: <set to the key 'DB_PASSWORD' in secret 'mobile-app-ws-secret'> Optional: false
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Progressing True NewReplicaSetAvailable
Available True MinimumReplicasAvailable
OldReplicaSets: <none>
NewReplicaSet: mobile-app-ws-86b9d5ddcb (2/2 replicas created)
Events: <none>
In the above example, I have described one of my deployments. And as you can see, there is a lot of information about the deployment such as the number of replicas, the pod template along with information such as the image used, ports, environment variables etc. and events related to the deployment.
Likewise, you can describe other resources as well to get a detailed output.
View Logs
To view logs related to our application pods, we can use kubectl logs
command.
$ kubectl logs mobile-app-ws-86b9d5ddcb-lqjdv
NOTE: Picked up JDK_JAVA_OPTIONS: --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
03-Jul-2022 06:42:57.913 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/8.5.81
03-Jul-2022 06:42:57.963 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Jun 8 2022 21:30:15 UTC
03-Jul-2022 06:42:57.963 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 8.5.81.0
03-Jul-2022 06:42:57.963 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux
As you can see above, we need to specify the name of our pod to the kubectl logs
command.
You can also run this command for a Deployment as well, as shown below.
$ kubectl logs deployment/mobile-app-ws
Found 2 pods, using pod/mobile-app-ws-86b9d5ddcb-lqjdv
NOTE: Picked up JDK_JAVA_OPTIONS: --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
03-Jul-2022 06:42:57.913 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/8.5.81
03-Jul-2022 06:42:57.963 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Jun 8 2022 21:30:15 UTC
Interacting with Running Pods
To open an interactive terminal inside a pod, we can use the kubectl exec
command as below.
If you are on Windows and using a terminal like Git Bash, then you might run into some errors. In that case, use the regular Windows command line.
C:\Users\Charith>kubectl exec -it mysql-984c75797-49266 -- bash
root@mysql-984c75797-49266:/# pwd
/
The above example opens an interactive Bash shell inside the container. Once connected, I can run Bash commands in the shell.
Since we are inside a MySQL pod, let’s try to connect to the database.
C:\Users\Charith>kubectl exec -it mysql-984c75797-49266 -- bash
root@mysql-984c75797-49266:/# mysql -u charith -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 68
Server version: 8.0.29 MySQL Community Server - GPL
Copyright (c) 2000, 2022, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
Here I have connected to the MySQL pod using the kubectl exect command and successfully connected to the database using mysql -u charith -p
command. This will prompt for the password of the user. Once that is provided, I get a MySQL prompt where I can run SQL commands.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| photo_app |
+--------------------+
2 rows in set (0.00 sec)
mysql>
So I have run a simple show databases
query and it shows me the results as expected.
Hope you have some understanding of basic Kubectl commands now and how to use them. We will be using these commands and more when we deep dive into Kubernetes.