DevOps Developer Jahia 8.2

How to install Jahia with Kubernetes

Question

How to install Jahia with Kubernetes?

Answer

🚦This procedure is not meant for a production environment as it has not been validated by our Product and QA teams. Please only use it for discovery purposes.

πŸ“Œ Optional:

πŸ“Œ Prerequisites:

  • Kubernetes cluster up and running (in our case, minikube)
  • kubectl installed and configured
  • You have an ingress controller

πŸ“Œ Provided files:

Here is an archive with all the manifests being used. Here is the structure: 

  • jahia-tutorial
    • 01-db
      • 01-mariadb-pvc.yaml
      • 02-mariadb-deployment.yaml
      • 03-mariadb-service.yaml
    • 02-jahia
      • 01-jahia-processing-pvc.yaml
      • 02-jahia-processing-ss.yaml
      • 03-jahia-processing-service.yaml
      • 04-jahia-browsing-ss.yaml
      • 05-jahia-browsing-service.yaml
    • 03-ingress
      • 03-ingress.yaml

🚩 Step-by-Step Installation Guide

βœ… Step 1: Prepare Kubernetes Namespace

It's recommended to deploy Jahia in its own namespace:

kubectl create namespace jahia
kubectl config set-context --current --namespace=jahia

βœ… Step 2: Set Up Database

Jahia 8 requires a database backend (e.g., MariaDB, PostgreSQL, etc.):

  • Create a file named 01-db/01-mariadb-pvc.yaml to request a persistent volume that will be used by the database engine: 
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jahia-mariadb-pv-claim
  labels:
    type: local
    component: database
    part-of: jahia-demo  
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: standard
  • Apply with:
kubectl apply -f 01-db/01-mariadb-pvc.yaml
  • Create a file named 01-db/02-mariadb-deployment.yaml to create the MariaDB pod: 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jahia-mariadb
  labels:
    type: local
    component: database
    part-of: jahia-demo
spec:
  selector:
    matchLabels:
      app: jahia-mariadb
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: jahia-mariadb
        type: local
        component: database
        part-of: jahia-demo
    spec:
      containers:
      - image: mariadb:10.11.15
        name: jahia-mariadb
        env:
          # Use secret in real usage
        - name: MARIADB_ROOT_PASSWORD
          value: password
        ports:
        - containerPort: 3306
          name: jahia-mariadb
        volumeMounts:
        - name: jahia-mariadb-persistent-storage
          mountPath: /var/lib/mysql
        args:
          - --max-allowed-packet=1G
      volumes:
      - name: jahia-mariadb-persistent-storage
        persistentVolumeClaim:
          claimName: jahia-mariadb-pv-claim
  • Deploy with:
kubectl apply -f 01-db/02-mariadb-deployment.yaml
  • Create a file named 01-db/03-mariadb-service.yaml so the database can be accessed by other pods: 
---
apiVersion: v1
kind: Service
metadata:
  name: jahia-mariadb
  labels:
    type: local
    component: database
    part-of: jahia-demo
spec:
  ports:
  - name: jahia-mariadb
    port: 3306
    targetPort: 3306
  selector:
    app: jahia-mariadb
  type: ClusterIP
  • Deploy with:
kubectl apply -f 01-db/03-mariadb-service.yaml

 

βœ… Step 3: Deploy the Jahia processing pod

  • Create a file named 02-jahia/01-jahia-processing-pvc.yaml to request a persistent volume that will be used by the Jahia processing:
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jahia-processing-pvc
  labels:
    type: local
    component: jahia
    part-of: jahia-demo
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  storageClassName: standard
  • Deploy with:
kubectl apply -f 02-jahia/01-jahia-processing-pvc.yaml

  • Create a file named 02-jahia/02-jahia-processing-ss.yaml to create the Jahia processing pod:
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: jahia-processing
  labels:
    app: jahia-processing
    type: local
    component: jahia
    part-of: jahia-demo
