Lab_02 - The Declarative Model

Lab 02: The Declarative Model

In this lab, we will switch from imperative to declarative. We are no longer telling Kubernetes what to do (and in what order) - we are simply telling it „this is the desired end state”, and K8s will implement the required changes in order to reach it.

Running a Pod

Connect to the master node with your user credentials. Make sure that there are no pods already running on the system (in the default namespace).

Create a simple pod YAML file in your home directory - let’s call it s01-pod.yaml.

Note

You can use any text editor you wish for this task. If you do not have a favorite, I would recommend nano:

nano ~/01-pod.yaml

Populate the file with the necessary information in order to create an nginx pod. The name of the pod should be nginx01, and the image used should be nginx. Remember that you will need:

  • apiVersion (pods exist since v1)

  • kind (Pod) (the kind is PascalCase)

  • metadata, with a field called name (mandatory)

  • spec, listing at least one container, with a name and an image

Here is a starting point:

apiVersion: v1
kind: ...
metadata:
  name: ...
spec:
  containers:
    - image: ...
      name: ...

Solution

apiVersion: v1
kind: Pod
metadata:
  name: nginx01
spec:
  containers:
    - image: nginx
      name: nginx

Run the pod on the cluster.

Hint

You can use kubectl apply or kubectl create, with the -f argument specifying the file to use.

Solution

kubectl apply -f 01-pod.yaml

Verify that the pod has been created and is running. On which host has the pod been scheduled?

Solution

kubectl get pod

Get the IP address of the pod. Connect to the IP address using curl to verify that the web server is serving content.

Hint

You could use kubectl describe to get the IP address, but it is also included in the output of kubectl get pod -o wide.

Solution

kubectl get pod -o wide
curl IP_ADDRESS

Getting Possible Options

There are many possible options that could be used in the YAML file. The easiest way to take a look at them is to see the actual configuration of your pod (the way Kubernetes sees it). Display the pod configuration in YAML format.

Hint

kubectl get pod -o yaml

Note

The status section is dynamically populated by Kubernetes at runtime (so it cannot be part of the original YAML file, used to create the pod). Focus on the spec section.

Solution

kubectl get pod nginx01 -o yaml

What is the restart policy of the pod?

Hint

Look for restartPolicy.

Note

Since we did not specify this field as part of the original YAML file, it has been populated with the default value.

For a full list of configuration options, try the following command:

kubectl explain pod --recursive

Note

It is strongly recommended to pipe it to the less command - there are many pages of possible options…

Print out the pod configuration in JSON format.

Not as easy to read by a human, is it? (although the fact that k8s pretty-prints it by default does help) However, it is much easier to parse by machines - including command-line tools such as jq.

Solution

kubectl get pod nginx01 -o json

Challenge: Speaking of jq - can you write a single command that prints out only the IP address of a specific pod?

Note

This is not easy in the beginning (it requires you to look up and understand the syntax used by jq to extract specific fields). However, it is a very useful thing to master if you ever need to deal with JSON-formatted data.

Solution

kubectl get pod nginx01 -o json | jq -r .status.podIP

Create another file (02-alpine.yaml) that starts an alpine pod. The name of the pod should be alpine01, and the image used should be alpine. Create the pod based on this file.

Solution

02-alpine.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: alpine01
spec:
  containers:
    - image: alpine
      name: alpine
kubectl apply -f 02-alpine.yaml

Verify that the pod is running. What do you see?

Solution

You will see that the pod continuously crashes and is automatically restarted.

kubectl get pod

Check the details of the pod. What is the reason for this behavior?

Hint

kubectl describe pod

By default, the alpine image will try to run sh, which is a shell, and expects to receive input…

Solution

kubectl describe pod alpine01

Actually, the describe command is not that helpful - you will see that the container keeps crashing, but you will not see the actual reason…

Delete the pod. Edit the 02-alpine.yaml to fix the problem.

Hint

When running a shell (or any other type of program that expects input on stdin) inside a container, you need to use -it on the command line. The equivalent in YAML is to set stdin: true (-i) and tty: trues (-t) for the container (.spec.containers)

Solution

kubectl delete pod alpine01
apiVersion: v1
kind: Pod
metadata:
  name: alpine01
spec:
  containers:
    - image: alpine
      name: alpine
      stdin: true # <---
      tty: true # <---

Create a pod based on the new file, and verify that the pod starts correctly.

Solution

kubectl apply -f 02-alpine.yaml
kubectl get pod

Attach to the running shell on the alpine container.

Hint

In a previous lab, we have used kubectl exec to run a new process inside an existing container. This time, we want to attach to the existing, main process inside the container. For this, we will use kubectl attach.

You need to specify -it on the command line!

Solution

kubectl attach -it alpine01

Exit the shell (type exit or press Ctrl-D).

What happens?

Note

If you have attached to the main process inside the container, and then stopped that process, the container is stopped. However, Kubernetes automatically restarts it - you will see the number of restarts incrementing.

kubectl get pod

Optional: RestartPolicy

Let’s explore the possible restart policies… The status of the container is dictated by its exit code - 0 means „success”, a non-zero code means „error”. To simulate this, we will attach to the container and use the commands exit 0 (for success), or exit 1 (for failure).

Attach to the running alpine container. Type exit 0. What happens?

Hint

this is a „success”. The container status will briefly change to „Completed”, and then the pod will be restarted.

Solution

kubectl attach -it alpine01
exit 0
kubectl get pod

Once the pod is running again, reattach to it. This time, type exit 1. What happens?

Hint

This is „exit with an error”. The container status will change to „Error”, and then the pod will be restarted.

Solution

kubectl attach -it alpine01

Delete the pod. Change the YAML file so that restartPolicy (under spec) is set to OnFailure.

Solution

kubectl delete pod alpine01
apiVersion: v1
kind: Pod
metadata:
  name: alpine01
spec:
  containers:
    - image: alpine
      name: alpine
      stdin: true
      tty: true
  restartPolicy: OnFailure # <---

Create a new pod based on the changed file.

Solution

kubectl apply -f 02-alpine.yaml

Attach to the running alpine container again. Type exit 0. What is different this time?

Solution

kubectl attach -it alpine01
exit 0
kubectl get pod

This time the pod is restarted only when it exits due to an error. Once the pod completes execution successfully, it remains stopped.

Optional: Running Multiple Pods

Create a single file ( 03-pods.yaml ) that starts both an alpine and an nginx pod.

Hint

The easiest way to do this is to simply use two yaml documents (separated by --- ) inside a single file.

Solution

03-pods.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: nginx02
spec:
  containers:
    - image: nginx
      name: nginx
---
apiVersion: v1
kind: Pod
metadata:
  name: alpine02
spec:
  containers:
    - image: alpine
      name: alpine
      stdin: true
      tty: true

Apply the file and verify that the two pods get created correctly.

Solution

kubectl apply -f 03-pods.yaml
kubectl get pod

Cleaning Up

Delete all pods.

Solution

kubectl delete pods --all

Last updated