Shared Provisioning
Contents
Learn how to configure Genesys Pulse.
Prerequisites
Please complete Before you begin instructions.
Information you will need:
- Versions:
- <image-version> = 9.0.100.10
- <chart-versions>= 9.0.100+10
- K8S namespace <namespace> (e.g. 'pulse')
- Project Name <project-name> (e.g. 'pulse')
- Postgres credentials
- <db-host>
- <db-port>
- <db-port-internal>
- <db-name>
- <db-user>
- <db-user-password>
- <db-superuser>
- <db-superuser-password>
- <db-ssl-mode>
- Docker credentials
- <docker-email>
- <docker-password>
- <docker-user>
- OpenShift credentials
- <openshift-url>
- <openshift-port>
- <openshift-token>
- Redis credentials
- <redis-host>
- <redis-port>
- <redis-password>
- <redis-enable-ssl>
- Tenant service variables
- <tenant-uuid>
- <tenant-sid>
- <tenant-name>
- GAuth/GWS service variables
- <gauth-url-external>
- <gauth-url-internal>
- <gauth-client-id>
- <gauth-client-secret>
- <gws-url-external>
- <gws-url-internal>
export CHART_VERSION='<chart-version>'
export DB_HOST='<db-host>'
export DB_NAME_SHARED='<db-name>'
export DB_NAME_SUPERUSER='<db-superuser>'
export DB_PASSWORD_SHARED='<db-user-password>'
export DB_PASSWORD_SUPERUSER='<db-superuser-password>'
export DB_PORT='<db-port>'
export DB_SSL_MODE='<db-ssl-mode>'
export DB_USER_SHARED='<db-user>'
export DOCKER_EMAIL='<docker-email>'
export DOCKER_PASSWORD='<docker-password>'
export DOCKER_REGISTRY='<docker-registry>'
export DOCKER_REGISTRY_SECRET_NAME='<docker-registry-secret-name>'
export DOCKER_TAG='<image-version>'
export DOCKER_USER='<docker-user>'
export GAUTH_CLIENT_ID='<gauth-client-id>'
export GAUTH_CLIENT_SECRET='<gauth-client-secret>'
export GAUTH_URL='<gauth-url-external>'
export GAUTH_URL_INTERNAL='<gauth-url-internal>'
export GWS_URL='<gws-url-external>'
export GWS_URL_INTERNAL='<gws-url-internal>'
export NAMESPACE='<namespace>'
export OS_ADD_SCC_TO_USER='<scc-user>'
export OS_PORT='<openshift-port>'
export OS_TOKEN='<openshift-token>'
export OS_URL='<openshift-url>'
export PROJECT_NAME='<project-name>'
export PULSE_ENDPOINT='<pulse-endpoint>'
export PULSE_HEALTH_PORT=8090
export PV_STORAGE_CLASS_RW_MANY='<rw-many-storage-class>'
export REDIS_ENABLE_SSL='<redis-enable-ssl>'
export REDIS_HOST='<redis-host>'
export REDIS_PASSWORD='<redis-password>'
export REDIS_PORT='<redis-port>'
export TENANT_UUID='<tenant-uuid>'
export TENANT_DCU='2'
export TENANT_NAME='<tenant-name>'
export TENANT_SID='<tenant-sid>'
Create project in OpenShift
Login using token
source .shared_init_variables
oc login --token="${OS_TOKEN}" \
--server="${OS_URL}:${OS_PORT}" \
--insecure-skip-tls-verify=true
Create project
source .shared_init_variables
oc new-project "${PROJECT_NAME}" \
--description="${PROJECT_NAME}" \
--display-name="${PROJECT_NAME}"
Add SCC to user
source .shared_init_variables
oc adm policy add-scc-to-user "${OS_ADD_SCC_TO_USER}" -z default -n "${NAMESPACE}"
Enable namespace
source .shared_init_variables
oc annotate namespace --overwrite "${NAMESPACE}" 'scheduler.alpha.kubernetes.io/defaultTolerations'='[{"operator": "Equal", "effect": "NoSchedule", "key": "team", "value": "pat"}]'
Switch to project
source .shared_init_variables
oc project "${PROJECT_NAME}"
Create secret for auth to registry
source .shared_init_variables
oc create secret docker-registry "${DOCKER_REGISTRY_SECRET_NAME}" \
--docker-server="${DOCKER_REGISTRY}" \
--docker-username="${DOCKER_USER}" \
--docker-password="${DOCKER_PASSWORD}" \
--docker-email="${DOCKER_EMAIL}"
oc secrets link default "${DOCKER_REGISTRY_SECRET_NAME}" --for=pull
PostgreSQL
Create shared db user
As PosgreQSL superuser save the following as create_shared_db_role.sql:CREATE ROLE "${DB_USER_SHARED}@${DB_HOST}" WITH NOSUPERUSER LOGIN ENCRYPTED PASSWORD '${DB_PASSWORD_SHARED}';
Run:
source .shared_init_variables
envsubst < ./create_shared_db_role.sql | \
PGPASSWORD=${DB_PASSWORD_SUPERUSER} psql -h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_NAME_SUPERUSER}" -f -
Create shared db and grant privileges
Save the following as create_shared_db.sql
CREATE DATABASE ${DB_NAME_SHARED};
GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME_SHARED} TO "${DB_USER_SHARED}@${DB_HOST}";
Run:
source .shared_init_variables
envsubst < ./create_shared_db.sql | \
PGPASSWORD=${DB_PASSWORD_SUPERUSER} psql -h "${DB_HOST}" -p "${DB_PORT}" -U "${DB_NAME_SUPERUSER}" -f -
Deployment
Preparations
Create pulse-postgres-configmap
Save as pulse-postgres-configmap.yaml:apiVersion: v1
kind: ConfigMap
metadata:
name: pulse-postgres-configmap
namespace: ${NAMESPACE}
data:
META_DB_HOST: '${DB_HOST}'
META_DB_PORT: '${DB_PORT}'
META_DB_SSL_MODE: '${DB_SSL_MODE}'
source .shared_init_variables
envsubst < ./pulse-postgres-configmap | \
oc apply --namespace=${NAMESPACE} \
-f -
Validate pulse-postgres-configmap
The following command should return created ConfigMap:source .shared_init_variables
oc get configmap pulse-postgres-configmap -n=${NAMESPACE}
NAME DATA AGE
pulse-postgres-configmap 3 5h5m
Create pulse-redis-configmap
Save as pulse-redis-configmap:apiVersion: v1
kind: ConfigMap
metadata:
name: pulse-redis-configmap
namespace: ${NAMESPACE}
data:
REDIS_HOST: '${REDIS_HOST}'
REDIS_PORT: '${REDIS_PORT}'
REDIS_ENABLE_SSL: '${REDIS_ENABLE_SSL}'
source .shared_init_variables
envsubst < ./pulse-redis-configmap | \
oc apply --namespace=${NAMESPACE} \
-f -
Validate pulse-redis-configmap
The following command should return created ConfigMap:source .shared_init_variables
oc get configmap pulse-redis-configmap -n=${NAMESPACE}
NAME DATA AGE
pulse-redis-configmap 3 4h38m
Create pulse-gws-secret
Save as pulse-gws-secret.yaml:apiVersion: v1
kind: Secret
metadata:
name: pulse-gws-secret
namespace: ${NAMESPACE}
type: Opaque
stringData:
clientId: ${GAUTH_CLIENT_ID}
clientSecret: ${GAUTH_CLIENT_SECRET}
source .shared_init_variables
envsubst < ./pulse-gws-secret.yaml | \
oc apply --namespace=${NAMESPACE} \
-f -
Validate pulse-gws-secret
The following command should return created secret:source .shared_init_variables
oc get secret pulse-gws-secret -n=${NAMESPACE}
NAME TYPE DATA AGE
pulse-gws-secret Opaque 2 5h4m
Create pulse-postgres-secret
Save as pulse-postgres-secret.yaml:apiVersion: v1
kind: Secret
metadata:
name: pulse-postgres-secret
namespace: ${NAMESPACE}
type: Opaque
stringData:
META_DB_ADMIN: '${DB_USER_SHARED}'
META_DB_ADMINPWD: '${DB_PASSWORD_SHARED}'
source .shared_init_variables
envsubst < ./pulse-postgres-secret.yaml | \
oc apply --namespace=${NAMESPACE} \
-f -
Validate pulse-postgres-secret
The following command should return created secret:source .shared_init_variables
oc get secret pulse-postgres-secret -n=${NAMESPACE}
NAME TYPE DATA AGE
pulse-postgres-secret Opaque 2 5h30m
Create pulse-redis-secret
Save as pulse-redis-secret.yaml:apiVersion: v1
kind: Secret
metadata:
name: pulse-redis-secret
namespace: ${NAMESPACE}
type: Opaque
stringData:
REDIS01_KEY: ${REDIS_PASWORD}
source .shared_init_variables
envsubst < ./pulse-redis-secret.yaml | \
oc apply --namespace=${NAMESPACE} \
-f -
Validate pulse-redis-secret
The following command should return created secret:source .shared_init_variables
oc get secret pulse-redis-secret -n=${NAMESPACE}
NAME TYPE DATA AGE
pulse-redis-secret Opaque 1 5h5m
Install init helm chart
Use this chart for shared Postgres database.
Get init helm chart
Download the init helm chart from JFrog using your credentials.
Prepare override file
Save as values-override-init.yaml:# Default values for init.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
image:
name: init
tag: "${DOCKER_TAG}"
pullPolicy: IfNotPresent
repository: "${DOCKER_REGISTRY}/pulse/"
imagePullSecrets: [name: ${DOCKER_REGISTRY_SECRET_NAME}]
# tenant identification, or empty for shared deployment
tenants:
- id: "${TENANT_UUID}"
name: "${TENANT_NAME}"
key: "${TENANT_SID}"
dcu: "${TENANT_DCU}"
# common configuration.
config:
dbName: "${DB_NAME_SHARED}"
# set "true" when need @host added for username
dbUserWithHost: true
# set "true" for CSI secrets
mountSecrets: false
# Postgres config map name
postgresConfig: "pulse-postgres-configmap"
# Postgres secret name
postgresSecret: "pulse-postgres-secret"
# Postgres secret key for user
postgresSecretUser: "META_DB_ADMIN"
# Postgres secret key for password
postgresSecretPassword: "META_DB_ADMINPWD"
## Service account settings
serviceAccount:
# Specifies whether a service account should be created
create: false
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
## Add annotations to all pods
##
podAnnotations: {}
## Containers should run as genesys user and cannot use elevated permissions
## !!! THESE OPTIONS SHOULD NOT BE CHANGED UNLESS INSTRUCTED BY GENESYS !!!
# securityContext: {}
# runAsUser: 500
# runAsGroup: 500
## Resource requests and limits
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
##
resources:
limits:
memory: 256Mi
cpu: 200m
requests:
memory: 128Mi
cpu: 100m
## Priority Class
## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
##
priorityClassName: ""
## Node labels for assignment.
## ref: https://kubernetes.io/docs/user-guide/node-selection/
##
nodeSelector: {}
## Tolerations for assignment.
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
##
tolerations: []
Install init helm chart
Run:source .shared_init_variables
envsubst < ./values-override-init.yaml | \
helm upgrade --install pulse-init pe-jfrog-stage/init \
--wait --wait-for-jobs \
--version="${CHART_VERSION}" \
--namespace="${NAMESPACE}" \
-f -
This command will finish with exit code 0 if installation is successful.
Validate init helm chart
The following command should report pulse-init job as Completed:source .shared_init_variables
oc get pods -n="${NAMESPACE}" -l "app.kubernetes.io/name=init,app.kubernetes.io/instance=pulse-init"
NAME READY STATUS RESTARTS AGE
pulse-init-job-bvstl 0/1 Completed 0 3h30m
Install pulse helm chart
Use this chart for the shared part.
Get pulse helm chart
Download the pulse helm chart from JFrog using your credentials.
Prepare override file
Save as values-override-pulse.yaml:# Default values for pulse.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
image:
name: pulse
tag: "${DOCKER_TAG}"
pullPolicy: IfNotPresent
repository: "${DOCKER_REGISTRY}/pulse/"
imagePullSecrets: [name: ${DOCKER_REGISTRY_SECRET_NAME}]
replicaCount: 2
# common configuration.
config:
dbName: "${DB_NAME_SHARED}"
# set "true" when need @host added for username
dbUserWithHost: true
# set "true" for CSI secrets
mountSecrets: false
# Postgres config map name
postgresConfig: "pulse-postgres-configmap"
# Postgres secret name
postgresSecret: "pulse-postgres-secret"
# Postgres secret key for user
postgresSecretUser: "META_DB_ADMIN"
# Postgres secret key for password
postgresSecretPassword: "META_DB_ADMINPWD"
# Redis config map name
redisConfig: "pulse-redis-configmap"
# Redis secret name
redisSecret: "pulse-redis-secret"
# Redis secret key for access key
redisSecretKey: "REDIS01_KEY"
# GAuth secret name
gwsSecret: "pulse-gws-secret"
# GAuth secret key for client_id
gwsSecretClientId: "clientId"
# GAuth secret key for client_secret
gwsSecretClientSecret: "clientSecret"
# monitoring settings
monitoring:
# enable the Prometheus metrics endpoint
enabled: false
# port is <options.managementPort>
# HTTP path is <options.managementContext><options.prometheusEndpoint>
# additional annotations required for monitoring PODs
# you can reference values of other variables as {{.Values.variable.full.name}}
podAnnotations: {}
# prometheus.io/scrape: "true"
# prometheus.io/port: "{{.Values.options.managementPort}}"
# prometheus.io/path: "{{.Values.options.managementContext}}{{.Values.options.prometheusEndpoint}}"
serviceMonitor:
# enables ServiceMonitor creation
enabled: false
# interval at which metrics should be scraped
scrapeInterval: 30s
# timeout after which the scrape is ended
scrapeTimeout:
# namespace of the ServiceMonitor, defaults to the namespace of the service
namespace:
additionalLabels: {}
# common log configuration
log:
# target directory where log will be stored, leave empty for default
logDir: ""
# path where volume will be mounted
volumeMountPath: /data/log
# log volume type: none | hostpath | pvc
volumeType: pvc
# log volume hostpath, used with volumeType "hostpath"
volumeHostPath: /mnt/log
# log PVC parameters, used with volumeType "pvc"
pvc:
name: pulse-logs
accessModes:
- ReadWriteMany
capacity: 10Gi
class: ${PV_STORAGE_CLASS_RW_MANY}
# application options
options:
authUrl: "https://${GAUTH_URL}"
authUrlInt: "http://${GAUTH_URL_INTERNAL}"
gwsUrl: "https://${GWS_URL}"
gwsUrlInt: "http://${GWS_URL_INTERNAL}"
## Service account settings
serviceAccount:
# Specifies whether a service account should be created
create: false
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
## Add annotations to all pods
##
podAnnotations: {}
## Add labels to all pods
##
podLabels: {}
## Containers should run as genesys user and cannot use elevated permissions
## !!! THESE OPTIONS SHOULD NOT BE CHANGED UNLESS INSTRUCTED BY GENESYS !!!
# securityContext: {}
# runAsUser: 500
# runAsGroup: 500
## Ingress configuration
ingress:
enabled: true
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
## recommended to increase proxy-body-size size
# nginx.ingress.kubernetes.io/proxy-body-size: 5m
hosts:
- host: "${PULSE_ENDPOINT}"
paths: [/]
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
gateway:
enabled: false
## Resource requests and limits
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
##
resources:
limits:
memory: 4Gi
cpu: 1
requests:
memory: 650Mi
cpu: 100m
## HPA Settings
## Not supported in this release!
hpa:
enabled: false
## Priority Class
## ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
##
priorityClassName: ""
## Node labels for assignment.
## ref: https://kubernetes.io/docs/user-guide/node-selection/
##
nodeSelector: {}
## Tolerations for assignment.
## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
##
tolerations: []
## Pod Disruption Budget Settings
podDisruptionBudget:
enabled: false
## Affinity for assignment.
## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
##
affinity: {}
# control network policies
networkPolicies:
enabled: false
Install pulse helm chart
Run:source .shared_init_variables
envsubst < ./values-override-pulse.yaml | \
helm upgrade --install pulse pe-jfrog-stage/pulse \
--wait \
--version="${CHART_VERSION}" \
--namespace="${NAMESPACE}" \
-f -
This command will finish with exit code 0 if installation is successful.
Validate pulse helm chart
The following report running pods:source .shared_init_variables
oc get pods -n="${NAMESPACE}" -l "app.kubernetes.io/name=pulse,app.kubernetes.io/instance=pulse"
NAME READY STATUS RESTARTS AGE
pulse-5dbd484467-bh82r 1/1 Running 0 4h26m
pulse-5dbd484467-wz7xt 1/1 Running 0 4h26m
Validation
Check logs for error
oc get pods
os logs <pulse-pod-id>
Health validation
GET /actuator/metrics/pulse.health.all
Run in two different consoles (1 -> 2).
Console 1:
source .shared_init_variables
export POD_NAME=$(oc get pods --namespace=${NAMESPACE} -l "app.kubernetes.io/name=pulse,app.kubernetes.io/instance=pulse" -o jsonpath="{.items[0].metadata.name}")
oc --namespace=${NAMESPACE} port-forward $POD_NAME ${PULSE_HEALTH_PORT}:${PULSE_HEALTH_PORT}
Console 2:
source .shared_init_variables
curl -X GET http://127.0.0.1:${PULSE_HEALTH_PORT:-?}/actuator/metrics/pulse.health.all \
-H 'Content-Type: application/json' | jq '.'
Genesys Pulse is successfully running and can connect to Postgres and Redis when:
- HTTP response code is 200
- JSON response is measurements.statistic.value=1
{ "name": "pulse.health.all", "description": "Provides overall application status", "baseUnit": "Boolean", "measurements": [ { "statistic": "VALUE", "value": 1 } ], "availableTags": [ { "tag": "deployment.code", "values": [ "pulse" ] }, { "tag": "application.name", "values": [ "pulse" ] } ] }
Troubleshooting
Check init helm manifests
Run to output manifest into helm-template directory:
source .shared_init_variables
envsubst < ./values-override-init.yaml | \
helm template \
--version="${CHART_VERSION}" \
--namespace="${NAMESPACE}" \
--debug \
--output-dir helm-template \
init pe-jfrog-stage/init \
-f -
Check pulse helm manifests
Run to output manifest into helm-template directory:
source .shared_init_variables
envsubst < ./values-override-pulse.yaml | \
helm template \
--version="${CHART_VERSION}" \
--namespace="${NAMESPACE}" \
--debug \
--output-dir helm-template \
pulse pe-jfrog-stage/pulse \
-f -