Data Engineering Zoomcamp – Semana 1

Durante la primera semana del bootcamp para Data Engineers que comenté hace unos días hemos practicado contenerización con docker creando imágenes para desplegar Postgresql. Mediante Python y la librería pandas hemos ingestado un dataset para realizar los ejercicios. Finalmente, hemos creado con Docker compose una aplicación con varios contenedores (postgresql y pgadmin para desplegar un GUI de gestión de la BD). La última parte era teoría de SQL.

Durante la semana me han surgido algunas dudas o problemas a la hora de instalar, configurar o implementar los scripts, aprovecho el post para hacer referencia a todos ellos:

Última actualización 23/01/2023

Prerequisitos

Antes de comenzar con esta parte del bootcamp es imprescindible instalar y configurar todo lo necesario para realizar cada uno de los pasos. En mi caso estoy trabajando sobre Windows 10.

  • Python (yo estoy usando 3.11 en un nuevo environment, aunque en el curso usan 3.9) – Descarga
  • Docker Descarga
    • Me dio bastante guerra correr Docker. Primero descargué la 4.16 y aunque el servicio estaba arrancado, el engine no, sin aviso de error. Hice un downgrade a la 4.4 y al menos ya sí me salían los errores por los que no podía levantarlo. Es necesario revisar dos puntos:
      • Habilitar virtualización en la BIOS. Deberás buscar el modelo de tu motherboard para saber dentro de qué opción está en la BIOS. En mi caso se trata de una ASUS con una UEFI moderna muy intuitiva.
      • Si utilizas Windows 10, es necesario instalar WSL (Windows Subsystem for Linux) y una distribución de Linux (yo elegí Ubuntu). En esta nota técnica de Microsoft están todos los pasos a seguir.
  • Aunque si instalas WSL ya tienes acceso a una línea de comandos UNIX, instalé MINGW64 de Git Bash como alternativa – Descarga
  • Terraform: la descarga desde la página oficial es un ejecutable pero debe arrancarse desde línea de comandos. Elige el directorio que prefieras para dejar dicho fichero terraform.exe y añade la ruta al PATH para facilitar el acceso.
  • Google Cloud CLI para poder aprovisionar la infra desde línea de comandos – Descarga

Dataset

El dataset con el que vamos es una extracción de los trayectos de los taxis de New York en Enero 2021. Originalmente la plataforma ofrecía el dataset en formato CSV y los videos/explicaciones indican como hacer la ingesta en Python con Pandas de un CSV. Sin embargo, si vamos ahora al repositorio vemos que en realidad se descargan parquets. El cambio es mínimo en el script, en lugar de hacer un pd.read_csv debemos usar la sentencia pd.read_parquet y además importar una nueva librería import pyarrow. El script ingest_data.py quedaría de la siguiente forma:

import pandas as pd
from sqlalchemy import create_engine
import argparse
import os
import pyarrow

def main(params):
    user = params.user
    password = params.password
    host = params.host
    port = params.port
    db = params.db
    table_name = params.table_name
    url = params.url

    source_file = 'output.parquet'
    
    # download parquet 
    os.system(f'wget ' + url + ' -o ' + source_file)

    conexion = 'postgresql://' + user + ':' + password + '@' + host + ':' + port + '/' + db
   
    engine = create_engine(conexion)

    # url = "https://d37ci6vzurychx.cloudfront.net/trip-data/yellow_tripdata_2021-01.parquet"
    df = pd.read_parquet(url)

    df.to_sql(name=table_name, con=engine, if_exists="append")


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Ingest Script')
    parser.add_argument('--user', help='User por Postgre SQL')
    parser.add_argument('--password', help='Pass por Postgre SQL')
    parser.add_argument('--host', help='Host por Postgre SQL')
    parser.add_argument('--port', help='Port por Postgre SQL')
    parser.add_argument('--db', help='Database por Postgre SQL')
    parser.add_argument('--table_name', help='Table por Postgre SQL')
    parser.add_argument('--url', help='Url for CSV file')

    args = parser.parse_args()

    main(args)

Docker y docker-compose

A lo largo del temario vamos creando contenedores de Docker por separado (para postgresql, para pgadmin y luego para el propio script python) que debemos conectar mediante la misma red para que tengan visibilidad entre sí. Más tarde, una vez asimilado este conocimiento, damos un paso más utilizando docker-compose para crear una aplicación Docker con varios contenedores ya interconectados entre sí.

A modo de resumen, estos son los comandos para crear cada uno de los contenedores.

Vamos a empezar casi por el final, y antes de usar docker-compose que ya lo integra. Lo primero que haríamos sería crear la red dentro de Docker que luego usarán nuestros contenedores para verse entre sí.

docker network create pg-network

El primer contenedor es para alojar la base de datos postgresql, para lo que debemos indicar los parámetros del environment (-e), el volumen o directorio físico de nuestro equipo donde se van a persistir los datos de la BD (y así no perderlos aunque apaguemos el contenedor) y por último los puertos de entrada y salida. Ojo a la ruta del volumen, me dio también algún problema. En el parámetro de volumen se especifican dos rutas separadas por «:», la parte de la izquierda es la ubicación física en nuestro equipo donde se almacenarán los datos del servidor de BBDD (importante, debe de ser absoluta) C:\Users\Marcos\Downloads\DataEngineeringBootcamp\Week1\NY_Taxis_DBny_taxi_postgres_data y la segunda parte sería la ubicación dentro del contenedor /var/lib/postgresql/data

