# 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       <none>        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)

Now, do it by writting a yaml file containing a deployment and a service and use
`kubectl apply` to send it to kube API.

