Installation

Contents

This section covers the installation and testing of the Enonic XP Kubernetes Operator.

Prerequisites

Kubernetes

A running Kubernetes cluster version 1.27+. The k8s cluster can be on-premise or any cloud service provider. The only thing that differs depending on the type of k8s clusters is which storage class to use.

Follow these steps to create a managed cluster using Amazon Web Services (AWS), Microsoft Azure or Google Cloud Platform GCP.

Kubectl

Is the Kubernetes command-line tool, kubectl, allows you to run commands against Kubernetes clusters. Download it from kubernetes.io.

Helm

Is a package manager for Kubernetes. Download it from helm.sh.

Create chart values file

Helm supports the use of chart files to configure the XP operator.

Create a chart file in a suitable location on your computer:

values.yaml
config: |-
  # Set storage class names for volumes to be used by XP deployments.
  operator.charts.values.storage.default.storageClassName=standard
  operator.charts.values.storage.shared.storageClassName=nfs

  # Default CPU and RAM to be used by XP deployments
  operator.charts.values.resources.cpu.defaultRequests=4
  operator.charts.values.resources.memory.defaultRequests=16Gi

Shared storage: Must be an NFS compatible storage class available in your cluster

+ Default storage: For optimal performance, use an SSD backed storage class

Visit the storage classes section for more details and compatibility list of supported storage classes.

The complete list of operator configuration options can be found in the Operator Helm chart

Installing the operator

Run the following command to install the operator on your cluster:

Namespaces - We will be installing the XP operator in the default kube-system namespace, indicating that it is a vital system component, but you can also create your own if desired.
$ helm upgrade --install \
	--namespace kube-system \
	--values values.yaml \
	xp-operator \
	https://repo.enonic.com/helm/xp-operator/xp-operator-0.17.16.tgz

Release "xp-operator" does not exist. Installing it now.
NAME: xp-operator
LAST DEPLOYED: Wed Apr 27 17:18:38 2022
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None

Verify installation

  1. Find the name of the operator pod. The name of the pod will start with xp-operator:

    $ kubectl -n kube-system get pods
    
    NAME                                                                READY   STATUS              RESTARTS   AGE
    pod/event-exporter-gke-7bf6c99dcb-7dl56                             2/2     Running             0          16d
    pod/kube-dns-5bfd847c64-2562d                                       4/4     Running             0          16d
    pod/kube-proxy-gke-xp-test-gke-cluster-default-pool-d0fdd01c-jnfl   1/1     Running             0          16d
    pod/l7-default-backend-d86c96845-j6m9b                              1/1     Running             0          16d
    pod/xp-operator-684bb48cc5-bqjqc                                    0/1     ContainerCreating   0          9s
  2. Check the operator logs for errors. Logs for a working operator should look something like this:

$ kubectl -n kube-system logs -f xp-operator-684bb48cc5-bqjqc

exec java -Doperator.charts.path=helm -Djava.util.logging.manager=org.jboss.logmanager.LogManager -javaagent:/opt/agent-bond/agent-bond.jar=jmx_exporter{{9779:/opt/agent-bond/jmx_exporter_config.yml}} -XX:+ExitOnOutOfMemoryError -cp . -jar /deployments/quarkus-run.jar
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2024-01-02 23:12:24,760 INFO  io.quarkus - java-operator 0.22.1 on JVM (powered by Quarkus 2.16.6.Final) started in 6.579s. Listening on: https://0.0.0.0:8443
2024-01-02 23:12:24,762 INFO  io.quarkus - Profile prod activated.
2024-01-02 23:12:24,764 INFO  io.quarkus - Installed features: [cdi, micrometer, rest-client, resteasy, resteasy-jackson, smallrye-context-propagation, vertx]
2024-01-02 23:12:25,808 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorIngress'
2024-01-02 23:12:25,889 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorXpClientCacheInvalidate'
2024-01-02 23:12:27,738 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorXp7DeploymentHelm'
2024-01-02 23:12:27,787 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorXp7AppStatusOnDeployments'
2024-01-02 23:12:27,799 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorDeleteAnnotation'
2024-01-02 23:12:27,803 INFO  com.eno.kub.ope.Operator - Adding schedule 'OperatorInformers' [delay: 16337, period: 30000]
2024-01-02 23:12:27,803 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorXp7ConfigStatus'
2024-01-02 23:12:27,804 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorIngressLabel'
2024-01-02 23:12:27,804 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorXp7AppInstaller'
2024-01-02 23:12:27,805 INFO  com.eno.kub.ope.Operator - Adding schedule 'OperatorXp7AppInstaller' [delay: 15212, period: 60000]
2024-01-02 23:12:27,805 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorXp7AppInstallerOnDeployments'
2024-01-02 23:12:27,806 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorConfigMapEvent'
2024-01-02 23:12:27,803 INFO  com.eno.kub.ope.Operator - Adding schedule 'OperatorConfigMapSync' [delay: 13252, period: 60000]
2024-01-02 23:12:27,804 INFO  com.eno.kub.ope.Operator - Adding schedule 'OperatorIngressLabel' [delay: 6622, period: 60000]
2024-01-02 23:12:27,806 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorXp7Config'
2024-01-02 23:12:27,807 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorIngressCertSync'
2024-01-02 23:12:27,807 INFO  com.eno.kub.ope.Operator - Adding schedule 'OperatorXp7ConfigSync' [delay: 10124, period: 60000]
2024-01-02 23:12:27,808 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorDomainCertSync'
2024-01-02 23:12:27,809 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorXp7AppStartStopper'
2024-01-02 23:12:27,809 INFO  com.eno.kub.ope.Operator - Adding schedule 'OperatorXp7AppStartStopper' [delay: 14806, period: 60000]
2024-01-02 23:12:27,809 INFO  com.eno.kub.ope.Operator - Adding listener 'OperatorXp7DeploymentStatus'
2024-01-02 23:12:27,810 INFO  com.eno.kub.ope.Operator - Adding schedule 'OperatorXp7DeploymentStatus' [delay: 4146, period: 60000]
2024-01-02 23:12:27,810 INFO  com.eno.kub.ope.Operator - Adding schedule 'OperatorXp7AppStatus' [delay: 19524, period: 60000]
2024-01-02 23:12:32,807 INFO  com.eno.kub.ope.Operator - Starting informers