docker run -it -e POSTGRES_USER="root" -e POSTGRES_PASSWORD="root" -e POSTGRES_DB="ny_taxi" -v C:\Users\Marcos\Downloads\DataEngineeringBootcamp\Week1\NY_Taxis_DBny_taxi_postgres_data:/var/lib/postgresql/data -p 5432:5432 --network=pg-network --name pg-database postgres:13 

El segundo será para disponer del cliente pgadmin, que nos permite gestionar el servidor de postgresql desde un GUI web. Durante los ejercicios también probamos pgcli para atacarla desde línea de comandos. Como en el caso previo, indicamos los parámetros de entorno (-e) y los puertos.

docker run -it -e PGADMIN_DEFAULT_EMAIL="admin@admin.com" -e PGADMIN_DEFAULT_PASSWORD="root" -p 8080:80 --network=pg-network --name pgadmin dpage/pgadmin4 

Por último, llegamos a docker-compose para el que definimos en un yaml (docker-compose.yaml) la configuración de los dos contenedores bajo las siguientes consideraciones:

  • El primer path de los volúmenes de postgresql y pgadmin es una ruta relativa al directorio donde está el yaml «.»
  • No es necesario configurar la red, ya que el propio docker-compose integra todos los servicios bajo el mismo paraguas y tienen conectividad entre ellos.
  • Añadimos a la configuración de pgadmin el volumen para persistir la configuración aunque se apaguen los contenedores.
services:
  pgdatabase:
    image: postgres:13
    environment:
      - POSTGRES_USER=root
      - POSTGRES_PASSWORD=root
      - POSTGRES_DB=ny_taxi
    volumes:
      - "./ny_taxi_postgres_data:/var/lib/postgresql/data:rw"
    ports:
      - "5432:5432"
  pgadmin:
    image: dpage/pgadmin4
    environment:
      - PGADMIN_DEFAULT_EMAIL=admin@admin.com
      - PGADMIN_DEFAULT_PASSWORD=root
    volumes:
      - "./data_pgadmin:/var/lib/pgadmin"
    ports:
      - "8080:80"

Los dos comandos básicos para desplegar/detener la aplicación en docker son:

docker-compose up
docker-compose down

PostgreSQL

Cuando desplegamos con docker-compose y crea el nuevo servidor de BBDD de postgresql no me conectaba desde pgadmin a la db que había creado (ny_taxi) en el contenedor siguiendo la configuración del video. La solución pasa por reemplazar el nombre de la base de datos postgres por la nuestra ny_taxi a la hora de configurar la conexión a un nuevo servidor:

Configuración de conexión de PostgreSQL

Configuración de conexión de PostgreSQL

Terraform

El stopper con el que me he encontrado mientras practicaba con Terraform es una tontería. Básicamente vamos a tener dos ficheros:

  • main.tf: fichero principal de terraform compuesto por tresbloques:
    • terraform: configuración para aprovisionar la infraestructura (versión de Terraform, ubicación del tfstate, proveedores que se utilizan en el fichero)
    • provider: en este caso como vamos la infra es sobre GCP usaremos el provider de Google
    • resource (n): habrá tantos como servicios vayamos a aprovisionar en la nube.
  • variables.tf: donde definimos una colección de variables que reutilizaremos en el propio main.

En primer lugar, para arrancar Terraform mediante el comando terraform init debemos ubicarnos en el directorio donde tengamos los ficheros de configuración (main.tf y variables.tf).

Bien, si os fijáis en el código de ejemplo de la repo del bootcamp en el fichero main.tf se utiliza la variable var.project para el bloque de project. Si no facilitamos el ID del proyecto que hemos creado en el GCP, nos arrojará un error de que el proyecto no tiene asignada facturación o que no tiene permisos sobre el API. Mi error era que ejecutaba el comando sin pasarle por parámetro el nombre del proyecto. Aunque al final lo solucioné añadiendo el ID en el variables.tf, dejo por aquí las dos formas:

La primera forma es utilizar el variables.tf según lo descargamos de la repo. En project solo se indica la descripción:


variable "project" {
  description = "Your GCP Project ID"
}

Por lo que cuando lanzamos por línea de comandos el terraform apply es necesario hacerlo con el parámetro del ID del proyecto:

terraform apply -var="project=ID-proyecto"

La otra opción es añadir a la variable project el parámetro default="ID-proyecto":

variable "project" {
  description = "digital-aloe-375022"
  default = "digital-aloe-375022"
  type = string
}

De forma que podemos lanzar el comando terraform apply sin parámetros.

terraform apply 

Comprobamos que se ha aprovisionado correctamente la infra desde terraform:

Output comando terraform apply
Output comando terraform apply

Y si accedemos al Google Cloud Platform podremos ver que se han generado un Cloud Storage Bucket (almacenamiento) y una base de datos BigQuery:

oogle Storage Bucket creado en el proyecto de prueba  (digital-aloe)
Google Storage Bucket creado en el proyecto de prueba (digital-aloe)
Google BigQuery creado en el proyecto de prueba (digital-aloe)
Google BigQuery creado en el proyecto de prueba (digital-aloe)

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

What is 8 + 7 ?
Please leave these two fields as-is: