Recommended Architectures

Overview

This section presents the recommended container architecture for WorkflowGen in order to run the web portals and Windows services. There will be many references to the image configuration properties; see the Configuration section for information on these.

This section is only about container architecture. SQL data and volumes should always be used regardless of the architecture.

See the SQL Server Hosting Options section for information on SQL database deployments, and the File Management section for information on volume deployment.

Single container

This is the simplest architecture you can run with WorkflowGen: a single container without replicas that runs both web applications and Windows Services. Therefore, you would set the WFGEN_START_SERVICE environment variable to all. This architecture is well suited to development and test environments, but it can also be considered when the performance with a single container fits the product usage. You can't replicate the container because there should only be one instance of each WorkflowGen Windows Service running.

Docker Compose example

This is the same example as in the Getting Started section. It has one WorkflowGen container that runs every service (web applications and Windows Services).

version: '3.7'
services:
  workflowgen:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    ports:
      - '8080:80'
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  database:
    image: advantys/workflowgen-sql:7.18.3-express-win-ltsc2019
    env_file:
      - '.\database.env'
    volumes:
      - 'sqldata:C:\wfgen\sql'

volumes:
  wfgdata:
  licenses:
    external: true
  sqldata:
  

Helm example

This example is different from the Getting Started example. This Helm release is not scalable in the cluster. It has a pod that runs all of the WorkflowGen services (web applications and Windows services) and another pod for the database. You can use the steps in the Getting Started example to generate the requested values. Don't forget to get the external IP address of the load balancer once it's created.

scalable: false

workflowgen:
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '1'
      memory: 2Gi
  config:
    WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
    WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
    WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
    WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
    WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
    WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
  secret:
    ApplicationSerialNumber: <YOUR_WFG_LIC_KEY>
    ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID>
    WFGEN_DATABASE_CONNECTION_STRING: 'Server=wfgen-database-0.wfgen-database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;'
    WFGEN_MACHINE_KEY_DECRYPTION_KEY: '39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85'
    WFGEN_MACHINE_KEY_VALIDATION_KEY: '82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9'
  license:
    secretName: wfgen-license-secret
    items:
      - key: WorkflowGen.lic
        path: WorkflowGen.lic
  dataPvcSpec:
    accessModes:
      - ReadWriteMany
    storageClassName: azurefile
    resources:
      requests:
        storage: 50Gi
  service:
    type: LoadBalancer

database:
  fullnameOverride: wfgen-database
  nodeSelector:
    kubernetes.io/os: linux
  securityContext:
    runAsUser: 0
    runAsGroup: 0
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '500m'
      memory: 1Gi
  config:
    ACCEPT_EULA: 'Y'
    SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
    WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
    WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
    WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
  secret:
    SA_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
    WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_USERNAME: WFGEN_USER
  volumeClaimTemplateSpec:
    accessModes:
      - ReadWriteOnce
    storageClassName: default
    resources:
      requests:
        storage: 100Gi
        
ingress:
  enabled: false

Multiple web application instances, single Windows Services instance

Since there can be only one instance of each WorkflowGen Windows Service running at a time, this architecture lets you run multiple replicas of the web applications in order to scale WorkflowGen to meet your traffic and processing needs without having more instances of the Windows Services.

You'll need to set the WFGEN_START_SERVICE environment variable to web_apps for the web applications' containers, and to win_services for the single container to run all of the Windows Services without web applications. This architecture is good for scaling the web portals to the traffic and processing needs, without too much pressure on the Windows Services.

Docker Compose example

version: '3.7'
services:
  workflowgen-web-apps:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    environment:
      WFGEN_START_SERVICE: web_apps
    ports:
      - '8080:80'
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  workflowgen-win-services:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    environment:
      WFGEN_START_SERVICE: win_services
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  database:
    image: advantys/workflowgen-sql:7.18.3-express-win-ltsc2019
    env_file:
      - '.\database.env'
    volumes:
      - 'sqldata:C:\wfgen\sql'

volumes:
  appdata:
  licenses:
    external: true
  sqldata:
  

Helm example

This is the same example as in the Getting Started section. The Windows Services containers will always be in the same pod when you use the WorkflowGen Helm chart. You can use the steps in the Getting Started example to generate the requested values. Don't forget to get the external IP address of the load balancer once it's created.

replicaCount: 3

workflowgen:
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '1'
      memory: 2Gi
  config:
    WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
    WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
    WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
    WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
    WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
    WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
  secret:
    ApplicationSerialNumber: <YOUR_WFG_LIC_KEY>
    ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID>
    WFGEN_DATABASE_CONNECTION_STRING: 'Server=wfgen-database-0.wfgen-database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;'
    WFGEN_MACHINE_KEY_DECRYPTION_KEY: '39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85'
    WFGEN_MACHINE_KEY_VALIDATION_KEY: '82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9'
  license:
    secretName: wfgen-license-secret
    items:
      - key: WorkflowGen.lic
        path: WorkflowGen.lic
  dataPvcSpec:
    accessModes:
      - ReadWriteMany
    storageClassName: azurefile
    resources:
      requests:
        storage: 50Gi
  service:
    type: LoadBalancer

winServices:
  dirSync:
    resources:
      limits:
        cpu: '1'
        memory: 1Gi
      requests:
        cpu: '500M'
        memory: 1Gi
  engine:
    resources:
      limits:
        cpu: '1'
        memory: 1Gi
      requests:
        cpu: '500M'
        memory: 1Gi

