
A continuación resumo como he desplegado un ejemplo de orquestación de ‘api service’ con contenedores Docker, desde Kubernetes, con la instalación de Minikube.
Minikube nos facilita ejecutar un clúster de Kubernetes de un solo nodo en nuestro PC, nos permite desarrollar pruebas y aprendizaje de Kubernetes sin necesidad de tener un clúster completo en un entorno de producción.
Desplegaremos tres Pods externos del ‘api service’ con un LoadBalancer buscando alta disponibilidad, y un pod interno para el ‘bd service’ con un ClusterIP.
En el siguiente manifiesto en (app.yml), defino un mapa de configuración de la base de datos, los secretos para acceder a la base de datos, el volumen persistente para esa base de datos y los despliegues de las imágenes en pods con los recursos que necesitan, ademas del servicio de la api y la bd para el direccionamiento IP:
- ConfigMap
- Secret
- PersistentVolume y PersistentVolumeClaim
- Deployment db X 1 internal
- Deployment api X 3 external
- Service
A continuación exponemos el servicio externo con Minikube, y observamos el funcionamiento de esta.
Fichero app.yml
ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
data:
DB_HOST: "db-service"
DB_NAME: "juegos"
juegos.sql: |
CREATE TABLE IF NOT EXISTS juegos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(255) NOT NULL,
plataforma VARCHAR(50)
);
INSERT INTO juegos (nombre, plataforma) VALUES ('Super Mario Bros.', 'NES');
INSERT INTO juegos (nombre, plataforma) VALUES ('The Legend of Zelda', 'NES');
INSERT INTO juegos (nombre, plataforma) VALUES ('Sonic the Hedgehog', 'Sega Genesis');
INSERT INTO juegos (nombre, plataforma) VALUES ('Final Fantasy VII', 'PlayStation');
INSERT INTO juegos (nombre, plataforma) VALUES ('Halo: Combat Evolved', 'Xbox');
En el mapa de configuración definimos la base de datos de mysql, indicando DB_HOST, DB_NAME, y el juegos.sql para la bd.
Secret
apiVersion: v1
kind: Secret
metadata:
name: mysql-secrets
namespace: default
type: Opaque
data:
username: dXNlcg== # "user" en Base64
password: cGFzc3dvcmQ= # "password" en Base64
En el secret definimos el username y el password, de la bd de mysql
PersistentVolume (PV)
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /mnt/data
Alamacenamineto físico del cluster.
PersistentVolumeClaim (PVC)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
Solicitud de almacenamiento que los pods usan para acceder a un PV.
Deployment db X 1 internal
apiVersion: apps/v1
kind: Deployment
metadata:
name: db
spec:
replicas: 1
selector:
matchLabels:
app: db
template:
metadata:
labels:
app: db
spec:
containers:
- name: db
image: mysql:8.0
ports:
- containerPort: 3306
env:
- name: MYSQL_DATABASE
valueFrom:
configMapKeyRef:
name: mysql-config
key: DB_NAME
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: mysql-secrets
key: username
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secrets
key: password
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secrets
key: password
- name: MYSQL_DB
valueFrom:
configMapKeyRef:
name: mysql-config
key: DB_NAME
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
- name: init-script
mountPath: /docker-entrypoint-initdb.d
volumes:
- name: mysql-storage
persistentVolumeClaim:
claimName: mysql-pvc
- name: init-script
configMap:
name: mysql-config
Definimos el número de réplicas en esta caso una, la plantilla del pod que pude ser de contenedores tipo docker, o una personalizada de docker hub, en este caso utilizamos una genérica mysql:8.0.
Deployment api X 3 external
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api-container
image: icorujo/flask-app
env:
- name: MYSQL_HOST
valueFrom:
configMapKeyRef:
name: mysql-config
key: DB_HOST
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: mysql-secrets
key: username
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secrets
key: password
- name: MYSQL_DB
valueFrom:
configMapKeyRef:
name: mysql-config
key: DB_NAME
ports:
- containerPort: 5000
Definimos el número de réplicas, en esta caso tres para tener una alta disponibilidad. Una plantilla del pod que pude ser de contenedores tipo de docker, o una personalizada de docker hub, en este caso utilizamos una especifica albergada en docker hub icorujo/flask-app.
Service api y bd
apiVersion: v1
kind: Service
metadata:
name: db-service
spec:
selector:
app: db
ports:
- protocol: TCP
port: 3306
targetPort: 3306
type: ClusterIP
Proporciona el direccionamiento IP al pod de la bd
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
selector:
app: api
ports:
- protocol: TCP
port: 80
targetPort: 5000
nodePort: 30080
type: LoadBalancer
Proporciona el direccionamiento IP al pod de la api
Exponemos el servicio externo con Minikube
- Arrancamos minikube, previo tener levantado el servicio de docker
minikube start

- Vemos que el servicio de minikube, está levantado
minikube status

- Exponemos el servicio definido el el archivo *.yml
kubectl apply -f .\app.yml

- Revisamos los pods expuestos, su estado y el direccionamineto IP que tienen
kubectl get pods -o wide

- Revisamos los servicios levantados, con la configuración de puertos que se les configuraron
kubectl get svc

- Obtenemos la URL que expone el servicio
minikube service api-service –url

Funcionamiento de la ‘api service’ expuesta
Abrimos la url expuesta, http://127.0.0.1:5233, y podemos fijarnos como el balanceador reparte la consulta entre las tres IPs aprovisionadas a los tres pods externos 10.244.0.37, 10.244.0.38 y la 10.244.0.39.



![]() | by Iván Rodríguez Corujo |