Azure · Sitecore
Escalando Sitecore Azure Web App
Antes de escalar Sitecore Azure Web App, debes leer la experiencia que tuve y que voy a compartir en este post.
Azure Web App
En Azure, puedes cambiar fácilmente recursos existentes casi en tiempo real para satisfacer las necesidades del negocio, y esto también se aplica a Web Apps donde puedes Scale Up y/o Scale Out tu aplicación.
Sitecore
Sitecore ofrece diferentes modelos de arquitectura para adaptarse a las necesidades del cliente, y sus roles varían dependiendo de la topología elegida. Sin embargo, tienes la posibilidad de escalar ya sea vertical u horizontalmente.
El entorno
Todo está alojado en Azure, utilizando Web Apps, y provisionado siguiendo la topología Sitecore XP Scaled. Aquí tienes una idea de cómo se veía el entorno

Antes de avanzar es importante conocer la diferencia entre Azure Web App y App Service Plans
Azure Web Apps vs App Service Plans
Durante la creación de Azure Web App, se te solicita que proporciones los Instance Details (1) que corresponde a la Web App, y el App Service Plan (2) que debe ser uno de los siguientes: crear uno nuevo o elegir uno existente desde la lista desplegable.

La relación entre Web App y App Service Plan se puede ilustrar con la imagen a continuación

N Las Web Apps pueden usar el mismo App Service Plan, siempre que los recursos que el App Service Plan pueda manejar.
Además de eso, una idea que ayuda a entender es pensar como
- App Service Plan es el servidor físico o virtual que tiene los recursos (CPU, memoria, etc)
- Web App es el servidor web donde se sitúan la configuración y los ajustes
Dicho esto, queríamos escalar Out tanto CM como CD, y todo salió bien con el CD, así que intentemos hacer lo mismo en CM.
Idea de Scale Out CM
Cuando escalas tu aplicación, se añade un Load Balancer delante de tu Azure Web App, y Sitecore CM espera exactamente eso para una escala horizontal
Puedes configurar múltiples instancias detrás de un balanceador de carga. Todas las instancias deben conectarse a una base de datos maestra ubicada de forma central
Por lo tanto, decidimos simplemente Scale Out la Web App de CM
Todo salió mal #1
Una vez que todas las instancias estaban en funcionamiento, se realizaron un par de pruebas y todo funcionaba muy bien.
Sin embargo, cuando varios usuarios comenzaron a trabajar, las cosas empezaron a salirse de control con las instancias reiniciándose aleatoriamente sin motivo y con el siguiente mensaje
WARN Shutdown message: CONFIG change
Siempre busca los pequeños detalles
Al escalar CM, el entorno pasó de 1 a N servidores, y Sitecore tiene diferentes requisitos para hacer que esto funcione
Parámetro InstanceName
Debes asegurarte de que cada instancia de CM tenga un nombre único, y eso está bien porque el valor por defecto establecido en el archivo Sitecore.config es (nombre de la máquina y nombre del sitio IIS), y cuando escales obtendrás una App Service clonada que se ejecuta con un nombre único.
<!-- INSTANCE NAME
Unique name for Sitecore instance.
Default value: (machine name and IIS site name)
-->
<setting name="InstanceName" value="" />
Publicación
Solo una instancia de CM puede realizar publicaciones, y debes asegurarte de que cada instancia de CM apunte a la instancia de CM de publicación, y de nuevo eso está bien porque el entorno tiene un Servicio de Publicación dedicado.
ValidationKey y DecryptionKey
Asegúrate de que los valores sean los mismos en todas las instancias de Sitecore dentro del entorno y de que el modificador IsolateApps no esté presente en ninguno de los valores, y en la configuración del entorno estos parámetros estaban establecidas de forma fija y estática.
Indexación
Dado que un Scale Out simplemente clona el sistema de archivos, y no permite que tengamos control en el sistema de archivos de cada nuevo servidor para modificar la configuración de Indexing, Sitecore CM se confundía con varios servidores realizando el rol de indexación.
Ahora, que se identificó el problema, la idea era provisionar un nuevo Content Management usando su propio App Service (y App Service Plan) donde el sistema de archivos podría modificarse según sea necesario.
Así que, llamemos a este nuevo Content Management CM02 y al existente CM01.
Habilitar el sub-rol de Indexing CM02
La idea es tener CM02 con el sub-rol de Indexing, y para lograrlo se debe hacer una modificación en el Web.config
<add key="role:define" value="ContentManagement, Indexing, Indexer"/>
A partir de Sitecore 9.2, cuando asignas el indexing sub-role a un servidor, ese rol gestiona la indexación de contenido automáticamente y los otros roles de servidor que no han sido asignados a este sub-rol no indexan contenido
Deshabilitar el sub-rol de Indexing CM01
IMPORTANTE: Si estás usando Sitecore 9.2 y posterior, no necesitas deshabilitar la indexación en otros CM
Para cada índice que hayas configurado, debes cambiar su indexUpdateStrategies a manual como se muestra en el ejemplo a continuación
<index id="sitecore_index" type="Sitecore.ContentSearch.SolrProvider.SolrSearchIndex,
Sitecore.ContentSearch.SolrProvider">
<param desc="name">$(id)</param>
<param desc="core">$(id)</param>
<param desc="propertyStore"
ref="contentSearch/indexConfigurations/databasePropertyStore"
param1="$(id)" />
<strategies hint="list:AddStrategy">
<strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/manual" />
</strategies>
Una vez aplicados estos cambios, así es como se veía el entorno

