Getting Started

Overview

This section presents how to quickly run the WorkflowGen container with a minimal architecture on Kubernetes.

There are known limitations when using Hyper-V isolation with the WorkflowGen container. It's recommended to use process isolation exclusively.

Kubernetes with AKS

This example is designed for Azure Kubernetes Service (AKS). To get started with AKS, see the Create a Windows Server container on an Azure Kubernetes Service (AKS) cluster using the Azure CLI Microsoft article.

Architecture overview

At the end of this section, you'll have this cluster configuration:

Azure resources view
Kubernetes objects view

Every container in the cluster will have access to the configuration and secrets inside their namespaces. Several Azure services will be deployed by Azure Kubernetes Service. This doesn't require any manual steps other than interacting with Kubernetes itself. The load balancer that the service will create will dispatch the requests between the WorkflowGen server replicas.

Prerequisites

As well, note that you should not create any other resources in Azure besides the cluster and its nodes. All required resources for the containers will be created by Kubernetes automatically. AKS is a fully-managed platform.

Add a PersistentVolumeClaim for shared storage

Now, you need to add a claim that represent the WorkflowGen data volume that will be used by your deployment. To do this, apply the following YAML to your cluster:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: wfgdata-pvc
spec:
accessModes:
- ReadWriteMany
storageClassName: azurefile
resources:
requests:
storage: 50Gi

Then, apply it to the cluster using the following command:

kubectl apply -c .\wfgdata-pvc.yml

Add your WorkflowGen license file to the cluster

Kubernetes enables you to manage secrets and configurations as files inside the cluster and inject them into pods. In this case, you'll add your license file as a secret and later inject it to the WorkflowGen pod. To add your license to the cluster, execute the following command:

kubectl create secret generic wfgen-license-secret --from-file C:\Path\To\WorkflowGen.lic

Add ConfigMaps for the services

As mentioned earlier, there is a mechanism in Kubernetes that allows you to manage your containers' configurations. Here, you'll create one for WorkflowGen and another for the database:

apiVersion: v1
kind: ConfigMap
metadata:
name: wfgen-config
data:
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
---
apiVersion: v1
kind: ConfigMap
metadata:
name: database-config
data:
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

The WFGEN_APP_SETTING_ApplicationUrl value will be changed to the load balancer's IP address after creating the WorkflowGen services. Therefore, it doesn't matter for now what is put in there because it will be changed later in this example.

Don't forget to apply this configuration:

kubectl apply -f .\config.yml

Add secrets for the services

Kubernetes also manages secrets for you. They are securely stored and only given to the containers as files.

You need an encryption key to put as a secret:

[guid]::NewGuid().ToString('N')
# fda7a6a81db2428b8885bd1210522755

Before creating the secrets, you must encode them in base64:

