Deploying Data Index and multiple SonataFlow application on Minikube

This document describes how to deploy a multiple SonataFlow workflow applications and the Data Index service using a local Kubernetes cluster, such as Minikube, using the SonataFlow Operator.

For more information about Minikube and related system requirements, see Getting started with Minikube documentation.

This use case is intended to represent an installation with:

  • A singleton Data Index Service with PostgreSQL persistence

  • The greeting workflow (no persistence), that is configured to register events to the Data Index Service.

  • The helloworld workflow (no persistence), that is configured to register events to the Data Index Service.

  • Both workflows are configured to register the process events on the Data Index Service.

You can directly access the UseCase2 example application we are going to follow at SonataFlow Data Index Use Cases with operator.

Prerequisites
  • Minikube installed with registry addon enabled

  • kubectl command-line tool is installed. Otherwise, Minikube handles it.

  • SonataFlow operator installed if workflows are deployed. To install the operator you can see Install the SonataFlow Operator.

We recommend that you start Minikube with the following parameters, note that the registry addon must be enabled.

minikube start --cpus 4 --memory 10240 --addons registry --addons metrics-server --insecure-registry "10.0.0.0/24" --insecure-registry "localhost:5000"

To verify that the registry addon was property added you can execute this command:

minikube addons list | grep registry
| registry                    | minikube | enabled ✅   | Google                         |
| registry-aliases            | minikube | disabled     | 3rd party (unknown)            |
| registry-creds              | minikube | disabled     | 3rd party (UPMC Enterprises)   |

You can check the Minikube installation by entering the following commands in a command terminal:

Verify Minikube version
minikube version
Verify kubectl CLI version
kubectl version

If kubectl is not installed, then Minikube handles it when you execute the following command:

