5.1 kubectl Basics

The kubectl utility is a command line tool that interfaces with the API Server to run commands against the cluster. The tool is typically run on the master node of the cluster. It effectively grants full administrative rights to the cluster and all of the nodes in the cluster.

The kubectl utility is documented fully at:

https://kubernetes.io/docs/user-guide/kubectl-overview/

In this section, we describe basic usage of the tool to get you started creating and managing pods and services within your environment.

Get Information About the Nodes in a Cluster

To get a listing of all of the nodes in a cluster and the status of each node, use the kubectl get command. This command can be used to obtain listings of any kind of resource that Kubernetes supports. In this case, the nodes resource:

$ kubectl get nodes
NAME                   STATUS    ROLES   AGE      VERSION
master.example.com     Ready     master  1h       v1.12.5+2.1.1.el7
worker1.example.com    Ready     <none>  1h       v1.12.5+2.1.1.el7
worker2.example.com    Ready     <none>  1h       v1.12.5+2.1.1.el7

You can get more detailed information about any resource using the kubectl describe command. If you specify the name of the resource, the output is limited to information about that resource alone; otherwise, full details of all resources are also printed to screen:

$ kubectl describe nodes worker1.example.com
Name:               worker1.example.com
Roles:              <none>   
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/hostname=worker1.example.com
Annotations:        flannel.alpha.coreos.com/backend-data: {"VtepMAC":"f2:24:33:ab:be:82"}
                    flannel.alpha.coreos.com/backend-type: vxlan
                    flannel.alpha.coreos.com/kube-subnet-manager: true
                    flannel.alpha.coreos.com/public-ip: 10.147.25.196
                    kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
...

Run an Application in a Pod

To create a pod with a single running Docker container, you can use the kubectl create command:

$ kubectl create deployment --image nginx hello-world
deployment.apps/hello-world created

Substitute hello-world with a name for your deployment. Your pods are named by using the deployment name as a prefix. Substitute nginx with a Docker image that can be pulled by the Docker engine.

Tip

Deployment, pod and service names conform to a requirement to match a DNS-1123 label. These must consist of lower case alphanumeric characters or -, and must start and end with an alphanumeric character. The regular expression that is used to validate names is '[a-z0-9]([-a-z0-9]*[a-z0-9])?'. If you use a name, for your deployment, that does not validate, an error is returned.

There are many additional optional parameters that can be used when you run a new application within Kubernetes. For instance, at run time, you can specify how many replica pods should be started, or you might apply a label to the deployment to make it easier to identify pod components. To see a full list of options available to you, run kubectl run -h.

To check that your new application deployment has created one or more pods, use the kubectl get pods command:

$ kubectl get pods
NAME                           READY     STATUS    RESTARTS   AGE
hello-world-5f55779987-wd857   1/1       Running   0          1m

Use kubectl describe to show a more detailed view of your pods, including which containers are running and what image they are based on, as well as which node is currently hosting the pod:

$ kubectl describe pods
Name:               hello-world-5f55779987-wd857
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               worker1.example.com/192.0.2.11
Start Time:         Mon, 10 Dec 2018 08:25:17 -0800
Labels:             app=hello-world
                    pod-template-hash=5f55779987
Annotations:        <none>
Status:             Running
IP:                 10.244.1.3
Controlled By:      ReplicaSet/hello-world-5f55779987
Containers:
  nginx:
    Container ID:   docker://417b4b59f7005eb4b1754a1627e01f957e931c0cf24f1780cd94fa9949be1d31
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:5d32f60db294b5deb55d078cd4feb410ad88e6fe77500c87d3970eca97f54dba
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Mon, 10 Dec 2018 08:25:25 -0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s8wj4 (ro)
Conditions:
  Type              Status   
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-s8wj4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s8wj4
    Optional:    false
QoS Class:       BestEffort  
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
....

Scale a Pod Deployment

To change the number of instances of the same pod that you are running, you can use the kubectl scale deployment command:

$ kubectl scale deployment --replicas=3 hello-world
deployment.apps/hello-world scaled

You can check that the number of pod instances has been scaled appropriately:

$ kubectl get pods
NAME                           READY     STATUS    RESTARTS   AGE
hello-world-5f55779987-tswmg   1/1       Running   0          18s
hello-world-5f55779987-v8w5h   1/1       Running   0          26m
hello-world-5f55779987-wd857   1/1       Running   0          18s

Expose a Service Object for Your Application

Typically, while many applications may only need to communicate internally within a pod, or even across pods, you may need to expose your application externally so that clients outside of the Kubernetes cluster can interface with the application. You can do this by creating a service definition for the deployment.

To expose a deployment using a service object, you must define the service type that should be used. If you are not using a cloud-based load balancing service, you can set the service type to NodePort. The NodePort service exposes the application running within the cluster on a dedicated port on the public IP address on all of the nodes within the cluster. Use the kubectl expose deployment to create a new service:

$ kubectl expose deployment hello-world --port 80 --type=LoadBalancer
service/hello-world exposed

Use kubectl get services to list the different services that the cluster is running, and to obtain the port information required to access the service:

$ kubectl get services
NAME          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
hello-world   LoadBalancer   10.102.42.160   <pending>     80:31847/TCP   3s
kubernetes    ClusterIP      10.96.0.1       <none>        443/TCP        5h13m

In this example output, you can see that traffic to port 80 inside the cluster is mapped to the NodePort 31847. The external IP that can be used to access the service is listed as <pending>, meaning that if you connect to the external IP address for any of the nodes within the cluster on the port 31847, you are able access the service.

For the sake of the example in this guide, you can open a web browser to point at any of the nodes in the cluster, such as http://worker1.example.com:31847/, and it should display the NGINX demonstration application.

Delete a Service or Deployment

Objects can be deleted easily within Kubernetes so that your environment can be cleaned. Use the kubectl delete command to remove an object.

To delete a service, specify the services object and the name of the service that you want to remove:

$ kubectl delete services hello-world

To delete an entire deployment, and all of the pod replicas running for that deployment, specify the deployment object and the name that you used to create the deployment:

$ kubectl delete deployment hello-world

Work With Namespaces

Namespaces can be used to further separate resource usage and to provide limited environments for particular use cases. By default, Kubernetes configures a namespace for Kubernetes system components and a standard namespace to be used for all other deployments for which no namespace is defined.

To view existing namespaces, use the kubectl get namespaces and kubectl describe namespaces commands.

The kubectl command only displays resources in the default namespace, unless you set the namespace specifically for a request. Therefore, if you need to view the pods specific to the Kubernetes system, you would use the --namespace option to set the namespace to kube-system for the request. For example, in a cluster with a single master node:

$ kubectl get pods --namespace=kube-system
NAME                                         READY   STATUS    RESTARTS   AGE
coredns-6c77847dcf-77grm                     1/1     Running   2          5h26m
coredns-6c77847dcf-vtk8k                     1/1     Running   2          5h26m
etcd-master.example.com                      1/1     Running   3          5h25m
kube-apiserver-master.example.com            1/1     Running   4          5h25m
kube-controller-manager-master.example.com   1/1     Running   4          5h25m
kube-flannel-ds-4c285                        1/1     Running   0          115m
kube-flannel-ds-ds66r                        1/1     Running   0          115m
kube-proxy-5lssw                             1/1     Running   0          117m
kube-proxy-tv2mj                             1/1     Running   3          5h26m
kube-scheduler-master.example.com            1/1     Running   3          5h25m
kubernetes-dashboard-64458f66b6-q8dzh        1/1     Running   4          5h26m