Kubernetes - Pods
Lab assignment for creating pods using kubectl
Prerequisites
- Kubernetes
- kubectl
Assignment
- Create a nginx webserver by running a simple pod with a single nginx container
1
kubectl run nginx --image=nginx
- Query our running pods
1
kubectl get pods
- Check the logs of the pod using the
1
kubectl logs pod/nginx
- Query the running pods with the -o option to get more information including it’s IP address
1
kubectl get pods -o wide
- Capture the IP address for this pod and confirm that we can ping it from control plane
1
NGINX_IP=$(kubectl get pods -o wide | awk '/nginx/ { print $6 }'); echo $NGINX_IP
1
ping -c 3 $NGINX_IP
- We can verifiy if the pod is accessible from other nodes in the cluster
1
ssh <node-name> ping -c 3 $NGINX_IP
- You can use port-forward to forward the port on the localhost and access the nginx webpage from the browser
1
kubectl port-forward pod/nginx 8080:80
- Navigate to http://localhost:8080 and verify that you are able to access the page.
We can also query the nginx pod by running curl, in another pod and pointing it at the pod IP address -
```sh kubectl run -it –rm curl –image=curlimages/curl:8.4.0 –restart=Never – http://$NGINX_IP
You’ll see that this pod, automatically cleaned itself after it was run owing to the –rm option -
```sh kubectl get pods -o wide
Let’s explore an alternative approach, we’ll run a pod with ubuntu that just runs with sleep infinity, we’ll also pass in the variable for our NGINX_IP pod so that it’s accessible as an environment variable within the pod -
```sh kubectl run –image=ubuntu ubuntu –env=”NGINX_IP=$NGINX_IP” – sleep infinity
And check that the pod is running -
```sh kubectl get pods -o wide
We’ll now execute a shell process, in the running ubuntu pod -
```sh kubectl exec -it ubuntu – bash
If we take a look whilst in this shell, we’ll see that sleep infinity, is process id 1, we will have our bash shell and then the ps command that we ran, is a subprocess of the bash shell -
ps -ef
As this is a ubuntu container, we can use the apt package manager to install curl. We will do an apt update, followed by an apt install -y curl -
apt update && apt install -y curl
And now we can query the nginx pod, using the NGINX_IP variable that we passed in at the start -
curl $NGINX_IP
Exit from the ubuntu container -
exit
And let’s remove these pods -
```sh kubectl delete pod/nginx pod/ubuntu –now
We can use the ```sh kubectl options of -o yaml, along with –dry-run=client, to show the yaml declaration that the cli is using, let’s tee this to a file called nginx.yaml at the same time -
```sh kubectl run nginx –image=nginx –dry-run=client -o yaml | tee nginx.yaml
Notice the restartPolicy option, if we wish to know more about a particular section of Kubernetes yaml, we can use the ```sh kubectl explain command. For example, to query this we would use pod (as per the entry Kind), then the path, spec.restartPolicy -
```sh kubectl explain pod.spec.restartPolicy
Let’s create this in kubernetes using the imperative approach of ```sh kubectl create with -f to specify the filename -
```sh kubectl create -f nginx.yaml
Whilst this succeeded this time, subsequent attempts will fail as ```sh kubectl cannot create an entity that already exists -
```sh kubectl create -f nginx.yaml
An alternative approach is to use the declarative approach of apply, meaning we are applying what this entity should look like. You will get a warning initially if you do this to an entity that was created -
```sh kubectl apply -f nginx.yaml
However, subsequent attempts will succeed -
```sh kubectl apply -f nginx.yaml
Let’s capture a ubuntu pod example, as yaml also, we won’t need the NGINX_IP variable -
```sh kubectl run –image=ubuntu –dry-run=client -o yaml ubuntu sleep infinity | tee ubuntu.yaml
Then we also apply this -
```sh kubectl apply -f ubuntu.yaml
And check our pods, we will now have both nginx and ubuntu running successfully, via yaml files -
```sh kubectl get pods -o wide
Let’s remove both of these pods -
```sh kubectl delete pod/nginx pod/ubuntu –now
Currently we have two separate files, but a yaml file can contain multiple declarations, let’s combine the two files with a — yaml separator, we will use tee to save this to combined.yaml -
{ cat nginx.yaml; echo “—”; cat ubuntu.yaml; } | tee combined.yaml |
If we apply this combined.yaml file, it will create both entities at the same time -
```sh kubectl apply -f combined.yaml
And we can see both pods in our Kubernetes cluster -
```sh kubectl get pods -o wide
We can also use this file to delete both entities, at the same time with the ```sh kubectl delete command -
```sh kubectl delete -f combined.yaml –now
Modify the combined.yaml file so that we are running a single pod, with two containers, moving the ubuntu containers section, into the nginx section. The ubuntu container will be configured as a sidecar that echo’s a log and exit’s if a file (/tmp/crash) exists. We will also update the metadata to match. The following command will create a working example -
cat «EOF > combined.yaml apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: mypod name: mypod spec: containers:
- image: nginx name: webserver resources: {}
- image: ubuntu name: sidecar args:
- /bin/sh
- -c
- while true; do echo “$(date +’%T’) - Hello from the sidecar”; sleep 5; if [ -f /tmp/crash ]; then exit 1; fi; done resources: {} dnsPolicy: ClusterFirst restartPolicy: Always status: {} EOF
Apply the new combined.yaml file -
```sh kubectl apply -f combined.yaml
You’ll now see that we have a single pod showing 2/2 to indicate that it is running 2 of 2 containers in the pod -
```sh kubectl get pods -o wide
Using ```sh kubectl we can describe the pod for further information, in particular the IP address and each of the containers (named webserver and sidecar) -
```sh kubectl describe pod/mypod
Let’s capture the mypod IP address -
MYPOD_IP=$(```sh kubectl get pods -o wide | awk ‘/mypod/ { print $6 }’); echo $MYPOD_IP
And check that this is accessible using a throwaway curl pod (n.b. in the video lesson I used curlimages/curl:latest, this image is found to have frequent changes and instability, therefore for the lab, I’ve fixed the tag to a known working version) -
```sh kubectl run -it –rm –image=curlimages/curl:8.4.0 –restart=Never curl – http://$MYPOD_IP
If we check the logs for the sidecar container, we will see this is working as expected, note the use of -c to specify the particular container, ctrl-c to exit -
```sh kubectl logs pod/mypod -c sidecar
Let’s crash the sidecar container, by creating the /tmp/crash file that it is looking for as an exit criteria -
```sh kubectl exec -it mypod -c sidecar – touch /tmp/crash
If we check our pods again, this will transition to a restart of 1, where it restarted the crashed container -
```sh kubectl get pods -o wide
And if we check the sidecar logs, this will have restarted -
```sh kubectl logs pod/mypod -c sidecar
If however, we wish to see the previous logs, we can do so with the -p option -
```sh kubectl logs pod/mypod -p -c sidecar
Let’s remove the pod -
```sh kubectl delete pod/mypod –now
And remove the yaml files -
rm nginx.yaml ubuntu.yaml combined.yaml
🎯 Challenge! 🎯 Using ```sh kubectl, run a pod with -it and –rm, the name of the pod should be matrix and it should use the image spurin/cmatrix, if it runs successfully you should see a matrix style display in the terminal that can be closed with ctrl-c, solution enclosed -
```sh kubectl run -it –rm matrix –image=spurin/cmatrix
In the next chapter there is a further study section on Kubernetes Pods (Init Containers). When you’re ready click Next to move on to the next lab 🚀