kubectl is available using Minikube
alias kubectl="minikube kubectl --"
Procedure
  1. After cloning the SonataFlow examples repository. Open a terminal and run the following commands

    cd serverless-operator-examples/serverless-workflow-dataindex-use-cases/
  2. Create the namespace:

    kubectl create namespace usecase2
  3. Deploy the Data Index Service and postgresql database:

    Here you can find the infrastructure kustomization required to deploy Data Index service and a postgresql database explained in this use case.

    Thas folder contains four files:

    • kustomization.yaml

    • 01-postgres.yaml

    • 02-dataindex.yaml

    • application.properties

    kustomization.yaml resources that deploy Data Index deployment with persistence to a postgresql database
    resources:
    - 01-postgres.yaml (1)
    - 02-dataindex.yaml (2)
    
    secretGenerator:
      - name: postgres-secrets
        literals:
          - POSTGRES_USER=sonataflow
          - POSTGRES_PASSWORD=sonataflow
          - POSTGRES_DB=sonataflow
          - PGDATA=/var/lib/postgresql/data/mydata
    
    configMapGenerator:
      - name: dataindex-properties
        files:
          - application.properties
    1 Postgres database deployment
    2 Data Index deployment
    01_postgres.yaml that deploys Postgresql database
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      labels:
        app.kubernetes.io/name: postgres
      name: postgres-pvc
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app.kubernetes.io/name: postgres
      name: postgres
    spec:
      replicas: 1
      selector:
        matchLabels:
          app.kubernetes.io/name: postgres
      template:
        metadata:
          labels:
            app.kubernetes.io/name: postgres
        spec:
          containers:
            - name: postgres
              image: postgres:13.2-alpine
              imagePullPolicy: 'IfNotPresent'
              ports:
                - containerPort: 5432
              volumeMounts:
                - name: storage
                  mountPath: /var/lib/postgresql/data
              envFrom:
                - secretRef:
                    name: postgres-secrets
              readinessProbe:
                exec:
                  command: ["pg_isready"]
                initialDelaySeconds: 15
                timeoutSeconds: 2
              livenessProbe:
                exec:
                  command: ["pg_isready"]
                initialDelaySeconds: 15
                timeoutSeconds: 2
              resources:
                limits:
                  memory: "256Mi"
                  cpu: "500m"
          volumes:
          - name: storage
            persistentVolumeClaim:
              claimName: postgres-pvc
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app.kubernetes.io/name: postgres
      name: postgres
    spec:
      selector:
        app.kubernetes.io/name: postgres
      ports:
        - port: 5432
    02-dataindex.yaml that deploys Data Index with persistence to the previous defined postgresql database
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app.kubernetes.io/name: data-index-service-postgresql
      name: data-index-service-postgresql
    spec:
      replicas: 1
      selector:
        matchLabels:
          app.kubernetes.io/name: data-index-service-postgresql
      template:
        metadata:
          labels:
            app.kubernetes.io/name: data-index-service-postgresql
        spec:
          containers:
            - name: data-index-service-postgresql
              image: quay.io/kiegroup/kogito-data-index-postgresql:latest
              imagePullPolicy: Always
              resources:
                limits:
                  memory: "256Mi"
                  cpu: "500m"
              ports:
                - containerPort: 8080
                  name: http
                  protocol: TCP
              env:
                - name: KOGITO_DATA_INDEX_QUARKUS_PROFILE
                  value: http-events-support
                - name: KUBERNETES_NAMESPACE
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.namespace
                - name: QUARKUS_DATASOURCE_USERNAME
                  valueFrom:
                    secretKeyRef:
                      key: POSTGRES_USER
                      name: postgres-secrets
                - name: QUARKUS_DATASOURCE_PASSWORD
                  valueFrom:
                    secretKeyRef:
                      key: POSTGRES_PASSWORD
                      name: postgres-secrets
              volumeMounts:
                - name: application-config
                  mountPath: "/home/kogito/config"
              livenessProbe:
                failureThreshold: 3
                httpGet:
                  path: /q/health/live
                  port: 8080
                  scheme: HTTP
                initialDelaySeconds: 0
                periodSeconds: 30
                successThreshold: 1
                timeoutSeconds: 10
              readinessProbe:
                failureThreshold: 3
                httpGet:
                  path: /q/health/ready
                  port: 8080
                  scheme: HTTP
                initialDelaySeconds: 0
                periodSeconds: 30
                successThreshold: 1
                timeoutSeconds: 10
          volumes:
            - name: application-config
              configMap:
                name: dataindex-properties
          initContainers:
            - name: init-postgres
              image: registry.access.redhat.com/ubi9/ubi-minimal:latest
              imagePullPolicy: IfNotPresent
              command: ['sh', '-c', 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;']
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app.kubernetes.io/name: data-index-service-postgresql
      name: data-index-service-postgresql
    spec:
      ports:
        - name: http
          port: 80
          targetPort: 8080
      selector:
        app.kubernetes.io/name: data-index-service-postgresql
      type: NodePort
    application.properties referenced by kustomization.yaml
    quarkus.http.port=8080
    quarkus.http.cors=true
    quarkus.http.cors.origins=/.*/
    
    quarkus.datasource.jdbc.url=jdbc:postgresql://postgres:5432/sonataflow?currentSchema=data-index-service
    quarkus.hibernate-orm.database.generation=update
    quarkus.flyway.migrate-at-start=true
    
    # Disable kafka client health check since the quarkus-http connector is being used instead.
    quarkus.smallrye-health.check."io.quarkus.kafka.client.health.KafkaHealthCheck".enabled=false

    Perform the deployments executing

    kubectl kustomize infra/dataindex | kubectl apply -f - -n usecase2
    configmap/dataindex-properties-hg9ff8bff5 created
    secret/postgres-secrets-22tkgc2dt7 created
    service/data-index-service-postgresql created
    service/postgres created
    persistentvolumeclaim/postgres-pvc created
    deployment.apps/data-index-service-postgresql created
    deployment.apps/postgres created

    Give some time for the data index to start, you can check that it’s running by executing.

    kubectl get pod -n usecase2
    NAME                                             READY   STATUS    RESTARTS       AGE
    data-index-service-postgresql-5d76dc4468-lb259   1/1     Running   0              2m11s
    postgres-7f78499688-lc8n6                        1/1     Running   0              2m11s
  4. Deploy the workflow:

    Here you can find the use case kustomization required to deploy the workflow

    Use case kustomization.yaml resources that deploys the workflow
    resources:
    - ../../infra/service_discovery
    - ../../workflows/sonataflow-greeting
    - ../../workflows/sonataflow-helloworld

    To see in more detail access to Building and Deploying Workflows with the Operator

    Perform the deployment executing

     kubectl kustomize usecases/usecase2 | kubectl apply -f - -n usecase2
    configmap/greeting-props created
    configmap/helloworld-props created
    sonataflow.sonataflow.org/greeting created
    sonataflow.sonataflow.org/helloworld created

    Give some time for the sonataflow operator to build and deploy the workflow. To check that the workflow is ready you can use this command.

    kubectl get workflow -n usecase2
    NAME       PROFILE   VERSION   URL   READY   REASON
    greeting             0.0.1           True
    helloworld           0.0.1           True
  5. Expose the workflows and get the urls:

    kubectl patch svc greeting helloworld -p '{"spec": {"type": "NodePort"}}' -n usecase2
    minikube service greeting --url -n usecase2
    minikube service helloworld --url -n usecase2
  6. Create a workflow instance:

    You must use the URLs calculated in step 5.

    curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"name": "John", "language": "English"}'    http://192.168.49.2:32407/greeting
    curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{}'    http://192.168.49.2:32327/helloworld
  7. Clean the use case:

    kubectl delete namespace usecase2