database:
  fullnameOverride: wfgen-database
  nodeSelector:
    kubernetes.io/os: linux
  securityContext:
    runAsUser: 0
    runAsGroup: 0
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '500m'
      memory: 1Gi
  config:
    ACCEPT_EULA: 'Y'
    SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
    WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
    WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
    WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
  secret:
    SA_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
    WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_USERNAME: WFGEN_USER
  volumeClaimTemplateSpec:
    accessModes:
      - ReadWriteOnce
    storageClassName: default
    resources:
      requests:
        storage: 100Gi

Multiple web application instances, dedicated Windows services containers

This recommended architecture is the most scalable. It has multiple containers for the web applications that can be scaled for increased traffic or processing needs, and has dedicated containers for each Windows Service: one for the directory synchronization service and one for the engine service. Therefore, you would set the WFGEN_START_SERVICE environment variable to web_apps for the web applications' containers, to dir_sync for the directory synchronization service container, and to engine for the engine service container. This architecture is good for high availability and high performance scenarios.

Docker Compose example

version: '3.7'
services:
  workflowgen-web-apps:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    environment:
      WFGEN_START_SERVICE: web_apps
    ports:
      - '8080:80'
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  workflowgen-dir-sync-service:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    environment:
      WFGEN_START_SERVICE: dir_sync
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  workflowgen-engine-service:
    image: advantys/workflowgen:7.18.3-win-ltsc2019
    restart: always
    env_file:
      - '.\workflowgen.env'
    environment:
      WFGEN_START_SERVICE: engine
    volumes:
      - 'wfgdata:C:\wfgen\data'
      - 'licenses:C:\wfgen\licenses:RO'
    depends_on:
      - database
  database:
    image: advantys/workflowgen-sql:7.18.3-express-win-ltsc2019
    env_file:
      - '.\database.env'
    volumes:
      - 'sqldata:C:\wfgen\sql'

volumes:
  wfgdata:
  licenses:
    external: true
  sqldata:

Helm example

This is the same example as in the Getting Started section. The Windows services containers will always be in the same pod when you use the WorkflowGen Helm chart. You can use the steps in the Getting Started example to generate the requested values. Don't forget to get the external IP address of the load balancer once it's created.

replicaCount: 3

workflowgen:
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '1'
      memory: 2Gi
  config:
    WFGEN_APP_SETTING_ApplicationUrl: http://10.0.1.1/wfgen
    WFGEN_DATABASE_CONNECTION_STRING_FILE: C:\secrets\WFGEN_DATABASE_CONNECTION_STRING
    WFGEN_APP_SETTING_ApplicationSerialNumber_FILE: C:\secrets\ApplicationSerialNumber
    WFGEN_APP_SETTING_ApplicationSecurityPasswordSymmetricEncryptionKey_FILE: C:\secrets\ApplicationSecurityPasswordSymmetricEncryptionKey
    WFGEN_MACHINE_KEY_DECRYPTION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_DECRYPTION_KEY
    WFGEN_MACHINE_KEY_VALIDATION_KEY_FILE: C:\secrets\WFGEN_MACHINE_KEY_VALIDATION_KEY
  secret:
    ApplicationSerialNumber: <YOUR_WFG_LIC_KEY>
    ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID>
    WFGEN_DATABASE_CONNECTION_STRING: 'Server=wfgen-database-0.wfgen-database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;'
    WFGEN_MACHINE_KEY_DECRYPTION_KEY: '39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85'
    WFGEN_MACHINE_KEY_VALIDATION_KEY: '82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9'
  license:
    secretName: wfgen-license-secret
    items:
      - key: WorkflowGen.lic
        path: WorkflowGen.lic
  dataPvcSpec:
    accessModes:
      - ReadWriteMany
    storageClassName: azurefile
    resources:
      requests:
        storage: 50Gi
  service:
    type: LoadBalancer

winServices:
  dirSync:
    resources:
      limits:
        cpu: '1'
        memory: 1Gi
      requests:
        cpu: '500M'
        memory: 1Gi
  engine:
    resources:
      limits:
        cpu: '1'
        memory: 1Gi
      requests:
        cpu: '500M'
        memory: 1Gi

database:
  fullnameOverride: wfgen-database
  nodeSelector:
    kubernetes.io/os: linux
  securityContext:
    runAsUser: 0
    runAsGroup: 0
  resources:
    limits:
      cpu: '1'
      memory: 2Gi
    requests:
      cpu: '500m'
      memory: 1Gi
  config:
    ACCEPT_EULA: 'Y'
    SA_PASSWORD_FILE: /mnt/secrets/SA_PASSWORD
    WFGEN_DATABASE_USER_USERNAME_FILE: /mnt/secrets/WFGEN_DATABASE_USER_USERNAME
    WFGEN_DATABASE_USER_PASSWORD_FILE: /mnt/secrets/WFGEN_DATABASE_USER_PASSWORD
    WFGEN_ADMIN_PASSWORD_FILE: /mnt/secrets/WFGEN_ADMIN_PASSWORD
  secret:
    SA_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_PASSWORD: 'strong(!)Pass'
    WFGEN_ADMIN_PASSWORD: 'strong(!)Pass'
    WFGEN_DATABASE_USER_USERNAME: WFGEN_USER
  volumeClaimTemplateSpec:
    accessModes:
      - ReadWriteOnce
    storageClassName: default
    resources:
      requests:
        storage: 100Gi

Last updated