This project deploys a robust infrastructure on Azure to handle a high scale moodle installation. This environment is able - and tested - to handle 400k concurrent users.
Introduction
Moodle is an open-source learning platform that was developed in 1999 by Martin Dougiamas, a computer scientist and educator from Australia. Moodle stands for Modular Object-Oriented Dynamic Learning Environment, and it is written in PHP, a popular web programming language. Moodle aims to provide educators and learners with a flexible and customizable online environment for teaching and learning, where they can create and access courses, activities, resources, and assessments. Moodle also supports collaboration, communication, and feedback among users, as well as various plugins and integrations with other systems and tools.
Moodle is widely used around the world by schools, universities, businesses, and other organizations, with over 100 million registered users and 250,000 registered sites as of 2020. Moodle is also supported by a large and active community of developers, educators, and users, who contribute to its development, documentation, translation, and support. [URL] is the official website of the Moodle project, where anyone can download the software, join the forums, access the documentation, participate in events, and find out more about Moodle.
Goal
The goal for this architecture is to have a Moodle environment that can handle 400k concurrent users and scale in and out its application resources according to usage.
Using Azure managed services to minimize operational burden was a design premise because standard Moodle reference architectures are based on Virtual Machines that comes with a heavy operational cost.
Challenges
Being a monolith application, scaling Moodle in a modern cloud native environment is challenging. We choose to use Kubernetes as its computing provider due to the fact that it allow us to build a Moodle artifact in an immutable way that allows it to scale out and in when needed in a fast and automatic way and also recover from potential failures by simply recreating its Deployments without the need to maintain Virtual Machine resources, introducing the concept of pets vs cattle[1] to a scenario that at first glance wouldn't be feasible.
Since Moodle is written in PHP it has no concept of database polling, creating a scenario where its underlying database is heavily impacted by new client requests, making it necessary to use an external database pooling solution that had to be custom tailored in order to handle the amount of connections for a heavy-traffic setup like this instead of using Azure Database for PostgreSQL's built-in pgbouncer.
The same effect is also observed in its Redis implementation, where a custom Redis cluster had to be created, whereas using Azure Cache for Redis would incur prohibitive costs due to the way it is set up for a more general usage.
1 - https://learn.microsoft.com/en-us/dotnet/architecture/cloud-native/definition#the-cloud
Architecture
This architecture uses Azure managed (PaaS) components to minimize operational burden by using Azure Kubernetes Service to run Moodle, Azure Storage Account to host course content, Azure Database for PostgreSQL Flexible Server as its database and Azure Front Door to expose the application to the public as well as caching commonly used assets. The solution also leverages Azure Availability Zones to distribute its component across different zones in the region to optimize its availability.
Provisioning the solution
The provisioning has two parts: setting up the infrastructure and the application. The first part uses Terraform to deploy easily. The second part involves creating Moodle's database and configuring the application for optimal performance based on the templates, number of users, etc. and installing templates, courses, plugins etc.
The following steps walk you through all tasks needed to have this job done.
Clone the repository
$ git clone https://github.com/Azure-Samples/moodle-high-scale
Provision the infrastructure
$ cd infra/
$ az login
$ az group create --name moodle-high-scale --location <region>
$ terraform init
$ terraform plan -var moodle-environment=production
$ terraform apply -var moodle-environment=production
$ az aks get-credentials --name moodle-high-scale --resource-group moodle-high-scale
Provision the Redis Cluster
$ cd ../manifests/redis-cluster
$ kubectl apply -f redis-configmap.yaml
$ kubectl apply -f redis-cluster.yaml
$ kubectl apply -f redis-service.yaml
Wait for all the replicas to be running
$ ./init.sh
Type 'yes' when prompted.
Deploy Moodle and its services
Change image in moodle-service.yaml and also adjust the moodle data storage account name in the nfs-pv.yaml (see commented lines in the files)
$ cd ../../images/moodle
$ az acr build --registry moodlehighscale<suffix> -t moodle:v0.1 --file Dockerfile .
$ cd ../../manifests
$ kubectl apply -f pgbouncer-deployment.yaml
$ kubectl apply -f nfs-pv.yaml
$ kubectl apply -f nfs-pvc.yaml
$ kubectl apply -f moodle-service.yaml
$ kubectl -n moodle get svc –watch
Provision the frontend configuration that will be used to expose Moodle and its assets publicly
$ cd ../frontend
$ terraform init
$ terraform plan
$ terraform apply
Approve the private endpoint connection request from Frontdoor in moodle-svc-pls resource.
Private Link Services > moodle-svc-pls > Private Endpoint Connections > Select the request from Front Door and click on Approve.
Install database
$ kubectl -n moodle exec -it deployment/moodle-deployment -- /bin/bash
$ php /var/www/html/admin/cli/install_database.php --adminuser=admin_user --adminpass=admin_pass --agree-license
Deploy Moodle Cron
Change image in moodle-cron.yaml
$ cd ../manifests
$ kubectl apply -f moodle-cron.yaml
Your Moodle installation is now ready to use!
Conclusion
You can create a Moodle environment that is scalable and reliable in minutes with a very simple approach, without having to deal with the hassle of operating its parts that normally comes with standard Moodle installations.