How to deploy?

How to deploy?

Introduction

This guide provides a step-by-step process to install the Sciamus Inventory Management System (IMS).

Prerequisites

Before starting the installation process, ensure the following prerequisites are met:

helm version
  • kubectl: Install and configure kubectl for K8s interaction.
kubectl version --client
  • Image Registry - as IMS is provided in the form of source code, you have to build binaries for all IMS microservices, deploy them in the form of images in image registy - prefferably one used by your CI/CD platform - that your K8s cluster can access (e.g., Docker Hub, private registry).

MongoDB

Make sure that database user for particular microservice is entitled to create databases. This is the easiest way to allow IMS system to manage its own database.

If you want to limit privileges, please make sure that application user is granted readWrite role for database used by the microservice.

This should be performed for all microservice databases.

  • ims-inventory
  • ims-inventory-view
  • ims-lock
  • ims-task

Build & Deploy Overview

The IMS repository includes several domains with source code for libraries and microservices.

To build and deploy the system, the following steps must be performed: Build

  1. Build the libraries
  2. Build the microservices, create images and deploy then in the image registry

Deploy

  1. Deploy Keycloak on your K8s cluster
  2. Deploy RabbitMQ on your K8s cluster
  3. Deploy the system on your K8s cluster

Build

Libraries

For each library - compile, build and deploy in package registry.

mvn --batch-mode deploy \
  --update-snapshots \
  -DskipTests \
  -Dmaven.install.skip=true \
  -Dmaven.repo.local=~/.m2/repository \
  --settings your_maven_settings.xml

This should be performed for all libraries provided in IMS repository.

IMS Microservices

Compile source code, build and deploy jar in package registry.

mvn --batch-mode deploy \
  --update-snapshots \
  -DskipTests \
  -Dmaven.install.skip=true \
  -Dmaven.repo.local=~/.m2/repository \
  --settings your_maven_settings.xml

Then build image and deploy it to image registry.

docker login "$REGISTRY"
docker build -t "$IMAGE_NAME":"$IMAGE_TAG" .
docker push  "$IMAGE_NAME":"$IMAGE_TAG"

Adjust REGISTRY, IMAGE_NAME, and IMAGE_TAG according to your needs (e.g. CI/CD standards).

This should be performed for all libraries provided in IMS repository.

Deploying Keycloak

Skip this part of deployment if your company is already using Keycloak. Remember to configure IMS microservices with an existing Keycloak instance.

Below is values.yml template configuration file, which must be filled in with the appropriate values:

appVersion: latest
image:
  registry: "change_me"
  tag: "latest"
  imagePullSecret: ""
keycloak:
  environment:
    name: "keycloak"
    replicas: 1
    port: 8080
    secrets:
      # If the existingSecret array contains keys,
      # they will be mounted even if you have created a default secret
      # If you use own secret key must be contains:
      #  KEYCLOAK_ADMIN
      #  KEYCLOAK_ADMIN_PASSWORD
      #  KC_DB_USERNAME
      #  KC_DB_PASSWORD
      existingSecrets: []
      defaultSecret:
        create: true
        data:
          db:
            username: "change_me"
            password: "change_me"
          keycloak:
            keycloakAdminUsername: "change_me"
            keycloakAdminPassword: "change_me"
    resources:
      requests:
        cpu: "10m"
        memory: "256Mi"
      limits:
        cpu: "1"
        memory: "1024Mi"
  configuration:
    db:
      url: "change_me"
      schema: "keycloak"
      provider: "postgres" #If you use postgre db
    realms:
      realm_som: "realm/export_som.json"
    relativePath: "/keycloak/auth"
    hostname: "change_me"
    metrics: true
    health: true
    http_enable: true
    java_opts: "-Dkeycloak.profile.feature.upload_scripts=enabled -Xmx2048m"
    log_level: "TRACE"

Install Keycloak on K8S cluster using Helm:

helm upgrade -n $namespace --install Keycloak .

Deploying RabbitMQ

Important note! RabbitMQ in IMS acts as an internal communication layer, thus it's reccomended to deploy dedicated RabbitMQ cluster as described below. You should not use your existing RabbitMQ platform that is used for other purposes - such solution was not tested and we can't say anything about such configuration.

Use Bitnami Helm chart for RabbitMQ: https://github.com/bitnami/charts/tree/main/bitnami/rabbitmq (opens in a new tab)

Note, that IMS utilizes quorum queues (opens in a new tab) to ensure persistency and high avaliability - thus persistence (PersistentVolume) should be enabled in your K8s cluster.

  1. Create PersistentVolume and PersistentVolumeClaim. This should be adjusted according to your K8s cluster configuration. E.g. you can use StorageClass to create PersistentVolume or even PersistentVolumeClaim - consult with your K8s cluster administrator.