Todo salió mal #2
Ahora ya tenemos todo lo necesario para un entorno con múltiples CM
- Balanceador de carga delante de los CMs
- Parámetro InstanceName con nombres únicos
- Un servidor de Publicación
- Mismo ValidationKey y DecryptionKey para todos los CMs
- Un CM para gestionar Indexing
Y las cosas parecían muy prometedoras, bueno… bueno… hasta que las instancias del CM01 escalado comenzaron a fallar y, nuevamente, de forma aleatoria y con exactamente el mismo mensaje.
WARN Shutdown message: CONFIG change
¿Qué más podría estar mal? Después de investigar, encontré algo que respondió a nuestra pregunta
De acuerdo con la documentación de Sitecore Managed Cloud
Scale out is not supported for CM
https://doc.sitecore.com/developers/managed-cloud/en/scaling-options-for-managed-cloud.html
La solución
Dicho eso, la única posibilidad sería tener CMs adicionales, cada una en su propio App Service Plan.
Sin embargo, como ya no estamos escalando la CM App Service, no tenemos un balanceador de carga para repartir la carga entre las múltiples CMs y hay algunas cosas importantes a saber:
- Azure Load Balancer no funciona con Azure App Services, incluso si configuras VNet para ellos
- WAF y Application Gateway no son compatibles con servidores de Content Management
Así que, o bien propones una solución de terceros que te ayude a tener un Load Balancer para tus CMs o puedes usar Azure Front Door, pero ten en cuenta lo siguiente:
El uso de esta tecnología dentro de una solución Sitecore está permitido, pero el equipo de Soporte de Sitecore solo puede ayudar con problemas del producto Sitecore que no sean únicos al uso de la tecnología, es decir, un problema del producto Sitecore que se pueda replicar sin la tecnología presente.
En algunos casos, el equipo de Soporte de Sitecore puede pedir la replicación del problema sin el uso de la tecnología, aunque intentarán evitarlo.
En mi caso, voy a usarla y así es como debe ser

Configurar Azure Front Door
Busca Front Doors y haz clic en Front Doors en el campo de búsqueda de Azure

Haz clic en Add para crear un nuevo Front Door

En Basics elige el Resource Group apropiado o crea uno nuevo, y Next : Configuration >

En Configuration verás 3 pasos, comencemos haciendo clic en la señal + en Step 1

En Add a frontend host proporciona el Host name (1), asegúrate de elegir Enabled para Session Affinity (2) y disabled para Web Application Firewall (3) – ya que Sitecore no lo requiere – y haz clic en Add

Pasemos al Step 2 haciendo clic en la señal +

Add a backend pool dándole un Name (1) y + Add a backend (2)

Elige un Backend host type (1), en nuestro caso un App Service, luego elige el Backend host name (2) y su Backend host header (3), y haz clic en Add

Asegúrate de repetir el paso anterior haciendo clic en + Add a backend hasta tener todos los CM Web Apps añadidos


Una vez que tengas todas las Web Apps, puedes continuar en las opciones de Add a backend pool y simplemente hacer clic en Add

Finalmente, configuremos el Step3 haciendo clic en la señal +

Dale un Name (1), y elige sus Frontends/domains (2) y el Backend pool (3), luego pulsa Add (4)

Ahora que tienes los 3 pasos configurados, haz clic en Review + Create

Revisa la información y haz clic en Create

Debes esperar hasta que Front Door esté provisionado, y puedes acceder desde tu navegador al nombre de host que configuraste, en mi caso es https://blog-vinicius-deschamps.azurefd.net

Genial, pero probablemente no querrás compartir un dominio azurefd.net con tus Content Editors para que accedan a tu CM. Veamos cómo configurar un dominio personalizado.
Dominio personalizado Azure Front Door
Ve a Front Door (1), selecciona Front Door designer (2), luego haz clic en el + (3) en Frontends/domains

Debes elegir un Custom host name, y recibirás un mensaje indicando que se debe realizar una configuración CNAME en tu DNS

Estoy usando Azure DNS, así que fui a mi dominio viniciusdeschamps.cloud (1), seleccioné Overview (2) y + Record set (3)

En Add record set, añade un Name (1), selecciona el Type (2) y añade el Alias (3), luego pulsa Ok (4)

Regresa a Front Door y escribe tu Custom host name (1) de nuevo, elige Enabled (2) para Custom Domain HTTPS, y en un entorno de Producción usa tu propio certificado, pero en mi caso voy a usar Front Door managed (3), y no olvides dejar Enabled (4) Session Affinity y pulsa Add (5)

En Front Door Designer verás la siguiente advertencia
The host ‘your-custom-host.domain’ is not present in any of the routing rules.
The host ‘your-custom-host.domain’ is missing a default route ‘/*’ path for both the HTTP and HTTPS protocolos

Selecciona las Routing rules existentes

Y en Frontends/domains elige el domain recientemente agregado de la lista

Luego, presiona Update

Una vez hecho, haz clic en Save en el diseñador de Front Door


Espera un momento hasta que recibas una confirmación de que la configuración se aplicó; en mi caso tomó un tiempo porque elegí el Front Door managed certificate


Sitecore Identity Server Unauthorized_Client
Una vez que el Azure Front Door se actualizó con el nuevo Custom Domain, intenté acceder a https://prodcm.viniciusdeschamps.cloud/sitecore y cuando se lanzó Identity Server apareció el siguiente mensaje
Sorry, there was an error: unauthorized_client
Y esto ocurre porque en la configuración de Identity Server debes establecer desde qué URL se deben aceptar las solicitudes de autenticación

Para solucionarlo, debes ir a la App Service de Sitecore Identity Server (1), Advanced Tools (2) y Go (3)

Selecciona Debug console, y PowerShell

Navega a site\wwwroot\Config\production, y accede al siguiente archivo Sitecore.IdentityServer.Host.xml y modifica la siguiente línea
<AllowedCorsOriginsGroup1>https://sc91vdsch-cm.azurewebsites.net|https://</AllowedCorsOriginsGroup1>

Al agregar todas las URLs de Content Management como sigue, y hacer clic en Save
<AllowedCorsOriginsGroup1>https://sc91vdsch-cm.azurewebsites.net|https://sc91vdsch-cm02.azurewebsites.net|https://sc91vdsch-cm03.azurewebsites.net|https://prodcm.viniciusdeschamps.cloud</AllowedCorsOriginsGroup1>

Una vez guardada la modificación, debes Restart el App Service de Sitecore Identity Server


Una vez que el reinicio se complete, intenta acceder a Sitecore CM usando el dominio personalizado configurado en Azure Front Door, en mi caso https://prodcm.viniciusdeschamps.cloud/sitecore y voilá sin error

Me dio redirección al Sitecore Experience Platform, y como puedes ver al CM02 pero eso no es lo que quiero para mis usuarios finales, así que hay pasos adicionales para abordarlo. Bueno, al menos sabemos que el Front Door está separando el tráfico

Dominios personalizados para App Services
Navega a los App Services, y elige uno de los CMs (1), selecciona Custom Domains (2) y copia el Custom Domain Verification ID (3)

Ve a tu proveedor de DNS, en mi caso Azure DNS, y vamos a añadir un nuevo Record Set

El paso a continuación es verificar la propiedad del dominio, y debes rellenar la información de la siguiente manera
- Name – asuid.SUBDOMAIN (p. ej. asuid.prodcm)
- Type – TXT
- Value – Pega el valor que copiaste de Custom Domain Verification ID

Regresa a Custom Domains, y haz clic en Add custom domain (3)

Teclea tu Custom Domain (1), luego haz clic en Validate (2)

A veces tarda un poco hasta que se sincronice el registro, y podrías ver el siguiente mensaje
Domain ownership
To verify domain ownership create CNAME and TXT record with your DNS provider
Como ya tenemos un CNAME configurado para Azure Front Door, el registro CNAME no es necesario

Espera un rato y trata de Validate el Custom Domain de nuevo, y si todo está OK, deberías ver lo siguiente y haz clic en Add custom domain

IMPORTANTE: Debes añadir el mismo dominio personalizado a cada CM App Service!
Y por último, cuando accedas a tu Azure Front Door dominio personalizado para acceder a Sitecore, notarás que ahora tienes una URL única para todo el Content Management, que en mi caso es https://prodcm.viniciusdeschamps.cloud

Y eso es todo!
Espero que te haya gustado, y nos vemos en mi próxima publicación.
Foto de Marius Masalar en Unsplash