Walkthrough: Adding the Horizon module

Abstract

Describes the infrastructure changes necessary to add the Horizon module.

Horizon is the next-generation editor in Sitecore Experience Platform. To add the Horizon module, you must create specific Docker images, add them to the Azure Container Registry (ACR), and then change the item in the Application repository before running the Mssql containers. You must also extend the Front Door configuration with an additional public-facing service name.

This walkthrough describes the infrastructure changes that you have to apply when you want to deploy the Horizon module on top of an already deployed Managed Cloud containers environment.

This walkthrough describes how to:

  • Register a domain name

  • Extend the Front Door configuration

  • Prepare the Docker files

  • Push the images to the Azure Container Registry (ACR)

  • Download the Horizon Container Deployment package

  • Copy the base Horizon Kubernetes configuration files

  • Define Horizon configuration overlays

  • Change the image in the Application repository

  • Run the mssql_init_hrz container

  • Configure Ingress

  • Enable the Horizon component

  • Apply the change

Because Horizon is a separate publicly available service, you must register a domain name for it.

To register a domain name:

  1. Navigate to the portal where your DNS name is managed from.

  2. Create an additional CNAME record for Horizon that points to Azure Front Door: {infrastructure_id}fdr.azurefd.net,

    where infrastructureId is your environment identifier that starts with mcc.

  3. Navigate to the Azure Portal and create a secret within the Key Vault for the environment:

    • Secret name - sitecore-hrz-host-namesitecore-hrz-host-name

    • Secret value - the Horizon hostname that you created in the previous step.

    image1.png

You must extend the Front Door configuration with an additional public-facing service name.

To extend the Front Door configuration:

  1. Navigate to frontdoor\backend-config.json and define the Horizon back-end config:

    {
            "name": "hrz-ingress",
            "probe_path": "/healthz/live",
            "backend_list": [
                {
                    "host_header": "hrz.sitecore"
                }
              ]
    }
    
  2. Navigate to frontdoor\main.tf and in the locals section, add a new variable to "sitecore_hrz_host_name“:

    sitecore_hrz_host_name = data.azurerm_key_vault_secret.sitecore_hrz_host_name.value
  3. Define the data resource to retrieve the Horizon host name from the Key Vault:

    data "azurerm_key_vault_secret" "sitecore_hrz_host_name" {
    name         = "sitecore-hrz-host-name"
    key_vault_id = data.azurerm_key_vault.this.id
    }
  4. In the "azure_frontdoor" resource, define an additional routing_rule:

    routing_rule {
        name               = "HTTPS-hrz"
        accepted_protocols = ["Https"]
        patterns_to_match  = ["/*"]
        frontend_endpoints = ["hrz-frontend-endpoint"]
        forwarding_configuration {
          forwarding_protocol = "MatchRequest"
          backend_pool_name   = "hrz-ingress"
        }
      }
    
  5. In the "azurerm_frontdoor" resource, define the frontend_endpoint:

    frontend_endpoint {
        name      = "hrz-frontend-endpoint"
        host_name =  local.sitecore_hrz_host_name
    }
  6. Adjust HttpToHttps so that it covers the HTTPS-hrz routing rule:

    image7.png
  7. You must now apply the changes with a pull request to the Infrastructure repository before you can continue with the next steps.

  8. Run the FrontDoor pipeline to apply the changes and wait until the pipeline is executed successfully.

  9. Define the “azurerm_frontdoor_custom_https_configuration” resource:

    resource "azurerm_frontdoor_custom_https_configuration" "hrz_https_configuration" {
      frontend_endpoint_id              = azurerm_frontdoor.this.frontend_endpoints["hrz-frontend-endpoint"]
      custom_https_provisioning_enabled = true
    
      custom_https_configuration {
        certificate_source                      = "AzureKeyVault"
        azure_key_vault_certificate_secret_name = data.azurerm_key_vault_certificate.sitecore_ingress_certificate.name
        azure_key_vault_certificate_vault_id    = data.azurerm_key_vault.this.id
        azure_key_vault_certificate_secret_version = data.azurerm_key_vault_certificate.sitecore_ingress_certificate.version
      }
    
      depends_on = [azurerm_frontdoor.this]
    }
  10. Apply the changes to the environment with a pull request to the infrastructure repository.

    The expected result:

    image9.png
  11. Run the FrontDoor pipeline to apply the changes and wait until the pipeline is executed successfully.

To prepare the Sitecore platform images to work with the Horizon service:

  • Install the Horizon integration asset image on top of Sitecore content management (CM) and MSSQL-INIT images.

Refer to the Kubernetes deployment guide for Sitecore Horizon for instructions on how to build corresponding custom images.

To push the images to the ACR:

A prerequisite for adding the Horizon module is the Horizon Container Deployment package.

To download the package:

  1. On dev.sitecore.net, navigate to the page for the specific Sitecore version that you use and in the Download options section, go to Container Deployment Package.

  2. Download the SitecoreHorizonContainerDeployment zip package and unarchive it to a local folder.

To copy the Horizon configuration files:

  1. Navigate locally to the Application repository folder and create a folder with the following path:

    roles\sitecore-{topology}\bases\components\horizon
  2. Copy the following Horizon base configuration files from the SitecoreHorizonContainerDeployment package into the folder that you created earlier:

    • k8s\ltsc2019\horizon\hrz.yaml

    • * k8s\ltsc2019\horizon\ patch-hrz-enable-dam.yaml

    • * k8s\ltsc2019\horizon\ patch-hrz-enable-sxa.yaml

    • overrides\{topology}\patch-cm.yaml

    • overrides\{topology}\patch-id.yaml

      Note

      The files marked with * are optional. They are required if you want integration with SXA and/or Dam. For more details about the SXA/Dam integration refer to the Horizon deployment guide.

    Horizon base files
  3. In the folder created in step 1, create the kustomization.yaml file with the following content:

    apiVersion: kustomize.config.k8s.io/v1alpha1
    kind: Component
    
    resources:
      - hrz.yaml
    
    patchesStrategicMerge:
    - patch-id.yaml
    - patch-cm.yaml
    # Uncomment following line to enable DAM integration in the Horizon
    #- patch-hrz-enable-dam.yaml
    # Uncomment following line to enable SXA integration in the Horizon
    #- patch-hrz-enable-sxa.yaml
    

To integrate the Horizon module configuration with the Managed Cloud Containers environment, you must define an overlay layer on top of the Horizon base configuration. This abstraction makes it easier to replace the Horizon base configuration in Horizon module upgrades in future releases.

To define the overlays:

  1. Create the roles\sitecore-{topology}\overlays\components\horizon\cm.yaml file with the following content:

    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: cm
    spec:
      progressDeadlineSeconds: 3600
      template:
        spec:
          containers:
          - name: sitecore-xp1-cm
            image: "{{ docker_images.sitecore.cm }}"
            env:
            - name: SITECORE_HOSTNAME_HRZ
              valueFrom:
                secretKeyRef:
                  key: hrz
                  name: sitecore-hostname
            - name: Sitecore_Horizon_ClientHost
              value: "https://$(SITECORE_HOSTNAME_HRZ)"
    
  2. Create the roles\sitecore-{topology}\overlays\components\horizon\id.yaml file with the following content:

    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: id
    spec:
      progressDeadlineSeconds: 3600
      template:
        spec:
          containers:
          - name: sitecore-xp1-id
            image: "{{ docker_images.sitecore.id }}"
            env:
            - name: SITECORE_HOSTNAME_CM
              valueFrom:
                secretKeyRef:
                  key: cm
                  name: sitecore-hostname
            - name: SITECORE_HOSTNAME_ID
              valueFrom:
                secretKeyRef:
                  key: id
                  name: sitecore-hostname
            - name: SITECORE_HOSTNAME_HRZ
              valueFrom:
                secretKeyRef:
                  key: hrz
                  name: sitecore-hostname
            - name: Sitecore_Sitecore__IdentityServer__AccountOptions__PasswordRecoveryUrl
              value: "https://$(SITECORE_HOSTNAME_CM)/sitecore/login?rc=1"
            - name: Sitecore_Sitecore__IdentityServer__Clients__DefaultClient__AllowedCorsOrigins__AllowedCorsOriginsGroup1
              value: "https://$(SITECORE_HOSTNAME_CM)"
            - name: Sitecore_Sitecore__IdentityServer__PublicOrigin
              value: "https://$(SITECORE_HOSTNAME_ID)"
            - name: SITECORE_ENVIRONMENT_TYPE
              value: "{{ sitecore_environment_type }}"
            - name: Sitecore_Sitecore__IdentityServer__Clients__DefaultClient__AllowedCorsOrigins__AllowedCorsOriginsGroup2
              value: "https://$(SITECORE_HOSTNAME_HRZ)"
    
    
    
  3. Create the roles\sitecore-{topology}\overlays\components\horizon\hrz.yaml file with the following content:

    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hrz
    spec:
      progressDeadlineSeconds: 3600
      template:
        spec:
          containers:
          - name: sitecore-horizon
            image: "{{ docker_images.sitecore.hrz }}"
            env:
            - name: SITECORE_HOSTNAME_HRZ
              valueFrom:
                secretKeyRef:
                  key: hrz
                  name: sitecore-hostname
            - name: SITECORE_HOSTNAME_CM
              valueFrom:
                secretKeyRef:
                  key: cm
                  name: sitecore-hostname
            - name: SITECORE_HOSTNAME_ID
              valueFrom:
                secretKeyRef:
                  key: id
                  name: sitecore-hostname
            - name: Sitecore_Sitecore__Authentication__OpenIdConnectOptions__CallbackAuthority
              value: "https://$(SITECORE_HOSTNAME_HRZ)"
            - name: Sitecore_SitecorePlatform__ContentManagementInternalUrl
              value: http://cm.{{ solution_id }}.svc.cluster.local
            - name: Sitecore_SitecorePlatform__ContentManagementUrl
              value: "https://$(SITECORE_HOSTNAME_CM)"
            - name: Sitecore_Sitecore__Authentication__OpenIdConnectOptions__Authority
              value: "https://$(SITECORE_HOSTNAME_ID)"
            - name: Sitecore_Sitecore__Authentication__BearerAuthenticationOptions__Authority
              value: "https://$(SITECORE_HOSTNAME_ID)"
    
    
  4. Create the roles\sitecore-{topology}\overlays\components\horizon\kustomization.yaml file with the following content:

    ---
    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    
    resources:
    - sitecore-roles.yaml
    
    patchesStrategicMerge:
    - cm.yaml
    - id.yaml
    - hrz.yaml
    
    
  5. To execute the overlays, navigate to roles\sitecore-{topology}\tasks\main.yaml and add the following:

    - name: Copy Sitecore roles configuration into Horizon overlay
      template:
        src: roles/sitecore-xp/templates/sitecore-roles.yaml
        dest: roles/sitecore-xp/overlays/components/horizon/sitecore-roles.yaml
    
    - name: Run Kustomization for Horizon integration
      shell: |
          kustomize build roles/sitecore-xp/overlays/components/horizon > roles/sitecore-xp/templates/sitecore-roles.yaml
    

    The expected result:

    image17.png

Note

This code example is for XP topology. For XM, replace ‘sitecore-xp’ with ‘sitecore-xm’.

Now you can add the Horizon-specific image and two new properties to the Application repository.

To change the images in the Application repository:

  • In the Application repository, navigate to config/docker-images and edit the docker-images.json file as follows:

    • Replace the cm image with cm-hrz, that you created earlier.

    • Add the mssql_init_hrz property, that you created earlier.

    • Add the hrz property, and point it to the Horizon service public image that corresponds to your Sitecore version. You can find this value from Horizon artifacts downloaded earlier.

      Navigate to k8s\ltsc2019\horizon\kustomization.yaml to find the actual image name and tag. For example:

      image18.png

To run the mssql-init-horizon container:

  1. Navigate to roles\sitecore-{topology}\templates\ and add the mssql-init-horizon job file under the name: mssql-init-horizon.yaml with the following content:

    apiVersion: batch/v1
    kind: Job
    metadata:
     name: horizon-mssql-init
    spec:
      template:
        spec:
          nodeSelector:
            kubernetes.io/os: windows
          imagePullSecrets:
            - name: sitecore-docker-registry
          containers:
          - name: mssql-init-horizon
            image: "{{ docker_images.sitecore.mssql_init_hrz }}"
            env:
            - name: sitecore_admin_password
              valueFrom:
                secretKeyRef:
                  name: sitecore-admin
                  key: sitecore-adminpassword.txt
            - name: SQL_ADMIN_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: sitecore-database
                  key: sitecore-databasepassword.txt
            - name: SQL_ADMIN_LOGIN
              valueFrom:
                secretKeyRef:
                  name: sitecore-database
                  key: sitecore-databaseusername.txt
            - name: SQL_SERVER
              valueFrom:
                secretKeyRef:
                  name: sitecore-database
                  key: sitecore-databaseservername.txt
            - name: SQL_ELASTIC_POOL_NAME
              valueFrom:
                secretKeyRef:
                  name: sitecore-database
                  key: sitecore-database-elastic-pool-name.txt
            - name: DATABASES_TO_DEPLOY
              value: hrz
          restartPolicy: Never
      backoffLimit: 5
    
    
  2. To add the Ansible tasks to execute the mssql-init-horizon job, navigate to roles\sitecore-{topology}\tasks\init.yaml and add the following script at the end of the file:

    - name: Execute horizon mssql-init jobs
      k8s:
        apply: true
        namespace: "{{ solution_id }}"
    
        state: present
        definition: "{{ lookup('template', 'mssql-init-horizon.yaml') }}"
    
    - name: 'Wait - Horizon Mssql-init job'
      k8s_info:
        kind: Job
        name: horizon-mssql-init
        namespace: "{{ solution_id }}"
    
      register: horizon_mssql_init_result
      until: (horizon_mssql_init_result.resources[0].status.conditions[0].type | default('')) == 'Complete'
      retries: 60
      delay: 60
    
    - name: Get all Horizon Mssql completed pods
      k8s_info:
        kind: Pod
        namespace: "{{ solution_id }}"
    
        label_selectors:
          - job-name = horizon-mssql-init
      no_log: true
      register: horizon_mssql_pod_list
    
    - name: Remove Horizon Mssql job's pods
      k8s:
        kind: Pod
        name: "{{ item.metadata.name }}"
        namespace: "{{ solution_id }}"
    
        state: absent
      no_log: true
      with_items: "{{ horizon_mssql_pod_list.resources }}"
    
    

Next you must define and apply the Ingress configuration and define the secrets.

To configure Ingress:

  1. In the Application repository, navigate to the roles\sitecore-{topology}\templates\ folder and create the ingress-hrz.yaml file with the following content:

    ---
    kind: Service
    apiVersion: v1
    metadata:
      name: hrz-external
    spec:
      type: ExternalName
      externalName: hrz.{{ solution_id }}.svc.cluster.local
      ports:
      - port: 80
    ---
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: sitecore-hrz-ingress
      annotations:
        kubernetes.io/ingress.class: "nginx"
        nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
        nginx.ingress.kubernetes.io/rewrite-target: /
        nginx.ingress.kubernetes.io/proxy-buffering: "on"
        nginx.ingress.kubernetes.io/proxy-buffers-number: "4"
        nginx.ingress.kubernetes.io/proxy-buffer-size: "256k"
    spec:
      rules:
      - host: "hrz.sitecore"
        http:
          paths:
          - path: /
            backend:
              serviceName: hrz-external
              servicePort: 80
    
    
  2. To define secrets, navigate to roles\sitecore-{topology}\templates\secrets.yaml and define the sitecore-hrz-host-name secret with sitecore-secret-provider.

  3. Extend the sitecore-hostname secret:

    - key: hrz
          objectName: sitecore-hrz-host-name
    
    

    The expected result

    image24.png
  4. Add sitecore-hrz-host-name as a secret-provider parameter:

    - |
              objectName: sitecore-hrz-host-name
              objectType: secret
    
    

    The expected result:

    image26.png

To enable the Horizon component:

  • In the Application repository, navigate to the roles\sitecore-{topology}\overlays\platform\kustomization.yaml file and enable Horizon with the components element, pointing to the Horizon module configuration scripts folder.

    components:
    -  ../../bases/components/horizon
    

Now that you have made all the required changes for the Horizon module to be added, you must apply the changes.

To apply the changes:

  1. Apply the application changes to the environment with a pull request to the application repository.

  2. Follow Kubernetes deployment guide from Horizon documentation to configure the SolrCloud search indexes after deployment.