Test the operator

The best way of verifying that thangs are working, is by creating a basic xp7deployment. The example below will create a namespace, a single-node XP7 server, pre-install selected applications, and configure an ingress.

Remember to use a unique namespace per XP deployment. Never use the same namespace as the operator.

Create xp7deployment

  1. Place this yaml file in a suitable location on your computer:

    simple.yaml
    # Create a namespace
    apiVersion: v1
    kind: Namespace
    metadata:
      name: my-namespace
      annotations:
        # Delete this namespace if the deployment is deleted
        enonic.cloud/remove.with.xp7deployment: my-deployment
    ---
    # Create deployment in the namespace
    apiVersion: enonic.cloud/v1
    kind: Xp7Deployment
    metadata:
      name: my-deployment
      namespace: my-namespace
    spec:
      enabled: true
      xpVersion: 7.13.5
    
      # Create one node
      nodeGroups:
        - name: main
          replicas: 1
    
          data: true
          master: true
    
          initContainers:
            # Preinstall Snapshotter app
            - image: enonic/snapshotter:3.1.0
              name: snapshotter-deploy
              mounts:
                - name: deploy
                  mountPath: /deploy
    
          resources:
            cpu: "2"
            memory: 4Gi
            dirs:
              # Snapshotter app copied to deploy folder
              - name: deploy
                size: 100Mi
                mountReadOnly: true
            # Disks private to the node
            disks:
              - name: blobstore
                size: 1Gi
              - name: snapshots
                size: 1Gi
              - name: export # Dumps and other data
                size: 1Gi
              - name: index # Node ES index
                size: 1Gi
              - name: work # Node cache
                size: 1Gi
    ---
    # Install content studio
    apiVersion: enonic.cloud/v1
    kind: Xp7App
    metadata:
      name: contentstudio
      namespace: my-namespace
    spec:
      url: https://repo.enonic.com/public/com/enonic/app/contentstudio/5.0.3/contentstudio-5.0.3.jar
      sha512: ba6b40ebf0808c6fa619ba2a05d07ce3e566eada7e9f3f34c1d280e9d1dcbd1e3c25eff9896d1057c4578ff3f516afa7a905c9e42ddc5e08f1cdf06f7e89774c
    ---
    # Add your own custom config
    apiVersion: enonic.cloud/v1
    kind: Xp7Config
    metadata:
      name: my-config
      namespace: my-namespace
    spec:
      nodeGroup: all
      file: com.my-app.cfg
      data: |
        my = config
    ---
    # Expose XP through an ingress
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-domain-com
      namespace: my-namespace
      annotations:
        enonic.cloud/xp7.vhost.mapping.my-mapping-site.source: /
        enonic.cloud/xp7.vhost.mapping.my-mapping-site.target: /site/default/master/homepage
    
        enonic.cloud/xp7.vhost.mapping.my-mapping-admin.source: /admin
        enonic.cloud/xp7.vhost.mapping.my-mapping-admin.target: /admin
        enonic.cloud/xp7.vhost.mapping.my-mapping-admin.idproviders: system
    spec:
      rules:
        - host: my-domain.com
          http:
            paths:
              - path: /
                pathType: ImplementationSpecific
                backend:
                  service:
                    name: main
                    port:
                      number: 8080
    
              - path: /admin
                pathType: ImplementationSpecific
                backend:
                  service:
                    name: main
                    port:
                      number: 8080
  2. Then run the following command to create the xp7deployment:

    kubectl apply -f single-xp7deployment-with-other-resources.yaml
    Output from a successful command
    namespace/my-namespace created
    xp7deployment.enonic.cloud/my-deployment created
    xp7app.enonic.cloud/contentstudio created
    xp7config.enonic.cloud/my-config created
    ingress.networking.k8s.io/my-domain-com created
  3. Verify that the namespace exists, and that the pods have started:

kubectl -n my-namespace get pods

Access XP Admin

With the XP running, we can try accessing the Admin - even without using an ingress.

  1. Get the su password by running this command:

    $ kubectl -n my-namespace get secret su -o go-template="{{ .data.pass | base64decode }}"

    This will output the plain text password.

  2. Activate port forwarding

    $ kubectl -n my-namespace port-forward main-0 8080
    
    Forwarding from 127.0.0.1:8080 -> 8080
    Forwarding from [::1]:8080 -> 8080
  3. Open http://localhost:8080 in your browser, and login with su and the password you obtained earlier.

Visit the operator usage section for more details.

Remove deployment

To remove the test deployment, run the following command:

Use the same yaml as when creating the deployment
kubectl delete -f simple.yaml
Volumes are typically not deleted when you remove the deployment, so take care to remove them afterwards.

Uninstalling the operator

Don´t uninstall the xp-operator while there are remaining xp7Deployments on your cluster

To remove the XP operator from your Kubernetes cluster, run the following command:

helm uninstall xp-operator

Contents

Contents