using namespace System.Text
function ConvertTo-Base64String {
[CmdletBinding()]
[OutputType([string])]
param (
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[ValidateNotNullOrEmpty()]
[string]$Value
)
process {
return [Convert]::ToBase64String([Encoding]::UTF8.GetBytes($Value))
}
}
# Database containers
"strong(!)Pass" | ConvertTo-Base64String # c3Ryb25nKCEpUGFzcw==
"WFGEN_USER" | ConvertTo-Base64String # V0ZHRU5fVVNFUg==
# WorkflowGen containers
"<YOUR_WFG_LIC_KEY>" | ConvertTo-Base64String # PFlPVVJfV0ZHX0xJQ19LRVk+
"<YOU_NEW_GUID>" | ConvertTo-Base64String # PFlPVV9ORVdfR1VJRD4=
"Server=database-0.database.default.svc.cluster.local,1433;Database=WFGEN;User ID=WFGEN_USER;Password=strong(!)Pass;" `
| ConvertTo-Base64String # V0ZHRU5fREFUQUJBU0VfQ09OTkVDVElPTl9TVFJJTkc9RGF0YSBTb3VyY2U9ZGF0YWJhc2UsMTQzMztOZXR3b3JrIExpYnJhcnk9REJNU1NPQ047SW5pdGlhbCBDYXRhbG9nPVdGR0VOO1VzZXIgSUQ9V0ZHRU5fVVNFUjtQYXNzd29yZD1zdHJvbmcoISlQYXNzOw==
"39B3AE9CCCF94AA47D795EC84F7CCB7928F5D59BE2EB2BBA4FE2AC0B3C8D0C85" | ConvertTo-Base64String # MzlCM0FFOUNDQ0Y5NEFBNDdENzk1RUM4NEY3Q0NCNzkyOEY1RDU5QkUyRUIyQkJBNEZFMkFDMEIzQzhEMEM4NQ==
"82F6247A5DBF8666FB60B8EFE6483360436F0EC426CC0351A9569C607B46C1FAD6497406DD8B0B519DD83CAA6764904C89999D742638ECE756E7C0B8799B45E9" `
| ConvertTo-Base64String # ODJGNjI0N0E1REJGODY2NkZCNjBCOEVGRTY0ODMzNjA0MzZGMEVDNDI2Q0MwMzUxQTk1NjlDNjA3QjQ2QzFGQUQ2NDk3NDA2REQ4QjBCNTE5REQ4M0NBQTY3NjQ5MDRDODk5OTlENzQyNjM4RUNFNzU2RTdDMEI4Nzk5QjQ1RTk=

Replace <YOUR_WFG_LIC_KEY> with your WorkflowGen license key, and replace <YOUR_NEW_GUID> with the GUID that you generated.

Those encoded values will go into the secrets declaration. To create the required secrets for the services, apply the following YAML:

apiVersion: v1
kind: Secret
metadata:
name: database-sec
type: Opaque
data:
SA_PASSWORD: c3Ryb25nKCEpUGFzcw==
WFGEN_DATABASE_USER_PASSWORD: c3Ryb25nKCEpUGFzcw==
WFGEN_ADMIN_PASSWORD: c3Ryb25nKCEpUGFzcw==
WFGEN_DATABASE_USER_USERNAME: V0ZHRU5fVVNFUg==
---
apiVersion: v1
kind: Secret
metadata:
name: wfgen-sec
type: Opaque
data:
ApplicationSerialNumber: <YOUR_WFG_LIC_KEY_BASE64>
ApplicationSecurityPasswordSymmetricEncryptionKey: <YOUR_NEW_GUID_BASE64>
WFGEN_DATABASE_CONNECTION_STRING: V0ZHRU5fREFUQUJBU0VfQ09OTkVDVElPTl9TVFJJTkc9RGF0YSBTb3VyY2U9ZGF0YWJhc2UsMTQzMztOZXR3b3JrIExpYnJhcnk9REJNU1NPQ047SW5pdGlhbCBDYXRhbG9nPVdGR0VOO1VzZXIgSUQ9V0ZHRU5fVVNFUjtQYXNzd29yZD1zdHJvbmcoISlQYXNzOw==
WFGEN_MACHINE_KEY_DECRYPTION_KEY: MzlCM0FFOUNDQ0Y5NEFBNDdENzk1RUM4NEY3Q0NCNzkyOEY1RDU5QkUyRUIyQkJBNEZFMkFDMEIzQzhEMEM4NQ==
WFGEN_MACHINE_KEY_VALIDATION_KEY: ODJGNjI0N0E1REJGODY2NkZCNjBCOEVGRTY0ODMzNjA0MzZGMEVDNDI2Q0MwMzUxQTk1NjlDNjA3QjQ2QzFGQUQ2NDk3NDA2REQ4QjBCNTE5REQ4M0NBQTY3NjQ5MDRDODk5OTlENzQyNjM4RUNFNzU2RTdDMEI4Nzk5QjQ1RTk=

Replace <YOUR_WFG_LIC_KEY_BASE64> with the value generated in the previous step for the WorkflowGen license key, and replace <YOUR_NEW_GUID_BASE64> with the value generated in the previous step for the new GUID.

