Compila un sistema de inferencia de TensorFlow escalable mediante Triton Inference Server y Tesla T4

En este instructivo, se muestra cómo compilar un sistema de inferencia de TensorFlow escalable que use NVIDIA Tesla T4 y Triton Inference Server (antes se llamaba TensorRT Inference Server o TRTIS). Si deseas obtener una descripción general de la arquitectura del sistema y revisar la terminología usada en esta serie, consulta la Parte 1 de esta serie. Si deseas obtener información para medir el rendimiento y ajustar el sistema, consulta la Parte 3 de esta serie.

Objetivos

  • Descargar un modelo previamente entrenado ResNet-50 y usa la integración de TensorFlow con TensorRT (TF-TRT) para aplicar las optimizaciones.
  • Compilar un sistema de servidor de inferencia para el modelo ResNet-50 mediante Triton.
  • Compilar un sistema de supervisión para Triton mediante Prometheus y Grafana.
  • Compilar una herramienta de prueba de carga mediante Locust

Costos

Además de usar la GPU de NVIDIA T4, en este instructivo, se usan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios.

Cuando termines este instructivo, no borres los recursos que creaste. Necesitas estos recursos en la Parte 3 de esta serie.

Antes de comenzar

  1. Accede a tu cuenta de Google Cloud. Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
  2. En la página del selector de proyectos de Google Cloud Console, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  3. Asegúrate de que la facturación esté habilitada para tu proyecto de Cloud. Descubre cómo confirmar que tienes habilitada la facturación en un proyecto.

  4. Habilita la API GKE.

    Habilita la API

  5. En la página del selector de proyectos de Google Cloud Console, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  6. Asegúrate de que la facturación esté habilitada para tu proyecto de Cloud. Descubre cómo confirmar que tienes habilitada la facturación en un proyecto.

  7. Habilita la API GKE.

    Habilita la API

Prepara un modelo ResNet-50

En este instructivo, entregarás un modelo ResNet-50 con el sistema de inferencia. En la siguiente sección, descargarás el modelo previamente entrenado. Si prefieres usar ese modelo previamente entrenado, puedes omitir esta sección. De lo contrario, si deseas crear el mismo modelo, sigue los pasos en esta sección.

Entrenarás un modelo ResNet-50 y lo exportarás en formato de modelo guardado. Para ello, consulta Entrena ResNet en Cloud TPU y realiza los siguientes cambios:

  1. Reemplaza la función de entrada de entrega image_serving_input_fn en /usr/share/tpu/models/official/resnet/imagenet_input.py por la siguiente función:

    def image_serving_input_fn():
      """Serving input fn for raw images."""
    
      # The shape of input tensor is changed to NWHC.
      input_tensor = tf.placeholder(
          shape=[None, 224, 224, 3],
          dtype=tf.float32,
          name='input_tensor')
    
      # this line is just for simplicity
      images = input_tensor
    
      return tf.estimator.export.TensorServingInputReceiver(
          features=images, receiver_tensors=input_tensor)
    

    Debido a que Triton no puede manejar el formato de string base64 de forma eficiente como datos de entrada, debes cambiar el formato del tensor de entrada de la string base64 a NWHC (N, ancho, altura, canal). Ten en cuenta que la primera dimensión de la opción shape (sexta línea del código) debe ser None. Si configuras esta dimensión en un número constante, el modelo no se cuantificará correctamente con INT8 en el paso posterior.

  2. Sigue el paso para ejecutar el modelo ResNet-50 con fake_imagenet en lugar de usar el conjunto de datos completo de ImageNet, ya que tarda unos días en completar el procedimiento si usas el conjunto de datos completo. El modelo entrenado mediante imágenes falsas suficiente para los fines de este instructivo.

  3. Modifica la cantidad de pasos de entrenamiento y la cantidad de iteraciones por bucle en el archivo de configuración para reducir el tiempo de entrenamiento. Por ejemplo, puedes cambiar /usr/share/tpu/models/official/resnet/configs/cloud/v2-8.yaml de la siguiente manera:

    train_steps: 100
    train_batch_size: 1024
    eval_batch_size: 1024
    iterations_per_loop: 100
    skip_host_call: True
    num_cores: 8
    
  4. Cuando ejecutes la secuencia de comandos de entrenamiento, especifica la ruta de exportación con la opción --export_dir. Esta opción indica a la secuencia de comandos que exporte el modelo entrenado en el formato de modelo guardado:

    export PYTHONPATH="$PYTHONPATH:/usr/share/tpu/models"
    python /usr/share/tpu/models/official/resnet/resnet_main.py \
        --tpu=${TPU_NAME} \
        --mode=train \
        --data_dir=gs://cloud-tpu-test-datasets/fake_imagenet/ \
        --model_dir=${MODEL_DIR} \
        --export_dir=${MODEL_DIR}/export \
        --config_file=/usr/share/tpu/models/official/resnet/configs/cloud/v2-8.yaml
    

    En este ejemplo, cuando la secuencia de comandos de entrenamiento finaliza de forma correcta, el modelo entrenado se exporta en el formato de modelo guardado en ${MODEL_DIR}/export en Cloud Storage.

