What are steps for beginners to install ERPNext on Kubernetes?#

Steps in brief.

Prepare Kubernetes

  1. Install LoadBalancer.
  2. Install Cert Manager and create ClusterIssuer.
  3. Install MariaDB with frappe specific configuration.
  4. Install NFS Server Provisioner Helm Chart with persistence enabled.

Install ERPNext

  1. Install ERPNext Helm Chart.
  2. Create push-backup-s3 and mariadb-root-password secret in erpnext namespace.

Create Resources

  1. Create New Site Job.
  2. Create New Site Ingress.
  3. Create CronJob to take backups and push them to cloud regularly.

What can be scaled?#

Frappe SocketIO, Background Workers (default, short, long), and Gunicorn/Nginx Deployments can be scaled independently without any complexities involved.

Use following command to scale deployments.

$ kubectl scale -n <namespace> deployment <deployment-name> --replicas <number>

Redis Databases can be scaled independently by installing separate Redis cluster Helm Chart(s). Use the hostname(s) provided by these helm chart(s) as redisCacheHost, redisQueueHost, and redisSocketIOHost.

It is unsure whether scheduler can be scaled out. It is set to replica: 1 by default.

How to auto scale deployments?#

Use Horizontal Pod Autoscaler to auto scale required deployments.

Example to auto scale Deployment/frappe-bench-stable-erpnext-erpnext, apply following hpa.yaml.

# hpa.yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
  name: frappe-bench-stable-erpnext-erpnext
  maxReplicas: 5
  minReplicas: 1
    apiVersion: apps/v1
    kind: Deployment
    name: frappe-bench-stable-erpnext-erpnext
  targetCPUUtilizationPercentage: 60

Create the resource.

$ kubectl apply -n <namespace> -f hpa.yml

How do I edit files and directories on sites volume?#

Create file named volume-editor.yaml

kind: Pod
apiVersion: v1
  name: volume-editor
    - name: sites
        claimName: <CLAIM NAME GOES HERE>
    - name: debugger
      image: busybox
      # change ['sleep', 'infinity'] for pod to run infinitely
      command: ['sleep', '3600']
        - mountPath: "/data"
          name: sites

Change value for spec.volumes[0].claimName to <helm-release-name>-erpnext and create the resource in namespace where ERPNext is installed.

Change the container image as per the need or editor of your choice.

$ kubectl -n <namespace> -f volume-editor.yaml

Run an interactive shell inside the pod/container sites volume mounted at /data.

$ kubectl -n <namespace> exec -it volume-editor sh
/ #

delete the pod after use

$ kubectl -n <namespace> delete -f volume-editor.yaml

How do I upgrade and migrate to the latest helm release?#

Execute following command:

$ helm repo update
$ helm upgrade <release-name> -n <namespace> frappe/erpnext \
    --set mariadbHost=mariadb.mariadb.svc.cluster.local \
    --set persistence.worker.storageClass=<storageClass> \
    --set persistence.logs.storageClass=<storageClass> \
    --set migrateJob.enable=true

Set migrateJob.enable to true if you know whether the image tag or the appVersion has changed. It will backup sites and migrate. Replace <release-name> with the installed helm release name, <namespace> with kubernetes namespace and <storageClass> with RWX storage class, e.g. rook-cephfs

Do not forget to edit the cronjob for backup and push to update image. Set image to latest stable tag. e.g. v12.9.2

kubectl patch cronjobs.batch -n <namespace> backup-and-push \
  -p '{"spec":{"jobTemplate":{"spec":{"template":{"spec":{"containers":[{"name":"push-backup","image":"frappe/erpnext-worker:v12"}]}}}}}}'

How do I customize values for the ERPNext helm chart?#

Download the values.yaml file locally and modify the content as per need. e.g. change socketIOImage.tag to edge and use the file to set values during helm install.

You may also use a custom image for your custom apps through the -f values.yaml or by using the --set <key>=<value> param.

$ wget -c https://raw.githubusercontent.com/frappe/helm/master/erpnext/values.yaml
$ code values.yaml
$ helm install <release-name> -n <namespace> frappe/erpnext -f values.yaml

How do I add custom domain to existing site?#

Example is using Kubernetes Nginx ingress annotations.

Create ingress resource with desired domain name with following annotation:

  nginx.ingress.kubernetes.io/upstream-vhost: main-site.example.com
  - host: custom-site.example.com