• Saltar a la navegación principal
  • Saltar al contenido principal
  • Saltar al pie de página
Bluetab

Bluetab

an IBM Company

  • Soluciones
    • DATA STRATEGY
    • DATA READINESS
    • DATA PRODUCTS AI
  • Assets
    • TRUEDAT
    • FASTCAPTURE
    • Spark Tune
  • Conócenos
  • Oficinas
    • España
    • Mexico
    • Perú
    • Colombia
  • talento
    • España
    • TALENT HUB BARCELONA
    • TALENT HUB BIZKAIA
    • TALENT HUB ALICANTE
    • TALENT HUB MÁLAGA
  • Blog
  • ES
    • EN

Bluetab

Azure Databricks Data Engineering Specialist

junio 20, 2023 by Bluetab

Azure Databricks Data Engineering Specialist

/ESPAÑA

Bluetab, an IBM Company. certificados ¡Great Place to Work & Best Work to Place! como una de las mejores compañías para trabajar.

Una compañía muy techie que nos ha llevado a ser el brazo fuerte de IBM en Data, Cloud, ML & IA y donde, para empresas clave de diversos sectores, ayudamos a acelerar y optimizar estrategias en plataformas de datos y en la nube, sacando al máximo las ventajas de su arquitectura y entornos de desarrollo.

Nos posicionamos como agnósticos de la tecnología y apostando por la innovación de los grandes fabricantes “hyperscalers”.

Dentro de nuestra línea estratégica de Cloud Native estamos buscando apasionados/as del Cloud Azure (somos Databricks & Gold Microsoft Partner) para participar en proyectos a nivel nacional e internacional donde podrás ponerte a prueba al máximo.

Podrás rodearte de la creciente Comunidad Azure/AWS/GCP Cloud Native al más estilo Bluetab. Estarás enfocado en la construcción de aplicaciones que aprovechan las ventajas de la computación en la nube, con características como la escalabilidad, bajo acoplamiento, resiliencia, observabilidad, optimización de costes y velocidad de entrega. ¿Te gustaría?

¿Con qué trabajamos?

  • Diseño y desarrollo de procesos de integración de datos con Python en Kubernetes o Databricks (Spark). Orquestación con DataFactory.
  • Diseño y construcción de modelos de datos tanto small data (SQL Server) como Big Data (Databricks).
  • Identificación y generalización de componentes reutilizables. Pruebas de despliegues en diferentes entornos.
  • Análisis de datos y generación de insights para las áreas de negocio internas o de cualquier otro cliente.
  • Despliegues CI/CD de servicios de infraestructura (IaC) con Terraform y/o ARM.
  • Productos: HashiCorp.
  • Más técnicas: Reactive Manifesto.
  • Herramientas: GitOps, Service Mesh, Distributed tracing.

  • Valorable Power BI para diseño y construcción de informes.
  • Valorable muy positivamente nivel alto de inglés para proyectos EMEA.
  1. D.: para muestra un botón, aquí tienes ejemplos de cosas chulas que hacemos en Bluetab de primera mano de nuestros Bluetabers:

Databricks sobre Azure – Una perspectiva de arquitectura:

https://www.bluetab.net/es/databricks-sobre-azure-una-perspectiva-de-arquitectura-parte-1/

Ahora viene lo bueno por ser bluetaber… ¿Qué ofrecemos?

  • Contrato indefinido con un salario competitivo.
    El salario se relaciona en función de los conocimientos técnicos detectados en el proceso y rol asignado, procurando respetar el sentido de equidad con la plantilla y siendo susceptible de mejora tras las evaluaciones continuas de desempeño.
  • La pregunta estrella. ¿Teletrabajo? Sí, Teletrabajo flexible. A tu entera disposición tendrás también las Oficinas ubicadas en el centro de Madrid con muy buena conexión.
  • Horarios flexibles de entrada/salida, adaptado a tus necesidades personales y jornada intensiva los viernes y los meses de verano, julio y agosto.
  • 23 días de vacaciones + 2 Bluetab days (nochebuena y nochevieja).
  • Tarjeta restaurant como beneficio social más allá del salario.
  • Seguro médico & póliza dental con una amplia cobertura también como beneficio social más allá del salario.
  • Disponibilidad además de plan de retribución flexible: Transporte + Guardería.
  • Formación continua gamificada a través del plan rewards, hasta 800 cursos y certificaciones oficiales.
  • Además, tendrás a tu alcance el programa Career Coach para acompañarte en todo lo relativo a tu desarrollo y crecimiento dentro de Bluetab, con un sistema objetivo de evaluación continua.
  • ¡Tú serás el dueño de tu crecimiento!
  • Tarjeta regalo Pass por importe de 50€ en el mes de tu cumpleaños.

 

Consideramos que la diversidad es enriquecedora y queremos velar por la inclusión e igualdad de oportunidades, por lo que contamos con un Plan de Igualdad y un Código Ético que recoge estos principios para garantizar la no discriminación de nuestras colaboradoras y colaboradores por cuestión de raza, color, nacionalidad, origen social, edad, sexo, estado civil, orientación sexual, ideología, opiniones políticas, religión o cualquier otra condición personal, física o social.

 

Bluetab is an IBM Company, but will remain the hiring entity. By proceeding with this application, you understand that Bluetab will share your personal information with other IBM affiliates involved in your recruitment process, wherever these are located. More Information on how IBM protects your personal information, including the safeguards in case of cross-border data transfer, are available here:

https://www.ibm.com/careers/us-en/privacy-policy/”

Si te apasiona la tecnología y quieres disfrutar en un entorno innovador y 100% tecnológico, Bluetab, an IBM Company es tu sitio.

¡Te esperamos!

#wearehiring #bluetabanibmcompany #bluetabers

Nivel de experiencia
  • Algo de responsabilidad
Sector
  • Servicios y tecnologías de la información
Tipo de empleo
  • Jornada completa
Funciones laborales
  • Tecnología de la información 
  • Ingeniería
¿Quieres saber más de lo que ofrecemos y ver otros casos de éxito?
DESCUBRE BLUETAB

