Cómo escalar una implementación de Kubernetes

Los entornos de Kubernetes te permiten escalar los recursos de tu base de datos de forma dinámica a medida que cambian las demandas de las cargas de trabajo. Usa estos procedimientos de escalamiento si implementaste Spanner Omni con el gráfico de Helm.

Antes de comenzar

Antes de escalar tu implementación de Kubernetes, debes hacer lo siguiente:

Como práctica recomendada, te sugerimos escalar verticalmente hasta al menos 32 GB de memoria por servidor antes de agregar más servidores para escalar de forma horizontal.

Limitaciones

El escalamiento en Kubernetes tiene las siguientes limitaciones:

  • Solo servidores que no son raíz: El escalamiento horizontal es compatible con las instancias que no son raíz. No se admite el escalamiento del servidor raíz.

  • Restricciones de almacenamiento de StatefulSet: Debido a que los volumeClaimTemplates de Kubernetes son inmutables, no puedes expandir los discos de Pods con un solo comando helm upgrade. En cambio, el escalamiento del almacenamiento requiere pasos manuales de expansión de volúmenes.

Escala verticalmente

Para ajustar los recursos de CPU o memoria de tus servidores, actualiza tu configuración con una actualización de Helm:

helm upgrade spanner-omni HELM_CHART_PATH \
  --version VERSION \
  --reuse-values \
  --set resources.cpu=CPU_CORES \
  --set resources.memory=MEMORY_LIMIT \
  -n NAMESPACE

Reemplaza lo siguiente:

  • HELM_CHART_PATH: Es la ruta de acceso a tu gráfico de Helm, por ejemplo, oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni.
  • VERSION: Es la versión del gráfico de Helm, por ejemplo, 1.1.0.
  • CPU_CORES: Es la cantidad de núcleos de CPU virtuales que se asignarán a cada pod de servidor, por ejemplo, 8.
  • MEMORY_LIMIT: Es el límite de RAM para cada Pod de servidor, por ejemplo, 32Gi.
  • NAMESPACE: Es el espacio de nombres de Kubernetes de la implementación, por ejemplo, spanner-ns.

Escala horizontalmente

Para escalar de forma horizontal, agrega más servidores a tu implementación. El escalamiento horizontal es compatible con los servidores que no son raíz.

Agrega servidores que no sean raíz

Para agregar servidores que no sean raíz, aumenta el recuento de réplicas en la configuración del gráfico de Helm. Puedes escalar todas las zonas de manera uniforme o escalar una zona específica.

Escala de manera uniforme

Para escalar cada zona en la implementación a 15 servidores, ejecuta el siguiente comando:

helm upgrade spanner-omni HELM_CHART_PATH \
  --version VERSION \
  --reuse-values \
  --set deployment.replicasPerZone=REPLICAS \
  -n NAMESPACE

Reemplaza lo siguiente:

  • HELM_CHART_PATH: Es la ruta de acceso al gráfico de Helm, por ejemplo, oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni.
  • VERSION: Es la versión del gráfico de Helm, por ejemplo, 1.1.0.
  • REPLICAS: Es la cantidad objetivo de réplicas de servidor por zona, por ejemplo, 15.
  • NAMESPACE: Es el espacio de nombres de Kubernetes, por ejemplo, spanner-ns.

Escala una zona específica

Si tu implementación inicial configuró diferentes recuentos de servidores para zonas individuales, puedes orientar una sola zona. Por ejemplo, para aumentar las réplicas de la primera zona dentro de la primera ubicación a 15, ejecuta el siguiente comando:

helm upgrade spanner-omni HELM_CHART_PATH \
  --version VERSION \
  --reuse-values \
  --set locations[0].zones[0].replicas=REPLICAS \
  -n NAMESPACE

Reemplaza REPLICAS por el recuento de réplicas de la zona de destino, por ejemplo, 15.

Para verificar que los servidores nuevos se unieron correctamente a la implementación, consulta la CLI de Spanner Omni para enumerar los servidores de implementación o ver tu panel de Grafana.

spanner deployment servers list \
  --zone=ZONE \
  --deployment-endpoint=ENDPOINT

Reemplaza lo siguiente:

  • ZONE: Es la zona que deseas enumerar, por ejemplo, us-central1-a.
  • ENDPOINT: Es el extremo externo de tu implementación, por ejemplo, ${ENDPOINT}:15000.

Quita los servidores que no son raíz

Reducir la escala verticalmente de los servidores requiere pasos adicionales, ya que el sistema debe reubicar de forma segura las particiones de datos fuera de los servidores retirados. Debido a que los StatefulSets de Kubernetes quitan los Pods del índice más alto al más bajo, primero debes orientar los servidores que no son raíz con el índice más alto para quitarlos.