Don't forget to apply this:

kubectl apply -f secrets.yml

Deploy the containers

You're now ready to deploy the services. You'll create two Deployment objects and one ReplicaSet object. The deployment will create ReplicaSets for all the services with different configurations. Those deployments can later be configured to automatically scale with the pods' usage. The ReplicaSet will provide the necessary services to the database container in order to run properly and avoid data losses. Don't forget that there should only be one instance of each WorkflowGen Windows Service running at all time. This container pattern is called a Singleton.

Database

This configuration will deploy the StatefulSet database along with a headless service. This object will also create a persistent volume claim based on the template provided in the declaration.

apiVersion: v1
kind: Service
metadata:
name: database
spec:
type: ClusterIP
clusterIP: None
ports:
- port: 1433
targetPort: mssql
protocol: TCP
name: mssql
selector:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: database
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: database
spec:
replicas: 1
serviceName: database
selector:
matchLabels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: database
template:
metadata:
labels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: database
spec:
terminationGracePeriodSeconds: 10
nodeSelector:
kubernetes.io/os: linux
containers:
- name: database
image: advantys/workflowgen-sql:7.18.3-ubuntu-18.04
imagePullPolicy: Always
securityContext:
runAsUser: 0
runAsGroup: 0
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1"
envFrom:
- configMapRef:
name: database-config
ports:
- name: mssql
containerPort: 1433
livenessProbe:
initialDelaySeconds: 30
timeoutSeconds: 5
exec:
command:
- pwsh
- -NoLogo
- -NoProfiles
- /usr/local/bin/healthcheck.ps1
readinessProbe:
initialDelaySeconds: 20
timeoutSeconds: 5
exec:
command:
- pwsh
- -NoLogo
- -NoProfiles
- /usr/local/bin/healthcheck.ps1
volumeMounts:
- mountPath: /var/opt/mssql
name: sqldata
- mountPath: /mnt/secrets
readOnly: true
name: secrets
volumes:
- name: secrets
secret:
secretName: database-sec
volumeClaimTemplates:
- metadata:
name: sqldata
spec:
accessModes:
- ReadWriteOnce
storageClassName: default
resources:
requests:
storage: 100Gi

Apply the database first:

kubectl apply -f database.yml

WorkflowGen web applications

apiVersion: apps/v1
kind: Deployment
metadata:
name: wfgen-webapps
spec:
replicas: 3
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: webapps
template:
metadata:
labels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: webapps
spec:
nodeSelector:
kubernetes.io/os: windows
containers:
- name: wfgen
image: advantys/workflowgen:7.18.3-win-ltsc2019
imagePullPolicy: Always
resources:
requests:
memory: "2Gi"
cpu: "1"
limits:
memory: "2Gi"
cpu: "1"
ports:
- name: http
containerPort: 80
protocol: TCP
envFrom:
- configMapRef:
name: wfgen-config
env:
- name: WFGEN_START_SERVICE
value: webapps
livenessProbe:
periodSeconds: 30
timeoutSeconds: 5
initialDelaySeconds: 60
exec:
command:
- powershell
- C:\healthcheck.ps1
livenessProbe:
timeoutSeconds: 5
initialDelaySeconds: 60
exec:
command:
- powershell
- -Command
- if (Test-Path "C:\iislog\W3SVC\*log") { return 0 } else { return 1 }
volumeMounts:
- mountPath: C:\wfgen\data
name: wfgdata
- mountPath: C:\wfgen\licenses
readOnly: true
name: licenses
- mountPath: C:\secrets
readOnly: true
name: secrets
volumes:
- name: wfgdata
persistentVolumeClaim:
claimName: wfgdata-pvc
- name: licenses
secret:
secretName: wfgen-license-secret
items:
# The following must match the name of the license item in
# the license secret, e.g. the name of the license file
- key: WorkflowGen.lic
path: WorkflowGen.lic
- name: secrets
secret:
secretName: wfgen-sec

