Skip to content

Instantly share code, notes, and snippets.

@geerlingguy
Last active January 19, 2024 02:15
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save geerlingguy/4613ea753d2286b6ed0cb4e3c272ce23 to your computer and use it in GitHub Desktop.
Save geerlingguy/4613ea753d2286b6ed0cb4e3c272ce23 to your computer and use it in GitHub Desktop.
Drupal in Kubernetes K3s on Raspberry Pi
# This manifest assumes 'drupal' namespace is already present:
#
# kubectl create namespace drupal
#
# Apply the manifest with:
#
# kubectl apply -f drupal.yml
---
kind: ConfigMap
apiVersion: v1
metadata:
name: drupal-config
namespace: drupal
data:
# Note: This is NOT secure. Don't use this in production!
settings.php: |-
<?php
$databases['default']['default'] = [
'database' => 'drupal',
'username' => 'drupal',
'password' => 'drupal',
'prefix' => '',
'host' => 'mariadb',
'port' => '3306',
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'driver' => 'mysql',
];
$settings['hash_salt'] = 'OTk4MTYzYWI4N2E2MGIxNjlmYmQ2MTA4';
$settings['trusted_host_patterns'] = ['^.+$'];
$settings['config_sync_directory'] = 'sites/default/files/config_OTk4MTYzY';
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: drupal-files-pvc
namespace: drupal
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: drupal
namespace: drupal
spec:
replicas: 1
selector:
matchLabels:
app: drupal
template:
metadata:
labels:
app: drupal
spec:
containers:
- name: drupal
image: 'drupal:8.8-apache'
ports:
- containerPort: 80
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 60
readinessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 30
volumeMounts:
- mountPath: /var/www/html/sites/default/
name: drupal-settings
- mountPath: /var/www/html/sites/default/files/
name: drupal-files
resources:
limits:
cpu: '1'
memory: '512Mi'
requests:
cpu: '500m'
memory: '256Mi'
volumes:
- name: drupal-settings
configMap:
name: drupal-config
- name: drupal-files
persistentVolumeClaim:
claimName: drupal-files-pvc
---
kind: Service
apiVersion: v1
metadata:
name: drupal
namespace: drupal
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
selector:
app: drupal
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: drupal
namespace: drupal
spec:
rules:
- host: drupal.10.0.100.99.nip.io
http:
paths:
- path: /
backend:
serviceName: drupal
servicePort: 80
# This manifest assumes 'drupal' namespace is already present:
#
# kubectl create namespace drupal
#
# Apply the manifest with:
#
# kubectl apply -f mariadb.yml
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mariadb-pvc
namespace: drupal
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: mariadb
namespace: drupal
spec:
replicas: 1
selector:
matchLabels:
app: mariadb
template:
metadata:
labels:
app: mariadb
spec:
containers:
- name: mariadb
image: tobi312/rpi-mariadb:10.3
ports:
- containerPort: 3306
env:
- name: MYSQL_DATABASE
value: drupal
- name: MYSQL_USER
value: drupal
- name: MYSQL_PASSWORD
value: drupal
- name: MYSQL_RANDOM_ROOT_PASSWORD
value: 'yes'
volumeMounts:
- mountPath: /var/lib/mysql/
name: database
resources:
limits:
cpu: '2'
memory: '512Mi'
requests:
cpu: '500m'
memory: '256Mi'
volumes:
- name: database
persistentVolumeClaim:
claimName: mariadb-pvc
---
kind: Service
apiVersion: v1
metadata:
name: mariadb
namespace: drupal
spec:
ports:
- port: 3306
targetPort: 3306
selector:
app: mariadb
@mkmojo
Copy link

mkmojo commented Jul 7, 2020

Hi @geerlingguy,

Thanks for sharing this and creating the Youtube video on how to deploy this to the cluster.
I have learned a lot from the pi cluster series.

Noticed that you mentioned in both this and the pi-hole deployment there are some security shortcuts taken in order to demo.
Do you think it possible to make a video on how to deploy in a secure fashion?

Thanks a lot for the awesome work!

@geerlingguy
Copy link
Author

