# kubernetes in practice
----
## The tools
* kubectl: kubernetes command line client
* helm: A package manager for kubernetes applications
----
### kubectl
```bash
kubectl <verb> [<class>] [<object>]
```
```
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master1 Ready controlplane,etcd 7d16h v1.18.6
worker1 Ready worker 7d16h v1.18.6
worker2 Ready worker 7d16h v1.18.6
worker3 Ready worker 7d16h v1.18.6
```
---
## Deployment
To define a deployment we create a yaml that basically contains:
* The name of the deployment
* How many replicas we would like to have
* The list of container and their names (usually 1)
* Which image(s) will be used for the pods
* Which ports will be exposed in the pod
There are other parameters we'll see next
----
deployment.yaml

----
### Basic commands
```bash
# Apply or update the deployment
kubectl apply -f deployment.yaml
# Check the pods
kubectl get pods
# Check the events and configuration of a deployment
kubectl describe deployment <deployment_name>
# Check the container logs in a pod
kubectl logs -f <pod_name>
# Check the events of a pod
kubectl describe pod <pod_name>
```
----
In this example we deploy a nginx with 3 replicas
[](https://asciinema.org/a/VYTq5YoGUOYvbxMi9TkvvHcNT)
----
The next example we create a port-forward against one of the pods to check that is serving on port 80
```bash
kubectl port-forward <pod> [<local-port>:]<pod-port>
```
[](https://asciinema.org/a/1dewOxdg8av8tBBbQjjwRkBky)
----
In the next example, we delete a pod. kubernetes is going to recreate it. And also delete the deployment
```bash
kubectl delete pod <pod-name>
kubectl delete deployment <deployment-name>
```
[](https://asciinema.org/a/yEn7nVBp9w8Z5r8k09RsEFUR8)
----
Now, we force the update of the image. This will restart all the pods
```bash
kubectl rollout restart deployment <deployment-name>
```
[](https://asciinema.org/a/FkfHrgVpZB3rEeLlwR4negJrL)
----
In this example, we could access to the pod console
```bash
kubectl exec -ti <pod-name> -- <command>
```
[](https://asciinema.org/a/Yyn9uuo3niVR5SeUFcr8qaqLA)
---
## Services
In general, a service creates a load balancer for all the pods of a deployment
We need to define:
* The selector to define what pods will be under the load balancer. e.g. ```app: nginx```
* The exposed port
* The kind of service. Most common ```NodePort```
----
Service.yaml

----
Example: create a service for the nginx and access to it. Note: the ip is not public for the deployer, we need to access to a pod to achieve this ip.
```bash
kubectl apply -f service.yaml
```
[](https://asciinema.org/a/nrJKceTHsbEqPmWorEFkP7Tcl)
---
## Configmaps & Secrets
Sometimes it is interesting to setup env variables for the containers of a deployment. e.g. to predefine passwords.
- configmaps: to store configuration, values, ... all are stored in plain text
- secrets: to store apikeys,... all stored in base64 codification
----
Example: setup the env variable DEBUG deployment.yaml with a static value harcoded in the deployment.yaml
```yaml
#...
containers:
- name: nginx
#...
env:
- name: DEBUG # Name of the env variable
value: "yes"
```
----
Example: two new variables are defined, one from a configmap and the other from a secret
```yaml
#...
env:
- name: API_URL # Name of the env variable
valueFrom:
configMapKeyRef:
name: my-configurations # Name of the configmap
key: EXTERNAL_API_URL # Name of the variable
- name: API_KEY
valueFrom:
secretKeyRef:
name: my-secrets # Name of the secret storage
key: API_KEY # Name of the variable
```
----
To define a configmap use this schema
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configurations
data:
EXTERNAL_API_URL: "127.0.0.1"
```
And apply with
``` bash
kubectl apply -f configmap.yaml
```
----
To define a secret use this schema
```yaml
apiVersion: v1
kind: Secret
metadata:
name: my-secrets
data:
API_KEY: "MTIzNAo=" #1234 in base64
```
And apply with
``` bash
kubectl apply -f secret.yaml
```
----
Let's see an example
[](https://asciinema.org/a/DbM4Ku4rr31o2fbmdEyYWbzmv)
----
We can "create" a file or path in the container from a configmap. Must define a:
- the volume declaration (from a configmap)
- and how k8s will mount it on the container
```yaml
spec:
containers:
- name: nginx
#...
volumeMounts:
- name: web-html # name of the volume
# destination path/file
mountPath: /usr/share/nginx/html/index.html
# name of the variable from the configmap
subPath: index.html
volumes:
- name: web-html # name of the volume
configMap:
name: web-html # name of the configmap
```
----
[](https://asciinema.org/a/FVhOC5HDFG0TpyiK9AV1fHxnf)
---
## Auto health checking of applications
Kubernetes knows if a container has crashed because the entrypoint has sent a signal
But sometimes the applications simply stop working without any crash
To check the health of an app k8s uses liveness probe
----
Example of checking if the nginx is returing the main page
```yaml
containers:
- name: nginx
#...
livenessProbe:
httpGet:
path: /
port: 80
```
----
[](https://asciinema.org/a/ZXVjxmFRTVGfmSEYS6NrNwufh)
----
You could specify:
- initialDelaySeconds: initial delay to start checking
- periodSeconds: check interval
- failureThreshold: how many failures before restarting the pod
```yaml
containers:
- name: nginx
#...
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30
```
----
But also use other probes
- startupProbe: check when the pod is initialized
- readinessProbe: check when the pod is ready to serve data, k8s prevent to send request before passing the probe
```yaml
containers:
- name: nginx
#...
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
```
----
An also the tests could be:
- http request (httpGet)
- command execution (exec)
- access to a port (tcpSocket)
```yaml
containers:
- name: nginx
#...
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
```
---
## Persistence
Kubernetes allows mounting volumes to be used in pods. These volumes could be storages of any type (EBS, cinder, ...) we only need a plugin
To use persistence, we use statefulsets instead of the deployment
Statefulsets provide ordering and uniqueness
----
- The pod mounts a volume that claims a persistent volume.
- The persistent volume claim determines the size and the storage class
- The storage class indicates to the cloud provider the type of storage

----
Diferences with deployments
- k8s maintain static names for each pod
- If the pod is deleted the persistent volume remains
- When a pod is deleted, k8s will wait to create a new one until the last one frees the persistent volume.
- If the statefulset is deleted the persistent volume remains
----
Part 1. statefulset.yaml
```yaml
apiVersion: apps/v1
kind: StatefulSet #A statefulset is specified
metadata:
name: mysql
spec:
serviceName: mysql # statefulsets needs this
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
#...
----
Part 2. statefulset.yaml
```yaml
spec:
containers:
- name: mysql
image: mysql:latest
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-vol # Specify the name of the volume
mountPath: /var/lib/mysql # Specify where mount this
volumes:
- name: mysql-vol # Specify the name of the volume
persistentVolumeClaim:
claimName: mysql-pv # Specify the name of the claim
```
----
Part 3. statefulset.yaml
```yaml
templates:
#...
volumeClaimTemplates:
- metadata:
name: mysql-vol
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
```
----
[](https://asciinema.org/a/QfTmF8BH0wHZzz4w8gnNJdofg)
----
Ivan Lausuch
Suse
{"metaMigratedAt":"2023-06-15T12:42:11.513Z","metaMigratedFrom":"YAML","title":"kubernetes in practice","breaks":"true","slideOptions":"{\"theme\":\"solarized\"}"}