Apply this replication controller:

kubectl apply -f wfgen-webapps.yml

Windows Services deployment

apiVersion: apps/v1
kind: Deployment
metadata:
name: wfgen-winservices
spec:
replicas: 1 # Singleton pattern
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: winservices
template:
metadata:
labels:
app.kubernetes.io/name: workflowgen
app.kubernetes.io/component: winservices
spec:
nodeSelector:
kubernetes.io/os: windows
containers:
- name: wfgen-dir-sync
image: advantys/workflowgen:7.18.3-win-ltsc2019
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "750m"
envFrom:
- configMapRef:
name: wfgen-config
env:
- name: WFGEN_START_SERVICE
value: dir_sync
livenessProbe:
periodSeconds: 30
timeoutSeconds: 5
initialDelaySeconds: 60
exec:
command:
- powershell
- C:\healthcheck.ps1
volumeMounts:
- mountPath: C:\wfgen\data
name: wfgdata
- mountPath: C:\wfgen\licenses
readOnly: true
name: licenses
- mountPath: C:\secrets
readOnly: true
name: secrets
- name: wfgen-engine
image: advantys/workflowgen:7.18.3-win-ltsc2019
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "750m"
envFrom:
- configMapRef:
name: wfgen-config
env:
- name: WFGEN_START_SERVICE
value: engine
livenessProbe:
periodSeconds: 30
timeoutSeconds: 5
initialDelaySeconds: 60
exec:
command:
- powershell
- C:\healthcheck.ps1
volumeMounts:
- mountPath: C:\wfgen\data
name: wfgdata
- mountPath: C:\wfgen\licenses
readOnly: true
name: licenses
- mountPath: C:\secrets
readOnly: true
name: secrets
volumes:
- name: wfgdata
persistentVolumeClaim:
claimName: wfgdata-pvc
- name: licenses
secret:
secretName: fgen-license-secret
items:
# The following must match the name of the license item in
# the license secret, e.g. the name of the license file
- key: WorkflowGen.lic
path: WorkflowGen.lic
- name: secrets
secret:
secretName: wfgen-sec

Apply the Windows Services:

kubectl apply -f wfgen-win-services.yml

Add a load balancer

Now, you need to add a public-facing load balancer in order to dispatch requests to your pods. To do this, execute the following command:

kubectl expose deployment wfgen-webapps --type=LoadBalancer --name=wfgen-service

You now need to wait for the IP to be provisioned. Execute the following command periodically until you get the load balancer's public IP:

kubectl get services wfgen-service

Once the value of EXTERNAL-IP is provisioned, copy it and modify the WorkflowGen configuration to change the WFGEN_APP_SETTING_ApplicationUrl value:

# wfgen-config.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: wfgen-config
data:
WFGEN_APP_SETTING_ApplicationUrl: 'http://<EXTERNAL_IP>/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

Replace <EXTERNAL_IP> with the value of EXTERNAL-IP that you have.

Apply it:

kubectl apply -f wfgen-config.yml

Then, restart all of the pods in the WorkflowGen deployment to apply the changes to them. You have to do this for the Windows services as well. To do this, execute the following commands:

kubctl scale deployment wfgen-webapps --replicas 0 -n wfgen-service
kubctl scale deployment wfgen-winservices --replicas 0 -n wfgen-service
# Wait until the scaling is done and then scale up
kubctl scale deployment wfgen-webapps --replicas 3 -n wfgen-service
kubctl scale deployment wfgen-winservices --replicas 1 -n wfgen-service

You should now have a working WorkflowGen with a load balancer and a database.

Kubernetes with AKS using Helm

Helm is a package manager–like tool for Kubernetes. It manages the sharing, deployment, updates and rollbacks of software developed for Kubernetes. Based on values provided, Helm generates definition files for the cluster with the template engine from the Go programming language. For each release, WorkflowGen now produces a chart that you can use with your cluster. To have the latest bug fixes and features from the chart, make sure to always pick the chart released with the latest update of WorkflowGen.