En la siguiente sección, se supone que el modelo está entrenado con el conjunto de datos falso en gs://cloud-tpu-test-datasets/fake_imagenet/ y que se exporta a gs://solutions-public-assets/tftrt-tutorial/resnet/export/1584366419/. En los siguientes pasos, cambiarás este URI según tu configuración.

Compila modelos optimizados con TF-TRT

En esta sección, optimizarás y cuantificarás el modelo previamente entrenado. En las siguientes secciones, usarás el entorno de trabajo que crearás en esta sección.

Crea un entorno de trabajo

Crea tu entorno de trabajo mediante la creación de una instancia de Compute Engine mediante Deep Learning VM Image. Debes optimizar y cuantificar el modelo ResNet-50 con TensorRT en esta instancia.

  1. Abre Cloud Shell

    Abra Cloud Shell

  2. Implementa una instancia y reemplaza PROJECT_ID por el ID del proyecto de Cloud que creaste antes:

    gcloud config set project PROJECT_ID
    gcloud config set compute/zone us-west1-b
    gcloud compute instances create working-vm \
        --scopes cloud-platform \
        --image-family common-cu101 \
        --image-project deeplearning-platform-release \
        --machine-type n1-standard-8 \
        --min-cpu-platform="Intel Skylake" \
        --accelerator=type=nvidia-tesla-t4,count=1 \
        --boot-disk-size=200GB \
        --maintenance-policy=TERMINATE \
        --metadata="install-nvidia-driver=True"
    

    Este comando inicia una instancia de Google Cloud con Tesla T4. En el primer inicio, instala automáticamente el controlador de GPU de NVIDIA que es compatible con TensorRT 5.1.5.

Crea archivos del modelo con diferentes optimizaciones

Aplica las siguientes optimizaciones al modelo ResNet-50 original mediante TF-TRT:

  • Optimización de grafos
  • Conversión a FP16, además de la optimización del grafo
  • Cuantización con INT8, además de la optimización del grafo