Querying Data Index service on Minikube

You can use the public Data Index endpoint to play around with the GraphiQL interface.

Procedure

This procedure apply to all use cases with that deploys the Data Index Service.

  • Get the Data Index Url:

minikube service data-index-service-postgresql --url -n my_usecase
  • Open the GrahiqlUI

Using the url returned, open a browser window in the following url http://192.168.49.2:32409/graphiql/,

that IP and port will be different in your installation, and don’t forget to add the last slash "/" to the url, otherwise the GraphiqlUI won’t be opened.

To see the process instances information you can execute this query:

{
  ProcessInstances {
    id,
    processId,
    processName,
    variables,
    state,
    endpoint,
    serviceUrl,
    start,
    end
  }
}

The results should be something like:

{
  "data": {
    "ProcessInstances": [
      {
        "id": "3ed8bf63-85c9-425d-9099-49bfb63608cb",
        "processId": "greeting",
        "processName": "workflow",
        "variables": "{\"workflowdata\":{\"name\":\"John\",\"greeting\":\"Hello from JSON Workflow, \",\"language\":\"English\"}}",
        "state": "COMPLETED",
        "endpoint": "/greeting",
        "serviceUrl": "http://greeting",
        "start": "2023-09-13T06:59:24.319Z",
        "end": "2023-09-13T06:59:24.400Z"
      }
    ]
  }
}

To see the jobs instances information, if any, you can execute this query:

{
  Jobs {
    id,
    processId,
    processInstanceId,
    status,
    expirationTime,
    retries,
    endpoint,
    callbackEndpoint
  }
}

The results should be something like:

{
  "data": {
    "Jobs": [
      {
        "id": "55c7aadb-3dff-4b97-af8e-cc45014b1c0d",
        "processId": "callbackstatetimeouts",
        "processInstanceId": "299886b7-2b78-4965-a701-16783c4162d8",
        "status": "EXECUTED",
        "expirationTime": null,
        "retries": 0,
        "endpoint": "http://jobs-service-postgresql/jobs",
        "callbackEndpoint": "http://callbackstatetimeouts:80/management/jobs/callbackstatetimeouts/instances/299886b7-2b78-4965-a701-16783c4162d8/timers/-1"
      }
    ]
  }
}

Found an issue?

If you find an issue or any misleading information, please feel free to report it here. We really appreciate it!