Cómo desplegar WordPress en K3s
Seguimos en la senda de los microservicios o contenedores con Kubernetes, esta vez mostrando cómo desplegar WordPress en K3s. Recordad que recientemente vimos cómo crear un entorno de Kubernetes en alta disponibilidad con Ubuntu y K3s.
Elaborar esta entrada me ha dado un poco de guerra, porque por una cosa u otra no conseguía realizar el despliegue de forma correcta, al final la clave es fijarse que los espacios de los YAML sean los correctos. Además, una nota más, al final de la entrada os dejo la fuente de la que he sacado la mayoría de la información, por que sí, yo al igual que todos, no obtengo la información de forma mágica.
Al igual que otras veces, voy a utilizar el laboratorio de pruebas creado en mi proveedor de confianza Clouding.io, que os recomiendo.
Desplegar WordPress en K3s
Recordar que en la entrada, que os he comentado en el primer párrafo, además de desplegar el entorno con K3s, también habilitamos el gestor de paquetes HELM; para después realizar la instalación de Ingress Nginx, pieza fundamental para que el entorno tenga visibilidad de forma externa.
Instalar Cert-Manager
Nos interesa que los proyectos web, que despleguemos en el entorno, puedan utilizar HTTPS con su correspondiente certificado. Para ello vamos a utilizar Cert-Manager, para crear y administrar certificados SSL, utilizando los suministrados desde la iniciativa Let’s Encrypt
Añadimos el repositorio Jetstack, para que nos suministre el «chart» que necesitamos:
helm repo add jetstack https://charts.jetstack.io
Y actualizamos:
helm repo update
Ahora sí, instalamos:
helm install \ cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --version v1.7.1 \ --set installCRDs=true
Ficheros en Github
Antes de nada, os comento que todos los YAML de esta entrada los podéis encontrar en un repositorio en Github que he creado para la ocasión: github.com/davidochobits/wordpress-in-k3s, se aceptan sugerencias.
Evidentemente los ficheros YAML los tenéis que adaptar a vuestras necesidades. En este ejemplo he creado un wordpress llamado laboratoriowp.bitsandlinux.com, que ahora mismo ya podéis ver funcionando. Aunque, en el proyecto he incorporado un servicio de mysql, diría que en entornos productivos, sería mucho mejor utilizar una conexión a un servidor mysql dedicado. Ya que crear un servicio mysql por cada wordpress es una locura.
Preparar los secretos para el despliegue
Tranquilos que en esta parte no necesitaremos ninguna máquina enigma. Simplemente, para no añadir en los YAML las contraseñas «a pelo», podemos utilizar un fichero «kustomization.yaml», que contendrá la información confindencial, sobre las contraseñas y las bases de datos a utilizar en el proyecto.
En este caso, con el contenido:
secretGenerator: - name: mysql-password literals: - password=contrasea2022 - name: mysql-user literals: - username=userwp - name: mysql-user-password literals: - passworduser=contrasea2022 - name: mysql-database literals: - database=multitenant_wpp
A continuación, utilizando el parámetro «-k«, generaremos los secretos desde el fichero:
kubectl apply -k .
Con el resultado, en mi caso:
secret/mysql-database-4f74mgddt5 created secret/mysql-password-6kffcc6hhg created secret/mysql-user-4t5mcf8dkm created secret/mysql-user-password-fkbf7g7th9 created
Creación de volúmenes
Los volúmenes en Kubernetes tienen dos tipos, el llamado PersistentVolume y el PersistentVolumeClaim. Un PersistentVolume (PV) es una pieza de almacenamiento en el clúster que ha sido aprovisionada por un administrador o aprovisionada dinámicamente mediante clases de almacenamiento.
En cambio, Un PersistentVolumeClaim (PVC) es un tipo de almacenamiento, como pods, que consume recursos en Kubernetes, como memoria y CPU, que pueden reclamar el tamaño y el modo de acceso para crear volúmenes con modos de acceso específicos. Estos se pueden configurar como acceso de lectura y escritura o de solo lectura.
Crear volúmenes para MySQL
Primero vamos a crear un PersistentVolume llamado «msyql-pv-volume.yaml», con esta información:
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv2
spec:
storageClassName: do-block-storage
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/var/lib/mysql1"
A continuación, creamos un fichero llamado «mysql-pv-claim.yaml» para definir un PersistentVolumeClain, como sigue:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pv-claim2 spec: storageClassName: do-block-storage accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
En ambos casos he definido un espacio de almacenamiento de 1 GB, aquí cada cual según sus necesidades.
Una vez hecho esto, desplegamos los volúmenes:
kubectl apply -f mysql-pv-volume.yaml kubectl apply -f mysql-pv-claim.yaml
Con el resultado:
persistentvolume/mysql-pv2 created persistentvolumeclaim/mysql-pv-claim2 created
Podemos ver la información de los volúmenes creados con:
kubectl get pv
Y vemos la información obtenida:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM
mysql-pv2 1Gi RWO Retain Bound default/mysql-pv-claim2
Crear volúmenes para WordPress
Ahora nos toca hacer mismo pero para los volúmenes que utilizará WordPress. Primero creamos un fichero llamado «wordpress-pv-volume.yaml», donde vamos a definir el PV, con el contenido:
apiVersion: v1
kind: PersistentVolume
metadata:
name: wordpress-pv2
spec:
storageClassName: do-block-storage
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/var/www1"
A continuación, creamos el PVC, con el nombre «wordpress-pv-claim.yaml», con el contenido:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: wordpress-pv-claim2 spec: storageClassName: do-block-storage accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
Y los creamos:
kubectl apply -f wordpress-pv-volume.yaml kubectl apply -f wordpress-pv-claim.yaml
Con el resultado, una vez aplicados:
persistentvolume/wordpress-pv2 created persistentvolumeclaim/wordpress-pv-claim2 created
Listamos todos los volúmenes creados:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM mysql-pv2 1Gi RWO Retain Bound default/mysql-pv-claim2 wordpress-pv2 1Gi RWO Retain Bound default/wordpress-pv-claim2
Crear el servicio MySQL
Ahora vamos a crear el fichero YAML, llamado «mysql-service.yaml», donde además de definir diferentes parámetros del servicio, vamos a utilizar los secretos que hemos creado antes, así que debemos tenerlos a mano. Podemos ver los secretos con el comando «kubectl describe secret«.
El contenido del fichero es el siguiente:
apiVersion: v1 kind: Service metadata: name: mysql-wp1 spec: ports: - port: 3306 selector: app: wordpress1 tier: mysql1 --- apiVersion: apps/v1 kind: Deployment metadata: name: mysql-wp1 spec: selector: matchLabels: app: wordpress1 tier: mysql1 strategy: type: Recreate template: metadata: labels: app: wordpress1 tier: mysql1 spec: containers: - image: mysql:latest name: mysql1 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-password-6kffcc6hhg key: password - name: MYSQL_USER valueFrom: secretKeyRef: name: mysql-user-4t5mcf8dkm key: username - name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: mysql-user-password-fkbf7g7th9 key: passworduser - name: MYSQL_DATABASE valueFrom: secretKeyRef: name: mysql-database-4f74mgddt5 key: database ports: - containerPort: 3306 name: mysql volumeMounts: - name: persistent-storage1 mountPath: /var/lib/mysql1 volumes: - name: persistent-storage1 persistentVolumeClaim: claimName: mysql-pv-claim2
Verificamos que todo esta OK, y así podemos aplicar:
kubectl apply -f mysql-service.yaml
Con el resultado:
service/mysql-wp1 created deployment.apps/mysql-wp1 created
Crear el servicio para WordPress
Ahora toca hacer lo propio para definir el servicio de WordPress, esto lo haremos creando el fichero «wordpress-service.yaml». Y lo mismo de antes, debemos tener a manos los secretos.
apiVersion: v1 kind: Service metadata: name: wordpress1 spec: ports: - port: 80 selector: app: wordpress1 tier: web1 type: LoadBalancer --- apiVersion: apps/v1 kind: Deployment metadata: name: wordpress1 spec: selector: matchLabels: app: wordpress1 tier: web1 strategy: type: Recreate template: metadata: labels: app: wordpress1 tier: web1 spec: containers: - image: wordpress:php8.1-apache name: wordpress1 env: - name: WORDPRESS_DB_HOST value: mysql-wp1:3306 - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-user-password-fkbf7g7th9 key: passworduser - name: WORDPRESS_DB_USER valueFrom: secretKeyRef: name: mysql-user-4t5mcf8dkm key: username - name: WORDPRESS_DB_NAME valueFrom: secretKeyRef: name: mysql-database-4f74mgddt5 key: database ports: - containerPort: 80 name: wordpress1 volumeMounts: - name: persistent-storage2 mountPath: /var/www1/html volumes: - name: persistent-storage2 persistentVolumeClaim: claimName: wordpress-pv-claim2
Revisamos todo y aplicamos:
kubectl apply -f wordpress-service.yaml
Con el resultado:
service/wordpress1 created deployment.apps/wordpress1 created
Con el comando «kubectl get svc«, podemos ver los servicios desplegados:
Utilizar letsencrypt para desplegar WordPress
En esta parte vamos a configurar el certificado SSL para nuestro proyecto, utilizando Let’s Encrypt. En el fichero que vamos a crear debemos definir nuestro correo electrónico:
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: wp-prod-issuer1 spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: davidochobits@colaboratorio.net privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx
El fichero lo guardamos con el nombre «wp_production_issuer.yaml»
Ejecutamos:
kubectl apply -f wp_production_issuer.yaml
Con el resultado:
clusterissuer.cert-manager.io/wp-prod-issuer created
Configurar Ingress con HTTPS y despliegue
Ahora que ya hemos configurado los certificados SSL, es hora de definir el registro para el Ingress de Nginx. Aquí tenemos que definir el dominio que vamos a utilizar, en mi caso laboratoriowp.bitsandlinux.com. Aquí importante, tenemos que tener este registro creado en nuestro proveedor habitual, en el apartado de DNS. Creamos el fichero «wordpress_ingress.yaml», con toda la información adaptada a nuestras necesidades:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: wordpress1 annotations: kubernetes.io/ingress.class: "nginx" cert-manager.io/cluster-issuer: "wp-prod-issuer1" spec: rules: - host: laboratoriowp.bitsandlinux.com http: paths: - path: "/" pathType: Prefix backend: service: name: wordpress1 port: number: 80 tls: - hosts: - laboratoriowp.bitsandlinux.com secretName: wordpress-tls1
Y desplegamos:
ingress.networking.k8s.io/wordpress1 created
Configuración de WordPress via web
Si todo ha ido bien, al ir a la web y poner el dominio configurado, tendríamos que poder acceder al nuevo wordpress.
Una vez configurado todo, podemos ver el resultado:
Conclusiones
Hemos visto como desplegar un WordPress con un MySQL utilizando tanto PersistenVolume como PersistentVolumeClaim. Cada maestrillo tiene su librillo y siempre hay diferentes caminos para llegar a una misma meta, depende de nuestro ingenio, habilidad y creatividad. En cualquier caso al hacerlo de esta manera, utilizamos diferentes piezas disponibles en Kubernetes y K3s.