Kubernetes — Orchestration Guide [ A Lovely Symphony 4]

Covenant Chukwudi
MyCloudSeries
Published in
6 min readApr 29, 2019
kubernetes orchestration guide series — image credits: myTectra.com

This is a continuation of our Kubernetes orchestration guide series. We started from learning what Kubernetes is, to learning about some of the fundamental components of Kubernetes.

In our last series, we learned some basic but very important commands which enabled us to apply our configuration files to our Kubernetes cluster instructing it to create our ourapp service and ourapp pod.

In this section, we will continue our Kubernetes journey learning about it’s awesomeness.

Kubectl describe

This is another very useful command tool in the Kubernetes toolchain. It enables us to view more details about a specific Kubernetes resource than is normally available when kubectl get command is executed.

The format of the command is as follows:

kubectl describe <objecttype> <resourcename>

For example, running kubectl describe on ourapp-container pod gives us more information about our pod.

$ kubectl describe pod ourapp-container

For me, it returns this:

Name:               ourapp-container
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: minikube/10.0.2.15
Start Time: Sun, 28 Apr 2019 00:13:06 +0100
Labels: component=web
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"labels":{"component":"web"},"name":"ourapp-container","namespace":"default"},"spec":{"con...
Status: Running
IP: 172.17.0.3
Containers:
ourapp:
Container ID: docker://e80aa835b4a330cf5aa39a9d4aa2636b1a6040a79fc50834a8f2945756658f72
Image: nginx
Image ID: docker-pullable://covenant/dockerize-nodejs-image@sha256:c202c7a933b5cb861836875f2877847292652ffeeca4d6256f328f4a9aa33563
Port: 5000/TCP
Host Port: 0/TCP
State: Running
Started: Mon, 29 Apr 2019 09:24:33 +0100
Last State: Terminated
Reason: Error
Exit Code: 137
Started: Sun, 28 Apr 2019 00:36:00 +0100
Finished: Mon, 29 Apr 2019 09:22:22 +0100
Ready: True
Restart Count: 1
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-6m7xl (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-6m7xl:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-6m7xl
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:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedCreatePodSandBox 6m kubelet, minikube Failed create pod sandbox: rpc error: code = Unknown desc = failed to start sandbox container for pod "ourapp-container": Error response from daemon: failed to update store for object type *libnetwork.endpoint: open : no such file or directory
Normal Killing 6m kubelet, minikube Killing container with id docker://ourapp:Need to kill Pod
Normal SandboxChanged 4m (x2 over 6m) kubelet, minikube Pod sandbox changed, it will be killed and re-created.
Normal Pulling 4m (x2 over 1d) kubelet, minikube pulling image "covenant/dockerize-nodejs-image"
Normal Pulled 4m (x2 over 1d) kubelet, minikube Successfully pulled image "covenant/dockerize-nodejs-image"
Normal Created 4m (x2 over 1d) kubelet, minikube Created container
Normal Started 4m (x2 over 1d) kubelet, minikube Started container

As you can see, there is a whole lot of information being returned to us upon execution of the command.

One part I want us to focus on at the moment is the Events section, it provides event information and messages for us on life-cycle messages and status of our Pod and can be very useful when trying to debug issues with our Pod.

We will discuss extensively what the importance of other information being returned to us.

Updating A Pod Image

In our last series, we created “ourapp-container” pod by running the kubectl apply -f command against our ourapp.yaml file.

Kubernetes makes it very easy to declaratively change the application or code-base of containers currently running in a Pod.

To illustrate this, let’s change the container in “ourapp-container” pod (which is the name of our initially created pod in the last series) to run an nginx server instead.

We do this by editing the configuration file containing our pod definition i.e ourapp.yaml, changing the image attribute on the container section to nginx.

apiVersion: v1
kind: Pod
metadata:
name: ourapp-container
labels:
component: web
spec:
containers:
- name: ourapp
image: nginx #was formerly covenant/dockerize-nodejs-image
ports:
- containerPort: 5000

Next, start minikube if you don’t have it running

$ minikube start

then re-run the command:

$ kubectl apply -f ourapp.yaml

Kubernetes immediately understands to replace our former docker image which contains our nodejs code with nginx.

It might take some time for the nginx image to be fully applied depending on the connection speed of your internet as Kubernetes would have to pull nginx from docker-hub. You can monitor the status of your pod by simply running kubectl describe on it and check the messages under the Events section.

$kubectl describe pod ourapp-container

You might see something like this which means Kubernetes is still pulling the image:

Normal   Pulling     2m    kubelet, minikube  pulling image "nginx"

If you see additional messages like this, it means your container is up and perfectly fine running nginx:

Normal  Pulling    2m    kubelet, minikube  pulling image "nginx"
Normal Pulled 1s kubelet, minikube Successfully pulled image "nginx"
Normal Created 1s kubelet, minikube Created container
Normal Started 1s kubelet, minikube Started container

Congratulations, You’ve successfully updated a Pod’s container’s image.

Nginx listens on port 80 as opposed to our nodejs code which listened on port 5000. In order to test our updated setup from the browser, we have to modify the port specification in the config files accordingly.

We start by modifying our containerPort attribute in our pod configuration file i.e ourapp.yaml to use 80 instead

apiVersion: v1
kind: Pod
metadata:
name: ourapp-container
labels:
component: web
spec:
containers:
- name: ourapp
image: nginx #was formerly covenant/dockerize-nodejs-image
ports:
- containerPort: 80 #formerly 5000

We execute kubectl apply -f command to apply this change:

$ kubectl apply -f ourapp.yaml

On executing the above command, you will notice this error come up which essentially tells us that we are not allowed to modify port attribute of a Pod’s container on-the-fly:

The Pod "ourapp-container" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations

We will introduce another type of Kubernetes object later that will allow us update such attributes but for now, we delete the pod before running kubectl apply -f, so we execute this first:

$ kubectl delete pod ourapp-container

then we execute this:

$ kubectl apply -f ourapp.yaml

Next, we update the “targetPort” in our service definition file i.e ourapp-node.yaml file to point to 80 also.

apiVersion: v1
kind: Service
metadata:
name: ourapp-node
spec:
type: NodePort
ports:
- port: 5050
targetPort: 80 #formerly 5000
nodePort: 30001
selector:
component: web

We also execute kubectl apply -f against our service file to apply the change:

$kubectl apply -f ourapp-node.yaml

If you had any errors or difficulties in executing any of these commands, do let me know.

Congratulations if you successfully came this far, now we can access our new setup. To do this, first execute minikube ip on the terminal to get the ip address of your virtual machine.

Next, type the ip address returned back to you together with the nodePort port number defined in your services file and you should see the nginx homepage similar to this:

successfully updated image

That’s it, we’ve successfully updated the our container image in our pod.

Sticky Notes

  1. We use kubectl describe command when we want to see detailed information about a Kubernetes resources such as pod, service, deployment e.t.c
  2. The format of a kubectl describe command is as follows: kubectl describe <objecttype> <resourcename>.
  3. Kubernetes is so powerful that it allows us to declaratively make changes to a Kubernetes resource.
  4. Kubernetes allows us to update the image of a container in a pod by simply changing the image attribute on the configuration file and executing kubectl apply -f against it.
  5. Not all attributes on a pod can be updated directly like that when the pod is running, some attribute such as Ports require you to delete the pod before such changes can be applied.

Conclusion

Kubernetes is not only a powerful orchestration ecosystem but also has an intelligent and efficient tool chain.

Ahead of our next article in this series, revert your ourapp.yaml file to its initial state to read this:

apiVersion: v1
kind: Pod
metadata:
name: ourapp-container
labels:
component: web
spec:
containers:
- name: ourapp
image: covenant/dockerize-nodejs-image
ports:
- containerPort: 5000

and your ourapp-node.yaml file also:

apiVersion: v1
kind: Service
metadata:
name: ourapp-node
spec:
type: NodePort
ports:
- port: 5050
targetPort: 5000
nodePort: 30001
selector:
component: web

MyCloudSeries is a training and consulting firm with expertise in Cloud Computing and DevOps. We assist organizations in their DevOps strategies, transformation, and implementation. We also provide Cloud Computing Support contact us at www.mycloudseries.com

--

--

Covenant Chukwudi
MyCloudSeries

I build products that would have positive effect on lives