Para reducir la cantidad de servidores, sigue estos pasos:

  1. Enumera los servidores de tu zona para identificar los candidatos que se quitarán:

    spanner deployment servers list \
      --zone=ZONE \
      --deployment-endpoint=ENDPOINT
    

    Resultado de ejemplo:

    NAME                                                          HOST                        PORT_BASE  ROOT  STATE
    zones/us-central1-a/servers/spanner-a-0.pod.spanner-ns:15000  spanner-a-0.pod.spanner-ns  15000      true  -
    zones/us-central1-a/servers/spanner-a-1.pod.spanner-ns:15000  spanner-a-1.pod.spanner-ns  15000      -     -
    

    Borra el servidor que no es raíz retirado con el índice más alto (por ejemplo, spanner-a-1.pod.spanner-ns:15000):

    spanner deployment servers delete SERVER_NAME \
      --zone=ZONE \
      --deployment-endpoint=ENDPOINT
    

    Reemplaza SERVER_NAME por el identificador del servidor, por ejemplo, spanner-a-1.pod.spanner-ns:15000.

    Verifica la lista de servidores hasta que se quite el servidor de destino de la lista. Después de la eliminación, el servidor pasa a un estado en mal estado en el sistema y se quita de la ruta de servicio activa.

  2. Reduce la escala verticalmente de la implementación de Helm ejecutando un comando de actualización de Helm para que coincida con el recuento de réplicas de destino. Por ejemplo, para disminuir las réplicas por zona a 1 Pod, ejecuta el siguiente comando:

    helm upgrade spanner-omni HELM_CHART_PATH \
      --version VERSION \
      --reuse-values \
      --set deployment.replicasPerZone=REPLICAS \
      -n NAMESPACE
    

    Reemplaza REPLICAS por el recuento de réplicas actualizado, por ejemplo, 1.

  3. Borra las reclamaciones de volúmenes persistentes (PVC) de Kubernetes asociadas con los Pods quitados. Para evitar la pérdida accidental de datos, Helm y Kubernetes no borran automáticamente las PVC cuando se reduce la escala verticalmente de un StatefulSet. Borra las PVC de forma manual para recuperar el almacenamiento por completo:

    kubectl delete pvc LOGS_PVC DATA_PVC -n NAMESPACE
    

    Por ejemplo, para borrar los volúmenes de registros y datos de spanner-a-1 en el espacio de nombres spanner-ns, haz lo siguiente:

    kubectl delete pvc logs-volume-spanner-a-1 data-volume-spanner-a-1 -n spanner-ns
    

Agrega una zona

Agregar una zona nueva a tu implementación aumenta la disponibilidad y protege tu base de datos contra interrupciones de una sola zona.

Por ejemplo, el siguiente comando inicializa una implementación en ejecución de una sola zona en Google Kubernetes Engine (GKE) en la zona us-east1-b de la región us:

helm upgrade --install spanner-omni HELM_CHART_PATH \
  --version VERSION \
  --set resources.cpu=2 \
  --set resources.memory=8Gi \
  --set global.platform=gke \
  --set-json 'locations=[{"name":"us","zones":[{"name":"us-east1-b","shortName":"east-b"}]}]' \
  -n NAMESPACE

Agrega la zona us-east1-c a esta configuración con los siguientes pasos:

  1. Inicia los Pods en la zona nueva. Para ello, ejecuta el comando helm upgrade y pasa un bloque JSON actualizado que incluya la zona de ubicación nueva:

    helm upgrade spanner-omni HELM_CHART_PATH \
      --version VERSION \
      --reuse-values \
      --set-json 'locations=[{"name":"us","zones":[{"name":"us-east1-b","shortName":"east-b"},{"name":"us-east1-c","shortName":"east-c"}]}]' \
      -n NAMESPACE
    
  2. Agrega la zona nueva con la CLI de Spanner Omni. Espera a que los Pods del servidor raíz en la zona recién creada entren en el estado Running y listo. Luego, ejecuta el comando de creación de la zona:

    spanner deployment zones create NEW_ZONE \
      --location=LOCATION \
      --root-servers=ROOT_SERVERS_LIST \
      --deployment-endpoint=ENDPOINT
    

    Reemplaza lo siguiente:

    • NEW_ZONE: Es el identificador de la zona que se agregará, por ejemplo, us-east1-c.
    • LOCATION: Es la ubicación de la implementación, por ejemplo, us.
    • ROOT_SERVERS_LIST: Es una lista separada por comas de los extremos del servidor raíz en la zona nueva, por ejemplo, spanner-east-c-0.pod.spanner-ns:15000,spanner-east-c-1.pod.spanner-ns:15000,spanner-east-c-2.pod.spanner-ns:15000.
    • ENDPOINT: Es el extremo de implementación externo, por ejemplo, ${ENDPOINT}:15000.
  3. Espera a que se complete la creación de la zona. La replicación de esquemas y tablas de bases de datos existentes en una zona nueva lleva tiempo. Supervisa el progreso de la sincronización de zonas con una lista de las zonas de implementación:

    spanner deployment zones list --deployment-endpoint=ENDPOINT
    