@mkmojo - The actual Drupal deployment here is pretty secure, but would need some changes to make it more scalable (e.g. using HPA by setting up NFS for shared files volume). I mention the security issue mostly because I didn't spend hours hardening the entire K3s cluster configuration (e.g. per-Pi firewalls, any kind of intrusion monitoring, configuring things like Fail2Ban, etc.), and that's something that is not easy to cover in a short-form YouTube series (nor is it the intention of that series).

For some of those basics, I highly suggest Ansible 101 - Episode 9 - First 5 min server security with Ansible.

Also, I am planning out a Kubernetes 101 series on YouTube... sometime in the next few months :) — it will cover more topics like RBAC and resource constraints in more depth.

@cyrtstein
Copy link

@mkmojo - thanks for asking that question!!
@geerlinguy - thanks for the very helpful answer!!!
I am following this using 4 Pi 4Bs (with 4 GB each). But so far everything works as is just like on the Turing Pi. Well, except that I could not for the life of me get kubectl installed on my master node. So I am just running kubectl from the Ubuntu 18 box that is also my ansible master (and that works fine). I am definitely planning to follow up on using fail2ban and ufw on my cluster.

@praveenmak
Copy link

If I want to run a daemonset (basically a service to run on every node). And I use the ingress, why I can't connect to it.
Is there a way to tell me what I could be doing wrong?

@Jeter-work
Copy link

Jeter-work commented Mar 27, 2021

First, thank you for all you have done by posting these.

I've made mistakes at every stage of the process, especially during the hardware assembly for my cluster, but also during bare metal installation, k3s install, and container installs.

I've fixed most of the problems, but this pod (drupal) still fails to work. It installs without error, but the website always says, "The website encountered an unexpected error. Please try again later."

The only change I've made from the above code is changing the IP to one of mine.

@geerlingguy
Copy link
Author

@Jeter-work - What I'd suggest is deleting the deployment and creating it again. Sometimes when you get that error, something with Drupal's database setup went wrong, and the easiest way (if you're just setting it up fresh) is to just delete and recreate it. I actually hit that problem in my Kubernetes 101 livestream too :D

@Jeter-work
Copy link

@geerlingguy - Thanks. I actually ended up doing that. Actually, I went forward, deleted everything then did them all again. I'm using a Picocluster with 10 pi 4B's. And once I finished mimicing your Turing Pi example, with HypriotOS and K3s, I decided to really get down in the weeds. I'm using 64-bit Ubuntu for ARM, and I'm going to try out two different Gluster configurations, one using the leftover space on SD cards, and one using LUNs served from a NAS. I expect the NAS to outperform the SD version, but the SD Card config will closer simulate hyperconverged infrastructure. Once I get the gluster set up, I'm going to configure K3s or MicroK8s. And as always, once I flash the cards, all steps are done with roles, and when I'm done I'll write a playbook to link all the roles and I'll do it all again until I have it automated. At some point I'm going to land on a config I like, and I'll settle the cluster into a stable config and move onto using it for other home lab stuff, firewall, pi-hole, stuff like that. Then maybe home automation?

@axiox
Copy link

axiox commented Oct 5, 2021

Hi Jeff

I keep getting this error on installation of drupal....
drupalerror

Not sure how to proceed from here...

Regards Ron

@RossWilliamson
Copy link

Thanks for these. I've been following your tutorial episode 4. Unfortunately I'm pretty new to all this. I'm getting a:

error: unable to recognize "drupal.yml": no matches for kind "Ingress" in version "extensions/v1beta1"

When running the manifest.

@geerlingguy
Copy link
Author

@RossWilliamson - That should probably be extensions/v1 I think, now, and it needs a couple other formatting changes for the actual ingress resource.

@RossWilliamson
Copy link

RossWilliamson commented Feb 12, 2022

@geerlingguy Thanks! I did some googling and the following seemed to work (I don't think you can do pull requests with gists so I'll paste it here). Again - I'm just learning so this worked for me but may well not be correct (I have no idea what the pathType: ImplementationSpecific does yet.)

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: drupal
  namespace: drupal
spec:
  rules:
    - host: drupal.192.168.1.101.nip.io
      http:
        paths:
          - path: /
            pathType: ImplementationSpecific
            backend:
              service:
                name: drupal
                port:
                  number: 80

@Speshals
Copy link

For those of you running into the image pull error for MariaDB, I changed the image to tobi312/rpi-mariadb:10.6-ubuntu and it seems to work on Raspberry Pi OS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment