Drupal 9 + MySQL 5.7 su Kubernetes
Published: 2024-03-21 13:32:45

---
title: Drupal 9 + MySQL 5.7 su Kubernetes
published: true
date: 2023-11-02 00:00:00 UTC
tags: 
canonical_url: https://theredcode.it/kubernetes/drupal-9-su-kubernetes/
---

Drupal è un CMS piuttosto popolare con una grande community dietro, ed è particolarmente popolare tra le grandi aziende e per i siti web complessi. Infatti, alcuni dei siti più visitati al mondo come [Nokia](https://www.nokia.com/phones/it_it),[Wish](https://www.wish.com/it), [NASA](https://www.nasa.gov/)utilizzano Drupal come CMS per i loro siti aziendali.

In questo post, andremo a vedere come <ins>configurare un’istanza di Drupal versione 9.5 con MySQL 5.7 su Kubernetes.
</ins>

**Spoiler** : sarà più lungo l’articolo che la sua effettiva realizzazione!

Questo è lo schema di ciò che otterremo alla fine:

![](https://theredcode.it/img/drupal-full-schema.png)

# Persistenza

Sappiamo che i container non sono persistenti, quindi è necessario utilizzare dei Persistent Volumes per preservare i dati che Drupal dovrà salvare… Altrimenti, tutte le modifiche scritte nel database o in qualsiasi directory andranno perse dopo il riavvio del container!

Andiamo quindi a definire due PVC, supponendo che il cluster Kubernetes su cui lavoriamo abbia a disposizione un provisioner che si occupa di eseguire il binding tra le claim per lo storage e i volumi persistenti.

![](https://theredcode.it/img/drupal-pvcs.png)

In questo caso richiediamo due volumi da 5 GB ciascuno, dove il primo sarà usato per i file del sito web e il secondo per il database MySQL. Chiaramente, questo dimensionamento è adatto a un ambiente di test o di demo, ma possono essere adattati!

```
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: drupal-pvc
spec:
 accessModes:
 - ReadWriteOnce
 resources:
 requests:
 storage: 5Gi


apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: mysql-pvc
spec:
 accessModes:
 - ReadWriteOnce
 resources:
 requests:
 storage: 5Gi

```

Invece, per installare l’istanza di MySQL utilizzeremo un Deployment e un Service. Si noti che eseguiamo MySQL con un’utenza amministrativa, che può essere anche cambiata seguendo le indicazioni presenti nella documentazione ufficiale.

![](https://theredcode.it/img/drupal-pvcs-and-secret.png)

Infatti, quando lo si utilizza in **produzione** , utilizzare credenziali personalizzate e sicure. Peraltro, è buona pratica memorizzare questo tipo di informazioni in un Secret, per cui procediamo con la sua definizione e includiamo la password dell’utente _root_:

```
apiVersion: v1
kind: Secret
metadata:
 name: mysql-creds
stringData:
 MYSQL_ROOT_PASSWORD: root_password

```

Il Deployment di MySQL è piuttosto semplice: utilizza un’immagine _mysql_ nella versione 5.7.8, tra le ultime disponibili e compatibili con la versione 9 di Drupal (vedi [documentazione](https://www.drupal.org/docs/getting-started/system-requirements/database-server-requirements)).

Inoltre, definiamo quelle che sono le **variabili di ambiente** che l’istanza dovrà utilizzare per configurare il database su cui l’istanza Drupal andrà a lavorare, e poi definiamo anche la **porta** 3306 come porta di ascolto per gli altri servizi e anche il **path** su cui il volume di MySQL creato in precedenza verrà montato.

```
apiVersion: apps/v1
kind: Deployment
metadata:
 name: mysql
spec:
 replicas: 1
 template:
 metadata:
 labels:
 app: mysql
 spec:
 containers:
 - env:
 - name: MYSQL_ROOT_PASSWORD
 valueFrom:
 secretKeyRef:
 name: mysql-creds
 key: MYSQL_ROOT_PASSWORD
 - name: MYSQL_DATABASE
 value: drupal-database
 image: "mysql:5.7.8"
 imagePullPolicy: IfNotPresent
 name: mysql
 ports:
 - containerPort: 3306
 name: mysql
 protocol: TCP
 volumeMounts:
 - mountPath: /var/lib/mysql
 name: drupal-pvc
 subPath: dbdata
 volumes:
 - name: drupal-pvc
 persistentVolumeClaim:
 claimName: mysql-pvc
 selector:
 matchLabels:
 app: mysql

```

Il _Deployment_ di Drupal sarà basato su un container con un’immagine di Drupal dal repository Docker Hub pari all’ultima versione ad oggi disponibile, ossia la 9.5.11.

Inoltre, utilizzeremo anche un container temporaneo (ovvero, un _initContainer_) la cui missione sarà quella di pre-popolare lo storage persistente con i dati utilizzati da Drupal.

![](https://theredcode.it/img/drupal-d.png)

Questo controller esporrà la **porta** 80 e ugualmente monterà un proprio **volume** con diverse cartelle per ogni componente necessario a Drupal per lavorare, come i _themes_, i _modules_ o i _sites_.

```
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
 app: drupal
 name: drupal
spec:
 replicas: 1
 template:
 metadata:
 labels:
 app: drupal
 spec:
 initContainers:
 - name: init-sites-volume
 imagePullPolicy: IfNotPresent
 image: drupal:9.5.11
 command: ['/bin/bash', '-c']
 args: ['cp -r /var/www/html/sites/ /data/; chown www-data:www-data /data/ -R']
 volumeMounts:
 - mountPath: /data
 name: pvc-drupal
 containers:
 - image: drupal:9.5.11
 imagePullPolicy: IfNotPresent
 name: drupal
 ports:
 - containerPort: 80
 volumeMounts:
 - mountPath: /var/www/html/modules
 name: pvc-drupal
 subPath: modules
 - mountPath: /var/www/html/profiles
 name: pvc-drupal
 subPath: profiles
 - mountPath: /var/www/html/sites
 name: pvc-drupal
 subPath: sites
 - mountPath: /var/www/html/themes
 name: pvc-drupal
 subPath: themes

 volumes:
 - name: pvc-drupal
 persistentVolumeClaim:
 claimName: drupal-pvc

 selector:
 matchLabels:
 app: drupal

```

Ultimo, ma non ultimo, creiamo i **Service** necessari per permettere ai due componenti di comunicare: quello per MySQL sarà di tipo ClusterIP, dal momento che dovrà interfacciarsi solo con Drupal, mentre quello per Drupal sarà di tipo LoadBalancer.

```
apiVersion: v1
kind: Service
metadata:
 name: mysql-service
spec:
 ports:
 - name: mysql
 port: 3306
 protocol: TCP
 selector:
 app: mysql

```

A seconda del tipo di infrastruttura Kubernetes su cui stiamo lavorando, sarà infatti possibile **accedere all’istanza tramite browser** : nel caso in cui si usi un cluster EKS su AWS, questo andrà a creare un Application Load Balancer che potremo usare per accedere alla prima pagina di Drupal:

```
apiVersion: v1
kind: Service
metadata:
 name: drupal-service
spec:
 ports:
 - name: http
 port: 80
 protocol: TCP
 selector:
 app: drupal
 type: LoadBalancer

```

![](https://theredcode.it/img/drupal-lb.png)

Ora che la nostra soluzione è stata definita e importata, **installiamo Drupal**. È sufficiente navigare verso l’indirizzo ottenuto nel passaggio precedente e seguire le istruzioni per l’installazione guidata. Utilizzate le credenziali del database configurate in precedenza nel Deployment di MySQL.

![](https://theredcode.it/img/drupal-installation.png)

Ad esempio, nel nostro caso, ecco i dati da specificare nella schermata di configurazione del database:

- Nome del database: _drupal-database_, come la variabile d’ambiente _MYSQL\_DATABASE_ nel Deployment di MySQL.
- Password del database: _root\_password_, come la variabile d’ambiente _MYSQL\_PASSWORD_ nel Secret di MySQL.
- Host: _mysql-service_, uguale al nome del Service MySQL
- Porta: 3306, uguale alla porta specificato nel Service MySQL

**Questo è tutto!**

Ora avete un’istanza di Drupal _funzionante_, distribuita in meno di 10 minuti.