Architecture overview

At the end of this section, you'll have this cluster configuration:

Azure resources view
Kubernetes objects view

Every container in the cluster will have access to the configuration and secrets inside their namespaces. Several Azure services will be deployed by Azure Kubernetes Service. This doesn't require any manual steps other than interacting with Kubernetes itself. The load balancer that the service will create will dispatch the requests between the WorkflowGen server replicas.

Prerequisites

As well, note that you should not create any other resources in Azure besides the cluster and its nodes. All required resources for the containers will be created by Kubernetes automatically. AKS is a fully-managed platform.

Create the symmetric encryption key

This value should be generated by you. A simple GUID will suffice since it has sufficient entropy not to be guessed:

[guid]::NewGuid().ToString('N')
# fda7a6a81db2428b8885bd1210522755

Add your WorkflowGen license file to the cluster

Kubernetes enables you to manage secrets and configurations as files inside the cluster and inject them into pods. In this case, you'll add your license file as a secret and later inject it to the WorkflowGen pod. To add your license to the cluster, execute the following command:

kubectl create secret generic wfgen-license-secret --from-file C:\Path\To\WorkflowGen.lic

Create a file with your values for the Chart

In order to generate the templates tailored to your configuration expectations, you have to provide some values to the helm command when you install or update a release. You can specify those values using the command line interface or with a file. In the case of a new installation, it will be easier with a file. Here are the values that you will need:

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
ingress:
enabled: false

Replace <YOUR_WFG_LIC_KEY> with your WorkflowGen license key, and replace <YOUR_NEW_GUID> with the GUID that you generated.

You can save this file as values.yaml. The name is not important.

Install the WorkflowGen chart

You now need to install the chart with those values. To do this, execute the following command:

helm install -f .\values.yaml wfg https://github.com/advantys/workflowgen-releases/releases/download/7.18.3/workflowgen-0.0.3.tgz

Helm will generate Kubernetes deployment files for you and install them on the cluster.

Update the application URL

This configuration will create a load balancer in front of the WorkflowGen containers. You will need to wait for it to get a public IP address. Execute the following command periodically until you get the load balancer's public IP:

kubectl get services wfgen-service

Once the value of EXTERNAL-IP is provisioned, copy it and modify the WorkflowGen configuration to change the WFGEN_APP_SETTING_ApplicationUrl value. To do this, you first need to get the name of the ConfigMap associated with the WorkflowGen deployment. The following command will give you all the ConfigMap objects in the default namespace:

kubectl get configmap

Copy the WorkflowGen ConfigMap name and replace <WFG_CONFIG_MAP> with the value in the following command:

kubectl edit configmap "<WFGEN_CONFIG_MAP>"

This will bring up an editor so you can replace the WFGEN_APP_SETTING_ApplicationUrl value with the correct IP address from the load balancer service. Save the file and exit the editor. To apply the changes made to the ConfigMap object, restart all of the pods in the WorkflowGen deployment. You have to do this for the Windows services as well. Get the name of the deployments with the following command:

kubectl get deployment

Replace <WEB_APPS_DEPLOYMENT_NAME> and <WIN_SERVICES_DEPLOYMENT_NAME> in the following script with the correct deployment names to restart all containers:

kubctl scale deployment "<WEB_APPS_DEPLOYMENT_NAME>" --replicas 0 -n wfgen-service
kubctl scale deployment "<WIN_SERVICES_DEPLOYMENT NAME>" --replicas 0 -n wfgen-service
# Wait until the scaling is done and then scale up
kubctl scale deployment "<WEB_APPS_DEPLOYMENT_NAME>" --replicas 3 -n wfgen-service
kubctl scale deployment "<WIN_SERVICES_DEPLOYMENT NAME>" --replicas 1 -n wfgen-service

You should now have a working WorkflowGen with a load balancer and a database.