Queremos Conocerte

    Al cumplimentar el formulario das tu consentimiento para el tratamiento de los datos que nos faciltas de forma voluntaria, libre e informada a efectos de participar en los procesos de selección de la Bluetab Solutions S.L.U. No cedemos ni cederemos tus datos a terceros, salvo autorización expresa u obligación legal. Tampoco están previstas transferencias internacionales a terceros países. Podrás ejercer tus derechos con relación a tus datos por escrito en la dirección Edificio Ruiz Picasso, Pl. Pablo Ruiz Picasso, 11, 2ª Planta, Tetuán, 28020 Madrid España o mediante el envío de un correo electrónico a dpo@beta.bluetab.net. Para más información al respecto consultar Política de Privacidad.

      Acepto la  política de privacidad

    Publicado en: Talento Etiquetado como: Madrid

    AWS Data Engineering Specialist

    junio 20, 2023 by Bluetab

    AWS Data Engineering Specialist

    /ESPAÑA

    Bluetab, an IBM Company. certificados ¡Great Place to Work & Best Work to Place! como una de las mejores compañías para trabajar.

    Una compañía muy techie que nos ha llevado a ser el brazo fuerte de IBM en Data, Cloud, ML & IA y donde, para empresas clave de diversos sectores, ayudamos a acelerar y optimizar estrategias en plataformas de datos y en la nube, sacando al máximo las ventajas de su arquitectura y entornos de desarrollo.

    Nos posicionamos como agnósticos de la tecnología y apostando por la innovación de los grandes fabricantes “hyperscalers”.

    Dentro de nuestra línea estratégica de Cloud Native estamos buscando apasionados/as del Cloud AWS (somos AWS Partner) para participar en proyectos a nivel nacional e internacional donde podrás ponerte a prueba al máximo.

    Podrás rodearte de la creciente Comunidad AWS/Azure/GCP Cloud Native al más estilo Bluetab. Estarás enfocado en la construcción de aplicaciones que aprovechan las ventajas de la computación en la nube, con características como la escalabilidad, bajo acoplamiento, resiliencia, observabilidad, optimización de costes y velocidad de entrega. ¿Te gustaría?

    ¿Con qué trabajamos?

    • Plataformas: AWS, Kubernetes, Docker.
    • Implementación Data Pipelines basados en AWS Serverless (Lambda, Glue, ECS).
    • Ejecución de código (lenguajes y frameworks): Python y/o Scala.
    • Despliegues CI/CD de servicios de infraestructura (IaC)con Terraform y/o Cloud Formation.
    • Trabajar en arquitecturas Big Data AWS EMR con Spark y capas de persistencia horizontalmente escalables en sistema Cloud S3.
    • Productos: 
    • Más técnicas: Reactive Manifesto, AWS Well-Architected Framework.
    • Herramientas:GitOps, Service Mesh, Distributed tracing.
    • Valorable muy positivamente nivel alto de inglés para proyectos EMEA.
    1. D.: para muestra un botón, aquí tienes ejemplos de cosas chulas que hacemos en Bluetab de primera mano de nuestros Bluetabers:

    Databricks sobre AWS – Una perspectiva de arquitectura:

    https://www.bluetab.net/es/databricks-sobre-aws-una-perspectiva-de-arquitectura-parte-1/

    Conceptos básicos de AWS Glue:

    https://www.bluetab.net/es/serverless-microservices/

    Ahora viene lo bueno por ser bluetaber… ¿Qué ofrecemos?

    • Contrato indefinido con un salario competitivo.
      El salario se relaciona en función de los conocimientos técnicos detectados en el proceso y rol asignado, procurando respetar el sentido de equidad con la plantilla y siendo susceptible de mejora tras las evaluaciones continuas de desempeño.
    • La pregunta estrella. ¿Teletrabajo? Sí, Teletrabajo flexible. A tu entera disposición tendrás también las Oficinas ubicadas en el centro de Madrid con muy buena conexión.
    • Horarios flexibles de entrada/salida, adaptado a tus necesidades personales y jornada intensiva los viernes y los meses de verano, julio y agosto.
    • 23 días de vacaciones + 2 Bluetab days (nochebuena y nochevieja).
    • Tarjeta restaurant como beneficio social más allá del salario.
    • Seguro médico & póliza dental con una amplia cobertura también como beneficio social más allá del salario.
    • Disponibilidad además de plan de retribución flexible: Transporte + Guardería.
    • Formación continua gamificada a través del plan rewards, hasta 800 cursos y certificaciones oficiales.
    • Además, tendrás a tu alcance el programa Career Coach para acompañarte en todo lo relativo a tu desarrollo y crecimiento dentro de Bluetab, con un sistema objetivo de evaluación continua.
    • ¡Tú serás el dueño de tu crecimiento!
    • Tarjeta regalo Pass por importe de 50€ en el mes de tu cumpleaños.

    Consideramos que la diversidad es enriquecedora y queremos velar por la inclusión e igualdad de oportunidades, por lo que contamos con un Plan de Igualdad y un Código Ético que recoge estos principios para garantizar la no discriminación de nuestras colaboradoras y colaboradores por cuestión de raza, color, nacionalidad, origen social, edad, sexo, estado civil, orientación sexual, ideología, opiniones políticas, religión o cualquier otra condición personal, física o social.

    Bluetab is an IBM Company, but will remain the hiring entity. By proceeding with this application, you understand that Bluetab will share your personal information with other IBM affiliates involved in your recruitment process, wherever these are located. More Information on how IBM protects your personal information, including the safeguards in case of cross-border data transfer, are available here:

    https://www.ibm.com/careers/us-en/privacy-policy/”

    Si te apasiona la tecnología y quieres disfrutar en un entorno innovador y 100% tecnológico, Bluetab, an IBM Company es tu sitio.

    ¡Te esperamos!

    #wearehiring #bluetabanibmcompany #bluetabers

     

    Nivel de experiencia
    • Algo de responsabilidad
    Sector
    • Servicios y tecnologías de la información
    Tipo de empleo
    • Jornada completa
    Funciones laborales
    • Tecnología de la información 
    • Ingeniería
    ¿Quieres saber más de lo que ofrecemos y ver otros casos de éxito?
    DESCUBRE BLUETAB

    Queremos Conocerte

      Al cumplimentar el formulario das tu consentimiento para el tratamiento de los datos que nos faciltas de forma voluntaria, libre e informada a efectos de participar en los procesos de selección de la Bluetab Solutions S.L.U. No cedemos ni cederemos tus datos a terceros, salvo autorización expresa u obligación legal. Tampoco están previstas transferencias internacionales a terceros países. Podrás ejercer tus derechos con relación a tus datos por escrito en la dirección Edificio Ruiz Picasso, Pl. Pablo Ruiz Picasso, 11, 2ª Planta, Tetuán, 28020 Madrid España o mediante el envío de un correo electrónico a dpo@beta.bluetab.net. Para más información al respecto consultar Política de Privacidad.

        Acepto la  política de privacidad

      Publicado en: Talento Etiquetado como: Madrid

      Data Governance Consultant

      junio 20, 2023 by Bluetab

      Data Governance Consultant

      /ESPAÑA

      Bluetab, an IBM Company. certificados ¡Great Place to Work & Best Work to Place! como una de las mejores compañías para trabajar.

      Una compañía muy techie que nos ha llevado a ser el brazo fuerte de IBM en Data, Cloud, ML & IA y donde, para empresas clave de diversos sectores, ayudamos a acelerar y optimizar estrategias en plataformas de datos y en la nube, sacando al máximo las ventajas de su arquitectura y entornos de desarrollo.

      Nos posicionamos como agnósticos de la tecnología y apostando por la innovación de los grandes fabricantes “hyperscalers”. 

      Podrás rodearte de la creciente Comunidad Data & Cloud Native al más estilo Bluetab, formando parte de dichas líneas estratégicas para participar en proyectos a nivel nacional e internacional donde podrás ponerte a prueba al máximo.

      Como perfil de Gobierno del Dato podrás definir junto con el cliente procedimientos y metodología a aplicar en las iniciativas, participar en las iniciativas de datos que se lancen para dar apoyo y asegurar que se siguen los pasos de gobierno del dato, dar formación sobre gobierno en general, asegurar la calidad del dato estableciendo procedimientos y reglas para su revisión, además de analizar las cargas que dependan de nosotros, etc, definir e implementar Dashboards de control (se necesita SQL).

      Además de eso se debe analizar posibles requisitos que surjan de estas interacciones para el equipo técnico y coordinar los nuevos desarrollos del equipo de implantaciones

      Obligatorio

      • +3 años de experiencia en gobierno de datos.
      • Conocimiento de los marcos de gobierno de datos más habituales (Dama, etc.)
      • Experiencia en definición e implantación de modelos de Gobierno del Dato
      • Conocimiento y experiencia de trabajo con alguna de las diferentes herramientas y tecnologías de gobierno de dato. (Collibra, Apache Atlas, Informática Data Quality...)
      • Capacidad para trabajar en un entorno dinámico.
      • Habilidades analíticas y de resolución de problemas, con la capacidad de identificar problemas y desarrollar estrategias para abordarlos.
      • Buena capacidad de interlocución con diferentes roles y perfiles

      Deseable

      • Nociones de modelado de datos, integración de datos, la calidad de los datos y la gestión de datos maestros.
      • Experiencia en estándares y procesos de calidad de datos.

      Ahora viene lo bueno por ser bluetaber… ¿Qué ofrecemos?

      • Contrato indefinido con un salario competitivo.
        El salario se relaciona en función de los conocimientos técnicos detectados en el proceso y rol asignado, procurando respetar el sentido de equidad con la plantilla y siendo susceptible de mejora tras las evaluaciones continuas de desempeño.
      • La pregunta estrella. ¿Teletrabajo? Sí, Teletrabajo flexible. A tu entera disposición tendrás también las Oficinas ubicadas en el centro de Madrid con muy buena conexión.
      • Horarios flexibles de entrada/salida, adaptado a tus necesidades personales y jornada intensiva los viernes y los meses de verano, julio y agosto.
      • 23 días de vacaciones + 2 Bluetab days (nochebuena y nochevieja).
      • Tarjeta restaurant como beneficio social más allá del salario.
      • Seguro médico & póliza dental con una amplia cobertura también como beneficio social más allá del salario.
      • Disponibilidad además de plan de retribución flexible: Transporte + Guardería.
      • Formación continua gamificada a través del plan rewards, hasta 800 cursos y certificaciones oficiales.
      • Además, tendrás a tu alcance el programa Career Coach para acompañarte en todo lo relativo a tu desarrollo y crecimiento dentro de Bluetab, con un sistema objetivo de evaluación continua.
      • ¡Tú serás el dueño de tu crecimiento!
      • Tarjeta regalo Pass por importe de 50€ en el mes de tu cumpleaños.

      Consideramos que la diversidad es enriquecedora y queremos velar por la inclusión e igualdad de oportunidades, por lo que contamos con un Plan de Igualdad y un Código Ético que recoge estos principios para garantizar la no discriminación de nuestras colaboradoras y colaboradores por cuestión de raza, color, nacionalidad, origen social, edad, sexo, estado civil, orientación sexual, ideología, opiniones políticas, religión o cualquier otra condición personal, física o social.

      Bluetab is an IBM Company, but will remain the hiring entity. By proceeding with this application, you understand that Bluetab will share your personal information with other IBM affiliates involved in your recruitment process, wherever these are located. More Information on how IBM protects your personal information, including the safeguards in case of cross-border data transfer, are available here:

      https://www.ibm.com/careers/us-en/privacy-policy/”

      Si te apasiona la tecnología y quieres disfrutar en un entorno innovador y 100% tecnológico, Bluetab, an IBM Company es tu sitio.

      ¡Te esperamos!

      #wearehiring #bluetabanibmcompany #bluetabers

      Nivel de experiencia
      • Algo de responsabilidad
      Sector
      • Servicios y tecnologías de la información
      Tipo de empleo
      • Jornada completa
      Funciones laborales
      • Tecnología de la información 
      • Ingeniería
      ¿Quieres saber más de lo que ofrecemos y ver otros casos de éxito?
      DESCUBRE BLUETAB

      Queremos Conocerte

        Al cumplimentar el formulario das tu consentimiento para el tratamiento de los datos que nos faciltas de forma voluntaria, libre e informada a efectos de participar en los procesos de selección de la Bluetab Solutions S.L.U. No cedemos ni cederemos tus datos a terceros, salvo autorización expresa u obligación legal. Tampoco están previstas transferencias internacionales a terceros países. Podrás ejercer tus derechos con relación a tus datos por escrito en la dirección Edificio Ruiz Picasso, Pl. Pablo Ruiz Picasso, 11, 2ª Planta, Tetuán, 28020 Madrid España o mediante el envío de un correo electrónico a dpo@beta.bluetab.net. Para más información al respecto consultar Política de Privacidad.

          Acepto la  política de privacidad

        Publicado en: Talento Etiquetado como: Madrid

        De documentos en papel a datos digitales con Fastcapture y Generative AI

        junio 7, 2023 by Bluetab

        De documentos en papel a datos digitales con Fastcapture y Generative AI

        Resumen

        Los avances en Generative AI y en los grandes modelos de lenguaje, LLMs por sus siglas en inglés (Large Language Models), permiten transferir el pre-entrenamiento de estos modelos en una tarea simple, como predecir las palabras que faltan en una frase a tareas más complejas, como procesar documentos en papel para extraer sus datos de forma automática. Esta transferencia del entrenamiento funciona tan bien que es posible plantear desarrollar casos de uso que cierren el gap entre la digitalización y las actividades que requieren documentos en papel.

        Hemos desarrollado un proyecto para modernizar la tecnología de AI de Fastcapture, nuestro IDP (Intelligent Document Processing), con Generative AI y LLMs. Hemos conectado Fastcapture con Hugging Face, un hub de la comunidad Open Source de AI. Los resultados que hemos obtenido están muy por encima de un F1 score de 0.9.

         

        Introducción

        Estamos viviendo una era de disrupciones. Esta situación está produciendo un momento de constantes avances tecnológicos. Me voy a fijar en 2 de ellos, la digitalización y el desarrollo de aplicaciones con inteligencia artificial (AI).

        La pandemia COVID-19 ha sido terrible. Ahora bien, una de sus consecuencias ha sido la aceleración de la digitalización. El crecimiento de usuarios digitales ha sido de 2 dígitos en la gran mayoría de las empresas. Sin embargo, muchas actividades en las empresas siguen requiriendo documentos en papel. Un informe del US Bureau of Labor Statistics indica que las compañías americanas se gastaron $5,3Bn en cargar manualmente los documentos durante el año 2021.

        Los avances en AI, y en particular los avances en Generative AI y en los grandes modelos de lenguaje han alcanzado un momento que, a parte de la aparición de aplicaciones sorprendentes como ChatGPT, permite el desarrollo de casos de uso de tratamiento de textos e imágenes con unos niveles de precisión muy elevados >0.9.

        Juntando estas piezas, hoy es realmente posible plantear automatizar el procesamiento de documentos en papel a escala para convertirlos en datos digitales listos para ser consumidos y analizados en cualquier otra actividad de la empresa. 

         

        El problema

        Muchas actividades en las empresas siguen requiriendo documentos en papel. Facturas, contratos, informes. Estos documentos contienen datos relevantes y disponer de una versión digital es clave para la digitalización de las empresas. 

        Una forma de convertir los documentos en papel en datos digitales es mediante cargas manuales. También se pueden convertir en datos digitales utilizando aplicaciones del tipo de un IDP. Un IDP consiste en un grupo de pipelines con pasos para procesar los documentos y convertirlos en datos digitales. El primer paso es la conversión del documento en texto con un modelo OCR (Optical Character Recognition). 

        A continuación vienen los pasos para tratar el texto. Los pasos de tratamiento del texto pueden utilizar modelos de AI. Típicamente estos modelos de AI están basados en una arquitectura RNN (Recurrent Neural Network). Los modelos RNN tratan la secuencia de palabras en orden, una a una. Estos modelos se enfrentan a 2 dificultades a la hora de realizar su tarea. La primera es su capacidad de tratamiento del contexto. Según se van alejando las palabras y las frases, el modelo empieza a perder su capacidad para relacionarlas. La segunda es la dificultad que tienen para escalar y, por lo tanto, para ser entrenados en grandes volúmenes de textos. Estas 2 dificultades suponen un techo para la precisión del IDP y por lo tanto para su capacidad de automatizar la conversión de documentos en papel en datos digitales.

         

        La solución propuesta

        Los LLM se basan en la arquitectura de los Transformers. Esta arquitectura propuesta en el paper “Attention is all you need” Vaswani et al. 2017 fué totalmente revolucionaria. Trata la secuencia a través del mecanismo de atención mediante matrices. El mecanismo de atención permite realizar un mejor procesamiento del contexto. 

        Todas las palabras se encuentran a la misma distancia entre sí medida en número de operaciones matemáticas. Y permite escalar el entrenamiento de forma horizontal. Los modelos basados en esta arquitectura se pueden entrenar con cantidades de textos muy grandes. 

        En el paper “Improving Language Understanding by Generative Pre-Training” Radford et al. 2018 proponen un nuevo framework de 2 fases para entrenar los LLMs. Un pre-entrenamiento no supervisado sobre un objetivo sencillo, predecir la siguiente palabra de un texto, y con grandes volúmenes de textos. Y un fine-tune para adaptar el modelo a resolver una tarea NLP concreta como extraer datos relevantes de un documento, y con pocos ejemplos. 

        Esta combinación es ideal para transferir el pre-entrenamiento de un modelo con grandes cantidades de textos a tareas para las que se disponen de pocos ejemplos. 

        Nuestra aproximación consiste en utilizar LLMs pre-entrenados disponibles en la comunidad Open Source y realizar un fine-tune para convertir los documentos en papel en datos digitales. 

        Hemos conectado nuestro IDP Fastcapture con el hub de Hugging Face donde residen LLMs pre-entrenados Open Source para acceder a ellos y generar versiones especializadas mediante un fine-tune en nuestro hub privado sin enviar los datos al hub público.

         

        Cómo incorporar los LLMs en un IDP

        La estrategia que hemos seguido para incorporar los LLMs en nuestro IDP Fastcapture se ha basado en 3 pilares, aprender a través de I+D, apoyarnos en la comunidad Open Source de AI y construir sobre lo que ya teníamos.

        Estos han sido los pasos clave del proyecto:

        1. La selección del LLM pre-entrenado
        2. El diseño del contexto del Transformer
        3. Utilizar entornos multi-GPU para realizar el fine-tune y el servicing

         

        La selección del LLM pre-entrenado

        La comunidad Open Source de AI da acceso a LLMs pre-entrenados con un nivel de calidad enterprise-grade. Nuestro caso de uso requiere un modelo tipo encoder con capacidades multi idioma. De esta manera un único modelo será capaz de extraer datos relevantes de documentos del mismo tipo con diferente idioma.

        Nos decantamos por el modelo pre-entrenado XLM-R propuesto en el paper “Unsupervised Cross-lingual Representation Learning at Scale” Conneau et al. 2020. El modelo XLM-R ha sido pre-entrenado en 2.5TB de textos con 100 idiomas. Hemos utilizado las siguientes tallas:

        Modelo

        Número de parámetros

        XLM-RLarge

        550M

        XLM-RXL

        3.5B



        Diseño del contexto del Transformer

        Diseñar cómo usar el contexto del LLM es un factor importante a la hora de conseguir niveles de performance de 0.9.

        Los documentos están organizados en páginas y frases. Lo que queremos es que el LLM analice frase a frase en búsqueda de datos relevantes. Los tipos de documentos que manejamos son más bien telegráficos, con poco texto. Esto suele ser una tónica habitual al tratar documentos en papel en el mundo empresarial. 

        Para dar una mejor oportunidad al LLM de hacer su tarea ubicamos la frase de interés a la derecha del contexto y completamos el contexto por la izquierda con las frases predecesoras que quepan.

        El siguiente esquema muestra el diseño al que nos referimos.

        Fine-tune y servicing en un entorno multi-GPU

        Realizar un fine-tune de un LLM requiere utilizar GPU’s (Graphics Processing Units). El modelo XLM-RLarge puede entrenarse sin utilizar un framework que optimice el uso de la memoria o que distribuya el modelo entre diferentes GPUs. 

        Sin embargo la versión XLM-RXL es tan grande que al realizar el algoritmo de gradient descent no cabe y requiere utilizar frameworks de optimización y/o que distribuyan el modelo en el entorno multi-GPU.

        El proyecto lo hemos realizado en una máquina virtual con 4 GPUs NVIDIA a10g, y hemos utilizado el framework propuesto en el paper “ZeRO: Memory Optimizations Toward Training Trillion Parameter Models” Rajbhandari et al. 2020. ZeRO optimiza el uso de la memoria para almacenar el estado del modelo a la hora de entrenar y permite distribuir los gradientes y los parámetros entre las GPUs.

        Utilizar entornos multi-GPU y frameworks de optimización como ZeRO, a parte de poder escalar el proceso de fine-tuning, permite gestionar los recursos computacionales que requieren modelos extra grandes. 

         

        Resultados

        En el proyecto hemos utilizado 2 juegos de datos, uno de factura y otro de informes económicos.

         

        El impacto de la talla en el performance depende del caso de uso

        Las siguientes gráficas muestran el F1 score de las 2 tallas, L y XL, en cada uno de los juegos de datos.

        Gráfica 1. F1 score fine-tune facturas XLM-RLarge
        Gráfica 2. F1 score fine-tune facturas XLM-RXL
        Gráfica 3. F1 score fine-tune informes XLM-RLarge
        Gráfica 4. F1 score fine-tune informes XLM-RXL

        Estas gráficas ayudan a visualizar la diferencia de performance entre las tallas L y XL en los 2 juegos de datos y poder decidir qué modelo utilizar en el IDP. En el caso de las facturas la talla XL obtiene un score medio 8 puntos básicos mejor que la talla L, mientras que en el caso de los informes económicos la diferencia del score medio es de 1 punto básico. 

        Al elegir el tamaño de modelo adecuado para cada caso de uso hay que considerar varios factores como el performance del modelo, los recursos de computación y el trade-off entre precisión y complejidad. En algunos casos, un modelo más pequeño puede proporcionar resultados suficientemente precisos con menores requisitos de computación y menor complejidad de mantenimiento. 

        La importancia de diseñar el contexto al trabajar con LLMs

        El diseño del contexto es clave para cualquier caso de uso con LLMs. La siguiente gráfica muestra el resultado de un fine-tune del modelo XLM-RLarge sin utilizar el contexto con diseño de ventana. El F1 score medio es 3 puntos básicos inferior sin utilizar el diseño de contexto con ventana.

        Gráfica 3. F1 score fine-tune informes XLM-RLarge
        sin el diseño de contexto con ventana

        Referencias

        Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Lukasz Kaiser, and Illia Polosukhin. 2017. Attention is all you need. arXiv:1706.03762 

        Alec Radford, Karthik Narasimhan, Tim Salimans, Ilya Sutskever. Improving Language Understanding by Generative Pre-Training. 2018. 

        Alexis Conneau, Kartikay Khandelwal, Naman Goyal, Vishrav Chaudhary, Guillaume Wenzek, Francisco Guzman, Edouard Grave, Myle Ott, Luke Zettlemoyer, Veselin Stoyanov. Unsupervised Cross-lingual Representation Learning at Scale. 2020. arXiv:1911.02116v2.

        Samyam Rajbhandari∗ , Jeff Rasley∗ , Olatunji Ruwase, Yuxiong He. ZeRO: Memory Optimizations Toward Training Trillion Parameter Models. 2020. arXiv:1910.02054v3

        ¿Quieres saber más de lo que ofrecemos y ver otros casos de éxito?
        DESCUBRE BLUETAB

        SOLUCIONES, SOMOS EXPERTOS

        DATA STRATEGY
        DATA FABRIC
        AUGMENTED ANALYTICS

        Te puede interesar

        Cómo depurar una Lambda de AWS en local

        octubre 8, 2020
        LEER MÁS

        Workshop Ingeniería del caos sobre Kubernetes con Litmus

        julio 7, 2021
        LEER MÁS

        Tenemos Plan B

        septiembre 17, 2020
        LEER MÁS

        Starburst: Construyendo un futuro basado en datos.

        mayo 25, 2023
        LEER MÁS

        $ docker run 2021

        febrero 2, 2021
        LEER MÁS

        El futuro del Cloud y GenIA en el Next ’23

        septiembre 19, 2023
        LEER MÁS

        Publicado en: Blog, Destacado, Tech

        Starburst: Construyendo un futuro basado en datos.

        mayo 25, 2023 by Bluetab

        Starburst: Construyendo un futuro basado en datos.

        Lucas Calvo

        Cloud Engineer

        Introducción

        En este nuevo artículo vamos a hablar de uno de nuestros partners: Starburst[1]. Starburst es la versión empresarial de Trino[2] realizando nuevas integraciones, mejoras de rendimiento, una capa de seguridad y restando complejidad a la gestión con una interfaz de usuario muy fácil de usar y que te permite realizar distintas configuraciones.

        Para los que no conocéis Trino, es un motor de consulta SQL distribuido open-source creado en 2012 por Facebook bajo el nombre Presto. Está diseñado para consultar grandes conjuntos de datos distribuidos en una o más fuentes de datos heterogéneas. Esto significa que podemos consultar datos que residen en diferentes sistemas de almacenamiento como HDFS, AWS S3, Google Cloud Storage o Azure Blob Storage. Trino también tiene la capacidad de federar diferentes fuentes de datos como MySQL, PostgreSQL, Cassandra, Kafka.

        Con las nuevas necesidades que van saliendo de arquitecturas orientadas al Data Mesh[3], plataformas analíticas como Starburst son cada vez más importantes y nos permiten centralizar y federar distintas fuentes de datos para así tener solo un punto de entrada a nuestra información. Con esta mentalidad, podemos hacer que nuestros usuarios accedan a la plataforma de Starburst con distintos roles y distinta granularidad de acceso para que puedan consultar los distintos dominios que poseen las empresas. Además Starburst no solo se queda en la consulta de datos, sino que nos permite conectarnos con herramientas analíticas como puedes ser DBT[4] o Jupyter Notebook[5] o herramientas de reporting como Power BI[6] para sacarle más rendimiento a todos nuestros datos. Pero Starburst no solo se queda en eso, sino que nos puede ayudar en la migraciones de datos hacia el Cloud, ya que fácilmente podemos conectarnos a las fuentes de datos y sacar toda la información para volcarlas en cualquier almacenamiento del Cloud.

        Como podéis observar, Starburst es capaz de analizar todos sus datos, dentro y alrededor de tu Data Lake, y se conecta a todo un ecosistema de herramientas. Por eso vamos a realizar una serie de artículos para tratar los puntos más relevantes como son el despliegue y configuración de la plataforma, integración con otras herramientas y gobierno y administración de usuarios. En este primer artículo, nos vamos a centrar en el despliegue de Starburst en Kubernetes, así como la configuración que se tiene que realizar para conectar con los distintos componentes de GCP. Además hemos añadido una capa de monitorización con Prometheus[7] y Grafana[8], donde hemos publicado un dashboard con distintas métricas importantes por si cualquier compañía quiere centralizar las métricas en Grafana. Para todo ello, nos vamos a apoyar de un repositorio que hemos creado con el levantamiento de la infraestructura y la instalación de Starburst.

        ¿Qué necesitas para entender este artículo?

        • Algunos conceptos sobre Terraform[9].
        • Algunos conceptos de Kubernetes.
        • Algunos conceptos de Helm.
        • Algunos conceptos de Prometheus.
        • Algunos conceptos de Grafana.
        • Un cuenta en GCP.
        • Una licencia de Starburst

        Arquitectura

        Como se puede observar en el diagrama, estos son los componentes que se van a desplegar para la configuración de Starburst. Como pieza central del despliegue, utilizaremos Google Kubernetes Engine. Este es el servicio administrado de orquestación de contenedores de Google. Utilizaremos Kubernetes ya que nos facilitará la gestión de Starburst y aprovecharemos las ventajas del autoscaling de Kubernetes para ampliar el número de workers de Starburst y escalar en más nodos para poder así tener más recursos de computación si tenemos algún pico de trabajo o de usuarios.

        Como configuración inicial de nuestro cluster de GKE, comenzaremos con un único nodepool para facilitar el despliegue. Un nodepool es una agrupación de nodos dentro de un cluster con la misma configuración y especificaciones de tipo de máquina. En nuestro caso, nuestro nodepool se llamará `default-node-pool` y el tipo de instancia utilizada será `e2-standard-16`, que es la recomendada por Starburst, ya que el tipo de carga de trabajo necesita nodos con bastante memoria. Además de la instalación de Starburst, también desplegaremos en el cluster tanto Prometheus como Grafana.

        Como hemos explicado anteriormente, Starburst está basado en Trino, que es un motor de consulta distribuido. Los principales componentes de Trino son el Coordinator y los Workers. El Coordinator de Trino es el componente responsable de analizar las sentencias, planificar las consultas y gestionar los nodos Workers de Trino. El Coordinator realiza un seguimiento de la actividad de cada Worker y orquesta la ejecución de una consulta. Los Workers son el componente responsable de ejecutar tareas y procesar datos. Los nodos Workers obtienen datos de los conectores e intercambian datos intermedios entre sí. El Coordinator es responsable de obtener los resultados de los Workers y devolver los resultados finales al cliente.

        Como componentes transversales de nuestra arquitectura, también desplegaremos una red con una subnet para realizar el despliegue de nuestro cluster de GKE, así como un bucket en Cloud Storage para realizar pruebas de escritura de datos desde Starburst.

        Además, como componente fuera de la arquitectura, tendremos jmeter[10], la herramienta con la que realizaremos pruebas de performance para probar la elasticidad de Starburst y poder probar el autoescalado de nuestro cluster.

        Despliegue de la infraestructura

        Una vez explicada la arquitectura vamos a proceder a realizar el despliegue de todos los componentes. Para ello, nos vamos a ayudar de Terraform como herramienta de IaC. Como partes importantes de este despliegue, tendremos la parte más de infraestructura tradicional que son las VPC, el cluster de GKE y la parte de Cloud Storage como hemos hablado antes, además de los componentes que desplegamos en Kubernetes de una forma totalmente automatizada que son Grafana y Prometheus.

        Vamos a empezar con la explicación de la infraestructura más clásica. Para este despliegue haremos uso de dos módulos que están subidos al github:

        • Módulo de GKE[11].
        • Módulo de VPC[12].

        Estos dos módulos están invocados en el `main.tf` del repositorio y hacen uso del provider de Google para el despliegue:

        
        ```tf
        provider "google" {
          project = var.project_id
          region  = var.region
        }
        
        provider "google-beta" {
          project = var.project_id
          region  = var.region
        }
        
        
        module "network" {
          source = "git@github.com:lucasberlang/gcp-network.git?ref=v1.0.0"
        
          project_id         = var.project_id
          description        = var.description
          enable_nat_gateway = true
          offset             = 1
        
          intra_subnets = [
            {
              subnet_name           = "private-subnet01"
              subnet_ip_cidr        = "10.0.0.0/24"
              subnet_private_access = false
              subnet_region         = var.region
            }
          ]
        
          secondary_ranges = {
            private-subnet01 = [
              {
                range_name    = "private-subnet01-01"
                ip_cidr_range = var.ip_range_pods
              },
              {
                range_name    = "private-subnet01-02"
                ip_cidr_range = var.ip_range_services
              },
            ]
          }
        
          labels = var.labels
        }
        
        resource "google_storage_bucket" "gcs_starburst" {
          name          = var.name
          location      = "EU"
          force_destroy = var.force_destroy
        }
        
        module "gke-starburst" {
          source = "git@github.com:lucasberlang/gcp-gke.git?ref=v1.1.0"
        
          project_id              = var.project_id
          name                    = "starburst"
          regional                = true
          region                  = var.region
          network                 = module.network.network_name
          subnetwork              = "go-euw1-bt-stb-private-subnet01-dev"
          ip_range_pods           = "private-subnet01-01"
          ip_range_services       = "private-subnet01-02"
          enable_private_endpoint = false
          enable_private_nodes    = false
          master_ipv4_cidr_block  = "172.16.0.0/28"
          workload_identity       = false
          kubernetes_version      = var.kubernetes_version
          
          gce_persistent_disk_csi_driver = true
        
          master_authorized_networks = [
            {
              cidr_block   = module.network.intra_subnet_ips.0
              display_name = "VPC"
            },
            {
              cidr_block   = "0.0.0.0/0"
              display_name = "shell"
            }
          ]
        
          cluster_autoscaling = {
            enabled             = true,
            autoscaling_profile = "BALANCED",
            max_cpu_cores       = 300,
            max_memory_gb       = 940,
            min_cpu_cores       = 24,
            min_memory_gb       = 90,
          }
        
        
          node_pools = [
            {
              name         = "default-node-pool"
              machine_type = "e2-standard-16"
              auto_repair  = false
              auto_upgrade = false
            },
          ]
          
          node_labels = {
            "starburstpool" = "default-node-pool"
          }
        
          istio     = var.istio
          dns_cache = var.dns_cache
          labels    = var.labels
        }
        ```
         

        Lo único importante a tener en cuenta, es que vamos a desplegar una red con una única subred y que el cluster de GKE está habilitado con el autoescalado para poder incrementar el número de nodos cuando haya una carga de trabajo. Asimismo, es importante tener en cuenta que se ha añadido una etiqueta a todos los nodos que es `»starburstpool» = «default-node-pool»` para aislar el propio despliegue de Starburst del que más tarde haremos uso. Aparte de estos componentes también desplegamos una Cloud Storage para luego configurar el conector de Hive.

        Por otra parte, como hemos comentado, también haremos el despliegue de Grafana y Prometheus. Para ello haremos uso del provider de Helm y de Kubernetes de Terraform. 

        El despliegue de estos componentes lo tenemos en el archivo `helm.tf`:

        ```tf
        resource "kubernetes_namespace" "prometheus" {
          metadata {
            name = "prometheus"
          }
        }
        
        resource "kubernetes_namespace" "grafana" {
          metadata {
            name = "grafana"
          }
        }
        
        resource "helm_release" "grafana" {
          chart      = "grafana"
          name       = "grafana"
          namespace  = kubernetes_namespace.grafana.metadata.0.name
          repository = "https://grafana.github.io/helm-charts"
        
          values = [
            file("templates/grafana.yaml")
          ]
        }
        
        resource "kubernetes_secret" "grafana-secrets" {
          metadata {
            name      = "grafana-credentials"
            namespace = kubernetes_namespace.grafana.metadata.0.name
          }
          data = {
            adminUser     = "admin"
            adminPassword = "admin"
          }
        }
        
        resource "helm_release" "prometheus" {
          chart      = "prometheus"
          name       = "prometheus"
          namespace  = kubernetes_namespace.prometheus.metadata.0.name
          repository = "https://prometheus-community.github.io/helm-charts"
        
          values = [
            file("templates/prometheus.yaml")
          ]
        }
        ```
         

        Hay varias cosas que tenemos que tener en cuenta, estas son las configuraciones que hemos añadido en los values de cada chart. 

        Primero vamos con los valores de Prometheus que hemos configurado. Hemos añadido una configuración extra para que recoja las métricas de Starburst una vez que se levante. Esto lo hemos hecho en la siguiente parte de la configuración:

        ```yaml
        extraScrapeConfigs: |
          - job_name: starburst-monitor
            scrape_interval: 5s
            static_configs:
              - targets: 
                - 'prometheus-coordinator-starburst-enterprise.default.svc.cluster.local:8081'
                - 'prometheus-worker-starburst-enterprise.default.svc.cluster.local:8081'
            metrics_path: /metrics
            scheme: http
        ```
         

        Lo único a tener en cuenta son los targets que hemos añadido, que básicamente son los servicios tanto del Coordinator como de los Workers de Starburst para que recoja todas las métricas.

        En la parte de Grafana hemos añadido tanto la configuración de Prometheus, como un dashboard que hemos creado custom para Starburst. 

        La configuración que hemos añadida es la siguiente:

        ```yaml
        datasources:
         datasources.yaml:
           apiVersion: 1
           datasources:
           - name: Prometheus
             type: prometheus
             url: http://prometheus-server.prometheus.svc.cluster.local
             isDefault: true
        
        
        dashboards:
          default:
            Starburst-cluster:
              gnetId: 18767
              revision: 1
              datasource: Prometheus
        ```
         

        En la carpeta infra del repositorio de Github, podrás encontrar todo el código necesario para realizar dicho despliegue.

        Instalación y configuración de Starburst

        Una vez que tengamos toda la infraestructura levantada, vamos a proceder a desplegar Starburst en nuestro cluster de GKE. Para ello, vamos a desplegar estos componentes:

        • Postgres Database on Kubernetes
        • Hive Metastore Service
        • Starburst Enterprise

        El servicio de Hive Mestastore es necesario para configurar el conector de Hive para así poder acceder o escribir a los datos que se guardan en Google Cloud Storage. Como backend de nuestro servicio de Metastore, vamos a desplegar un base de datos PostgreSQL, para así poder guardar toda la información de la metadata en esta base de datos. Además tendremos que configurar el servicio de Hive para pasarle las credenciales de Google Cloud y que tenga permisos para poder leer y escribir de GCS. Por lo tanto, vamos a proceder primero a declarar algunas variables de entorno que necesitaremos para descargar los charts del repositorio privado de Starburst y algunas variables de configuración más que necesitaremos para realizar el despliegue.

        Esta serían las variables que vamos a necesitar en nuestro despliegue:

        ```bash
        export admin_usr=     # Choose an admin user name you will use to login to Starburst & Ranger. Do NOT use 'admin'
        export admin_pwd=     # Choose an admin password you will use to login to Starburst & Ranger. MUST be a minimum of 8 characters and contain at least one uppercase, lowercase and numeric value.
        
        export registry_pwd= #Credentials harbor registry
        export registry_usr= #Credentials harbor registry
        export starburst_license=starburstdata.license #License Starburst
        # Zone where the cluster will be deployed. e.g. us-east4-b
        export zone="europe-west1"
        # Google Cloud Project ID where the cluster is being deployed
        export google_cloud_project=
        # Google Service account name. The service account is used to access services like GCS and BigQuery, so you should ensure that it has the relevant permissions for these
        # Give your cluster a name
        export cluster_name=
        
        # These next values are automatically set based on your input values
        # We'll automatically get the domain for the zone you are selecting. Comment this out if you don't need DNS
        #export google_cloud_dns_zone_name=$(gcloud dns managed-zones describe ${google_cloud_dns_zone:?Zone not set} --project ${google_cloud_project_dns:?Project ID not set} | grep dnsName | awk '{ print $2 }' | sed 's/.$//g')
        
        # This is the public URL to access Starburst
        export starburst_url=${cluster_name:?Cluster Name not set}-starburst.${google_cloud_dns_zone_name}
        # This is the public URL to access Ranger
        export ranger_url=${cluster_name:?Cluster Name not set}-ranger.${google_cloud_dns_zone_name}
        
        # Insights DB details
        # These are the defaults if you choose to deploy your postgresDB to the K8s cluster
        # You can adjust these to connect to an external DB, but be advised that the nodes in the K8s cluster must have access to the URL
        export database_connection_url=jdbc:postgresql://postgresql:5432/insights
        export database_username=
        export database_password=
        
        # Data Products. Leave the password unset as below, if you are connecting directly to the coordinator on port 8080
        export data_products_enabled=true
        export data_products_jdbc_url=jdbc:trino://coordinator:8080
        export data_products_username=${admin_usr}
        export data_products_password=
        
        # Starburst Access Control
        export starburst_access_control_enabled=true
        export starburst_access_control_authorized_users=${admin_usr}
        
        # These last remaining values are static
        export xtra_args_hive="--set objectStorage.gs.cloudKeyFileSecret=service-account-key"
        export xtra_args_starburst="--values starburst.catalog.yaml"
        export xtra_args_ranger=""
        ```
         

        Una vez definidas nuestras variables de entorno procederemos a crearnos un secreto de Kubernetes para configurar las credenciales con las que Hive se va a conectar a GCS.

        ```bash
        kubectl create secret generic service-account-key --from-file key.json
        ```
         

        Para ello, como paso previo, nos hemos creado una service account con permisos en Cloud Storage y en Bigquery y nos hemos descargado las credenciales de esa service account. También como paso previo, añadiremos los repositorio de Helm con el siguiente comando:

        ```bash
        helm repo add --username ${registry_usr} --password ${registry_pwd} starburstdata https://harbor.starburstdata.net/chartrepo/starburstdata
        helm repo add bitnami https://charts.bitnami.com/bitnami
        ```
         

        Una vez que tenemos la configuración previa hecha, vamos a proceder a desplegar el servicio de PostgreSQL primero, y posteriormente, el Hive Metastore. Para ello haremos uso de Helm. Para el despliegue de PostgreSQL usaremos el siguiente comando:

        ```bash
        helm upgrade postgres bitnami/postgresql --install --values postgres.yaml \
            --version 12.1.6 \
            --set primary.nodeSelector.starburstpool=default-node-pool \
            --set readReplicas.nodeSelector.starburstpool=default-node-pool
        ```
         

        Hay varios factores a tener en cuenta en el comando anterior. El primero es que el despliegue de PostgreSQL lo haremos en los nodos que tengan el tag `starburstpool=default-node-pool`, que es nuestro worker pool por defecto. Usaremos la versión 12.1.6 de PostgreSQL y la configuración que hemos añadido en postgres es la siguiente:

        ```yaml
        fullnameOverride: postgresql
        
        global:
          postgresql:
            auth:
              database: postgres
              username: postgres
              postgresPassword: ****
          storageClass: "standard"
        primary:
          initdb:
            scripts:
              init.sql: |
                create database hive;
                create database ranger;
                create database insights;
                create database datacache;
        
        service:
          type: ClusterIP
        ``` 

        Esta información se encuentra en el archivo `postgres.yaml` y nos configurará el usuario y contraseña de PostgreSQL, y nos creará 4 bases de datos que usa internamente Starburst como backend. En nuestro caso, como podéis observar, hemos configurado el servicio de backend en el mismo cluster que la configuración de Starburst, pero esto se puede configurar fuera del cluster de Kubernetes para entornos productivos. Básicamente podríamos tener un servicio gestionado como es Cloud Sql para así evitar problemas en producción.

        Ahora vamos a proceder con el despliegue del servicio de Hive Metastore, esto lo haremos con el siguiente comando:

        ```bash
        helm upgrade hive starburstdata/starburst-hive --install --values hive.yaml \
            --set registryCredentials.username=${registry_usr:?Value not set} \
            --set registryCredentials.password=${registry_pwd:?Value not set} \
            --set nodeSelector.starburstpool=default-node-pool  \
            --set objectStorage.gs.cloudKeyFileSecret=service-account-key
        ``` 

        Aquí tenemos que tener en cuenta varias cosas importantes, la primera es que como en el servicio de PostgreSQL el despliegue se va a realizar en los nodos con el tag `starburstpool=default-node-pool`. El segundo punto importante es que hemos realizado la configuración de las credenciales de Google para que funcione el conector de hive, esto lo hemos realizado con el siguiente comando:

        `--set objectStorage.gs.cloudKeyFileSecret=service-account-key` 

        Con esta acción,  montamos el fichero de credenciales como un archivo en el despliegue de Hive para que tenga visibilidad en las credenciales. Los valores extras que hemos añadido a la configuración de hive se encuentran en el archivo `hive.yaml` y son los siguientes:

        ```yaml
        database:
          external:
            driver: org.postgresql.Driver
            jdbcUrl: jdbc:postgresql://postgresql:5432/hive
            user: #user postgres
            password: #password postgres
          type: external
        
        expose:
          type: clusterIp
        
        image:
          repository: harbor.starburstdata.net/starburstdata/hive
        
        registryCredentials:
          enabled: true
          registry: harbor.starburstdata.net/starburstdata
        ```
         

        Una vez que tenemos desplegado tanto el servicio de Postgres como el de Hive Metastore, podemos proceder a desplegar Starburst. Primero necesitaremos realizar una serie de pasos previos. El primero será crearnos un secreto de Kubernetes con la licencia de Starburst, el segundo será crearnos un secreto con las variables de entornos que hemos definido antes, esto lo haremos con un pequeño script para quitar complejidad y que nos coja las variables que ya hemos definido. 

        Con el siguiente comando procederemos a realizar los pasos anteriores:

        ```bash
        kubectl create secret generic starburst --from-file ${starburst_license}
        chmod 755 load_secrets.sh && . ./load_secrets.sh
        kubectl apply -f secrets.yaml
        ```
         

        Una vez que tenemos las configuraciones previas vamos a proceder a desplegar Starburst con el siguiente comando:

        ```bash
        helm upgrade starburst-enterprise starburstdata/starburst-enterprise --install --values starburst.yaml \
            --set sharedSecret="$(openssl rand 64 | base64)" \
            --set coordinator.resources.requests.memory=$(echo $(( $(kubectl get nodes --selector='starburstpool=default-node-pool' -o jsonpath='{.items[0].status.allocatable.memory}' | awk -F "Ki" '{ print $1 }')*10/100 ))Ki) \
            --set coordinator.resources.requests.cpu=$(echo $(( $(kubectl get nodes --selector='starburstpool=default-node-pool' -o jsonpath='{.items[0].status.allocatable.cpu}' | awk -F "m" '{ print $1 }')*10/100 ))m) \
            --set coordinator.resources.limits.memory=$(echo $(( $(kubectl get nodes --selector='starburstpool=default-node-pool' -o jsonpath='{.items[0].status.allocatable.memory}' | awk -F "Ki" '{ print $1 }')*10/100 ))Ki) \
            --set coordinator.resources.limits.cpu=$(echo $(( $(kubectl get nodes --selector='starburstpool=default-node-pool' -o jsonpath='{.items[0].status.allocatable.cpu}' | awk -F "m" '{ print $1 }')*10/100 ))m) \
            --set worker.resources.requests.memory=$(echo $(( $(kubectl get nodes --selector='starburstpool=default-node-pool' -o jsonpath='{.items[0].status.allocatable.memory}' | awk -F "Ki" '{ print $1 }') - 10500000 ))Ki) \
            --set worker.resources.requests.cpu=$(echo $(( $(kubectl get nodes --selector='starburstpool=default-node-pool' -o jsonpath='{.items[0].status.allocatable.cpu}' | awk -F "m" '{ print $1 }') - 3500 ))m) \
            --set worker.resources.limits.memory=$(echo $(( $(kubectl get nodes --selector='starburstpool=default-node-pool' -o jsonpath='{.items[0].status.allocatable.memory}' | awk -F "Ki" '{ print $1 }') - 10500000 ))Ki) \
            --set worker.resources.limits.cpu=$(echo $(( $(kubectl get nodes --selector='starburstpool=default-node-pool' -o jsonpath='{.items[0].status.allocatable.cpu}' | awk -F "m" '{ print $1 }') - 3500 ))m) \
            --set coordinator.nodeSelector.starburstpool=default-node-pool 
        ```
         

        Aquí como podéis observar, hay varias cosas a tener en cuenta. La primera es que todos los componentes de Starburst que se despliegan lo hacen en los nodos con el tag `starburstpool=default-node-pool`. Esto simplemente lo hemos hecho para quitar complejidad a la demo.  En entornos productivos, una buena práctica sería tener un nodepool para el Coordinator y otro nodepool para los Workers de Starburst.

        Otra cosa a tener en cuenta es la configuración de la memoria y cpu que se hace tanto en los Workers como en el Coordinator. Como buenas prácticas, Starburst recomienda que haya un pod worker por cada nodo que se despliega en nuestro cluster de Kubernetes. Para ello lo que hemos hecho es ajustar la memoria y cpu de nuestros pods al tamaño de máquina que tenemos. Por último están los valores de configuración que hemos utilizado en el despliegue de Starburst, estos se pueden encontrar en el archivo `starburst.yaml` y son los siguientes:

        ```yaml
        catalogs:
          hive: |
            connector.name=hive
            hive.security=starburst
            hive.metastore.uri=thrift://hive:9083
            hive.gcs.json-key-file-path=/gcs-keyfile/key.json
            hive.gcs.use-access-token=false
          postgres: |
            connector.name=postgresql
            connection-url=jdbc:postgresql://postgresql:5432/insights
            connection-user=******
            connection-password=******
          bigquery: |
              connector.name=bigquery
              bigquery.project-id=******
              bigquery.credentials-file=/gcs-keyfile/key.json
        prometheus:
          enabled: true
          agent:
            version: "0.16.1"
            port: 8081
            config: "/etc/starburst/telemetry/prometheus.yaml"
          rules:
            - pattern: trino.execution<name=QueryManager><>(running_queries|queued_queries)
              name: $1
              attrNameSnakeCase: true
              type: GAUGE
            - pattern: 'trino.execution<name=QueryManager><>FailedQueries\.TotalCount'
              name: 'starburst_failed_queries'
              type: COUNTER
            - pattern: 'trino.execution<name=QueryManager><>(running_queries)'
              name: 'starburst_running_queries'
            - pattern: 'trino.execution<name=QueryManager><>StartedQueries\.FiveMinute\.Count'
              name: 'starburst_started_queries'
            - pattern: 'trino.execution<name=SqlTaskManager><>InputPositions\.FiveMinute\.Count'
              name: 'starburst_input_rows'
            - pattern: 'trino.execution<name=SqlTaskManager><>InputDataSize\.FiveMinute\.Count'
              name: 'starburst_input_data_bytes'
            - pattern: 'trino.execution<name=QueryManager><>UserErrorFailures\.FiveMinute\.Count'
              name: 'starburst_failed_queries_user'
            - pattern: 'trino.execution<name=QueryManager><>ExecutionTime\.FiveMinutes\.P50'
              name: 'starburst_latency_p50'
            - pattern: 'trino.execution<name=QueryManager><>WallInputBytesRate\.FiveMinutes\.P90'
              name: 'starburst_latency_p90'
            - pattern: 'trino.failuredetector<name=HeartbeatFailureDetector><>ActiveCount'
              name: 'starburst_active_node'
            - pattern: 'trino.memory<type=ClusterMemoryPool, name=general><>FreeDistributedBytes'
              name: 'starburst_free_memory_pool'
            - pattern: 'trino.memory<name=ClusterMemoryManager><>QueriesKilledDueToOutOfMemory'
              name: 'starburst_queries_killed_due_to_out_of_memory'
            - pattern: 'java.lang<type=Memory><HeapMemoryUsage>committed'
              name: 'starburst_heap_size_usage'
            - pattern: 'java.lang<type=Threading><>ThreadCount'
              name: 'starburst_thread_count'
        coordinator:
          envFrom:
          - secretRef:
              name: environment-vars
          additionalProperties: |
            starburst.data-product.enabled=${ENV:data_products_enabled}
            data-product.starburst-jdbc-url=${ENV:data_products_jdbc_url}
            data-product.starburst-user=${ENV:data_products_username}
            data-product.starburst-password=
            query.max-memory=1PB
            starburst.access-control.enabled=${ENV:starburst_access_control_enabled}
            starburst.access-control.authorized-users=${ENV:starburst_access_control_authorized_users}
          etcFiles:
            properties:
              config.properties: |
                coordinator=true
                node-scheduler.include-coordinator=false
                http-server.http.port=8080
                discovery-server.enabled=true
                discovery.uri=http://localhost:8080
                usage-metrics.cluster-usage-resource.enabled=true
                http-server.authentication.allow-insecure-over-http=true
                web-ui.enabled=true
                http-server.process-forwarded=true
                insights.persistence-enabled=true
                insights.metrics-persistence-enabled=true
                insights.jdbc.url=${ENV:database_connection_url}
                insights.jdbc.user=${ENV:database_username}
                insights.jdbc.password=${ENV:database_password}
              password-authenticator.properties: |
                password-authenticator.name=file
          nodeSelector:
            starburstpool: default-node-pool
          resources:
            limits:
              cpu: 2
              memory: 12Gi
            requests:
              cpu: 2
              memory: 12Gi
        
        expose:
          type: clusterIp
          ingress:
            serviceName: starburst
            servicePort: 8080
            host: 
            path: "/"
            pathType: Prefix
            tls:
              enabled: true
              secretName: tls-secret-starburst
            annotations:
              kubernetes.io/ingress.class: nginx
              cert-manager.io/cluster-issuer: letsencrypt
        
        registryCredentials:
          enabled: true
          password: ******
          registry: harbor.starburstdata.net/starburstdata
          username: ******
        
        starburstPlatformLicense: starburst
        
        userDatabase:
          enabled: true
          users:
          - password: ******
            username: ******
        
        worker:
          envFrom:
          - secretRef:
              name: environment-vars
          autoscaling:
            enabled: true
            maxReplicas: 10
            minReplicas: 3
            targetCPUUtilizationPercentage: 40
          deploymentTerminationGracePeriodSeconds: 30
          nodeSelector:
            starburstpool: default-node-pool
          resources:
            limits:
              cpu: 8
              memory: 40Gi
            requests:
              cpu: 8
              memory: 40Gi
          starburstWorkerShutdownGracePeriodSeconds: 120
          tolerations:
            - key: "kubernetes.azure.com/scalesetpriority"
              operator: "Exists"
              effect: "NoSchedule"
        
        additionalVolumes:
          - path: /gcs-keyfile/key.json
            subPath: key.json
            volume:
              configMap:
                name: "sa-key"
        ```
         

        En esta configuración hay varios valores a tener en cuenta, como son catalogs, prometheus, worker y additionalVolumes.

        Vamos a empezar explicando la parte de catalogs. Para los que no lo sepan, un catálogo en Starburst es la configuración que permite acceder a unas fuentes de datos determinadas. Cada clúster de Starburst puede tener configurados múltiples catálogos y, por tanto, permitir el acceso a diversas fuentes de datos. En nuestro caso hemos definido el catálogo de Hive, PostgreSQL y Bigquery para poder acceder a dichas fuentes de datos:

        ```yaml
        catalogs:
          hive: |
            connector.name=hive
            hive.security=starburst
            hive.metastore.uri=thrift://hive:9083
            hive.gcs.json-key-file-path=/gcs-keyfile/key.json
            hive.gcs.use-access-token=false
          postgres: |
            connector.name=postgresql
            connection-url=jdbc:postgresql://postgresql:5432/insights
            connection-user=******
            connection-password=******
          bigquery: |
              connector.name=bigquery
              bigquery.project-id=******
              bigquery.credentials-file=/gcs-keyfile/key.json
        ```
         

        La segunda configuración a tener en cuenta es la de Prometheus, esto lo realizamos para exponer ciertas métricas a Prometheus y poder sacar información relevante en un dashboard de Grafana. Para ello tenemos la siguiente configuración:

        ```yaml
        prometheus:
          enabled: true
          agent:
            version: "0.16.1"
            port: 8081
            config: "/etc/starburst/telemetry/prometheus.yaml"
          rules:
            - pattern: trino.execution<name=QueryManager><>(running_queries|queued_queries)
              name: $1
              attrNameSnakeCase: true
              type: GAUGE
            - pattern: 'trino.execution<name=QueryManager><>FailedQueries\.TotalCount'
              name: 'starburst_failed_queries'
              type: COUNTER
            - pattern: 'trino.execution<name=QueryManager><>(running_queries)'
              name: 'starburst_running_queries'
            - pattern: 'trino.execution<name=QueryManager><>StartedQueries\.FiveMinute\.Count'
              name: 'starburst_started_queries'
            - pattern: 'trino.execution<name=SqlTaskManager><>InputPositions\.FiveMinute\.Count'
              name: 'starburst_input_rows'
            - pattern: 'trino.execution<name=SqlTaskManager><>InputDataSize\.FiveMinute\.Count'
              name: 'starburst_input_data_bytes'
            - pattern: 'trino.execution<name=QueryManager><>UserErrorFailures\.FiveMinute\.Count'
              name: 'starburst_failed_queries_user'
            - pattern: 'trino.execution<name=QueryManager><>ExecutionTime\.FiveMinutes\.P50'
              name: 'starburst_latency_p50'
            - pattern: 'trino.execution<name=QueryManager><>WallInputBytesRate\.FiveMinutes\.P90'
              name: 'starburst_latency_p90'
            - pattern: 'trino.failuredetector<name=HeartbeatFailureDetector><>ActiveCount'
              name: 'starburst_active_node'
            - pattern: 'trino.memory<type=ClusterMemoryPool, name=general><>FreeDistributedBytes'
              name: 'starburst_free_memory_pool'
            - pattern: 'trino.memory<name=ClusterMemoryManager><>QueriesKilledDueToOutOfMemory'
              name: 'starburst_queries_killed_due_to_out_of_memory'
            - pattern: 'java.lang<type=Memory><HeapMemoryUsage>committed'
              name: 'starburst_heap_size_usage'
            - pattern: 'java.lang<type=Threading><>ThreadCount'
              name: 'starburst_thread_count'
        ```
         

        En la configuración de los workers, vamos a activar el autoescalado de estos pods. Para ello vamos a realizar una configuración para que haya un mínimo de 3 pods workers que se traducirán en 3 nodos en nuestro cluster de GKE y un máximo de 10 pods. Para el autoescalado vamos a usar la métrica de consumo de CPU. 

        Los valores son los siguientes:

        ```yaml
        worker:
          envFrom:
          - secretRef:
              name: environment-vars
          autoscaling:
            enabled: true
            maxReplicas: 10
            minReplicas: 3
            targetCPUUtilizationPercentage: 40
        ```
         

        Por último, añadiremos un volumen adicional a nuestro despliegue para poder montar las credenciales de Google cloud tanto en el coordinator como en los workers.

        Esto lo haremos de la siguiente forma:

        ```yaml
        additionalVolumes:
          - path: /gcs-keyfile/key.json
            subPath: key.json
            volume:
              configMap:
                name: "sa-key"
        ```
         

        Con todos estos pasos, tendríamos nuestro cluster de Starburst ya operativo.

        Consultas en GCP y autoescalado de Starburst

        Una vez realizado el levantamiento del cluster de Starburst, vamos a realizar algunas consultas para probar su rendimiento y funcionamiento. Para ello vamos a realizar consultas de lectura en el esquema de TPCH[13] y después vamos a escribir la salida de estas consultas en el bucket de Google que hemos creado en los pasos de despliegue. 

        Las consultas que vamos a ejecutar se encuentran en la carpeta de queries en los archivos `tpch.sql` y `gcs_storage.sql`.

        Para lanzar las consultas será tan sencillo como irnos al apartado de consultas de la interfaz web y ejecutar las primeras consultas del archivo `tpch.sql`:

        ```sql
         CREATE SCHEMA hive.logistic WITH (location = 'gs://starburst-bluetab-test/logistic');
        
        CREATE VIEW "hive"."logistic"."shipping_priority" SECURITY DEFINER AS
        SELECT
          l.orderkey
        , SUM((l.extendedprice * (1 - l.discount))) revenue
        , o.orderdate
        , o.shippriority
        FROM
          tpch.tiny.customer c
        , tpch.tiny.orders o
        , tpch.tiny.lineitem l
        WHERE ((c.mktsegment = 'BUILDING') AND (c.custkey = o.custkey) AND (l.orderkey = o.orderkey))
        GROUP BY l.orderkey, o.orderdate, o.shippriority
        ORDER BY revenue DESC, o.orderdate ASC;
        
        
        CREATE VIEW "hive"."logistic"."minimum_cost_supplier" SECURITY DEFINER AS
        SELECT
          s.acctbal
        , s.name SupplierName
        , n.name Nation
        , p.partkey
        , p.mfgr
        , s.address
        , s.phone
        , s.comment
        FROM
          tpch.tiny.part p
        , tpch.tiny.supplier s
        , tpch.tiny.partsupp ps
        , tpch.tiny.nation n
        , tpch.tiny.region r
        WHERE ((p.partkey = ps.partkey) AND (s.suppkey = ps.suppkey) AND (p.size = 15) AND (p.type LIKE '%BRASS') AND (s.nationkey = n.nationkey) AND (n.regionkey = r.regionkey) AND (r.name = 'EUROPE') AND (ps.supplycost = (SELECT MIN(ps.supplycost)
        FROM
          tpch.tiny.partsupp ps
        , tpch.tiny.supplier s
        , tpch.tiny.nation n
        , tpch.tiny.region r
        WHERE ((p.partkey = ps.partkey) AND (s.suppkey = ps.suppkey) AND (s.nationkey = n.nationkey) AND (n.regionkey = r.regionkey) AND (r.name = 'EUROPE'))
        )))
        ORDER BY s.acctbal DESC, n.name ASC, s.name ASC, p.partkey ASC;
        
        
        
        select
          cst.name as CustomerName,
          cst.address,
          cst.phone,
          cst.nationkey,
          cst.acctbal as BookedOrders,
          cst.mktsegment,
          nat.name as Nation,
          reg.name as Region
        from tpch.sf1.customer as cst
        join tpch.sf1.nation as nat on nat.nationkey = cst.nationkey
        join tpch.sf1.region as reg on reg.regionkey = nat.regionkey
        where reg.regionkey = 1;
        
        select
          nat.name as Nation,
          avg(cst.acctbal) as average_booking
        from tpch.sf100.customer as cst
        join tpch.sf100.nation as nat on nat.nationkey = cst.nationkey
        join tpch.sf100.region as reg on reg.regionkey = nat.regionkey
        where reg.regionkey = 1
        group by nat.name;
        ```
         

        En estas pruebas crearemos una serie de vistas y haremos unos selects con varios cruces sobre las tablas de customer(15000000 rows), nation(25 rows) y region(5 rows) del esquema sf100 para comprobar que todo funciona correctamente y ver que tenemos nuestra plataforma operativa. Una vez comprobado que todo es correcto, probaremos a escribir algunos resultados en el bucket que hemos creado.

        Para ello lanzaremos las consultas que se encuentran en el archivo `gcs_storage.sql`:

        {"type":"elementor","siteurl":"https://bluetab.net/es/wp-json/","elements":[{"id":"1a82503","elType":"widget","isInner":false,"isLocked":false,"settings":{"code_language":"python","code_block":"```sql\n CREATE SCHEMA hive.logistic WITH (location = 'gs://starburst-bluetab-test/logistic');\n\nCREATE VIEW \"hive\".\"logistic\".\"shipping_priority\" SECURITY DEFINER AS\nSELECT\n  l.orderkey\n, SUM((l.extendedprice * (1 - l.discount))) revenue\n, o.orderdate\n, o.shippriority\nFROM\n  tpch.tiny.customer c\n, tpch.tiny.orders o\n, tpch.tiny.lineitem l\nWHERE ((c.mktsegment = 'BUILDING') AND (c.custkey = o.custkey) AND (l.orderkey = o.orderkey))\nGROUP BY l.orderkey, o.orderdate, o.shippriority\nORDER BY revenue DESC, o.orderdate ASC;\n\n\nCREATE VIEW \"hive\".\"logistic\".\"minimum_cost_supplier\" SECURITY DEFINER AS\nSELECT\n  s.acctbal\n, s.name SupplierName\n, n.name Nation\n, p.partkey\n, p.mfgr\n, s.address\n, s.phone\n, s.comment\nFROM\n  tpch.tiny.part p\n, tpch.tiny.supplier s\n, tpch.tiny.partsupp ps\n, tpch.tiny.nation n\n, tpch.tiny.region r\nWHERE ((p.partkey = ps.partkey) AND (s.suppkey = ps.suppkey) AND (p.size = 15) AND (p.type LIKE '%BRASS') AND (s.nationkey = n.nationkey) AND (n.regionkey = r.regionkey) AND (r.name = 'EUROPE') AND (ps.supplycost = (SELECT MIN(ps.supplycost)\nFROM\n  tpch.tiny.partsupp ps\n, tpch.tiny.supplier s\n, tpch.tiny.nation n\n, tpch.tiny.region r\nWHERE ((p.partkey = ps.partkey) AND (s.suppkey = ps.suppkey) AND (s.nationkey = n.nationkey) AND (n.regionkey = r.regionkey) AND (r.name = 'EUROPE'))\n)))\nORDER BY s.acctbal DESC, n.name ASC, s.name ASC, p.partkey ASC;\n\n\n\nselect\n  cst.name as CustomerName,\n  cst.address,\n  cst.phone,\n  cst.nationkey,\n  cst.acctbal as BookedOrders,\n  cst.mktsegment,\n  nat.name as Nation,\n  reg.name as Region\nfrom tpch.sf1.customer as cst\njoin tpch.sf1.nation as nat on nat.nationkey = cst.nationkey\njoin tpch.sf1.region as reg on reg.regionkey = nat.regionkey\nwhere reg.regionkey = 1;\n\nselect\n  nat.name as Nation,\n  avg(cst.acctbal) as average_booking\nfrom tpch.sf100.customer as cst\njoin tpch.sf100.nation as nat on nat.nationkey = cst.nationkey\njoin tpch.sf100.region as reg on reg.regionkey = nat.regionkey\nwhere reg.regionkey = 1\ngroup by nat.name;\n```\n","_title":"","_margin":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_margin_tablet":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_margin_mobile":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_padding":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_padding_tablet":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_padding_mobile":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_element_width":"","_element_width_tablet":"","_element_width_mobile":"","_element_custom_width":{"unit":"%","size":"","sizes":[]},"_element_custom_width_tablet":{"unit":"px","size":"","sizes":[]},"_element_custom_width_mobile":{"unit":"px","size":"","sizes":[]},"_element_vertical_align":"","_element_vertical_align_tablet":"","_element_vertical_align_mobile":"","_position":"","_offset_orientation_h":"start","_offset_x":{"unit":"px","size":"0","sizes":[]},"_offset_x_tablet":{"unit":"px","size":"","sizes":[]},"_offset_x_mobile":{"unit":"px","size":"","sizes":[]},"_offset_x_end":{"unit":"px","size":"0","sizes":[]},"_offset_x_end_tablet":{"unit":"px","size":"","sizes":[]},"_offset_x_end_mobile":{"unit":"px","size":"","sizes":[]},"_offset_orientation_v":"start","_offset_y":{"unit":"px","size":"0","sizes":[]},"_offset_y_tablet":{"unit":"px","size":"","sizes":[]},"_offset_y_mobile":{"unit":"px","size":"","sizes":[]},"_offset_y_end":{"unit":"px","size":"0","sizes":[]},"_offset_y_end_tablet":{"unit":"px","size":"","sizes":[]},"_offset_y_end_mobile":{"unit":"px","size":"","sizes":[]},"_z_index":"","_z_index_tablet":"","_z_index_mobile":"","_element_id":"","_css_classes":"","motion_fx_motion_fx_scrolling":"","motion_fx_translateY_effect":"","motion_fx_translateY_direction":"","motion_fx_translateY_speed":{"unit":"px","size":4,"sizes":[]},"motion_fx_translateY_affectedRange":{"unit":"%","size":"","sizes":{"start":0,"end":100}},"motion_fx_translateX_effect":"","motion_fx_translateX_direction":"","motion_fx_translateX_speed":{"unit":"px","size":4,"sizes":[]},"motion_fx_translateX_affectedRange":{"unit":"%","size":"","sizes":{"start":0,"end":100}},"motion_fx_opacity_effect":"","motion_fx_opacity_direction":"out-in","motion_fx_opacity_level":{"unit":"px","size":10,"sizes":[]},"motion_fx_opacity_range":{"unit":"%","size":"","sizes":{"start":20,"end":80}},"motion_fx_blur_effect":"","motion_fx_blur_direction":"out-in","motion_fx_blur_level":{"unit":"px","size":7,"sizes":[]},"motion_fx_blur_range":{"unit":"%","size":"","sizes":{"start":20,"end":80}},"motion_fx_rotateZ_effect":"","motion_fx_rotateZ_direction":"","motion_fx_rotateZ_speed":{"unit":"px","size":1,"sizes":[]},"motion_fx_rotateZ_affectedRange":{"unit":"%","size":"","sizes":{"start":0,"end":100}},"motion_fx_scale_effect":"","motion_fx_scale_direction":"out-in","motion_fx_scale_speed":{"unit":"px","size":4,"sizes":[]},"motion_fx_scale_range":{"unit":"%","size":"","sizes":{"start":20,"end":80}},"motion_fx_transform_origin_x":"center","motion_fx_transform_origin_y":"center","motion_fx_devices":["desktop","tablet","mobile"],"motion_fx_range":"","motion_fx_motion_fx_mouse":"","motion_fx_mouseTrack_effect":"","motion_fx_mouseTrack_direction":"","motion_fx_mouseTrack_speed":{"unit":"px","size":1,"sizes":[]},"motion_fx_tilt_effect":"","motion_fx_tilt_direction":"","motion_fx_tilt_speed":{"unit":"px","size":4,"sizes":[]},"sticky":"","sticky_on":["desktop","tablet","mobile"],"sticky_offset":0,"sticky_offset_tablet":"","sticky_offset_mobile":"","sticky_effects_offset":0,"sticky_effects_offset_tablet":"","sticky_effects_offset_mobile":"","sticky_parent":"","_animation":"","_animation_tablet":"","_animation_mobile":"","animation_duration":"","_animation_delay":"","_transform_rotate_popover":"","_transform_rotateZ_effect":{"unit":"px","size":"","sizes":[]},"_transform_rotateZ_effect_tablet":{"unit":"deg","size":"","sizes":[]},"_transform_rotateZ_effect_mobile":{"unit":"deg","size":"","sizes":[]},"_transform_rotate_3d":"","_transform_rotateX_effect":{"unit":"px","size":"","sizes":[]},"_transform_rotateX_effect_tablet":{"unit":"deg","size":"","sizes":[]},"_transform_rotateX_effect_mobile":{"unit":"deg","size":"","sizes":[]},"_transform_rotateY_effect":{"unit":"px","size":"","sizes":[]},"_transform_rotateY_effect_tablet":{"unit":"deg","size":"","sizes":[]},"_transform_rotateY_effect_mobile":{"unit":"deg","size":"","sizes":[]},"_transform_perspective_effect":{"unit":"px","size":"","sizes":[]},"_transform_perspective_effect_tablet":{"unit":"px","size":"","sizes":[]},"_transform_perspective_effect_mobile":{"unit":"px","size":"","sizes":[]},"_transform_translate_popover":"","_transform_translateX_effect":{"unit":"px","size":"","sizes":[]},"_transform_translateX_effect_tablet":{"unit":"px","size":"","sizes":[]},"_transform_translateX_effect_mobile":{"unit":"px","size":"","sizes":[]},"_transform_translateY_effect":{"unit":"px","size":"","sizes":[]},"_transform_translateY_effect_tablet":{"unit":"px","size":"","sizes":[]},"_transform_translateY_effect_mobile":{"unit":"px","size":"","sizes":[]},"_transform_scale_popover":"","_transform_keep_proportions":"yes","_transform_scale_effect":{"unit":"px","size":"","sizes":[]},"_transform_scale_effect_tablet":{"unit":"px","size":"","sizes":[]},"_transform_scale_effect_mobile":{"unit":"px","size":"","sizes":[]},"_transform_scaleX_effect":{"unit":"px","size":"","sizes":[]},"_transform_scaleX_effect_tablet":{"unit":"px","size":"","sizes":[]},"_transform_scaleX_effect_mobile":{"unit":"px","size":"","sizes":[]},"_transform_scaleY_effect":{"unit":"px","size":"","sizes":[]},"_transform_scaleY_effect_tablet":{"unit":"px","size":"","sizes":[]},"_transform_scaleY_effect_mobile":{"unit":"px","size":"","sizes":[]},"_transform_skew_popover":"","_transform_skewX_effect":{"unit":"px","size":"","sizes":[]},"_transform_skewX_effect_tablet":{"unit":"deg","size":"","sizes":[]},"_transform_skewX_effect_mobile":{"unit":"deg","size":"","sizes":[]},"_transform_skewY_effect":{"unit":"px","size":"","sizes":[]},"_transform_skewY_effect_tablet":{"unit":"deg","size":"","sizes":[]},"_transform_skewY_effect_mobile":{"unit":"deg","size":"","sizes":[]},"_transform_flipX_effect":"","_transform_flipY_effect":"","_transform_rotate_popover_hover":"","_transform_rotateZ_effect_hover":{"unit":"px","size":"","sizes":[]},"_transform_rotateZ_effect_hover_tablet":{"unit":"deg","size":"","sizes":[]},"_transform_rotateZ_effect_hover_mobile":{"unit":"deg","size":"","sizes":[]},"_transform_rotate_3d_hover":"","_transform_rotateX_effect_hover":{"unit":"px","size":"","sizes":[]},"_transform_rotateX_effect_hover_tablet":{"unit":"deg","size":"","sizes":[]},"_transform_rotateX_effect_hover_mobile":{"unit":"deg","size":"","sizes":[]},"_transform_rotateY_effect_hover":{"unit":"px","size":"","sizes":[]},"_transform_rotateY_effect_hover_tablet":{"unit":"deg","size":"","sizes":[]},"_transform_rotateY_effect_hover_mobile":{"unit":"deg","size":"","sizes":[]},"_transform_perspective_effect_hover":{"unit":"px","size":"","sizes":[]},"_transform_perspective_effect_hover_tablet":{"unit":"px","size":"","sizes":[]},"_transform_perspective_effect_hover_mobile":{"unit":"px","size":"","sizes":[]},"_transform_translate_popover_hover":"","_transform_translateX_effect_hover":{"unit":"px","size":"","sizes":[]},"_transform_translateX_effect_hover_tablet":{"unit":"px","size":"","sizes":[]},"_transform_translateX_effect_hover_mobile":{"unit":"px","size":"","sizes":[]},"_transform_translateY_effect_hover":{"unit":"px","size":"","sizes":[]},"_transform_translateY_effect_hover_tablet":{"unit":"px","size":"","sizes":[]},"_transform_translateY_effect_hover_mobile":{"unit":"px","size":"","sizes":[]},"_transform_scale_popover_hover":"","_transform_keep_proportions_hover":"yes","_transform_scale_effect_hover":{"unit":"px","size":"","sizes":[]},"_transform_scale_effect_hover_tablet":{"unit":"px","size":"","sizes":[]},"_transform_scale_effect_hover_mobile":{"unit":"px","size":"","sizes":[]},"_transform_scaleX_effect_hover":{"unit":"px","size":"","sizes":[]},"_transform_scaleX_effect_hover_tablet":{"unit":"px","size":"","sizes":[]},"_transform_scaleX_effect_hover_mobile":{"unit":"px","size":"","sizes":[]},"_transform_scaleY_effect_hover":{"unit":"px","size":"","sizes":[]},"_transform_scaleY_effect_hover_tablet":{"unit":"px","size":"","sizes":[]},"_transform_scaleY_effect_hover_mobile":{"unit":"px","size":"","sizes":[]},"_transform_skew_popover_hover":"","_transform_skewX_effect_hover":{"unit":"px","size":"","sizes":[]},"_transform_skewX_effect_hover_tablet":{"unit":"deg","size":"","sizes":[]},"_transform_skewX_effect_hover_mobile":{"unit":"deg","size":"","sizes":[]},"_transform_skewY_effect_hover":{"unit":"px","size":"","sizes":[]},"_transform_skewY_effect_hover_tablet":{"unit":"deg","size":"","sizes":[]},"_transform_skewY_effect_hover_mobile":{"unit":"deg","size":"","sizes":[]},"_transform_flipX_effect_hover":"","_transform_flipY_effect_hover":"","_transform_transition_hover":{"unit":"px","size":"","sizes":[]},"motion_fx_transform_x_anchor_point":"","motion_fx_transform_x_anchor_point_tablet":"","motion_fx_transform_x_anchor_point_mobile":"","motion_fx_transform_y_anchor_point":"","motion_fx_transform_y_anchor_point_tablet":"","motion_fx_transform_y_anchor_point_mobile":"","_background_background":"","_background_color":"","_background_color_stop":{"unit":"%","size":0,"sizes":[]},"_background_color_b":"#f2295b","_background_color_b_stop":{"unit":"%","size":100,"sizes":[]},"_background_gradient_type":"linear","_background_gradient_angle":{"unit":"deg","size":180,"sizes":[]},"_background_gradient_position":"center center","_background_image":{"url":"","id":"","size":""},"_background_image_tablet":{"url":"","id":"","size":""},"_background_image_mobile":{"url":"","id":"","size":""},"_background_position":"","_background_position_tablet":"","_background_position_mobile":"","_background_xpos":{"unit":"px","size":0,"sizes":[]},"_background_xpos_tablet":{"unit":"px","size":0,"sizes":[]},"_background_xpos_mobile":{"unit":"px","size":0,"sizes":[]},"_background_ypos":{"unit":"px","size":0,"sizes":[]},"_background_ypos_tablet":{"unit":"px","size":0,"sizes":[]},"_background_ypos_mobile":{"unit":"px","size":0,"sizes":[]},"_background_attachment":"","_background_repeat":"","_background_repeat_tablet":"","_background_repeat_mobile":"","_background_size":"","_background_size_tablet":"","_background_size_mobile":"","_background_bg_width":{"unit":"%","size":100,"sizes":[]},"_background_bg_width_tablet":{"unit":"px","size":"","sizes":[]},"_background_bg_width_mobile":{"unit":"px","size":"","sizes":[]},"_background_video_link":"","_background_video_start":"","_background_video_end":"","_background_play_once":"","_background_play_on_mobile":"","_background_privacy_mode":"","_background_video_fallback":{"url":"","id":"","size":""},"_background_slideshow_gallery":[],"_background_slideshow_loop":"yes","_background_slideshow_slide_duration":5000,"_background_slideshow_slide_transition":"fade","_background_slideshow_transition_duration":500,"_background_slideshow_background_size":"","_background_slideshow_background_size_tablet":"","_background_slideshow_background_size_mobile":"","_background_slideshow_background_position":"","_background_slideshow_background_position_tablet":"","_background_slideshow_background_position_mobile":"","_background_slideshow_lazyload":"","_background_slideshow_ken_burns":"","_background_slideshow_ken_burns_zoom_direction":"in","_background_hover_background":"","_background_hover_color":"","_background_hover_color_stop":{"unit":"%","size":0,"sizes":[]},"_background_hover_color_b":"#f2295b","_background_hover_color_b_stop":{"unit":"%","size":100,"sizes":[]},"_background_hover_gradient_type":"linear","_background_hover_gradient_angle":{"unit":"deg","size":180,"sizes":[]},"_background_hover_gradient_position":"center center","_background_hover_image":{"url":"","id":"","size":""},"_background_hover_image_tablet":{"url":"","id":"","size":""},"_background_hover_image_mobile":{"url":"","id":"","size":""},"_background_hover_position":"","_background_hover_position_tablet":"","_background_hover_position_mobile":"","_background_hover_xpos":{"unit":"px","size":0,"sizes":[]},"_background_hover_xpos_tablet":{"unit":"px","size":0,"sizes":[]},"_background_hover_xpos_mobile":{"unit":"px","size":0,"sizes":[]},"_background_hover_ypos":{"unit":"px","size":0,"sizes":[]},"_background_hover_ypos_tablet":{"unit":"px","size":0,"sizes":[]},"_background_hover_ypos_mobile":{"unit":"px","size":0,"sizes":[]},"_background_hover_attachment":"","_background_hover_repeat":"","_background_hover_repeat_tablet":"","_background_hover_repeat_mobile":"","_background_hover_size":"","_background_hover_size_tablet":"","_background_hover_size_mobile":"","_background_hover_bg_width":{"unit":"%","size":100,"sizes":[]},"_background_hover_bg_width_tablet":{"unit":"px","size":"","sizes":[]},"_background_hover_bg_width_mobile":{"unit":"px","size":"","sizes":[]},"_background_hover_video_link":"","_background_hover_video_start":"","_background_hover_video_end":"","_background_hover_play_once":"","_background_hover_play_on_mobile":"","_background_hover_privacy_mode":"","_background_hover_video_fallback":{"url":"","id":"","size":""},"_background_hover_slideshow_gallery":[],"_background_hover_slideshow_loop":"yes","_background_hover_slideshow_slide_duration":5000,"_background_hover_slideshow_slide_transition":"fade","_background_hover_slideshow_transition_duration":500,"_background_hover_slideshow_background_size":"","_background_hover_slideshow_background_size_tablet":"","_background_hover_slideshow_background_size_mobile":"","_background_hover_slideshow_background_position":"","_background_hover_slideshow_background_position_tablet":"","_background_hover_slideshow_background_position_mobile":"","_background_hover_slideshow_lazyload":"","_background_hover_slideshow_ken_burns":"","_background_hover_slideshow_ken_burns_zoom_direction":"in","_background_hover_transition":{"unit":"px","size":"","sizes":[]},"_border_border":"","_border_width":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_border_width_tablet":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_border_width_mobile":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_border_color":"","_border_radius":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_border_radius_tablet":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_border_radius_mobile":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_box_shadow_box_shadow_type":"","_box_shadow_box_shadow":{"horizontal":0,"vertical":0,"blur":10,"spread":0,"color":"rgba(0,0,0,0.5)"},"_box_shadow_box_shadow_position":" ","_border_hover_border":"","_border_hover_width":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_border_hover_width_tablet":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_border_hover_width_mobile":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_border_hover_color":"","_border_radius_hover":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_border_radius_hover_tablet":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_border_radius_hover_mobile":{"unit":"px","top":"","right":"","bottom":"","left":"","isLinked":true},"_box_shadow_hover_box_shadow_type":"","_box_shadow_hover_box_shadow":{"horizontal":0,"vertical":0,"blur":10,"spread":0,"color":"rgba(0,0,0,0.5)"},"_box_shadow_hover_box_shadow_position":" ","_border_hover_transition":{"unit":"px","size":"","sizes":[]},"_mask_switch":"","_mask_shape":"circle","_mask_image":{"url":"","id":"","size":""},"_mask_notice":"","_mask_size":"contain","_mask_size_tablet":"","_mask_size_mobile":"","_mask_size_scale":{"unit":"%","size":100,"sizes":[]},"_mask_size_scale_tablet":{"unit":"px","size":"","sizes":[]},"_mask_size_scale_mobile":{"unit":"px","size":"","sizes":[]},"_mask_position":"center center","_mask_position_tablet":"","_mask_position_mobile":"","_mask_position_x":{"unit":"%","size":0,"sizes":[]},"_mask_position_x_tablet":{"unit":"px","size":"","sizes":[]},"_mask_position_x_mobile":{"unit":"px","size":"","sizes":[]},"_mask_position_y":{"unit":"%","size":0,"sizes":[]},"_mask_position_y_tablet":{"unit":"px","size":"","sizes":[]},"_mask_position_y_mobile":{"unit":"px","size":"","sizes":[]},"_mask_repeat":"no-repeat","_mask_repeat_tablet":"","_mask_repeat_mobile":"","hide_desktop":"","hide_tablet":"","hide_mobile":"","_attributes":"","custom_css":""},"defaultEditSettings":{"defaultEditRoute":"content"},"elements":[],"widgetType":"elementor-syntax-highlighter","editSettings":{"defaultEditRoute":"content","panel":{"activeTab":"content","activeSection":"content_section"}},"htmlCache":"\t\t<div class=\"elementor-widget-container\">\n\t\t\t<pre><code class='language-python'>```sql\n CREATE SCHEMA hive.logistic WITH (location = 'gs://starburst-bluetab-test/logistic');\n\nCREATE VIEW &quot;hive&quot;.&quot;logistic&quot;.&quot;shipping_priority&quot; SECURITY DEFINER AS\nSELECT\n  l.orderkey\n, SUM((l.extendedprice * (1 - l.discount))) revenue\n, o.orderdate\n, o.shippriority\nFROM\n  tpch.tiny.customer c\n, tpch.tiny.orders o\n, tpch.tiny.lineitem l\nWHERE ((c.mktsegment = 'BUILDING') AND (c.custkey = o.custkey) AND (l.orderkey = o.orderkey))\nGROUP BY l.orderkey, o.orderdate, o.shippriority\nORDER BY revenue DESC, o.orderdate ASC;\n\n\nCREATE VIEW &quot;hive&quot;.&quot;logistic&quot;.&quot;minimum_cost_supplier&quot; SECURITY DEFINER AS\nSELECT\n  s.acctbal\n, s.name SupplierName\n, n.name Nation\n, p.partkey\n, p.mfgr\n, s.address\n, s.phone\n, s.comment\nFROM\n  tpch.tiny.part p\n, tpch.tiny.supplier s\n, tpch.tiny.partsupp ps\n, tpch.tiny.nation n\n, tpch.tiny.region r\nWHERE ((p.partkey = ps.partkey) AND (s.suppkey = ps.suppkey) AND (p.size = 15) AND (p.type LIKE '%BRASS') AND (s.nationkey = n.nationkey) AND (n.regionkey = r.regionkey) AND (r.name = 'EUROPE') AND (ps.supplycost = (SELECT MIN(ps.supplycost)\nFROM\n  tpch.tiny.partsupp ps\n, tpch.tiny.supplier s\n, tpch.tiny.nation n\n, tpch.tiny.region r\nWHERE ((p.partkey = ps.partkey) AND (s.suppkey = ps.suppkey) AND (s.nationkey = n.nationkey) AND (n.regionkey = r.regionkey) AND (r.name = 'EUROPE'))\n)))\nORDER BY s.acctbal DESC, n.name ASC, s.name ASC, p.partkey ASC;\n\n\n\nselect\n  cst.name as CustomerName,\n  cst.address,\n  cst.phone,\n  cst.nationkey,\n  cst.acctbal as BookedOrders,\n  cst.mktsegment,\n  nat.name as Nation,\n  reg.name as Region\nfrom tpch.sf1.customer as cst\njoin tpch.sf1.nation as nat on nat.nationkey = cst.nationkey\njoin tpch.sf1.region as reg on reg.regionkey = nat.regionkey\nwhere reg.regionkey = 1;\n\nselect\n  nat.name as Nation,\n  avg(cst.acctbal) as average_booking\nfrom tpch.sf100.customer as cst\njoin tpch.sf100.nation as nat on nat.nationkey = cst.nationkey\njoin tpch.sf100.region as reg on reg.regionkey = nat.regionkey\nwhere reg.regionkey = 1\ngroup by nat.name;\n```\n </code></pre><script>\nif (!document.getElementById('syntaxed-prism')) {\n\tvar my_awesome_script = document.createElement('script');\n\tmy_awesome_script.setAttribute('src','https://bluetab.net/wp-content/plugins/syntax-highlighter-for-elementor/assets/prism2.js');\n\tmy_awesome_script.setAttribute('id','syntaxed-prism');\n\tdocument.body.appendChild(my_awesome_script);\n} else {\n\twindow.Prism && Prism.highlightAll();\n}\n</script>\t\t</div>\n\t\t"}]} 

        En esta prueba lo más relevante es que vamos a escribir los datos de la tablas customer(15000000 rows), orders(150000000 rows), supplier(1000000 rows), nation(25 rows) y region(5 rows) en nuestro bucket de GCS.

        Como comentamos anteriormente, Starburst no solo es una herramienta que te permite lanzar consultas para analizar datos, sino que también te puede ayudar en las migraciones de datos de tu compañía, volcando la información de tu base de datos a tu plataforma de la nube. Una cosa muy importante a tener en cuenta es que Starburst te permite trabajar con distintos tipos de fichero, pudiendo escribir tus tablas finales en ORC, Parquet o formatos como Delta o Hudi dándote una libertad muy amplia en las migraciones al cloud.

        Como última prueba para ver que todo está funcionando correctamente, vamos a lanzar una consulta para federar distintos datos de diversas fuentes. En nuestro caso, federaremos datos de la anterior tabla que hemos creado en Google Cloud Storage llamada customer con una tabla llamada nation, que nos crearemos en el PostgreSQL que hemos configurado en nuestro despliegue, y la tabla region que está en el esquema tcph. Esta consulta la podemos encontrar en el archivo `federate.sql`:

        create schema postgres.logistic;
        create table postgres.logistic.nation as select * from tpch.sf1.nation;
        
        select
          cst.name as CustomerName,
          cst.address,
          cst.phone,
          cst.nationkey,
          cst.acctbal as BookedOrders,
          cst.mktsegment,
          nat.name as Nation,
          reg.name as Region
        from hive.datalake.customer as cst
        join postgres.logistic.nation as nat on nat.nationkey = cst.nationkey
        join tpch.sf1.region as reg on reg.regionkey = nat.regionkey
        where reg.regionkey = 1;
         

        Este tipo de consultas es uno de los puntos fuertes que tiene Starburst, poder federar consultas que se encuentren en distintos silos de información sin la necesidad de migrar los datos y pudiendo atacar a distintos Cloud o a información que se tenga en el onpremise. 

        Una vez que hemos probado que tanto las consultas como la escritura en GCS funcionan correctamente, vamos a realizar unos test de performance para simular usuarios en paralelo y ver como autoescala nuestra plataforma. Vamos a configurar JMeter para estas pruebas. Para ello hemos tenido que configurar el conector jdbc de trino para que mande consultas a nuestro cluster.

        Vamos a simular 20 usuarios en paralelo, y cada uno lanzará una secuencia de 5 consultas. Esto significa que habrá 20 consultas en paralelo al mismo tiempo, simulando un escenario real, ya que generalmente no se lanzarán consultas de todos los usuarios en el mismo momento. Las consultas que vamos a ejecutar son las siguiente:

        ```sql
        select
          cst.name as CustomerName,
          cst.address,
          cst.phone,
          cst.nationkey,
          cst.acctbal as BookedOrders,
          cst.mktsegment,
          nat.name as Nation,
          reg.name as Region
        from tpch.sf1.customer as cst
        join tpch.sf1.nation as nat on nat.nationkey = cst.nationkey
        join tpch.sf1.region as reg on reg.regionkey = nat.regionkey
        where reg.regionkey = 1;
        
        SELECT
          s.acctbal
        , s.name SupplierName
        , n.name Nation
        , p.partkey
        , p.mfgr
        , s.address
        , s.phone
        , s.comment
        FROM
          tpch.tiny.part p
        , tpch.tiny.supplier s
        , tpch.tiny.partsupp ps
        , tpch.tiny.nation n
        , tpch.tiny.region r
        WHERE ((p.partkey = ps.partkey) AND (s.suppkey = ps.suppkey) AND (p.size = 15) AND (p.type LIKE '%BRASS') AND (s.nationkey = n.nationkey) AND (n.regionkey = r.regionkey) AND (r.name = 'EUROPE') AND (ps.supplycost = (SELECT MIN(ps.supplycost)
        FROM
          tpch.tiny.partsupp ps
        , tpch.tiny.supplier s
        , tpch.tiny.nation n
        , tpch.tiny.region r
        WHERE ((p.partkey = ps.partkey) AND (s.suppkey = ps.suppkey) AND (s.nationkey = n.nationkey) AND (n.regionkey = r.regionkey) AND (r.name = 'EUROPE'))
        )))
        ORDER BY s.acctbal DESC, n.name ASC, s.name ASC, p.partkey ASC;
        
        SELECT
        count(*)
        FROM
          tpch.sf1.customer c
        , tpch.sf1.orders o
        , tpch.sf1.lineitem l
        WHERE ((c.mktsegment = 'BUILDING') AND (c.custkey = o.custkey) AND (l.orderkey = o.orderkey))
        GROUP BY l.orderkey, o.orderdate, o.shippriority
        ORDER BY o.orderdate ASC;
        ```
         

        Si nos fijamos, en nuestro cluster de Kubernetes podemos ver que se están levantando más workers de Starburst por el momento de alta demanda en nuestra simulación:

        Esto es una de las características más cómodas e importantes que nos da Starburst, ya que hace que nuestra plataforma de analítica de datos sea 100% elástica y podamos ir adaptándonos a los picos de demanda que tengamos.

        Métricas

        Por último, Starburst nos proporciona una interfaz donde visualizar ciertas métricas del consumo de nuestro cluster, como puede ser la memoria, la cpu o las consultas realizadas en tiempo real en nuestro cluster.

        Además de estas métricas, hemos añadido también a nuestra configuración el despliegue de Prometheus y Grafana para integrarnos con las herramientas más comunes dentro de cualquier organización. Las métricas que hemos añadido a Grafana son consumo de memoria de nuestro cluster de Starburst, consultas realizadas por los usuarios, consultas con errores, memoria total de nuestro cluster de Kubernetes y Workers activos. Una vez integradas dichas métricas, el dashboard que tendríamos sería el siguiente:

        Una vez integrado con Grafana, podríamos crearnos alertas de envío de mensajes por si hay algún problema en nuestro cluster de Starburst, y así tener todo el flujo de operaciones cubierto para evitarnos dolores de cabeza si hubiera algún tipo de incidencia o indisponibilidad.

        El dashboard está publicado en Grafana[14] para que cualquier persona pueda hacer uso de él.

        Conclusiones

        Desde hace ya unos años, las grandes corporaciones se enfrentan a un desafío común cuando intentan compartir y analizar información entre departamentos ya que cada departamento almacena y gestiona sus datos de manera aislada. Estos silos dificultan el acceso y la integración de datos, lo que impide una visión completa y unificada de la información empresarial. La falta de interoperabilidad entre los silos de datos obstaculiza la toma de decisiones informada, ralentiza los procesos analíticos y limita la capacidad de las organizaciones para obtener una ventaja competitiva. Si tu organización se encuentra en una situación similar, Starburst es tu herramienta.

        Starburst te facilita el acceso y análisis a todos estos silos de información y da la capacidad de federar datos de diversas fuentes y ubicaciones, ya sea datos en el Cloud o en tu datacenter onpremise. Permite realizar consultas en tiempo real sin necesidad de mover o transformar los datos previamente. Esto agiliza el proceso analítico y brinda a las organizaciones una visión 360 de sus datos. Además, no solo te ayuda a la hora de consultar datos de distintas fuentes, sino que también te puede ayudar en tus migraciones al Cloud, ya que te permite consultar cualquier origen y volcar dicha información en un almacenamiento como S3 o GCS en formato de ficheros abierto, como puede ser Parquet.

        Una de las principales ventajas de Starburst, es que te permite desplegar la infraestructura en Kubernetes para aprovechar así todo su potencial. Kubernetes te da la capacidad de adaptarse dinámicamente a la carga de trabajo. Con esta función, los clústeres de Starburst pueden aumentar o disminuir automáticamente el número de Workers según la demanda. Esto permite optimizar el uso de recursos y garantizar un rendimiento óptimo, ya que los pods adicionales se crean cuando la carga aumenta y se eliminan cuando disminuye. Esto dentro de cualquier organización es un punto muy importante, ya que mejora la eficiencia operativa al minimizar el tiempo de inactividad y los costos innecesarios, al tiempo que asegura una disponibilidad constante y una respuesta ágil a los picos de trabajo. Además, una cosa a tener en cuenta es que puedes realizar la instalación de Starburst tanto en cualquiera de los Cloud, como en onpremise.

        Además, también te permite tener un roleado y gobierno de los usuarios dentro de tu plataforma, dando una granularidad a nivel de acceso a los datos a cada usuario, permitiéndote crear roles para ciertos esquemas, tablas o hasta columnas y filas dentro de una tabla.

        Los que trabajamos con datos sabemos de la dificultad de trabajar con multitud de fuentes de datos, entornos diversos, herramientas de todo tipo, etc. Uno de los puntos más diferenciales de Starburst es tener la capacidad de consultar los datos desde su almacenamiento, eliminando duplicidad de información, pudiendo así tener una mejor eficiencia en cuanto al storage, y facilitando también el gobierno de estos datos.

        En conclusión, Starburst es una herramienta a tener en cuenta si quieres llevar a tu organización al siguiente nivel en el mundo de los datos, o si te estás planteando una estrategia de datos con una visión y una filosofía más orientada al data mesh.

        Referencias

        [1] Qué es Starburst.[link] 

        [2] Qué es Trino. [link]

        [3] Principios del Data Mesh. [link]

        [4] Introducción  a DBT. [link]

        [5] Introducción a Jupyter Notebook. [link]

        [6] Introducción a Power BI. [link]

        [7] Qué es Prometheus.. [link]

        [8] Qué es Grafana. [link]

        [9] Qué es Terraform. [link]

        [10] Qué es Jmeter.[link]

        [11] Módulo de GKE.[link]

        [12] Módulo de VPC.[link]

        [13] Qué es TPCH.[link]

        [14] Dashboard Grafana.[link]

        [15] Repositorio de Github con el despliegue.[link]

        Navegación

        Lucas Calvo

        Cloud Engineer

        ¿Quieres saber más de lo que ofrecemos y ver otros casos de éxito?
        DESCUBRE BLUETAB

        SOLUCIONES, SOMOS EXPERTOS

        DATA STRATEGY
        DATA FABRIC
        AUGMENTED ANALYTICS

        Te puede interesar

        Mitos y verdades de los ingenieros de software

        junio 13, 2022
        LEER MÁS

        Gobierno de Datos: ¿tendencia o necesidad?

        octubre 13, 2022
        LEER MÁS

        Los Incentivos y el Desarrollo de Negocio en las Telecomunicaciones

        octubre 9, 2020
        LEER MÁS

        Características esenciales que debemos tener en cuenta al adoptar un paradigma en la nube

        septiembre 12, 2022
        LEER MÁS

        Bluetab se incorporará a IBM

        julio 9, 2021
        LEER MÁS

        Detección de Fraude Bancario con aprendizaje automático

        septiembre 17, 2020
        LEER MÁS

        Publicado en: Blog, Practices, Tech

        CDKTF: Otro paso en el viaje del DevOps, introducción y beneficios.

        mayo 9, 2023 by Bluetab

        CDKTF: Otro paso en el viaje del DevOps, introducción y beneficios.

        Lucas Calvo

        Cloud Engineer

        Introducción

        En este artículo vamos a hablar de CDKTF y de cómo utilizar todas sus ventajas para desplegar infraestructura de forma programática y reutilizable en GCP. También veremos cómo integrar CDKTF con tus módulos de terraform[1] para desplegar infraestructura más reutilizable bajo la supervisión de tu organización.

        CDKTF abre un mundo de posibilidades para llevar a nuestra organización al siguiente nivel de automatización, además de facilitar el despliegue de la infraestructura a las personas más cercanas a la parte de desarrollo. En este artículo daremos algunas indicaciones de cuando es una buena opción utilizar CDKTF y cuando seguir utilizando terraform a través de HCL, ya que no en todos los casos de usos el CDKTF nos aportará un valor añadido.

        ¿Qué necesitas para entender este artículo?

        • Algunos conceptos sobre Terraform[2].
        • Instalar el CDKTF [3].
        • Algunos conceptos sobre python.
        • Necesitas una cuenta gratuita en GCP.

        Todo el código utilizado en este artículo está en el repositorio[4] de Github.

        ¿Es CDKTF la solución milagrosa para los despliegues en nuestra organización? Veámoslo.

        ¿Que es el CDKTF?

        CDKTF, también llamado Cloud Development Kit for Terraform, permite definir y aprovisionar infraestructura de forma programática. En este artículo utilizaremos python para desplegar algunos recursos en GCP. El punto fuerte de CDKTF es que no necesitas aprender HashiCorp Configuration Language (HCL), sólo necesitas saber Python que es más flexible que HCL porque te permite crear más integraciones con herramientas de tu organización y con otras APIs. Incluso puedes crear algunas clases específicas en Python para hacer tu código más reutilizable.

        Primeros pasos con CDKTF

        Una vez explicado CDKTF, procederemos a crear nuestro primer proyecto. Para ello desplegaremos un cloud storage y un topic de pubsub en GCP, utilizaremos recursos terraform por simplicidad. Comenzaremos explicando varios comandos del CDKTF:

        • cdktf init –template=python

        Este comando crea un nuevo proyecto CDK para Terraform usando una plantilla. Esto es muy útil cuando se quiere empezar a utilizar un nuevo proveedor, en nuestro caso el proveedor de Google.

        Una vez ejecutado este comando veremos la siguiente plantilla:

        Los ficheros más importantes son `main.py` y `cdktf.json`. Hablemos de ellos.

        En el fichero `main.py` es donde se declara toda la infraestructura que vamos a desplegar con su lógica. Haremos uso del proveedor de Google para definir nuestros recursos, `cloud storage` y `pubsub topic`. Luego para definir e importar el proveedor de google y la librería de almacenamiento y pubsub importaremos los siguientes módulos en python:

        ```python
        from imports.google.provider import GoogleProvider
        from imports.google.storage_bucket import StorageBucket
        from imports.google.pubsub_topic import PubsubTopic
        ``` 

        Estos proveedores se definen en el archivo `cdktf.json`, este archivo es donde puedes proporcionar los ajustes de configuración personalizados para tu aplicación y definir los proveedores y módulos que deseas utilizar. Cuando inicializamos la plantilla con el comando `cdktf init –template=python`, la plantilla genera un archivo `cdktf.json` básico en tu directorio raíz que puedes personalizar para tu aplicación.

        Este archivo tiene la siguiente información:

        ```json
        {
          "language": "python",
          "app": "pipenv run python main.py",
          "projectId": "da305019-c0fc-4e47-b4ad-1a705cdd8811",
          "sendCrashReports": "false",
          "terraformProviders": ["google@~> 4.0"],
          "terraformModules": [],
          "codeMakerOutput": "imports",
          "context": {
            "excludeStackIdFromLogicalIds": "true",
            "allowSepCharsInLogicalIds": "true"
          }
        }
        ``` 

        En la línea terraformProviders hemos definido el proveedor de google que contiene todos los recursos que necesitamos. En la sección Integración con tus propios módulos aprenderemos a configurar este fichero para utilizar tus propios módulos terraform.

        Una vez configurados los proveedores ya podemos definir nuestros recursos con Python:

        ```python
        class MyStack(TerraformStack):
            def __init__(self, scope: Construct, id: str):
                super().__init__(scope, id)
        
                GoogleProvider(self, "google", region="europe-west4",project="xxxxx")
                length = 5
                suffix = ''.join((random.choice(string.ascii_lowercase) for x in range(length)))
                bucket = StorageBucket(self, "gcs", name = "cdktf-test-1234-bt-"+ str(suffix), location = "EU", force_destroy = True)
                topic = PubsubTopic(self, "topic" ,name = "cdktf-topic", labels={"tool":"cdktf"})
                TerraformOutput(self,"bucket_self_link",value=bucket.self_link)
                TerraformOutput(self,"topic-id",value=topic.id)
        
        app = App()
        MyStack(app, "first_steps")
        
        app.synth()
        ``` 

        Estas líneas de código despliegan un cloud storage y un topic como hemos dicho previamente, también hemos creado un `string` aleatorio en python para añadir al cloud storage como sufijo. Para ello hemos añadido dos librerías más: `string` y `random`. Además, hemos añadido a nuestro script algunas salidas para ver alguna información importante sobre nuestro despliegue como `topic_id` o `bucket_self_link`.

        El resultado final de nuestros primeros scripts con CDKTF es el siguiente:

        ```python
        from constructs import Construct
        from cdktf import App, TerraformStack, TerraformOutput
        from imports.google.provider import GoogleProvider
        from imports.google.storage_bucket import StorageBucket
        from imports.google.pubsub_topic import PubsubTopic
        import random
        import string
        
        class MyStack(TerraformStack):
            def __init__(self, scope: Construct, id: str):
                super().__init__(scope, id)
        
                GoogleProvider(self, "google", region="europe-west4",project="xxxxx")
                length = 5
                suffix = ''.join((random.choice(string.ascii_lowercase) for x in range(length)))
                bucket = StorageBucket(self, "gcs", name = "cdktf-test-1234-bt-"+ str(suffix), location = "EU", force_destroy = True)
                topic = PubsubTopic(self, "topic" ,name = "cdktf-topic", labels={"tool":"cdktf"})
                TerraformOutput(self,"bucket_self_link",value=bucket.self_link)
                TerraformOutput(self,"topic-id",value=topic.id)
        
        app = App()
        MyStack(app, "first_steps")
        
        app.synth()
        ``` 

        Ahora podemos desplegar nuestra infraestructura, para ello necesitamos ejecutar algunos comandos con CDKTF. En primer lugar, tenemos que descargar los proveedores y módulos para una aplicación y generar las construcciones CDK para ellos. Para ello utilizamos `cdktf get`. Utiliza el archivo de configuración `cdktf.json` para leer la lista de proveedores. Este comando sólo genera los bindings de los proveedores que faltan, por lo que es muy rápido si nada ha cambiado.

        ```bash
        cdktf get
        ``` 

        Esta es la salida del comando:

        Usamos el flag –force para recrear todos los bindings. Con el proveedor descargado procederemos al despliegue ejecutando el comando `cdktf deploy`:

        ```bash
        cdktf deploy
        ``` 

        Esta es la salida del comando:

        Con todos estos pasos hemos procedido a desplegar nuestra primera aplicación con el CDKTF. Algo bastante sencillo y con código muy reutilizable. Ahora vamos a proceder a la destrucción de la infraestructura para no incurrir en ningún coste. Utilizaremos el comando `cdktf destroy`.

        Integraciones con tus propios módulos

        Perfecto, una vez comprobado cómo funciona el CDKTF vamos a integrarlo con los módulos terraform que se desarrollan en nuestra empresa. Esto nos permitiría hacer el código mucho más reutilizable permitiendo que todo lo que se despliegue en el CDKTF se despliegue con los patrones que hemos definido en los módulos. Para esta prueba ejecutaremos la misma creación (gcs y topic) pero esta vez haciendo uso de los módulos previamente desarrollados que podéis encontrar en el siguiente repositorio.

        • Cloud Storage[5]
        • Pubsub[6]

        Estos módulos han sido desarrollados con HCL y tienen ciertas nomenclaturas y lógica para facilitar al máximo el despliegue al resto de desarrolladores de mi organización.

        Así que procedamos a crear otra plantilla con el comando `cdktf init –template=python` pero esta vez para usar nuestros propios módulos.

        Una vez ejecutado tenemos la misma plantilla que en el apartado anterior. Ahora vamos a proceder a modificar el `cdktf.json` para añadir los módulos que vamos a utilizar y dos proveedores, google y google-beta, que son necesarios para el uso de estos módulos.

        Este es el fichero `cdktf.json`:

        ```json
        {
          "language": "python",
          "app": "pipenv run python main.py",
          "projectId": "f02a016f-d673-4390-86db-65348eadfb3f",
          "sendCrashReports": "false",
          "terraformProviders": ["google@~> 4.0", "google-beta@~> 4.0"],
          "terraformModules": [
            {
              "name": "gcp_pubsub",
              "source": "git::https://github.com/lucasberlang/gcp-pubsub.git?ref=v1.2.0"
            },
            {
              "name": "gcp_cloud_storage",
              "source": "git::https://github.com/lucasberlang/gcp-cloud-storage.git?ref=v1.2.0"
            }
          ],
          "codeMakerOutput": "imports",
          "context": {
            "excludeStackIdFromLogicalIds": "true",
            "allowSepCharsInLogicalIds": "true"
          }
        }
        ```
         

        Hemos añadido la línea terraform Modules donde indicamos el nombre del módulo y la fuente, en este caso nuestro repositorio de github. También hemos añadido la línea terraform providers como en el apartado anterior.

        Una vez añadidos los proveedores y los módulos terraform vamos a instanciarlos en nuestro main, para ello solo tenemos que añadirlos como librerías y luego invocarlos con los parámetros que estén definidos en nuestro módulo. Puedes ir al readme del módulo que está subido en github para ver que parámetros son obligatorios y cuales son opcionales, también puedes ver salidas de esos módulos.

        El código quedaría de la siguiente manera:

        ```python
        #!/usr/bin/env python
        from constructs import Construct
        from cdktf import App, TerraformStack, TerraformOutput
        from imports.google.provider import GoogleProvider
        from imports.google_beta.provider import GoogleBetaProvider
        from imports.gcp_pubsub import GcpPubsub
        from imports.gcp_cloud_storage import GcpCloudStorage
        import random
        import string
        
        class MyStack(TerraformStack):
            def __init__(self, scope: Construct, ns: str):
                super().__init__(scope, ns)
                GoogleProvider(self, "google", region="europe-west4")
                GoogleBetaProvider(self, "google-beta", region="europe-west4")
                length = 5
                suffix = ''.join((random.choice(string.ascii_lowercase) for x in range(length)))
                tags = {"provider" : "go",
                        "region" : "euw4",
                        "enterprise" : "bt",
                        "account" : "poc",
                        "system" : "ts",
                        "environment" : "poc",
                        "cmdb_name" : "",
                        "security_exposure_level" : "mz",
                        "status" : "",
                        "on_service" : "yes"}
        
                topic = GcpPubsub(self,"topic",
                  name = "cdktf-topic",
                  project_id = "xxxxxxx",
                  offset = 1,
                  tags = tags)
                  
                bucket = GcpCloudStorage(self,"bucket",
                  name = "cdktf-test-1234-bt-" + suffix,
                  project_id = "xxxxxxx",
                  offset = 1,
                  location = "europe-west4",
                  force_destroy = True,
                  tags = tags)
                
                TerraformOutput(self,"topic_id",value=topic.id_output)
                TerraformOutput(self,"bucket_self_link",value=bucket.bucket_output)
        
        app = App()
        MyStack(app, "cdktf_modules")
        
        app.synth()
        ```
         

        Para invocar nuestros módulos que hemos añadido previamente en el archivo `cdktf.json`, sólo tenemos que añadir este código:

        ```python
        from imports.gcp_pubsub import GcpPubsub
        from imports.gcp_cloud_storage import GcpCloudStorage
        ``` 

        El resto del código es la invocación de nuestros módulos con una serie de parámetros para inicializarlos, como región, nombre, etc. También hemos añadido las salidas para tener algo de información sobre la creación de los recursos en GCP. Ahora, vamos a proceder al despliegue de los recursos para comprobar el correcto funcionamiento de CDKTF.

        ```bash
        cdktf get --force
        cdktf deploy
        ``` 

        Una vez desplegada, comprobaremos nuestra infraestructura en GCP y procederemos a borrar toda con el comando `cdktf destroy`.

        Evoluciones que puedes añadir a tu empresa

        Gracias al CDKTF podemos crear nuevos automatismos mucho más nativos que con el HCL tradicional ya que podemos integrarnos con todo tipo de backend en nuestro propio desarrollo. Esto abre todo un nuevo mundo de posibilidades en el despliegue automático de infraestructuras.

        Por ejemplo, si en tu empresa siempre te piden el mismo tipo de infraestructura desde los equipos de desarrollo, como una base de datos, un cluster kubernetes y luego los componentes de seguridad y comunicaciones asociados al caso de uso, ¿por qué no automatizar este proceso y no crear proyectos terraform a la carta?.

        Podemos evolucionar nuestra plataforma de automatización creando un portal web que invoque a nuestro microservicio hecho con el CDKTF que hará las validaciones oportunas y luego procederá al despliegue. Esto también se podría hacer con terraform pero no de una forma tan nativa como con el CDKTF ya que ahora usando python (u otro lenguaje, Typescript, Go etc…) podemos crear flujos de trabajo mucho más complejos llamando a otros backends y haciendo todo tipo de integraciones con nuestras herramientas corporativas. Podríamos generar una plataforma de despliegue para automatizar todos nuestros despliegues genéricos que nos solicitan desde otros equipos como aplicaciones, analítica de datos, reporting, etc. Podríamos crear la siguiente arquitectura para resolver este problema:

        Conclusiones

        Después de haber trabajado varios años con terraform creo que el CDKTF es su evolución natural, aunque todavía está en una fase prematura. No cuenta con una comunidad tan grande como la que terraform tiene con HCL, lo que hace difícil iniciarse con esta herramienta. Depurar el código suele ser complicado y no tan fácil como con HCL. Los tutoriales oficiales no son muy completos por lo que muchas veces tendrás que encontrar tu propio camino para resolver algunos problemas derivados del uso de CDKTF. También creo que el CDKTF está en un punto de madurez como lo estaba terraform hace años en la versión inferior a la 0.11.0, es decir, funciona bien aunque todavía le queda mucho camino por recorrer.

        Creo que si tu empresa ya utiliza terraform (HCL) de forma madura, cambiar el modelo a CDKTF no va a suponer grandes beneficios. El único beneficio de usar CDKTF es en un caso de uso como el mencionado en la sección anterior, donde puedes mezclar el uso de tus módulos ya desarrollados con HCL y CDKTF para llevar la automatización de cierta infraestructura a un nivel superior.

        Por otro lado, CDKTF es una herramienta que podría recomendar si conoces python (u otros lenguajes) y no quieres aprender un lenguaje específico como HCL. CDKTF puede ser una buena herramienta si tu empresa no está en un punto de madurez avanzado con terraform o cualquier herramienta de IaC. El CDKTF te permite desarrollar de una forma más sencilla tu infraestructura como código, las integraciones con otras herramientas dentro de tu organización serán mucho más sencillas ya que podrás utilizar tu lenguaje de programación favorito para realizarlas. Puede crear clases y módulos reutilizables de forma sencilla, creando una comunidad de desarrollo CDKTF dentro de su propia empresa y permitiendo a los desarrolladores estar más apegados a la infraestructura, lo que siempre es un reto. También la parte de pruebas de tu código CDKTF será mucho más fácil y nativa haciendo uso de pytest u otros frameworks [7]. Probar con terraform (HCL) es más tedioso y ya tienes que usar frameworks como terratest para integrarlos en tu código.

        En general creo que CDKTF es una buena herramienta y es la evolución natural de Terraform. Si queremos llevar nuestra automatización a otro nivel e integrarla con portales web o herramientas organizativas, CDKTF es la herramienta que necesitamos. También abre un mundo de posibilidades para los equipos de desarrollo, ya que podrán desplegar cualquier tipo de infraestructura utilizando un lenguaje de programación. Habrá que ver cómo evoluciona para ver cómo encaja en nuestras organizaciones y si alcanza el punto de madurez que ha alcanzado Terraform.

        Referencias

        [1] Ques es terraform.[link]

        [2] Módulos de Terraform. [link]

        [3] Guía de instalación del CDKTF. [link]

        [4] Repositorio de CKDTF GitHub. [link]

        [5] Repositorio de Cloud storage GitHub. [link]

        [6] Repositorio de Pubsub GitHub. [link]

        [7] Frameworks de testing.. [link]

        Navegación

        Lucas Calvo

        Cloud Engineer

        ¿Quieres saber más de lo que ofrecemos y ver otros casos de éxito?
        DESCUBRE BLUETAB

        SOLUCIONES, SOMOS EXPERTOS

        DATA STRATEGY
        DATA FABRIC
        AUGMENTED ANALYTICS

        Te puede interesar

        Cómo preparar la certificación AWS Data Analytics – Specialty

        noviembre 17, 2021
        LEER MÁS

        Cambios de liderazgo en Bluetab EMEA

        abril 3, 2024
        LEER MÁS

        Espiando a tu kubernetes con kubewatch

        septiembre 14, 2020
        LEER MÁS

        LakeHouse Streaming en AWS con Apache Flink y Hudi (Parte 2)

        octubre 4, 2023
        LEER MÁS

        Introducción a los productos de HashiCorp

        agosto 25, 2020
        LEER MÁS

        KubeCon 2023: Una mirada hacia el futuro de Kubernetes

        abril 26, 2023
        LEER MÁS

        Publicado en: Blog, Practices, Tech

        • « Ir a la página anterior
        • Página 1
        • Páginas intermedias omitidas …
        • Página 5
        • Página 6
        • Página 7
        • Página 8
        • Página 9
        • Páginas intermedias omitidas …
        • Página 23
        • Ir a la página siguiente »

        Footer

        LegalPrivacidadPolítica de cookies

        Patrono

        Patrocinador

        © 2025 Bluetab Solutions Group, SL. All rights reserved.