Use case: Web application (Moodle) + DB with Volume backend

In this page we will deploy a typical service: a web application (moodle) connected to a DB (mysql), which uses a persistent volume in the backend.

1. Claim persistent volume

Let’s first allocate the Ceph volume that the DB will use to store its data. Create the following file volclaim.json:

{
   "kind": "PersistentVolumeClaim",
   "apiVersion": "v1",
   "metadata": {
       "name": "db-vol"
    },
   "spec": {
       "accessModes": [
           "ReadWriteOnce"
       ],
       "resources": {
           "requests": {
               "storage": "4Gi"
           }
       },
       "storageClassName": "hdd"
   }
}

Note the StorageClassName whose name is hdd for our Platform, the name we give to the volume, db-vol, and the requested size, 4 GB.

Apply the request:

$ kubectl create -f volclaim.json
  persistentvolumeclaim/db-vol created

Let’s query the volume status:

$ kubectl get pvc
NAME          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
db-vol        Bound    pvc-fbf4bd91-5229-11e9-95ff-549f35ad4eca   4Gi        RWO            hdd            9s

2. Create secret password

Let’s now record the password that we will use to access the MySQL DB. The password is created with the following command:

kubectl create secret generic mysql-pass --from-literal=password=$PASSWORD

where $PASSWORD is a strong password. Keep note of it as it won’t be displayed again. To query the secrets:

$ kubectl get secrets
NAME                  TYPE                                  DATA   AGE
mysql-pass            Opaque                                1      9s

3. Deploy MySQL

Let’s create the database. Create the following file mysql-vol.yaml:

apiVersion: v1
kind: Service
metadata:
  name: mysql-db
  labels:
    app: moodle
spec:
  ports:
    - port: 3306
  selector:
    app: moodle
    tier: mysql
  clusterIP: None
---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-db
  labels:
    app: moodle
spec:
  selector:
    matchLabels:
           app: moodle
           tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
           labels:
              app: moodle
              tier: mysql
    spec:
           containers:
           - image: mysql:5.6
             name: mysql
             env:
             - name: MYSQL_ROOT_PASSWORD
               valueFrom:
                  secretKeyRef:
                       name: mysql-pass
                       key: password
             volumeMounts:
             - mountPath: /var/lib/mysql
               name: mysql-data
             ports:
             - containerPort: 3306
               name: mysql
           volumes:
           - name: mysql-data
             persistentVolumeClaim:
                  claimName: db-vol

This files describes two objects:

  • the MySQL deployment (name: mysql-db)
  • the correspondent service (name: mysql-db) that exposes the database (port 3306) to the other deployments.

Note:

  • the environment variable MYSQL_ROOT_PASSWORD whose value is gathered from the previously stored secret mysql-pass;
  • the persistent volume db-vol mounted on the directory /var/lib/mysql.

Create the deployment:

$ kubectl create -f mysql-vol.yaml
  service/mysql-db created
  deployment.apps/mysql-db created

Check:

$ kubectl get svc
  NAME                  TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                      AGE
  mysql-db              ClusterIP      None             <none>          3306/TCP                     78m

$ kubectl get pods
  NAME                                   READY   STATUS    RESTARTS   AGE
  mysql-db-cc64cdbdd-t4b5s               1/1     Running   0          78m

Before continuing, we need to set some parameter in MySQL otherwise Moodle won’t be installed. Let’s log in the container:

$ kubectl exec -ti mysql-db-cc64cdbdd-t4b5s bash
  root@mysql-db-cc64cdbdd-t4b5s:/#

  root@mysql-db-cc64cdbdd-t4b5s:/# mysql -u root -p$PASSWORD

  mysql> set global innodb_large_prefix = `ON`;
  mysql> set global innodb_file_format=Barracuda;
  mysql> exit

where $PASSWORD is the password stored in the secret.

Of course it would be better to change the configuration and restart the MySQL service, but with the current implementation stopping the service leads to stopping and recreating the pod, so the configuration is lost.

TODO: Understand how to set the configuration parameters in the YAML file!

4. Deploy Moodle

Create the file moodle.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mymoodle
  labels:
    app: moodle
spec:
  selector:
    matchLabels:
      app: moodle
      tier: frontend
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: moodle
        tier: frontend
    spec:
      containers:
      - image: bitnami/moodle:latest
        name: mymoodle
        env:
        - name: MOODLE_DATABASE_USER
          value: "root"
        - name: MOODLE_DATABASE_NAME
          value: "moodle"
        - name: MOODLE_DATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-pass
              key: password
        - name: MARIADB_HOST
          value: mysql-db

Note the deployment name, moodle, and the environment parameters. In particular the parameter $MARIADB_HOST will access the database using the DB service name, mysql-db.

Issue the command:

$ kubectl create -f moodle.yaml
  deployment.apps/mymoodle created

$ kubectl get pods
  NAME                                   READY   STATUS    RESTARTS   AGE
  mymoodle-9d6c59c8b-mpf68               1/1     Running   0          66m

The installation will take some time. Meanwhile we can access the container and check that we can access the database using the DB service name:

root@mymoodle-9d6c59c8b-mpf68:/# mysql -u root -h mysql-db -p$PASSWORD
MySQL [(none)]>

The installation is completed when ps aux run on the container will show the following processes:

root@mymoodle-9d6c59c8b-mpf68:/# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root       151  0.0  0.0 279032 33660 ?        S    14:28   0:00 /opt/bitnami/apache/bin/httpd -f /opt/bitnami/apache/conf/httpd.conf -D FOREGROUND
...

We can now expose moodle:

$ kubectl expose deployment mymoodle --type="LoadBalancer" --port 80

$ kubectl get svc
  NAME                  TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                      AGE
  mymoodle              LoadBalancer   10.152.183.49    90.147.190.19   80:30192/TCP                 116s

Finally, open a bowser and type the EXTERNAL-IP that LoadBalancer assigned to the service (in this case: 90.147.190.19). Happy Moodl’ing!

Log in Moodle as an Admin with username and password that you can read in the moodle container environmental variables (env) MOODLE_USERNAME and MOODLE_PASSWORD.