# Kubernetes 101 ## Install `k3s` For this lesson, we will use `k3s` as `kubernetes` flavor. `k3s` is really easy to install: ``` curl -sfL https://get.k3s.io | sh - ``` ### Check Check the nodes: ``` kubectl get nodes ``` ``` NAME STATUS ROLES AGE VERSION isen-x Ready control-plane,master 100s v1.22.5+k3s1 ``` `k3s` will use your server as `control-plane` but also as `worker` (master) ## First deployment Create your first deployment ```shell kubectl create deployment first-dep --image=gcr.io/google-samples/kubernetes-bootcamp:v1 ``` View the deployment ```shell kubectl get deployments ``` ``` NAME READY UP-TO-DATE AVAILABLE AGE first-dep 1/1 1 1 1m ``` View the pods: ```shell kubectl get pods ``` ``` NAME READY STATUS RESTARTS AGE first-dep-69c7f7c9f4-jzbh8 1/1 Running 0 14s ``` View the events: ```shell kubectl get events ``` ## Create a Service By default, the Pod is only accessible by its internal IP address within the Kubernetes cluster. To make the `first-dep` container accessible from outside the Kubernetes virtual network, you have to expose the Pod as a Kubernetes [_Service_](https://kubernetes.io/docs/concepts/services-networking/service/). Expose the Pod to the public internet using the `kubectl expose` command: ```shell kubectl expose deployment first-dep --type=LoadBalancer --port=8080 ``` The `--type=LoadBalancer` flag indicates that you want to expose your Service outside of the cluster. View the Service you created: ```shell kubectl get services ``` The output is similar to: ``` NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE first-dep LoadBalancer 10.108.144.78 141.95.107.55 8080:30369/TCP 21s kubernetes ClusterIP 10.96.0.1 443/TCP 23m ``` Check that the service works as expected. Q: using curl, which command can you run to perform a HTTP request to your `first-dep` deployment? List pods again ``` kubectl get pods ``` Q: how many pods do you have? Why? ## Logs You can check the logs of your pods. First list your pods: ``` kubectl get pods ``` Then logs: ``` kubectl logs first-dep-69c7f7c9f4-jzbh8 Kubernetes Bootcamp App Started At: 2022-01-08T21:09:13.992Z | Running On: first-dep-69c7f7c9f4-jzbh8 Running On: first-dep-69c7f7c9f4-jzbh8 | Total Requests: 1 | App Uptime: 38.775 seconds | Log Time: 2022-01-08T21:09:52.767Z Running On: first-dep-69c7f7c9f4-jzbh8 | Total Requests: 2 | App Uptime: 41.24 seconds | Log Time: 2022-01-08T21:09:55.232Z Running On: first-dep-69c7f7c9f4-jzbh8 | Total Requests: 3 | App Uptime: 41.879 seconds | Log Time: 2022-01-08T21:09:55.871Z ``` ## Edit your deployment ``` kubectl describe deployment first-dep # You will see yaml output # This will show you what your deployment look like in your k8s environment ``` You can also describe your service: ``` kubectl describe services/first-dep ``` Now edit your deployment ``` kubectl edit deployment first-dep # This will open vim with the yaml of your deployment ``` Change the `replicas` (in `spec` section) to `2` Check again the pods ``` kubectl get pods -o wide ``` Q: how can you do a curl request to a specific pod? Q: how many pods do you have? Test your application multiple time: ``` curl http://141.95.107.55:8080/ # change 141.95.107.55 with your ip ... curl http://141.95.107.55:8080/ # change 141.95.107.55 with your ip ... curl http://141.95.107.55:8080/ # change 141.95.107.55 with your ip ``` Q: is the output always the same? Explain why. You can also change the replicas using the `scale` command: ``` kubectl scale deployment/first-dep --replicas=3 ``` ## Execution from pods We can execute commands directly on the container once the Pod is up and running. For this, we use the `exec` command and use the name of the Pod as a parameter. Let’s list the environment variables: ``` kubectl exec first-dep-69c7f7c9f4-jzbh8 -- env ``` Next let’s start a bash session in the Pod’s container: ``` kubectl exec -it first-dep-69c7f7c9f4-jzbh8 -- bash ``` We have now an open console on the container where we run our NodeJS application. The source code of the app is in the server.js file: `cat server.js` You can check that the application is up by running a curl command: `curl localhost:8080` _Note: here we used localhost because we executed the command inside the NodeJS Pod. If you cannot connect to localhost:8080, check to make sure you have run the kubectl exec command and are launching the command from within the Pod_ To close your container connection type `exit`. ## Updating the app To update the image of the application to version 2, use the `set image` command, followed by the deployment name and the new image version: ``` kubectl set image deployments/first-dep kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2 ``` The command notified the Deployment to use a different image for your app and initiated a rolling update. Check the status of the new Pods, and view the old one terminating with the `get pods` command: ``` kubectl get pods ``` Verify the update using curl ``` curl http://141.95.107.55:8080/ # change 141.95.107.55 with your ip ``` Q: do you see the `v=2`? You can also check if everything went fine using: ``` kubectl rollout status deployments/first-dep ``` To view the current image version of the app, run the `describe pods` command: ``` kubectl describe pods ``` In the `Image` field of the output, verify that you are running the latest image version (v2). ## Rollbacking the app Let’s perform another update, and deploy an image tagged with `v10` : ``` kubectl set image deployments/first-dep kubernetes-bootcamp=gcr.io/google-samples/kubernetes-bootcamp:v10 ``` Use `get deployments` to see the status of the deployment: ``` kubectl get deployments ``` Notice that the output doesn't list the desired number of up-to-date Pods. Run the `get pods` command to list all Pods: ``` kubectl get pods ``` Notice that some of the Pods have a status of `ImagePullBackOff`. To get more insight into the problem, run the `describe pods` command: ``` kubectl describe pods ``` In the `Events` section of the output for the affected Pods, notice that the `v10` image version did not exist in the repository. _Note: you can also use `kubectl get events` to retrieve the error._ To roll back the deployment to your last working version, use the `rollout undo` command: ``` kubectl rollout undo deployments/first-dep ``` The `rollout undo` command reverts the deployment to the previous known state (v2 of the image). Updates are versioned and you can revert to any previously known state of a deployment. Use the `get pods` commands to list the Pods again: ``` kubectl get pods ``` Three Pods are running. To check the image deployed on these Pods, use the `describe pods` command: ``` kubectl describe pods ``` The deployment is once again using a stable version of the app (v2). The rollback was successful. ## Clean up Now you can clean up the resources you created in your cluster: ```shell kubectl delete service first-dep kubectl delete deployment first-dep ``` ## demo-flask app Now, you are on your own, deploy the demo-flask app with 3 replicas on your kubernetes cluster. The demo-flask app image is available at: [arnaudmorin/demo-flask](https://hub.docker.com/r/arnaudmorin/demo-flask)