This project is focused on making it easy to set up a standardized, scalable, secure Kubernetes environment that can host multiple instances of Open edX. See Motivation below.
Specifically, this repository contains:
This repository does not set up the Kubernetes cluster or provision individual Open edX instances.
See technology stack and architecture below for more details.
Many Open edX providers and users have a need to deploy multiple instances of Open edX onto Kubernetes, but there is currently no standardized way to do so and each provider must build their own tooling to manage that. This project aims to provide an easy and standardized approach that incorporates industry best practices and lessons learned.
In particular, this project aims to provide the following benefits to Open edX operators:
infra-example
but it is just a starting point and not recommended for production use.metrics-server
and vertical-pod-autoscaler
tutor k8s
commands directly (as documented below) or you can use a CI/CD tool like Grove to deploy instances/images.We are tracking that in issue 26, so check that issue for the current status.
Supporting one really large instance is not a core design goal, but it should work well and we may consider including this as a goal in the future. Please reach out to us or get involved with this project if you have this requirement.
This helm chart uses ingress-nginx as a load balancer alongside cert-manager to provide automatic SSL certificates. Because of how Helm works, the cert-manager sub-chart will be installed into the same namespace as the parent harmony chart. But if you already have cert-manager on your cluster, this will create a conflict. You should take special care not to install cert-manager twice due to it installing several non-namespaced resources. If you already installed cert-manager by different means, make sure set cert-manager.enabled: false
for this chart.
In addition, the cert-manager Helm charts do not install the required CRDs used by cert-manager, so you will need to manually install and upgrade them to the correct version as described in the instructions below. This is due to the some limitations in the management of CRDs by Helm.
Tutor does not offer an autoscaling mechanism by default. This is a critical feature when your application starts to receive more and more traffic. Kubernetes offers two main autoscaling methods:
Pod-based scaling: This mechanism consists of the creation and adjustment of new pods to cover growing workloads. Here we can mention tools like Horizontal Pod autoscaler (HPA) and Vertical pod autoscaler (VPA). The first consist of automatically increasing or decreasing the number of pods in response to a workload’s metric consumption (generally CPU and memory), and the second one aims to stabilize the consumption and resources of every pod by providing suggestions on the best configuration for a workload based on historical resource usage measurements. Both of them are meant to be applied over Kubernetes Deployment instances.
Node-based scaling: This mechanism allows the addition of new NODES to the Kubernetes cluster so compute resources are guaranteed to schedule new incoming workloads. Tools worth mentioning in this category are cluster-autoscaler (CA) and Karpenter.
For the scope of this project, the focus will be in the pod-based scaling mechanisms since Node-based scaling tools require configuration which is external to the cluster, which is out of the scope for this Helm chart for now.
The approach will be to use pod autoscaling on each environment separately (assuming there are installations on different namespaces) following the steps below:
For this recommended approach, you need to have a Kubernetes cluster in the cloud with at least 12GB of usable memory (that’s enough to test 2 Open edX instances).
kubectl cluster-info
and make sure it displays some
information about the cluster (e.g. two URLs).values-example.yaml
to values.yaml
and edit it to put in your email address and customize other settings.
The email address is required for Lets Encrypt to issue HTTPS certificates. It is not shared with anyone else.kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.10.1/cert-manager.crds.yaml --namespace=harmony
You can check the version of cert-manager that is going to be installed by the chart by running
helm dependency list
or by checking the corresponding line in the harmony-chart/Chart.yaml
file.
helm install --namespace harmony --create-namespace -f values.yaml harmony ./harmony-chart
Note: in the future, if you make any changes to values.yaml
, then run this command to update the deployment:
helm upgrade --namespace harmony -f values.yaml harmony ./harmony-chart
Note: if possible, it’s preferred to use a cloud-hosted cluster instead (see previous section). But if you don’t have a cluster available in the cloud, you can use minikube to try this out locally. The minikube version does not support HTTPS and is more complicated due to the need to use tunnelling.
minikube
if you don’t have it already.minikube start
(you can also use minikube dashboard
to access the Kubernetes dashboard).helm install --namespace harmony --create-namespace -f values-minikube.yaml harmony ./harmony-chart
minikube tunnel
(you may need to enter a password), and then you should be able to access the cluster (see
“External IP” below). If this approach is not working, an alternative is to runminikube service harmony-ingress-nginx-controller -n harmony
http://127.0.0.1:52806
plus /cluster-echo-test
(e.g. http://127.0.0.1:52806/cluster-echo-test
)127.0.0.1
as the external IP. You will need to remember
to include the port numbers shown above when accessing the instances.The ingress NGINX Controller is used to automatically set up an HTTPS reverse proxy for each Open edX instance as it gets deployed onto the cluster. There is just one load balancer with a single external IP for all the instances on the cluster. To get its IP, use:
kubectl get svc -n harmony harmony-ingress-nginx-controller
To test that your load balancer is working, go to http://<the external ip>/cluster-echo-test
.
You may need to ignore the HTTPS warnings, but then you should see a response with some basic JSON output.
Important: First, get the load balancer’s IP (see “external IP” above), and set the DNS records for the instance you
want to create to be pointing to the load balancer (Usually if you want the LMS at lms.example.com
, you’ll need to set
two A records for lms.example.com
and *.lms.example.com
, pointing to the external IP from the load balancer).
You also will need to have the tutor-contrib-harmony-plugin installed into Tutor:
pip install -e 'git+https://github.com/openedx/openedx-k8s-harmony.git#egg=tutor-contrib-harmony-plugin&subdirectory=tutor-contrib-harmony-plugin'
Next, create a Tutor config directory unique to this instance, and configure it:
export INSTANCE_ID=openedx-01
export TUTOR_ROOT=~/deployments/tutor-k8s/$INSTANCE_ID
tutor plugins enable k8s_harmony
tutor config save -i --set K8S_NAMESPACE=$INSTANCE_ID
Then deploy it:
tutor k8s start
tutor k8s init
Note that the init
command may take quite a long time to complete. Use the commands that Tutor says (“To view the logs
from this job, run:”) in a separate terminal in order to monitor the status. Also note that if you want to use the MFEs,
you’ll need a custom image and it won’t work out
of the box.
You can repeat step 3 many times to install multiple instances onto the cluster.
Tutor creates an Elasticsearch pod as part of the Kubernetes deployment. Depending on the number of instances Memory and CPU use can be lowered by running a central ES cluster instead of an ES pod for every instance.
To enable set elasticsearch.enabled=true
in your values.yaml
and deploy the chart.
For each instance you would like to enable this on, set the configuration values in the respective config.yml
:
K8S_HARMONY_ENABLE_SHARED_ELASTICSEARCH: true
RUN_ELASTICSEARCH: false
tutor k8s harmony create-elasticsearch-user
.tutor images build openedx
.tutor k8s start && tutor k8s init
.In order for SSL to work without warnings the CA certificate needs to be mounted in the relevant pods. This is not yet implemented as due to an outstanding issue in tutor that had not yet been completed at the time of writing.
Just run helm uninstall --namespace harmony harmony
to uninstall this.
If you use DigitalOcean, you can use Terraform to quickly spin up a cluster, try this out, then shut it down again.
Here’s how. First, put the following into infra-tests/secrets.auto.tfvars
including a valid DigitalOcean access token:
cluster_name = "harmony-test"
do_token = "digital-ocean-token"
Then run:
cd infra-example
terraform init
terraform apply
cd ..
export KUBECONFIG=`pwd`/infra-example/kubeconfig
Then follow steps 1-4 above. When you’re done, run terraform destroy
to clean
up everything.