Estructura de servicio frontend - backend con Kubernets - Ejemplo práctico

by Josep Llauradó Selvas


Posted on 2020-11-24


En esta entrada muestro una configuración de ejemplo con 2 nodos frontend, un nodo backend con MySQL usando Kubernetes. El objetivo es que os hagáis una idea de cómo se puede configurar por si queréis hacer un copy-paste.

 

Base de datos

La estructura del servicio de BBDD tiene la siguiente forma:

En el vemos que existe un servicio NFS accesible por los nodos de trabajo, en nuestro caso el kub-n1 y kub-n2, pero que no los tienen montados en puntos de montaje (Esto lo hará Kubernetes por nosotros). También vemos que el kub-master tiene la IP publica, aunque esta no estará servida por el mismo, sino que lo delegara de forma transparente al nodo de trabajo que tenga el ‘Pod’ de BBDD, en este caso será el kub-n1. 

Empezamos pues la configuración con un volumen persistente, que nos permitirá almacenar los datos de la BBDD de forma transparente entre los diferentes nodos existentes del clúster. A nivel de servidor realizamos la instalación en el nodo máster de un NFS Server (podría estar en otro servidor), as 

# cat mydbnfs.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mydbdata
spec:
  capacity:
    storage: 40Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: standard
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: "/var/local/exports/mydbdata"
    server: "xx.xx.xx.xx"

De este fichero es importante destacar el nodo storageClassName, que nosotros hemos definido como ‘standard’, y que será usado posteriormente por el servicio de MySQL para almacenar sus datos. En resumen: El almacenamiento se escoge de forma dinámica en función de este nombre. 

Ahora definiremos el claim para que sea usado por nuestro replicaset mediante un volumeclaim:

# cat mydbdata-volumeclaim.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mydbdata-claim
spec:
  storageClassName: standard
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

Y ahora el replicaset:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydb
  labels:
    app: myweb
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      tier: backend
  template:
    metadata:
      labels:
        tier: backend
    spec:
      terminationGracePeriodSeconds: 30
      containers:
      - name: mydb
        image: docker-repo.domain.com:5000/mydb
        imagePullPolicy: Always
        ports:
        - name: mysql-server
          containerPort: 3306
        volumeMounts:
        - mountPath: /var/lib/mysql
          name: mydb-volume
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: <secretpassword>
        - name: MYSQL_DATABASE
          value: myweb
        - name: MYSQL_USER
          value: admin
        - name: MYSQL_PASSWORD
          value: <secretpassword>
      volumes:
      - name: mydb-volume
        persistentVolumeClaim:
          claimName: mydbdata-claim

Se pueden juntar ficheros usando un separador, como se muestra ahora. Siguiendo el ejemplo anterior:

...
      storage: 5Gi

---

apiVersion: apps/v1
...

Y finalmente ahora definimos el servicio:

# cat mydb-service.yaml
kind: Service
apiVersion: v1
metadata:
  name: mydb-srv
  labels:
    app: mydb-srv
spec:
  ports:
  - port: 3307
    targetPort: 3306
  selector:
    tier: backend
  type: LoadBalancer
  externalIPs: ["xx.xx.xx.xx"]

Con esto definimos el servidor de backend.

Frontend - PHP + Apache

Ahora definimos el frontend. En este caso es un Symfony 5 con PHP y Apache que accederá a la BBDD. El esquema es el siguiente:

Aquí destacaremos los 2 pods que serán usados en el balanceo de carga por el kube-master para balancear la carga, así como el uso compartido de imágenes por el docker registry… este registro es alimentado por Jenkins a partir de imágenes compiladas del código fuente que tenemos en Bitbucket.

Empezamos con el replica set:

# cat myweb-replicaset.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb
  labels:
    app: myweb
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      terminationGracePeriodSeconds: 30
      containers:
      - name: myweb
        image: docker-repo.domain.com:5000/myweb:test
        imagePullPolicy: Always
        ports:
        - name: https-server
          containerPort: 443
        - name: http-server
          containerPort: 80
        volumeMounts:
        - mountPath: /var/www/html/cache
          name: myweb-volume
      volumes:
      - name: myweb-volume
        emptyDir: {}

De este fichero destacamos el replicas: 3, que define que desplegará 3 servidores iguales contra la misma imagen. En este caso debemos tener en cuenta sobre todo la gestión de sesiones, que deberá de almacenarse en un recurso compartido como puede ser la BBDD.

Ahora definimos el servicio:

# cat myweb-service.yaml
kind: Service
apiVersion: v1
metadata:
  name: myweb-srv
  labels:
    app: myweb-srv
spec:
  ports:
  - port: 443
    targetPort: 443
  selector:
    tier: frontend
  type: LoadBalancer
  externalIPs: ["xx.xx.xx.xx"]

Finalmente podremos disponer ya de nuestro esquema de servidores up and running.

Regards!

homepage
Leave a Comment:


BeyondBlueSky - 2019

Website developed using Symfony 5, Bootstrap 4 and Open Iconic