Quita una zona

Puedes retirar una zona activa de tu implementación de varias zonas para reducir los recursos o alinearte con los cambios de topología.

Quita la zona us-east1-c que creaste en la sección anterior. Para ello, sigue estos pasos:

  1. Borra la zona y, luego, inicia su desmantelamiento dentro de Spanner Omni:

    spanner deployment zones delete ZONE --deployment-endpoint=ENDPOINT
    

    Reemplaza ZONE por la zona que deseas quitar, por ejemplo, us-east1-c.

  2. Verifica que se haya quitado la zona. Ejecuta un comando de lista y espera hasta que la zona ya no aparezca en el resultado:

    spanner deployment zones list --deployment-endpoint=ENDPOINT
    
  3. Quita los servidores del clúster de Kubernetes. Para ello, ejecuta un comando de actualización de Helm y pasa un bloque JSON de ubicaciones actualizado que excluya la zona quitada:

    helm upgrade spanner-omni HELM_CHART_PATH \
      --version VERSION \
      --reuse-values \
      --set-json 'locations=[{"name":"us","zones":[{"name":"us-east1-b","shortName":"east-b"}]}]' \
      -n NAMESPACE
    

Escala el almacenamiento

Debido a que los volumeClaimTemplates de Kubernetes son inmutables, no puedes aumentar las capacidades de almacenamiento de los Pods con el comando helm upgrade directamente. En su lugar, debes realizar una expansión manual del volumen. Para obtener más información, consulta la guía de expansión de volúmenes de StatefulSet de GKE.

Para expandir el almacenamiento en disco, sigue estos pasos:

  1. Define los parámetros para la expansión del volumen como variables de entorno en tu terminal:

    NEW_SIZE="NEW_SIZE"
    NAMESPACE="NAMESPACE"
    RELEASE_NAME="spanner-omni"
    STATEFULSET_NAMES="STATEFULSET_NAME_1 STATEFULSET_NAME_2 STATEFULSET_NAME_3"
    HELM_CHART_PATH="HELM_CHART_PATH"
    VERSION="VERSION"
    

    Reemplaza lo siguiente:

    • NEW_SIZE: Es el tamaño de la capacidad de almacenamiento de destino, por ejemplo, 200Gi.
    • NAMESPACE: Es el espacio de nombres de Kubernetes, por ejemplo, spanner-ns.
    • STATEFULSET_NAME_1, STATEFULSET_NAME_2, …: Son los nombres de los StatefulSets en tu implementación, que suelen corresponder a los nombres cortos de tus zonas (por ejemplo, spanner-east-b spanner-east-c).
    • HELM_CHART_PATH: Es la ruta de acceso a tu gráfico de Helm, por ejemplo, oci://us-docker.pkg.dev/spanner-omni/charts/spanner-omni.
    • VERSION: Es la versión del gráfico de Helm, por ejemplo, 1.1.0.
  2. Ejecuta los comandos para aplicar parches a las PVC, borrar los StatefulSets (dejando intactos los Pods de backend) y actualizar la implementación de Helm:

    # Patch all associated PVCs directly.
    for pvc in $(kubectl get pvc -n $NAMESPACE \
      -l app.kubernetes.io/instance=$RELEASE_NAME \
      -o name | grep "data-volume"); do
      kubectl patch $pvc -n $NAMESPACE -p "{\"spec\":{\"resources\":{\"requests\":{\"storage\":\"$NEW_SIZE\"}}}}"
    done
    
    # Delete the StatefulSet while leaving backend pods intact (orphan cascade).
    kubectl delete statefulset $STATEFULSET_NAMES -n $NAMESPACE --cascade=orphan
    
    # Run Helm upgrade to align the templates with the expanded size.
    helm upgrade $RELEASE_NAME $HELM_CHART_PATH \
      --version $VERSION \
      --reuse-values \
      --set storage.data.size=$NEW_SIZE \
      -n $NAMESPACE
    

Próximos pasos