# pv-and-pvc.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: sciamus-rabbitmq-pv
spec:
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  capacity:
    storage: 8Gi
  storageClassName: standard
  hostPath:
    path: /tmp/sciamus-rabbitmq-pv
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sciamus-rabbitmq-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 8Gi
  storageClassName: standard
  volumeName: sciamus-rabbitmq-pv
kubectl -n ims apply -f ./pv-and-pvc.yaml
  1. Prepare RabbitMQ user definitions and store it in Secret. You can use preffered approach to storage sensitive data (such as passwords) using solution utilized in your environment (e.g. AWS Secret Manger or Vault or any other solution that suits your needs).
# load_definition.json
# This is an example of users that could be configured in RabbitMQ cluster.
#   ims-app             - Application user, used by IMS microservices, without GUI access
#   rabbitmq-admin      - RabbitMQ admin, full priviliges
#   rabbitmq-monitoring - User with GUI access, without restrictions, with monitoring priviliges
#   rabbitmq-management - User with GUI access, without restrictions, with management priviliges
#   rabbitmq-user-rw    - User with GUI access, withouth configuration priviliges, with management priviliges
#   rabbitmq-user-ro    - User with GUI access, read only, with management priviliges
# For details see https://www.rabbitmq.com/docs/management#permissions.
{
  "users": [
    {
      "name": "ims-app",
      "password": "top-secret-password",
      "tags": ""
    },
    {
      "name": "rabbitmq-admin",
      "password": "top-secret-password",
      "tags": "administrator"
    },
    {
      "name": "rabbitmq-monitoring",
      "password": "top-secret-password",
      "tags": "monitoring"
    },
    {
      "name": "rabbitmq-management",
      "password": "top-secret-password",
      "tags": "management"
    },
    {
      "name": "rabbitmq-user-rw",
      "password": "top-secret-password",
      "tags": "monitoring"
    },
    {
      "name": "rabbitmq-user-ro",
      "password": "top-secret-password",
      "tags": "monitoring"
    }
  ],
  "permissions": [
    {
      "user": "ims-app",
      "vhost": "/",
      "configure": ".",
      "read": ".",
      "write": "."
    },
    {
      "user": "rabbitmq-admin",
      "vhost": "/",
      "configure": ".",
      "read": ".",
      "write": "."
    },
    {
      "user": "rabbitmq-monitoring",
      "vhost": "/",
      "configure": ".",
      "read": ".",
      "write": "."
    },
    {
      "user": "rabbitmq-management",
      "vhost": "/",
      "configure": ".",
      "read": ".",
      "write": "."
    },
    {
      "user": "rabbitmq-user-rw",
      "vhost": "/",
      "configure": "^$",
      "read": ".",
      "write": "."
    },
    {
      "user": "rabbitmq-user-ro",
      "vhost": "/",
      "configure": "^$",
      "read": ".",
      "write": "^$"
    }
  ],
  "vhosts": [
    {
      "name": "/"
    }
  ]
}
kubectl -n ims \
  create secret generic ims-rabitmq-load-definition \
  --from-file ./load_definition.json
  1. Create erlang cookie as Secret
kubectl -n ims \
  create secret generic ims-rabitmq-erlang-cookie \
  --from-literal=rabbitmq-erlang-cookie=$(openssl rand -hex 64 | base64 -w 0 | base64 -d)
  1. Configure values
# values.yaml
image:
  registry: docker.io
  repository: bitnami/rabbitmq
  tag: 3.12.13-debian-12-r2
  debug: true
 
auth:
  existingErlangSecret: "ims-rabitmq-erlang-cookie"
 
clustering:
  rebalance: all
  forceBoot: true
 
loadDefinition:
  enabled: true
  existingSecret: "ims-rabitmq-load-definition"
 
extraConfiguration: |-
  management.path_prefix = /rabbitmq
  load_definitions = /app/load_definition.json
  raft.wal_max_size_bytes = 128000000
  cluster_formation.target_cluster_size_hint = {{ .Values.replicaCount }}
  log.default.level = debug
  log.file = false
  log.console = true
  log.console.level = debug
  log.console.formatter = json
 
replicaCount: 3
 
resources:
  requests:
    cpu: 750m
    memory: 1024Mi
  limits:
    cpu: 1500m
    memory: 1024Mi
 
persistence:
  storageClass: "-" # Forces static provision
  accessModes:
    - ReadWriteMany
  existingClaim: "sciamus-rabbitmq-pvc"
 
metrics:
  enabled: true
 
volumePermissions:
  enabled: true
  resources:
    requests:
      cpu: 50m
      memory: 12Mi
    limits:
      cpu: 100m
      memory: 24Mi
  1. Install RabbitMQ using Helm
# add bitnami repo
helm repo add bitnami https://charts.bitnami.com/bitnami
 
# install RabbitMQ (with preconfigured PV & PVC)
helm upgrade \
  --namespace ims \
  -f values.yaml \
  --install ims-rabbitmq \
  bitnami/rabbitmq --version 13.0.0