spec:
  serviceName: jahia-processing
  replicas: 1
  selector:
    matchLabels:
      app: jahia-processing
  template:
    metadata:
      labels:
        app: jahia-processing
    spec:
      containers:
        - name: jahia-processing
          image: jahia/jahia-ee:8.2.1.0
          ports:
            - containerPort: 8080
          env:
            - name: DB_VENDOR
              value: "mariadb"
            - name: DB_HOST
              value: "jahia-mariadb.jahia.svc.cluster.local"
            - name: DB_NAME
              value: "jahia"
            - name: DB_USER
              value: "root"
            - name: DB_PASS
              value: "password"
            - name: CLUSTER_ENABLED
              value: "true"
            - name: PROCESSING_SERVER
              value: "true"
            - name: JAHIA_LICENSE
              value: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
            - name: jahia_cfg_cluster.node.serverId
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: CATALINA_OPTS
              value: -DjvmRoute=$(jahia_cfg_cluster.node.serverId)
          volumeMounts:
            - name: jahia-storage
              mountPath: /var/jahia
      volumes:
        - name: jahia-storage
          persistentVolumeClaim:
            claimName: jahia-processing-pvc
  • Deploy with:
kubectl apply -f 02-jahia/02-jahia-processing-pvc.yaml

  • Create a file named 02-jahia/03-jahia-processing-service.yaml so it can be accessed later:
---
apiVersion: v1
kind: Service
metadata:
  name: jahia-processing
  labels:
    type: local
    component: jahia
    part-of: jahia-demo
spec:
  type: NodePort
  ports:
  - name: jahia-processing
    port: 8080
    targetPort: 8080
  selector:
    app: jahia-processing
  • Deploy with:
Step 5: Making Jahia nodes accessible from "outside"

βœ… Step 4: Deploy the Jahia browsing pods

  • Create a file named 02-jahia/04-jahia-browsing-ss.yaml to create the Jahia browsing pods:
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: jahia-browsing
  labels:
    app: jahia-browsing
    type: local
    component: jahia
    part-of: jahia-demo
spec:
  serviceName: jahia-browsing
  replicas: 3
  selector:
    matchLabels:
      app: jahia-browsing
  template:
    metadata:
      labels:
        app: jahia-browsing
    spec:
      containers:
        - name: jahia-browsing
          image: jahia/jahia-ee:8.2.1.0
          ports:
            - name: jahia-browsing
              containerPort: 8080
          env:
            - name: DB_VENDOR
              value: "mariadb"
            - name: DB_HOST
              value: "jahia-mariadb.jahia.svc.cluster.local"
            - name: DB_NAME
              value: "jahia"
            - name: DB_USER
              value: "root"
            - name: DB_PASS
              value: "password"
            - name: CLUSTER_ENABLED
              value: "true"
            - name: PROCESSING_SERVER
              value: "false"
            - name: JAHIA_LICENSE
              value: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
            - name: jahia_cfg_cluster.node.serverId
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: CATALINA_OPTS
              value: -DjvmRoute=$(jahia_cfg_cluster.node.serverId)
          volumeMounts:
            - name: jahia-storage
              mountPath: /var/jahia
  volumeClaimTemplates:
  - metadata:
      name: jahia-storage
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 5Gi
      storageClassName: standard
  • Deploy with:
kubectl apply -f 02-jahia/04-jahia-browsing-ss.yaml

  • Create a file named 02-jahia/05-jahia-browsing-service.yaml so it can be accessed later:
---
apiVersion: v1
kind: Service
metadata:
  name: jahia-browsing
  labels:
    app: jahia-browsing
    type: local
    component: jahia
    part-of: jahia-demo
spec:
  selector:
    app: jahia-browsing
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

Deploy with:

kubectl apply -f 02-jahia/05-jahia-browsing-service.yaml

βœ… Step 5: Making Jahia nodes accessible from "outside"

  • Create a file named 03-ingress/01-ingress.yaml to create the Jahia browsing pods:
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webapp-ingress
  labels:
    type: local
    component: jahia
    part-of: jahia-demo
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "sticky-session-cookie"
spec:
  ingressClassName: nginx
  rules:
    - host: jahia-processing.local
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: jahia-processing
                port:
                  number: 8080
    - host: jahia-browsing.local
      http:
        paths:
            - path: /
              pathType: Prefix
              backend:
                service:
                  name: jahia-browsing
                  port:
                    number: 8080

