Preparing container installation
Prepare networking
Create the Ingress controller on AKS
In PowerShell, execute the following commands as administrator:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginxhelm repo updatehelm install ingress-nginx ingress-nginx/ingress-nginx --create-namespace --namespace ingress-basic --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz --set controller.nodeSelector."kubernetes\.io/os"=linux --set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux
Once Ingress is installed you should be able to get the inbound and outbound IP addresses.
Register the outbound IP Address
Once Ingress is installed, you can get the outbound IP addresses.
-
On Azure portal, look at the Load Balancer configuration for the outbound role, and get the IP address.
-
Configure the outbound IP address be configured for the database instance to allow the containers to connect to the database.
In Oracle OCI, you can enable the IP Address by allowing it in the network configuration. .
Register the Inbound IP Address
Once Ingress is installed you should be able to get the inbound IP addresses.
-
On Azure portal, look at the Load Balancer configuration for the inbound role, and get the IP address.
-
Configure the Inbound IP address s in the DNS for your subdomain.
Prepare Settings
Prepare the Key Vault for installing WorkZone
All pod secrets for WorkZone are stored in a Key Vault. You need to set the pod secrets before doing the actual container deployment. See platform-specific (Azure) documentation for creating a Key Vault.
The following values should exist in the Key Vault.
| Key | Description |
|---|---|
| WORKZONE-ADREPLICATOR-OAUTH2-CLIENTSECRET | Used in dbupgrade job. |
| WORKZONE-AZURE-CLIENTID | |
| WORKZONE-AZURE-CLIENTSECRET | Used in oauth2. |
| WORKZONE-AZURE-TENANTID | |
| WORKZONE-CONTACTSYNCCONFIG-ENCRYPTION-KEY | Encryption for password encryption. |
| WORKZONE-CONTACTSYNCCONFIG-DECRYPTION-KEY | Decryption for decrypting password. |
| WORKZONE-DB-ARCHIVE | |
| WORKZONE-DB-DSN | |
| WORKZONE-DB-HOSTNAME | |
| WORKZONE-DB-ODBC | |
| WORKZONE-DB-ODPNET | |
| WORKZONE-DB-PORT | |
| WORKZONE-DB-PROTOCOL | |
| WORKZONE-DB-SERVER-MODE | |
| WORKZONE-DB-SID | |
| WORKZONE-DB-SJUSER-PASSWORD | |
| WORKZONE-DB-SJUSER-USERNAME | |
| WORKZONE-DB-SYS-PASSWORD | |
| WORKZONE-DB-SYS-USERNAME | |
| WORKZONE-PDF-CRAWLER-CLIENTSECRET | |
| WORKZONE-PROCESS-EXCHANGE-CLIENTID | The GUID of the client ID. |
| WORKZONE-PROCESS-EXCHANGE-CLIENTSECRET | The secret used to access the application in Entra ID. |
| WORKZONE-PROCESS-EXCHANGE-MAILBOX | The email address of the Exchange user who sends smartmails. |
| WORKZONE-PROCESS-EXCHANGE-SERVER-URI | The endpoint for the Exchange service. |
| WORKZONE-PROCESS-EXCHANGE-TENANTID | The GUID of the tenant ID. |
| WORKZONE-PROCESS-OAUTH2-CLIENTSECRET | The OAUTH2 secret used by WorkZone Process. |
| WORKZONE_SHAREPOINT_CLIENT_ID | SharePoint client ID |
| WORKZONE_SHAREPOINT_SP_CLIENT_SECRET | SharePoint client secret |
| WORKZONE_SHAREPOINT_SP_TENANT_ID | SharePoint Tenant ID |
| WORKZONE_ODATA_URL | WorkZone OData URL |
| WORKZONE_WZ_CLIENT_ID | Client ID for the WorkZone app registration |
|
WORKZONE_WZ_CLIENT_SECRET |
Client secret for the WorkZone app registration |
|
WORKZONE_WZ_TENANT_ID |
Tenant ID for the WorkZone app registration |
|
WORKZONE_ALLOWED_URLS |
WorkZone server URL (OData) |
|
WORKZONE_WorkZoneSettings__ApplicationIdUrl |
Uri of the WorkZone app registration (by default, it is the same as WorkZone URL) |
Prepare a namespace for the WorkZone containers
To prepare for WorkZone deployment, it is important to create a namespace to register secrets for the PODS.
kubectl create namespace <insert-namespace-name-here>
Prepare secrets for the WorkZone containers
Register the Oracle Wallet as a Secret
Once the wallet file is available, you can register the secret ”wallet” in the same name space as the WorkZonepods.
Place the prompt in the unpacked wallet folder.
You may have to create the name space for deployment before you register the wallet.
##
kubectl create secret generic wallet `--namespace <WorkZone name Space > `
--from-file=./cwallet.sso `
--from-file=./ewallet.p12 `
--from-file=./keystore.jks `
--from-file=./ojdbc.properties `
--from-file=./README `
--from-file=./sqlnet.ora `
--from-file=./tnsnames.ora `
--from-file=./truststore.jks
##
kubectl get secrets -n workzone
Register the SSL Certificates as a Secret
-
Navigate to the directory that contains SSL certificate files (crt & key files) and create the tls secreat (See Right)
-
Add/update the secret name and the corresponding host name in the environment file (tls section in ingress)
-
Ensure each ingress resource can populate the tls field.
-
Create the secret in the WorkZone namespace using below command:
kubectl create secret tls <secret-name> -n <namespace-name> --key=<private-key> --cert=<certificate>Example:kubectl create secret tls ingress-cert-workzone -n workzone --key=key.pem --cert=cert.pem##kubectl get secrets -n workzone
Prepare environment files for WorkZone container installation
Prerequisite: You should have a running Azure AKS and a Windows node pool.
- Copy and paste the code below, and save it as a
values.yamlfile.# Default values for workzone namespace. # This is a YAML-formatted file. # Declare variables to be passed into your templates. affinity: {} # Azure Key Vault provider for Secrets Store CSI Driver allows you to get secret contents stored in an Azure Key Vault instance and use the Secrets Store CSI driver interface to mount them into Kubernetes pods # https://azure.github.io/secrets-store-csi-driver-provider-azure/configurations/identity-access-modes/ # Modes for accessing a Key Vault instance: PodIdentity, UserAssignedManagedIdentity ##accessMode: PodIdentity # if eq .Values.secretProvider.accessMode "PodIdentity". The selector to identify which pods should be assigned to the AzureIdentity. # AAD Pod Identity will go through a list of pods and look for value of pod label with key aadpodidbinding that is equal to this value ##podIdentitySelector: csi-secrets-store global: affinity: {} podAntiAffinity: enabled: false externalSecrets: enabled: false secretStoreRefName: certStoreRefName: commonStoreRefName: secretProvider: enabled: true nodeSelector: kubernetes.io/os: windows kubernetes.io/arch: amd64 tolerations: - effect: NoSchedule key: os operator: Equal value: windows podDisruptionBudget: enabled: false minAvailable: 1 # Vertical Pod Autoscaler configuration vpa: # Enable VPA for the deployments enabled: false # Update policy for VPA, refer to https://github.com/kubernetes/autoscaler/blob/master/vertical-pod-autoscaler/docs/quickstart.md updatePolicy: updateMode: Recreate # InPlaceOrRecreate that updates resource requests in-place is available since Kubernetes 1.33 minReplicas: 1 workzone: url: http://localhost airGappedConfiguration: enabled: false gmsaCredentialSpecName: gmsa-workzone wzc: client: url: http://wzc-client/app/client wzcnf: configurator: url: http://wzcnf-configurator/app/configurator wzcs: autopurge: # Cron schedule for running auto purge. Default 12:30 AM schedule: "30 0 * * *" explorer: url: http://wzcs-explorer/explorer notifications: url: http://wzcs-notifications/notifications oauth2: url: http://wzcs-oauth2/oauth2 internalUrl: http://wzcs-oauth2/oauth2 internalDaprUrl: http://localhost:3500/v1.0/invoke/wzcs-oauth2/method/oauth2 odata: url: http://wzcs-odata/odata internalRootUrl: http://wzcs-odata internalUrl: http://wzcs-odata/odata internalDaprRootUrl: http://localhost:3500/v1.0/invoke/wzcs-odata/method internalDaprUrl: http://localhost:3500/v1.0/invoke/wzcs-odata/method/odata odata4: url: http://wzcs-odata4/odata4 internalRootUrl: http://wzcs-odata4 internalUrl: http://wzcs-odata4/odata4 internalDaprRootUrl: http://localhost:3500/v1.0/invoke/wzcs-odata4/method internalDaprUrl: http://localhost:3500/v1.0/invoke/wzcs-odata4/method/odata4 office: url: http://wzcs-office/Office sourceimport: # Cron schedule for running source import schedule: "*/30 * * * *" wopi: url: http://wzcs-wopi/wopi wopiclient: url: http://wzcs-wopiclient/wopiclient scim: url: http://wzcs-scim/provisioning wzo: api: url: http://wzo-api/wzoserver publicExchange: true graphApi: false wzfo: staticfilesprovider: url: http://wzfo-staticfilesprovider/App/Office wzlogic: auth: wzuser: CONTACTSYNCUSER oid: 7911dc40-c92d-4631-b4ab-9fef93204c37 oauth2: clientId: ContactSyncService contactlookupservice: url: http://wzlogic-contactlookupservice/ latestApiUrl: http://wzlogic-contactlookupservice/api/v1/ContactLookup contactsyncconfigservice: url: http://wzlogic-contactsyncconfigservice/ latestApiUrl: http://wzlogic-contactsyncconfigservice/api/v1/ContactSyncConfiguration cprsubscriptionservice: url: http://wzlogic-cprsubscriptionservice/ schedule: "0 4 * * 1-5" cprupdateservice: url: http://wzlogic-cprupdateservice/ subscriptionservice: url: http://wzlogic-subscriptionservice/ schedule: "0 4 * * 1-5" updateservice: url: http://wzlogic-updateservice/ datafordeler: CprBaseUri: https://s5-certservices.datafordeler.dk/ CvrBaseUri: https://s5-certservices.datafordeler.dk/ BfeBaseUri: https://certservices.datafordeler.dk/ EventsBaseUri: https://s5-certservices.datafordeler.dk/ wzp: process: url: http://wzp-process/process internalUrl: http://wzp-process/process localUrl: http://localhost/process replicaCount: 1 # the prerequisite for the functionality of the dedicated node for wzp-process is the appropriate preparation of the environment: dedicatedNodes: enabled: false autoscaling: enabled: false minReplicas: 1 maxReplicas: 2 massdispatch: url: http://wzp-massdispatch appdata: enabled: false size: 10Gi publicExchange: true # This section allows you to provide custom images for wzp components - values should be provided in customer's yaml customizations: enabled: false # image: # here you can provide repository for custom images in format <imagename>: <path/to/image>, i.e. init: workzone/EXAMPLE_CUSTOMER/wzp/init # tag: "latest" wzpdf: oauth2: clientId: WZPDF.CRAWLER pdfengine: url: http://wzpdf-pdfengine/render dedicatedNodes: enabled: false pdfcrawler: dedicatedNodes: enabled: false pdfservice: url: http://wzpdf-pdfengine/render pvc: enabled: false name: pdfpersistence wzsp: spconnector: url: http://wzsp-spconnector/spconnector internalUrl: http://localhost:3500/v1.0/invoke/wzsp-spconnector/method/spconnector frontend: url: http://wzsp-frontend/frontend internalUrl: http://localhost:3500/v1.0/invoke/wzsp-frontend/method/frontend kmdtxt: api: url: https://kmdtxt-api/api internalUrl: http://kmdtxt-api:5000 wzdocumentmerge: api: url: https://wzdocumentmerge-service/documentmerge wzps: secretservice: url: http://wzps-secretservice/secretservice latestApiUrl: http://wzps-secretservice/api/v1/SecretService wzrs: api: url: https://wzrs/wzrs/SuggestRedaction db: #if need to customize below paramemeters, add value into environment .yaml file(eg. cataks.yaml) tablespacemap: DATA cultures: da-DK corporate_access_code: "N" freetext: "N" externalServices: sharepoint: sharepointUrl: interact: enabled: false smartpost: enabled: false #kmdtxt settings api: cors: allow_origins: "'[\"http://localhost\"]'" dapr: Dapr (Distributed Application Runtime) is an open-source, portable, and event-driven runtime that helps developers build microservice-based applications for the cloud and edge environments.secretProvider: Modes for accessing a Key Vault instance:PodIdentity,UserAssignedManagedIdentity. Azure Key Vault provider for Secrets Store CSI Driver allows you to get secret contents stored in an Azure Key Vault instance and use the Secrets Store CSI driver interface to mount them into Kubernetes pods.accessMode: PodIdentity: If eq .Values.secretProvider.accessMode "PodIdentity". The selector to identify which pods should be assigned to the AzureIdentity. AAD Pod Identity will go through a list of pods and look for value of pod label with key aadpodidbinding that is equal to this value.sourceimport: Cron schedule for running source import.db: If you need to customize the db paramemeters, add value intoenvironment.yamlfile.- Copy and paste the code below, and save as an
environment.yamlfile.# global env specific file global: image: registry: wzdevcr.azurecr.io pullPolicy: Always tag: "latest" # Enable only if secret wzcommon-secrets is present commonsecrets: enabled: false dapr: enabled: false tracing: enabled: false ingress: enabled: true className: "external-ingress" annotations: { # Sets Listener protocol HTTPS and port 443 nginx.ingress.kubernetes.io/use-regex: "true", nginx.ingress.kubernetes.io/force-ssl-redirect: "true" } hostname: <environment_url> tls: - secretName: <secret-name> hosts: - <environment_url> teamsHostname: <environment_url> WORKZONE_CORPORATE_ACCESS_CODE: 'false' WORKZONE_CULTURES: da-DK;en-GB WORKZONE_FREETEXTINDEX: 'false' WORKZONE_TABLESPACEMAP: DATA logs: persistence: enabled: true size: 10Gi vpa: enabled: true workzone: url: https://<environment_url> wzc: client: url: https://<environment_url>/app/client wzcnf: configurator: url: https://<environment_url>/app/configurator wzcs: agentsub: mailerAuthCertificateSecret: wildcard-test-workzone-cloud mailerAuthCertificateKeyVault: wz-common-kv explorer: url: https://<environment_url>/explorer notifications: url: https://<environment_url>/notifications oauth2: url: https://<environment_url>/oauth2 odata: url: https://<environment_url>/odata odata4: url: https://<environment_url>/odata4 office: url: https://<environment_url>/Office wopi: url: https://<environment_url>/wopi wopiclient: url: https://<environment_url>/wopiclient scim: url: https://<environment_url>/provisioning wzo: api: graphApi: true wzfo: staticfilesprovider: url: https://<environment_url>/App/Office wzlogic: contactlookupservice: url: https://<environment_url>/contactlookup latestApiUrl: https://<environment_url>/contactlookup/api/v1/ContactLookup logLevel: Verbose cprsubscriptionservice: url: https://<environment_url>/cprsubscriptionservice schedule: "0 */3 * * *" logLevel: Verbose cprupdateservice: url: https://<environment_url>/cprupdateservice logLevel: Verbose subscriptionservice: url: https://<environment_url>/subscriptionservice schedule: "0 */3 * * *" logLevel: Verbose updateservice: url: https://<environment_url>/updateservice logLevel: Verbose contactsyncconfigservice: url: https://<environment_url>/contactsyncconfigservice latestApiUrl: https://<environment_url>/contactsyncconfigservice/api/v1/ContactSyncConfiguration logLevel: Verbose datafordeler: CprBaseUri: https://test04-s5-certservices.datafordeler.dk/ CvrBaseUri: https://test03-s5-certservices.datafordeler.dk/ EventsBaseUri: https://test03-s5-certservices.datafordeler.dk/ wzp: process: url: https://<environment_url>/process massdispatch: appdata: enabled: true wzpdf: pdfengine: url: https://<environment_url>/render pdfservice: url: https://<environment_url>/render wzrs: api: url: https://<environment_url>/wzrs/SuggestRedaction wzsp: spconnector: url: https://<environment_url>/spconnector kmdtxt: api: url: https://<environment_url>/kmdtxt wzdocumentmerge: api: url: https://<environment_url>/documentmerge wzps: secretservice: logLevel: Verbose db: ipAddress: 192.168.20.126 ## change to DB IP port: 1522 change to DB port cultures: da-DK;en-GB wallet: enabled: true secretName: wallet externalServices: sharepoint: sharepointUrl: https://<your_sharepointUrl>.sharepoint.com interact: enabled: true smartpost: enabled: true #kmdtxt settings api: cors: allow_origins: "'[\"https://<environment_url>\"]'" # External Secrets Operator reads information from a third-party service like Azure Key Vault and automatically injects the values as Kubernetes Secrets. # Enable this only if you are using External Secrets Operator else set to false externalSecrets: enabled: true provider: # pass the provider name, default is Azure KV key: # provide the key path secretStoreRefName: azure-store certStoreRefName: azure-store commonStoreRefName: # Set to false if you are using External Secrets Operator and remove the block if you are using secretProvider secretProvider: enabled: falseannotations: Sets Listener protocol HTTPS and port 443.<environment_url>: Replace with the URL of your environment<your_sharepointUrl>: Replace with the SharePointUrl for your company
- Copy the
values.yamlandenvironment.yamlfiles into a folder.
Prepare environment files for external secrets
The External Secrets Operator extends Kubernetes with custom resources that define where secrets stored and how they should be synchronized. The controller fetches secrets from an external API and creates the corresponding Kubernetes secrets. If the secret from the external API changes, the controller automatically reconciles the state in the cluster and update the Kubernetes secrets accordingly.
See the official documentation Overview - External Secrets Operator for more information about integrating External Secrets Operator with Kubernetes and using multiple secret providers.
If your secrets are managed by External Secrets Operator, ensure that it is installed on your Kubernetes cluster.
If you are using secretProvider, set its value to true in the values.yaml file as shown below.
Configuration of values.yaml file:
externalSecrets:
enabled: false
secretStoreRefName:
certStoreRefName:
commonStoreRefName:
secretProvider:
enabled: true
If you are using externalSecrets, set the externalSecrets value to true in your environment's value.yaml file. Then provide the appropriate secret store name in the secretStoreRefName field. You must also provide the external secrets provider name, for example vault for Hashi Corp vault, and provide the key path to the key.
If the provider field is empty, the default provider is Azure.
Configuration for your environment's values.yaml file:
externalSecrets:
enabled: true
provider:
key:
secretStoreRefName:
certStoreRefName:
commonStoreRefName:
Set the secretProvider value to false if you are using externalSecrets (External Secrets Operator) and remove the secretProvider block if you are using secretProvider.
secretProvider:
enabled: false