Note, that commands and configuration presented above are based on Helm chart version 13.0.0 and RabbitMQ version 3.12.13. You can adjust versions according to your needs and newer versions avaliability.

Deploying IMS Microservices

Microservices are launched using generative solutions. For this purpose, the values_{your_env}.yml file is used to select the environment, followed by installation using Helm, as shown further below.

The process of starting microservices in IMS is described below, using the ims-gateway-service microservice as an example.

For documentation purposes, the file has been divided into the general section and the ims-gateway-service section.

values_{your_env}.yml - general:

general:
  namespace: "ns-name"
  internalConfiguration:
    mongodb:
      protocol: "mongodb"
      parameters:
        base: "yourBase"
        query: "yourQuery"
      defaultSecret:
        mongodbHost: "yourMongoDBHost"
        mongodbPort: yourPort
      secretKeys:
        mongoHost: "yourMongoHost"
        mongoPort: "yourMongoPort"
        mongoUser: "yourMongoUser"
        mongoPassword: "yourMongoPassword"
    rabbitmq:
      rabbitmqHost: "yourRabbithost"
      rabbitmqPort: yourPort
      secretKeys:
        rabbitmqUser: "yourRabbitMQUser"
        rabbitmqPassword: "yourRabbitMQPassword"
  internalCredential:
    mongodb:
      mongoUser: "yourMongoUser"
      mongoPwd: "yourMongoPwd"
    rabbitmq:
      rabbitmqUser: "yourRabbitMQUser"
      rabbitmqPwd: "yourRabbitMQPwd"
  externalConfiguration:
    postgresHost: "yourPostgressHost"
    ingressHost: "yourIngressHost"
    keycloakAuthUrl: "yourKeyCloakAuthUrl"
    keycloakRealm: ims
  specifyLabels:
    monitoring: "example-app"

values_{your_env}.yml - ims-gateway-service:

ims-si-gateway:
  global:
    image:
      repository: "registryUrl"
      pullPolicy: IfNotPresent
      tagOverride: ""
    imagePullSecrets: "no needed"
    secrets:
      defaultSecret:
        create: false
      needed: true
      existingSecrets:
        - name: namespace-app-secret
  mongodb:
    enabled: false
 
  env:
  - name: _JAVA_OPTIONS
    value: "-XX:MaxRAMPercentage=70 -XX:+ExitOnOutOfMemoryError"
 
  service:
    type: ClusterIP
    protocol: TCP
    port: 8080
    targetPort: 8080
 
  resources:
    limits:
      cpu: 500m
      memory: 1024Mi
    requests:
      cpu: 10m
      memory: 1024Mi
  diagnosticMode:
    enabled: true
    customStartupProbe:
      httpGet:
        path: /actuator/health/liveness
        port: 8080
        scheme: HTTP
      timeoutSeconds: 1
      periodSeconds: 30
      successThreshold: 1
      failureThreshold: 10
 
    customLivenessProbe:
      httpGet:
        path: /actuator/health/liveness
        port: 8080
        scheme: HTTP
      timeoutSeconds: 1
      periodSeconds: 10
      successThreshold: 1
      failureThreshold: 3
 
    customReadinessProbe:
      httpGet:
        path: /actuator/health/readiness
        port: 8080
        scheme: HTTP
      initialDelaySeconds: 60
      timeoutSeconds: 1
      periodSeconds: 10
      successThreshold: 1
      failureThreshold: 2
 
  configurationManagement:
    ims:
      apiBase: "/si-gateway/api/v1"
      loggingTrace: "false"
      defaultLimit: 50
    client:
      inventory-view:
        url: your-url/inventory-view/api/v1
      lock:
        url: your-url/lock/api/v1
      task:
        url: your-url/task/api/v1
 
 
  ## @param extraDeployment Array of extra objects to deploy with the release
  ## For example - VirtualService
  extraDeployment:
    
      apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      metadata:
        name: ims-si-gateway-virtualservice
      spec:
        hosts:
       your-host
        gateways:
         istio-system/sitom
        http:
         match:
           uri:
              prefix: /your-gateway
          route:
           destination:
              host: your-gateway
              port:
                number: 8080
  affinity:
    enabled: false

The values_{your_env}.yml file overrides the values defined in the values.yml file, allowing configuration for a specific environment.

In the values_{your_env}.yml file, additional configurations can be applied using keys prefixed with extra (e.g., extraConfiguration, extraDeployment).

The final step is to execute the helm upgrade command, which applies the configuration for the selected environment and starts the microservice.

- helm upgrade --debug -f ./values_{your_env}.yaml --install ${releaseName} --namespace=namespace-{your_env} ./.chart/.

This process should be repeated for all IMS microservices.

Real-Life Deployment

We recommend that the installation of the IMS system in real (DEV, TEST, PROD) environments be carried out using CI/CD class tools.