Estas optimizaciones se explican en la sección Ajuste del rendimiento en la parte 1 de esta serie.

  1. En Cloud Console, ve a Compute Engine > Instancias de VM.

    Ir a Instancias de VM

    Verás la instancia que creaste en la sección anterior.

  2. Haz clic en SSH para abrir la consola de la terminal de la instancia. Usa esta terminal para ejecutar los comandos de este instructivo.

  3. En la terminal, clona el repositorio que necesitas para este instructivo y cambia el directorio actual:

    cd $HOME
    git clone https://github.com/GoogleCloudPlatform/gke-tensorflow-inference-system-tutorial
    cd gke-tensorflow-inference-system-tutorial/server
    
  4. Descarga un modelo ResNet-50 previamente entrenado (o copia el modelo que creaste) a un directorio local:

    mkdir -p models/resnet/original/00001
    gsutil cp -R gs://solutions-public-assets/tftrt-tutorial/resnet/export/1584366419/* models/resnet/original/00001
    
  5. Compila una imagen de contenedor que contenga herramientas de optimización para TF-TRT:

    docker build ./ -t trt-optimizer
    docker image list
    

    El último comando muestra los ID de imágenes. Copia el ID de la imagen que tiene el nombre del repositorio tft-optimizer. En el siguiente ejemplo, el ID de la imagen es 3fa16b1b864c.

    REPOSITORY                     TAG                 IMAGE ID            CREATED              SIZE
    trt-optimizer                  latest              3fa16b1b864c        About a minute ago   6.96GB
    nvcr.io/nvidia/tensorflow      19.05-py3           01c8c4b0d7ff        2 months ago         6.96GB
    gcr.io/inverting-proxy/agent   <none>              81311f835221        2 months ago         856MB
    
  6. Aplica las optimizaciones al modelo original y reemplaza IMAGE-ID por el ID de la imagen que copiaste en el paso anterior:

    export IMAGE_ID=IMAGE-ID
    
    nvidia-docker run --rm \
        -v `pwd`/models/:/workspace/models ${IMAGE_ID} \
        --input-model-dir='models/resnet/original/00001' \
        --output-dir='models/resnet' \
        --precision-mode='FP32' \
        --batch-size=64
    
    nvidia-docker run --rm \
        -v `pwd`/models/:/workspace/models ${IMAGE_ID} \
        --input-model-dir='models/resnet/original/00001' \
        --output-dir='models/resnet' \
        --precision-mode='FP16' \
        --batch-size=64
    
    nvidia-docker run --rm \
        -v `pwd`/models/:/workspace/models ${IMAGE_ID} \
        --input-model-dir='models/resnet/original/00001' \
        --output-dir='models/resnet' \
        --precision-mode='INT8' \
        --batch-size=64 \
        --calib-image-dir='gs://cloud-tpu-test-datasets/fake_imagenet/' \
        --calibration-epochs=10
    

    Los tres comandos anteriores corresponden a las tres optimizaciones: optimización de grafos, conversión a FP16 y cuantización con INT8. Existe un proceso adicional llamado calibración para la cuantización INT8. Para ese proceso, debes proporcionar datos de entrenamiento si especificas la opción --calib-image-dir en los últimos tres comandos. Usa los datos de entrenamiento que usaste para entrenar el modelo original. El proceso de depuración solo tarda unos 5 minutos.

    Cuando se completan los comandos, los objetos binarios del modelo optimizado se almacenan en el directorio ./models/resnet. La estructura del directorio es la siguiente:

    models
    └── resnet
        ├── FP16
        │   └── 00001
        │       ├── saved_model.pb
        │       └── variables
        ├── FP32
        │   └── 00001
        │       ├── saved_model.pb
        │       └── variables
        ├── INT8
        │   └── 00001
        │       ├── saved_model.pb
        │       └── variables
        └── original
            └── 00001
                ├── saved_model.pb
                └── variables
                    ├── variables.data-00000-of-00001
                    └── variables.index
    

En la siguiente tabla, se resume la relación entre los directorios y las optimizaciones.

Directorio Optimización
original Modelo original (sin optimización con TF-TRT)
FP32 Optimización de grafos
FP16 Conversión a FP16, además de la optimización del grafo
INT8 Cuantización con INT8, además de la optimización del grafo

Implementa un servidor de inferencia

En esta sección, implementarás servidores de Triton con cinco modelos. En primer lugar, debes subir el objeto binario del modelo que creaste en la sección anterior a Cloud Storage. Luego, crearás un clúster de GKE y, luego, implementarás servidores Triton en él.

