---
title: Kubernetes, cas pràctic.
tags: daw, kubernetes, M8, dam, M15
---
<div style="width: 30%; margin-left: auto;">

</div>
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Llicència de Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />Aquesta obra està subjecta a una llicència de <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Reconeixement-CompartirIgual 4.0 Internacional de Creative Commons</a>
<div style="width: 200px;margin: 0 auto;">

</div>
# Kubernetes, cas pràctic.
## Habilitant l'entorn.
Kubernetes és especialment útil quan treballem amb plataformes al núvol però no farem les proves de desenvolupament directament sobre la plataforma de terceres parts (o si).
Tenim disponibles dues solucions de programari que ens permeten desplegar i provar sistemes kubernetes en local:
- [minikube](https://minikube.sigs.k8s.io/docs/): per a ús de desenvolupament, ens recreat tota la arquitectura kubernetes al nostre portàtil.
- [microk8s](https://microk8s.io/): solució multiplataforma que permet creat _master nodes_ i _worker nodes_ que treballin junts com a un únic sistema kubernetes.
En aquests apunts ens limitarem a treballar amb __minikube__.
### Instal·lació de minikube.
Abans de l'instal·lació, és important recordar, sobre tot per a aquells que no treballin directament sobre un sistema Linux, que minikube necessita un [driver](https://minikube.sigs.k8s.io/docs/start/) que pot ser un programari de contenidors, de màquines virtuals, o la pròpia màquina local, aquesta darrera opció només es recomana per usuaris experimentats i només està disponible pels usuaris d'algunes versions de Linux.
Seguiu les instruccions de la [pàgina oficial](https://minikube.sigs.k8s.io/docs/start/).
Engegueu el servei de minikube indicant el driver dessitjat:
```bash=
isard@isard:~$ minikube start --driver docker
😄 minikube v1.30.1 en Ubuntu 22.10 (amd64)
✨ Using the docker driver based on user configuration
📌 Using Docker driver with root privileges
👍 Starting control plane node minikube in cluster minikube
🚜 Pulling base image ...
💾 Descargando Kubernetes v1.26.3 ...
> preloaded-images-k8s-v18-v1...: 397.02 MiB / 397.02 MiB 100.00% 135.65
> gcr.io/k8s-minikube/kicbase...: 373.53 MiB / 373.53 MiB 100.00% 28.67 M
🔥 Creando docker container (CPUs=2, Memory=2200MB) ...
🐳 Preparando Kubernetes v1.26.3 en Docker 23.0.2...
▪ Generando certificados y llaves
▪ Iniciando plano de control
▪ Configurando reglas RBAC...
🔗 Configurando CNI bridge CNI ...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🔎 Verifying Kubernetes components...
🌟 Complementos habilitados: storage-provisioner, default-storageclass
💡 kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
isard@isard:~$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
```
Minikube instala la seva pròpia versió de kubectl, per aquells que treballin amb Linux i no tinguin instal·lada cap versió de kubectl, és una bona idea, tal i com expliquen a la pàgina de minikube, crear el següent alias:
```
alias kubectl="minikube kubectl --"
```
Per aturar el sistema i esborrar tots els clusters creats:
```
isard@isard:~$ minikube delete --all
🔥 Eliminando "minikube" en docker...
🔥 Eliminando /home/isard/.minikube/machines/minikube...
💀 Removed all traces of the "minikube" cluster.
🔥 Successfully deleted all profiles
isard@isard:~$
```
## Desplegant la calculadora
Ara que ja tenim el nostre entorn funcional podem passar a la segona fase: desplegar la nostra calculadora web en un entorn kubernetes.
Recordem el codi de la nostra calculadora:
```python=
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
Servei API-REST implementat en Flask per realitzar operacions matemàtiques bàsiques.
- suma
- resta
- multiplica
- divideix
Els serveis estan disponibles al port 5000
Dependències: flask ($ pip3 install flask)
"""
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/')
def hello_world():
return jsonify({'name': 'Calculadora'})
@app.route('/suma/<op1>/<op2>')
def suma(op1, op2):
n_op1 = float(op1)
n_op2 = float(op2)
resultat = {'operador': 'suma', 'resultat': n_op1 + n_op2}
return jsonify(resultat), 200
@app.route('/resta/<op1>/<op2>')
def resta(op1, op2):
n_op1 = float(op1)
n_op2 = float(op2)
resultat = {'operador': 'resta', 'resultat': n_op1 - n_op2}
return jsonify(resultat), 200
@app.route('/multiplica/<op1>/<op2>')
def multiplica(op1, op2):
n_op1 = float(op1)
n_op2 = float(op2)
resultat = {'operador': 'multiplicacio', 'resultat': n_op1 * n_op2}
return jsonify(resultat), 200
@app.route('/divideix/<op1>/<op2>')
def divisio(op1, op2):
n_op1 = float(op1)
n_op2 = float(op2)
resultat = {'operador': 'divisio', 'resultat': n_op1 / n_op2}
return jsonify(resultat), 200
if __name__=='__main__':
app.run(host='0.0.0.0', port='5000')
```
El primer pas consiteix en crear un contenidor per a la nostra aplicació:
- Contingut del fitxer Dockerfile:
```yaml=
FROM python:latest
RUN pip install flask
WORKDIR /calculadora
COPY ./calc.py /calculadora/
CMD ["python", "calc.py"]
EXPOSE 5000
```
- Compilar i pujar a DockerHub:
```bash=
docker build -t jdaxavi/calculadora .
docker push jdaxavi/calculadora
```
Ara ja tenim la nostra calculadora preparada per enviar-la al núvol dins del seu contenidor.
El primer pas serà crear un fitxer yaml de deploy. El més còmode és anar a la pàgina oficial de kubernetes [https://kubernetes.io/es/](https://kubernetes.io/es/) clicar al link de documentació [https://kubernetes.io/es/docs/home/](https://kubernetes.io/es/docs/home/) i cercar Deployment al textbox de cerca. La primera entrada ens porta a la documentació dels objectes Deploy [https://kubernetes.io/docs/concepts/workloads/controllers/deployment/](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/), i a dins podem trobar un exemple:
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
```
A partir d'aquest exemple podem anar construint el nostre propi fitxer yaml que descrigui el __deploy__ de la nostra app calculadora.
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: calculadora # nginx-deployment
labels:
app: calculadora # nginx
spec:
replicas: 5 #3
selector:
matchLabels:
app: calculadora # nginx
template:
metadata:
labels:
app: calculadora # nginx
spec:
containers:
- name: calculadora # nginx
image: jdaxavi/calculadora:latest
ports:
- containerPort: 5000 # 80
```
necessitarem també un 'Service' per adreçar-nos a la nostra aplicació, seguint el cas anterior, cercarem un exemple a la documentació de kubernetes i l'afegirem al mateix fitxer. Hem de recordar que YAML permet multiples documents si els separem per '---'.
[https://kubernetes.io/es/docs/concepts/services-networking/service/](https://kubernetes.io/es/docs/concepts/services-networking/service/)
Així quedaria el nostre fitxer calculadora.yaml ampliat amb el 'service' a més del 'deploy':
```yaml=
apiVersion: apps/v1
kind: Deployment
metadata:
name: calculadora # nginx-deployment
labels:
app: calculadora # nginx
spec:
replicas: 5 #3
selector:
matchLabels:
app: calculadora # nginx
template:
metadata:
labels:
app: calculadora # nginx
spec:
containers:
- name: calculadora # nginx
image: jdaxavi/calculadora:latest
ports:
- containerPort: 5000 # 80
---
apiVersion: v1
kind: Service
metadata:
name: calculadora-servei
spec:
type: NodePort # ClusterIP per defecte
selector:
app: calculadora
ports:
- protocol: TCP
port: 5000
targetPort: 5000
nodePort: 30101 # entre 30.000 i 32.767
```
Parem atenció a que el 'service' pot tenir un port diferent al que hem configurat al 'pod':
- port: 5000 fa referència al port utilitzat al servei.
- targetPort: 5000 hem d'utilitzar el mateix que hem declarat al contenidor.
- nodePort: Port que s'obrirà a tots els nodes on s'executi el nostre servei; ha d'estar dins del rang (30000,32767). Només l'especificarem si hem triat el tipus NodePort.
Ara ja podem passar a crear el nostre ConfigMap, el desarem a un fitxer anomenat calculadora-config.yaml
```yaml=
apiVersion: v1
kind: ConfigMap
metadata:
name: calculadora-config
data:
calculadora-url: calculadora-servei
```
Ara desde un terminal i el nostre servei minikube arrencat crearem els objectes que acabem de configurar:
```bash=
# En primer lloc el ConfigMap (tot i que per la nostra app no és necessari):
$ kubectl apply -f calculadora-config.yaml
configmap/calculadora-config created
$ kubectl apply -f calculadora.yaml
deployment.apps/calculadora created
service/calculadora-servicio created
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/calculadora-6857984764-5865m 1/1 Running 0 92s
pod/calculadora-6857984764-5bjfh 1/1 Running 0 92s
pod/calculadora-6857984764-9gzbr 1/1 Running 0 92s
pod/calculadora-6857984764-pms65 1/1 Running 0 92s
pod/calculadora-6857984764-z9bsb 1/1 Running 0 92s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/calculadora-servicio NodePort 10.97.145.182 <none> 5000:30101/TCP 92s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 124m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/calculadora 5/5 5 5 92s
NAME DESIRED CURRENT READY AGE
replicaset.apps/calculadora-6857984764 5 5 5 92s
```
Per poder connectar amb la nostra aplicació, hem de conèixer l'adreça IP del node on està corrent el servei:
```bash=
$ minikube ip
192.168.49.2
$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
minikube Ready control-plane,master 133m v1.23.3 192.168.49.2 <none> Ubuntu 20.04.2 LTS 5.15.0-30-generic docker://20.10.12
$ curl http://192.168.49.2:30101
{"name":"Calculadora"}
```
## Monitorització dels pods
Un cop arrencats podem veure els logs de cada pod individual amb la següent comanda i forçar el seguiment amb el flag -f:
```
$ kubectl logs -f pod/calculadora-68fdd5dd4f-27r4l
* Serving Flask app 'calculadora'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
* Running on http://10.244.0.15:5000
Press CTRL+C to quit
127.0.0.1 - - [14/Nov/2023 14:54:34] "GET / HTTP/1.1" 200 -
```