βœ… Step 6: Accessing Jahia UI

  • Check your deployment status:
kubectl get pods,svc,pvc,all,ingress -n jahia
  • You should have something like that: 
    NAME                                READY   STATUS    RESTARTS   AGE
    pod/jahia-browsing-0                1/1     Running   0          64m
    pod/jahia-browsing-1                1/1     Running   0          53m
    pod/jahia-browsing-2                1/1     Running   0          53m
    pod/jahia-mariadb-67568b79c-ldfx4   1/1     Running   0          21h
    pod/jahia-processing-0              1/1     Running   0          65m
    
    NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
    service/jahia-browsing     ClusterIP   10.106.161.15    <none>        8080/TCP         20h
    service/jahia-mariadb      ClusterIP   10.108.227.216   <none>        3306/TCP         21h
    service/jahia-processing   NodePort    10.98.158.47     <none>        8080:32611/TCP   20h
    
    NAME                                                   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
    persistentvolumeclaim/jahia-mariadb-pv-claim           Bound    pvc-5eb0cae8-aff2-425e-8607-7ffee16713fc   5Gi        RWO            standard       <unset>                 21h
    persistentvolumeclaim/jahia-processing-pvc             Bound    pvc-bfca1cdd-a1ae-42d1-8291-bc4509a2f5f7   5Gi        RWO            standard       <unset>                 21h
    persistentvolumeclaim/jahia-storage-jahia-browsing-0   Bound    pvc-e18794e0-2ea6-4428-bb33-72e00852ce9b   5Gi        RWO            standard       <unset>                 20h
    persistentvolumeclaim/jahia-storage-jahia-browsing-1   Bound    pvc-424ac28b-e55c-4c33-abd3-dbb9b5ec9645   5Gi        RWO            standard       <unset>                 20h
    persistentvolumeclaim/jahia-storage-jahia-browsing-2   Bound    pvc-b47a8ba2-5c8b-4bd1-8aee-3044257e15ae   5Gi        RWO            standard       <unset>                 20h
    
    NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/jahia-mariadb   1/1     1            1           21h
    
    NAME                                      DESIRED   CURRENT   READY   AGE
    replicaset.apps/jahia-mariadb-67568b79c   1         1         1       21h
    
    NAME                                READY   AGE
    statefulset.apps/jahia-browsing     3/3     20h
    statefulset.apps/jahia-processing   1/1     20h
    
    NAME                                       CLASS   HOSTS                                         ADDRESS        PORTS   AGE
    ingress.networking.k8s.io/webapp-ingress   nginx   jahia-processing.local,jahia-browsing.local   192.168.49.2   80      18h
  • Update your hosts file so jahia-processing.local and jahia-browsing.local can be resolved to the given IP.
  • Open the following URLs: 

βœ… You're now running Jahia 8.2.2.0 on Kubernetes!

🚦 Troubleshooting & Useful Commands:

Check logs:

kubectl logs -f deploy/jahia-processing

Monitor events:

kubectl get events -w

If a pod is stuck, describe it:

kubectl describe pod <pod-name>

If you want to enter in a pod:  

kubectl exec --stdin --tty pod/JAHIA_POD_ID -- /bin/bash

 Using the Docker registry from Docker (ghcr.io)

Create a secret in Kubernetes: 

kubectl create secret docker-registry github_docker_registry_cred --docker-server=https://ghcr.io --docker-username=<GITHUB_USERNAME> --docker-password=<GITHUB_TOKEN> --docker-email=<GITHUB_EMAIL>

Modify the file jahia-processing-deployment.yaml and jahia-browsing-deployment.yaml so this secret is used, for example: 

  template:
    metadata:
      labels:
        app: jahia-processing
    spec:
      imagePullSecrets:
        - name: github_docker_registry_cred
      containers:
        - name: jahia-processing
          image: ghcr.io/jahia/jahia-ee:8.2.2.0