Deploy WordPress su Kubernetes

Come anticipato, ecco i passaggi basilari per deployare WordPress su un’installazione di Kubernetes come quella dell’articolo precedente. L’unica differenza del setup precedente, è che ho abbandonato NFS Subdir External Provisioner in favore di Longhorn, ora sufficientemente maturo per garantire scalabilità (ReadWriteMany) e iperconvergenza della soluzione.

Per creare oggetti all’interno di Kubernetes si utilizza il formato YAML. È possibile creare singoli file per i singoli oggetti, in modo da poterli modificare “pezzo per pezzo”, oppure mettere tutto in unico file e applicarlo tutto insieme. Oppure, come preferisco io, si può utilizzare un Kubernetes IDE come Lens ed editare “al volo” gli oggetti, applicando le modifiche da GUI. Di seguito metterò solo il contenuto dello YAML.

Nel resto dell’articolo, il codice YAML inizierà con ‘—‘, quando invece opero da terminale, inizierà con ‘#‘.

Al fine di organizzare e compartimentare i deploy su Kubernetes, creiamo un namespace, dentro al quale metteremo tutti gli oggetti che compongono lo stack WordPress che stiamo creando:

---
apiVersion: v1
kind: Namespace
metadata:
  name: marcobertorelloit-wp
  labels:
    name: marcobertorelloit-wp

Successivamente, creiamo una password che andremo ad utilizzare come password dell’utente root di Mysql.

# echo -n MyP4sSw0Rd! | base64
TXlQNHNTdzBSZCE=

Ora possiamo archiviare questa password in un secret di kubernetes e metterla a disposizione per essere utilizzata dal nostro deploy:

---
apiVersion: v1
kind: Secret
metadata:
  name: wp-db-secrets
  namespace: marcobertorelloit-wp
type: Opaque
data:
  MYSQL_ROOT_PASSWORD: TXlQNHNTdzBSZCE=

La prima cosa di cui avrà bisogno il nostro Mysql, sarà un disco (o meglio, un Volume), dove archiviare in maniera persistente il nostro database. Su Kubernetes, sarà necessario creare una PersistenVolumeClaim, ovvero una richiesta, per il nostro storage provider, di uno spazio di archiviazione:

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-volume
  namespace: marcobertorelloit-wp
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: longhorn  

Adesso abbiamo tutto il necessario per poter descrivere il nostro Mysql sul cluster Kubernets:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  namespace: marcobertorelloit-wp
  labels:
    app: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: database
        image: mysql:8
        envFrom:
          - secretRef:
              name: wp-db-secrets
        ports:
          - containerPort: 3306
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-data
        persistentVolumeClaim:
          claimName: mysql-volume

Il nostro database partirà, ma non ci sarà possibile accedervi, a meno di non creare un servizio per esso:

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

A questo punto occorre fermarsi un attimo, perchè il “motore” del nostro db è partito (o sta partendo), ma occore creare in database che userà wordpress. Per fare questo identifichiamo il pod e colleghiamoci all’interno. Colleghiamoci a mysql e creiamo il db:

# k0s kubectl get pods -n marcobertorelloit-wp
NAME                         READY   STATUS    RESTARTS   AGE
mysql-7774b9f74c-cnzmr       1/1     Running   0          24h
# k0s kubectl exec -it mysql-7774b9f74c-cnzmr -n marcobertorelloit-wp -- bash
bash-4.4# mysql -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1161
Server version: 8.0.31 MySQL Community Server - GPL

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database wordpress;
Query OK, 1 row affected (0.29 sec)

mysql> 

Siamo quindi pronti alla costruzione del nostro WordPress. Anche questo componente è composto a sua volta, così come il precedente, da un PersistenVolumeClaim, un Deployment e un Servizio. In aggiunta andremo ad attivare una rete di Ingress, necessaria nel caso non si voglia utilizzare un Servizio LoadBalancer ma comoda a prescindere, sopratutto per la possibilità di applicarvi un WAF per la protezione del servizio. Al momento della creazione del servizio, dimostrerò le tre alternative: ClusterIP, NodePort e LoadBalancer.

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: wordpress-volume
  namespace: marcobertorelloit-wp
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  storageClassName: longhorn

Da notare l’accessModes, impostato a ReadWriteMany, necessario per poter far girare due repliche bilanciate del servizio web.

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
  namespace: marcobertorelloit-wp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      containers:
        - name: wordpress
          image: wordpress:latest
          ports:
          - containerPort: 80
            name: wordpress-http
          volumeMounts:
            - name: wordpress-data
              mountPath: /var/www/html
          env:
            - name: WORDPRESS_DB_HOST
              value: mysql-service.marcobertorelloit-wp.svc.cluster.local
            - name: WORDPRESS_DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: wp-db-secrets
                  key: MYSQL_ROOT_PASSWORD
            - name: WORDPRESS_DB_USER
              value: root
            - name: WORDPRESS_DB_NAME
              value: wordpress
      volumes:
        - name: wordpress-data
          persistentVolumeClaim:
            claimName: wordpress-volume

arrivati a questo punto si può scegliere con che tipo di servizio si vuole operare: ClusterIP, NodePort e LoadBalancer. Se avete seguito la guida precedente e disponete di Metallb, il nostro setup li supporta tutti e tre. Vediamo le differenze sostanziali:

ClusterIP: Exposes the service on a cluster-internal IP. Choosing this value makes the service only reachable from within the cluster. This is the default ServiceType

NodePort: Exposes the service on each Node’s IP at a static port (the NodePort). A ClusterIP service, to which the NodePort service will route, is automatically created. You’ll be able to contact the NodePort service, from outside the cluster, by requesting <NodeIP>:<NodePort>.

LoadBalancer: Exposes the service externally using a cloud provider’s load balancer. NodePort and ClusterIP services, to which the external load balancer will route, are automatically created.

Personalmente uso un servizio ClusterIP, insieme alla Ingress per poter raggiungere il servizio sull’ indirizzo IP assegnato al LoadBalancer della Ingress. Tuttavia vedremo tutte e tre le configurazioni.

ClusterIP+Ingress:

---
kind: Service
apiVersion: v1
metadata:
  name: wordpress-service
  namespace: marcobertorelloit-wp
spec:
  type: ClusterIP
  selector:
    app: wordpress
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-wordpress
  namespace: marcobertorelloit-wp
spec:
  rules:
  - host: www.marcobertorello.it
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: wordpress-service
            port:
              number: 80
  ingressClassName: nginx

NodePort:

---
kind: Service
apiVersion: v1
metadata:
  name: wordpress-service

  namespace: marcobertorelloit-wp
spec:
  type: NodePort
  selector:
    app: wordpress
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80

LoadBalancer:

---
kind: Service
apiVersion: v1
metadata:
  name: wordpress-service

  namespace: marcobertorelloit-wp
spec:
  type: LoadBalancer
  selector:
    app: wordpress
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80

A questo punto, il mio sito WordPress è stato deployato con successo sul mio cluster Kubernetes (in precedenza girava con un setup simile, ma su un cluster Docker Swarm).

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.

© 2024 Bertorello.info | WordPress Theme : ScrollMe

Utilizzando il sito, accetti l'utilizzo dei cookie da parte nostra. maggiori informazioni

Questo sito utilizza i cookie per fornire la migliore esperienza di navigazione possibile. Continuando a utilizzare questo sito senza modificare le impostazioni dei cookie o cliccando su "Accetta" permetti il loro utilizzo.

Chiudi