Sube el objeto binario del modelo

  1. Sube los objetos binarios del modelo a un bucket de almacenamiento y reemplaza PROJECT_ID por el ID del proyecto del proyecto de Google Cloud:

    export PROJECT_ID=PROJECT_ID
    export BUCKET_NAME=${PROJECT_ID}-models
    
    mkdir -p original/1/model/
    cp -r models/resnet/original/00001/* original/1/model/
    cp original/config.pbtxt original/1/model/
    cp original/imagenet1k_labels.txt original/1/model/
    
    mkdir -p tftrt_fp32/1/model/
    cp -r models/resnet/FP32/00001/* tftrt_fp32/1/model/
    cp tftrt_fp32/config.pbtxt tftrt_fp32/1/model/
    cp tftrt_fp32/imagenet1k_labels.txt tftrt_fp32/1/model/
    
    mkdir -p tftrt_fp16/1/model/
    cp -r models/resnet/FP16/00001/* tftrt_fp16/1/model/
    cp tftrt_fp16/config.pbtxt tftrt_fp16/1/model/
    cp tftrt_fp16/imagenet1k_labels.txt tftrt_fp16/1/model/
    
    mkdir -p tftrt_int8/1/model/
    cp -r models/resnet/INT8/00001/* tftrt_int8/1/model/
    cp tftrt_int8/config.pbtxt tftrt_int8/1/model/
    cp tftrt_int8/imagenet1k_labels.txt tftrt_int8/1/model/
    
    mkdir -p tftrt_int8_bs16_count4/1/model/
    cp -r models/resnet/INT8/00001/* tftrt_int8_bs16_count4/1/model/
    cp tftrt_int8_bs16_count4/config.pbtxt tftrt_int8_bs16_count4/1/model/
    cp tftrt_int8_bs16_count4/imagenet1k_labels.txt tftrt_int8_bs16_count4/1/model/
    
    gsutil mb gs://${BUCKET_NAME}
    gsutil -m cp -R original tftrt_fp32 tftrt_fp16 tftrt_int8 tftrt_int8_bs16_count4 \
        gs://${BUCKET_NAME}/resnet/
    

    En este paso, subiste un archivo de configuración config.pbtxt además del objeto binario del modelo. Por ejemplo, a continuación se muestra el contenido de original/1/model/config.pbtxt:

    name: "original"
    platform: "tensorflow_savedmodel"
    max_batch_size: 64
    input {
        name: "input"
        data_type: TYPE_FP32
        format: FORMAT_NHWC
        dims: [ 224, 224, 3 ]
    }
    output {
        name: "probabilities"
        data_type: TYPE_FP32
        dims: 1000
        label_filename: "imagenet1k_labels.txt"
    }
    default_model_filename: "model"
    instance_group [
      {
        count: 1
        kind: KIND_GPU
      }
    ]
    dynamic_batching {
      preferred_batch_size: [ 64 ]
      max_queue_delay_microseconds: 20000
    }
    

Ten en cuenta que los siguientes parámetros de ajuste se especifican en este archivo. El tamaño del lote y la cantidad de grupos de instancias se explican en la sección Ajuste del rendimiento en la parte 1 de esta serie.

  • Nombre del modelo
  • Nombre del tensor de entrada y de salida
  • Asignación de GPU a cada modelo
  • Tamaño del lote y cantidad de grupos de instancias

En la siguiente tabla, se resumen los cinco modelos que implementaste en esta sección.

Nombre del modelo Optimización
original Modelo original (sin optimización con TF-TRT)
tftrt_fp32 Optimización de grafos
(tamaño del lote=64, grupos de instancias=1)
tftrt_fp16 La conversión a FP16, además de la optimización del grafo
(tamaño de lote=64, grupos de instancias=1)
tftrt_int8 Cuantización con INT8 además de la optimización del grafo
(tamaño del lote=64, grupos de instancias=1)
tftrt_int8_bs16_count4 Cuantización con INT8, además de la optimización de grafos
(tamaño de lote =16, grupos de instancias=4)

Implementa servidores de inferencia mediante Triton

  1. Crea un clúster de GKE mediante nodos de procesamiento con NVIDIA Tesla T4:

    gcloud auth login
    gcloud config set compute/zone us-west1-b
    gcloud container clusters create tensorrt-cluster \
        --num-nodes=20
    gcloud container node-pools create t4-pool \
        --num-nodes=1 \
        --machine-type=n1-standard-8 \
        --cluster=tensorrt-cluster \
        --accelerator type=nvidia-tesla-t4,count=1
    

    Estos comandos crean un clúster de GKE con 20 nodos y agregan un grupo de nodos de GPU gpu-pool. El grupo de nodos de GPU consta de una única instancia de n1-standard-8 con GPU NVIDIA Tesla T4. La cantidad de instancias de GPU debe ser igual o mayor que la cantidad de Pods del servidor de inferencia porque la GPU NVIDIA Tesla T4 no puede compartirse por varios Pods en la misma instancia. La opción --num-nodes del comando anterior especifica la cantidad de instancias.

  2. Muestra la información del clúster:

    gcloud container clusters list
    

    El resultado es similar al siguiente:

    NAME              LOCATION    MASTER_VERSION  MASTER_IP      MACHINE_TYPE   NODE_VERSION    NUM_NODES  STATUS
    tensorrt-cluster  us-west1-b  1.14.10-gke.17  XX.XX.XX.XX    n1-standard-1  1.14.10-gke.17  21         RUNNING
    
  3. Muestra la información del grupo de nodos:

    gcloud container node-pools list --cluster tensorrt-cluster
    

    El resultado es similar al siguiente:

    NAME          MACHINE_TYPE   DISK_SIZE_GB  NODE_VERSION
    default-pool  n1-standard-1  100           1.14.10-gke.17
    t4-pool       n1-standard-8  100           1.14.10-gke.17
    
  4. Habilita la carga de trabajo daemonSet:

    gcloud container clusters get-credentials tensorrt-cluster
    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nvidia-driver-installer/cos/daemonset-preloaded.yaml
    

    Este comando carga el controlador de GPU de NVIDIA en los nodos del grupo de nodos de GPU. También carga automáticamente el controlador cuando agregas un nodo nuevo al grupo de nodos de GPU.

  5. Implementa servidores de inferencia en el clúster:

    sed -i.bak "s/YOUR-BUCKET-NAME/${PROJECT_ID}-models/" trtis_deploy.yaml
    kubectl create -f trtis_service.yaml
    kubectl create -f trtis_deploy.yaml
    
  6. Espera unos minutos hasta que los servicios estén disponibles.

  7. Obtén la dirección clusterIP de Triton y almacénala en la variable de entorno que usas en los pasos siguientes:

    export TRITON_IP=$(kubectl get svc inference-server \
      -o "jsonpath={.spec['clusterIP']}")
    echo ${TRITON_IP}
    

En este punto, el servidor de inferencia está entregando cuatro modelos ResNet-50 que creaste en la sección Crea archivos de modelo con diferentes optimizaciones. Los clientes pueden especificar el modelo que se usará cuando se envíen solicitudes de inferencia.

Implementa servidores de supervisión con Prometheus y Grafana

  1. Implementa servidores de Prometheus en el clúster:

    sed -i.bak "s/CLUSTER-IP/${TRITON_IP}/" prometheus-configmap.yml
    kubectl create namespace monitoring
    kubectl apply -f prometheus-service.yml -n monitoring
    kubectl create -f clusterRole.yml
    kubectl create -f prometheus-configmap.yml -n monitoring
    kubectl create -f prometheus-deployment.yml -n monitoring
    
  2. Obtén la URL de extremo del servicio de Prometheus. Copia el extremo porque lo usas para configurar Grafana en los pasos siguientes.

    ip_port=$(kubectl get svc prometheus-service \
      -o "jsonpath={.spec['clusterIP']}:{.spec['ports'][0]['port']}" -n monitoring)
    echo "http://${ip_port}"
    
  3. Implementa servidores de Grafana en el clúster:

    kubectl create -f grafana-service.yml -n monitoring
    kubectl create -f grafana-deployment.yml -n monitoring
    
  4. Espera unos minutos hasta que todos los servicios estén disponibles.

  5. Obtén la URL de extremo del servicio de Grafana.

    ip_port=$(kubectl get svc grafana-service \
      -o "jsonpath={.status['loadBalancer']['ingress'][0]['ip']}:{.spec['ports'][0]['port']}" -n monitoring)
    echo "http://${ip_port}"
    
  6. Abre esta URL desde un navegador web y accede con el ID del usuario y la contraseña predeterminados (admin y admin). Se te solicitará que cambies la contraseña predeterminada.

  7. Haz clic en el ícono Agrega tu primera fuente de datos y, en la lista Bases de datos de series temporales, selecciona Prometheus.

  8. En la pestaña Configuración, en el campo URL, configura la URL del extremo del servicio de Prometheus. La URL del extremo es la que anotaste en el paso 2.

    URL del extremo del servicio de Prometheus.

  9. Haz clic en Guardar y probar y, luego, en el ícono de Grafana para volver a la pantalla principal.

  10. Haz clic en el ícono Crear tu primer panel y, luego, en Agregar panel nuevo para agregar una métrica de supervisión.

  11. En la pestaña Consulta, ingresa nv_gpu_utilization en Métricas.

    Establece una métrica para supervisar el uso de GPU.

  12. En la pestaña Panel, en Título del panel, ingresa GPU Utilization. A continuación, haz clic en la flecha hacia la izquierda.

    Establece el título del panel para el uso de GPU.

    Verás el grafo de uso de GPU.

    Grafo para uso de GPU.

  13. Haz clic en el ícono Agregar panel y, luego, en Agregar panel nuevo y repite los pasos del paso 11 para agregar un grafo a la métrica nv_gpu_memory_used_bytes con el título GPU Memory Used.

Implementa una herramienta de prueba de carga

En esta sección, implementarás la herramienta de prueba de carga de Locust en GKE y generarás cargas de trabajo para medir el rendimiento de los servidores de inferencia.

  1. Crea una imagen de Docker que contenga bibliotecas cliente de Triton y, luego, súbela a Container Registry:

    cd ../client
    git clone https://github.com/triton-inference-server/server
    cd server
    git checkout r19.05
    docker build -t tritonserver_client -f Dockerfile.client .
    gcloud auth configure-docker
    docker tag tritonserver_client \
        gcr.io/${PROJECT_ID}/tritonserver_client
    docker push gcr.io/${PROJECT_ID}/tritonserver_client
    

    El proceso de compilación tarda unos 5 minutos.

  2. Crea una imagen de Docker para generar cargas de trabajo de prueba y, luego, súbela a Container Registry:

    cd ..
    sed -i.bak "s/YOUR-PROJECT-ID/${PROJECT_ID}/" Dockerfile
    docker build -t locust_tester -f Dockerfile .
    docker tag locust_tester gcr.io/${PROJECT_ID}/locust_tester
    docker push gcr.io/${PROJECT_ID}/locust_tester
    

    Esta imagen se compiló a partir de la imagen que creaste en el paso anterior.

  3. Implementa los archivos service_master.yaml y deployment_master.yaml de Locust:

    sed -i.bak "s/YOUR-PROJECT-ID/${PROJECT_ID}/" deployment_master.yaml
    sed -i.bak "s/CLUSTER-IP-TRTIS/${TRITON_IP}/" deployment_master.yaml
    
    kubectl create namespace locust
    kubectl create configmap locust-config --from-literal model=original --from-literal saddr=${TRITON_IP} --from-literal rps=10 -n locust
    
    kubectl apply -f service_master.yaml -n locust
    kubectl apply -f deployment_master.yaml -n locust
    

    El recurso configmap se usa para especificar el modelo de aprendizaje automático al que los clientes envían solicitudes de inferencia.

  4. Espera unos minutos hasta que los servicios estén disponibles.

  5. Obtén la dirección clusterIP de locust-master y almacénala en una variable de entorno:

    export LOCUST_MASTER_IP=$(kubectl get svc locust-master -n locust \
        -o "jsonpath={.spec['clusterIP']}")
    echo ${LOCUST_MASTER_IP}
    
  6. Implementa el cliente Locust:

    sed -i.bak "s/YOUR-PROJECT-ID/${PROJECT_ID}/" deployment_slave.yaml
    sed -i.bak "s/CLUSTER-IP-LOCUST-MASTER/${LOCUST_MASTER_IP}/" deployment_slave.yaml
    kubectl apply -f deployment_slave.yaml -n locust
    

    Estos comandos implementan 10 Pods de cliente de Locust que puedes usar para generar cargas de trabajo de prueba. Si no puedes generar suficientes solicitudes con la cantidad actual de clientes, puedes cambiar la cantidad de Pods con el siguiente comando:

    kubectl scale deployment/locust-slave --replicas=20 -n locust
    

    Cuando no haya suficiente capacidad para que un clúster predeterminado aumente la cantidad de réplicas, te recomendamos que aumentes la cantidad de nodos en el clúster de GKE.

  7. Copia la URL de la consola de Locust y, luego, abre esta URL en un navegador web:

    export LOCUST_IP=$(kubectl get svc locust-master -n locust \
         -o "jsonpath={.status.loadBalancer.ingress[0].ip}")
    echo "http://${LOCUST_IP}:8089"
    

    Verás la siguiente consola. Puedes generar cargas de trabajo de prueba desde esta consola.

    Consola de Locust que se usa para generar cargas de trabajo de prueba.

Completaste la compilación del sistema de servidor de inferencia. Puedes verificar los Pods en ejecución:

  1. Verifica el Pod del servidor de inferencia:

    kubectl get pods
    

    El resultado es similar al siguiente:

    NAME                                READY   STATUS    RESTARTS   AGE
    inference-server-67786cddb4-qrw6r   1/1     Running   0          83m
    
  2. Verifica los Pods de Locust:

    kubectl get pods -n locust
    

    El resultado es similar al siguiente:

    NAME                                READY   STATUS    RESTARTS   AGE
    locust-master-75f6f6d4bc-ttllr      1/1     Running   0          10m
    locust-slave-76ddb664d9-8275p       1/1     Running   0          2m36s
    locust-slave-76ddb664d9-f45ww       1/1     Running   0          2m36s
    locust-slave-76ddb664d9-q95z9       1/1     Running   0          2m36s
    
  3. Verifica los Pods de supervisión:

    kubectl get pods -n monitoring
    

    El resultado es similar al siguiente:

    NAME                                     READY   STATUS    RESTARTS   AGE
    grafana-deployment-644bbcb84-k6t7v       1/1     Running   0          79m
    prometheus-deployment-544b9b9f98-hl7q8   1/1     Running   0          81m
    

En la siguiente parte de esta serie, deberás usar este sistema de servidores de inferencia para conocer cómo varias optimizaciones mejoran el rendimiento y cómo interpretarlas.

¿Qué sigue?