Hoje em dia, cada vez menos dependemos de aplicações hospedadas em servidores específicos, podemos roda-las conteinerizadas e em ambientes serverless, assim economizamos tempo de gerenciamento de maquina e focamos realmente em entregar valor!

O Airflow não é exceção, ele é um software que pode ser hospedado no AWS ECS (Elastic Container Service) via docker e nesse tutorial eu vou lhes mostrar como fazer isso!

Montando a imagem Docker

A imagem Docker do airflow, para nossa sorte, já foi desenvolvida pelo usuário puckel, mas ela precisa de algumas modificações para rodarmos tudo o que precisamos.

FROM puckel/docker-airflow:1.10.7

USER root

COPY /dags ./dags

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
COPY requirements.txt /requirements.txt
RUN pip install -r /requirements.txt

# Add directory in which pip installs to PATH
ENV PATH="/usr/local/airflow/.local/bin:${PATH}"

USER airflow
COPY --chown=airflow:airflow airflow.cfg /usr/local/airflow/airflow.cfg

ENTRYPOINT ["/entrypoint.sh"]

EXPOSE 8080
EXPOSE 8793
EXPOSE 5555

Como vemos acima, para essa imagem rodar, precisamos fazer algumas coisas:

  • Criar uma pasta de DAGs onde elas serão colocadas para leitura e execução no Airflow
  • Criar um arquivo de entrypoint.sh onde ficam algumas informações de entrada de sistemas
  • Criar um arquivo de requirements.txt onde ficarão todas as bibliotecas extras e necessárias para a execução dos softwares
  • Criar um arquivo de airflow.cfg onde fique todas as configurações do Airflow

Criando a pasta de DAGs

Esta é a parte mais tranquila de fazer, basta você fazer um:

mkdir dags

E pronto! xD

Arquivo de Chamada de Processos - entrypoint.sh

O arquivo de entrypoint servirá como uma base para podermos iniciar diferentes containers com diversas funções com a mesma imagem, assim conseguimos atribuir a função corretamente.

 #!/usr/bin/env bash

: "${REDIS_HOST:="redis"}"
: "${REDIS_PORT:="6379"}"
: "${REDIS_PASSWORD:=""}"

: "${POSTGRES_HOST:=""}"
: "${POSTGRES_PORT:="5432"}"
: "${POSTGRES_USER:=""}"
: "${POSTGRES_PASSWORD:=""}"
: "${POSTGRES_DB:=""}"
: "${MONGO_DB_ATLAS_URI:=""}"

# Defaults and back-compat
: "${AIRFLOW_HOME:="/usr/local/airflow"}"
: "${AIRFLOW__CORE__FERNET_KEY:=${FERNET_KEY:=$(python -c "from cryptography.fernet import Fernet; FERNET_KEY = Fernet.generate_key().decode(); print(FERNET_KEY)")}}"
: "${AIRFLOW__CORE__EXECUTOR:=${EXECUTOR:-Celery}Executor}"

if [ -n "$REDIS_PASSWORD" ]; then
    REDIS_PREFIX=:${REDIS_PASSWORD}@
else
    REDIS_PREFIX=
fi

AIRFLOW__CELERY__BROKER_URL="redis://$REDIS_PREFIX$REDIS_HOST:$REDIS_PORT/1"
AIRFLOW__CORE__SQL_ALCHEMY_CONN="postgresql+psycopg2://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB"
AIRFLOW__CELERY__RESULT_BACKEND="db+postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB"


export \
  AIRFLOW_HOME \
  AIRFLOW__CELERY__BROKER_URL \
  AIRFLOW__CELERY__RESULT_BACKEND \
  AIRFLOW__CORE__EXECUTOR \
  AIRFLOW__CORE__FERNET_KEY \
  AIRFLOW__CORE__LOAD_EXAMPLES \
  AIRFLOW__CORE__SQL_ALCHEMY_CONN \


# Load DAGs examples (default: Yes)
if [[ -z "$AIRFLOW__CORE__LOAD_EXAMPLES" && "${LOAD_EX:=n}" == n ]]
then
  AIRFLOW__CORE__LOAD_EXAMPLES=False
fi


case "$1" in
  webserver)
    echo "INITDB"
    airflow initdb
    echo "CREATING USER"
    airflow create_user -r Admin -u USUARIO -e EMAIL@EMAIL.com -f Admin -l descricao -p SENHA1234
    echo "DEPLOY DONE"
    exec airflow webserver
    ;;
  scheduler|flower|version)
    exec airflow "$@"
    ;;
  worker)
    exec airflow "$@"
    ;;
  *)
    # The command is something like bash, not an airflow subcommand. Just run it in the right environment.
    exec "$@"
    ;;
esac

Mais para frente, dentro do docker-compose.yml, você entenderá mais sobre a utilidade deste arquivo!

Criando um arquivo de requirements.txt - requisitos das suas DAGs

Este arquivo também é fácil de ser criado! Ele é só o conjunto de libs que você quer que seja instalado dentro do seu Airflow, porém tome cuidado sempre com as versões das libs que você está usando e se ela já vem instalada previamente no container!

Criando um arquivo de airflow.cfg - configurações do Airflow

O arquivo airflow.cfg é basicamente a configuração do seu Airflow. Existem algumas coisas que você pode escolher setar, como qual executor você vai querer usar, tipos de autenticação e muitas outras configurações.

Recomendo você pegar este arquivo originalmente do Airflow e configurar conforme suas necessidades!

Docker-Compose, ou como a gente vai fazer rodar localmente de toda essa bodega

Nosso docker-compose é este:

version: '3'

services:
  redis:
    image: 'redis:5.0.3'
    command: redis-server

  postgres:
    image: postgres:10.4
    environment:
      - POSTGRES_USER=airflow
      - POSTGRES_PASSWORD=airflow
      - POSTGRES_DB=airflow
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    ports:
      - 5432:5432

  webserver:
    build: .
    restart: always
    build: .
    depends_on:
      - postgres
      - redis
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - POSTGRES_HOST=postgres
      - POSTGRES_PORT=5432
      - POSTGRES_USER=airflow
      - POSTGRES_PASSWORD=airflow
      - POSTGRES_DB=airflow
      - FERNET_KEY=${AIRFLOW_FERNET_KEY}
      - AIRFLOW_BASE_URL=http://localhost:8080
      - ENABLE_REMOTE_LOGGING=False
      - STAGE=dev
    ports:
        - "8080:8080"
    command: webserver
    healthcheck:
      test: ["CMD-SHELL", "[ -f /usr/local/airflow/airflow-webserver.pid ]"]
      interval: 30s
      timeout: 30s
      retries: 3

  flower:
    build: .
    restart: always
    depends_on:
      - redis
      - webserver
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - POSTGRES_HOST=postgres
      - POSTGRES_PORT=5432
      - POSTGRES_USER=airflow
      - POSTGRES_PASSWORD=airflow
      - POSTGRES_DB=airflow
      - STAGE=dev
    ports:
      - "5555:5555"
    command: flower

  scheduler:
    build: .
    restart: always
    depends_on:
      - webserver
    volumes:
      - ./dags:/usr/local/airflow/dags
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - POSTGRES_HOST=postgres
      - POSTGRES_PORT=5432
      - POSTGRES_USER=airflow
      - POSTGRES_PASSWORD=airflow
      - POSTGRES_DB=airflow
      - FERNET_KEY=${AIRFLOW_FERNET_KEY}
      - AIRFLOW_BASE_URL=http://localhost:8080
      - ENABLE_REMOTE_LOGGING=False
      - STAGE=dev
    command: scheduler

  worker:
    build: .
    restart: always
    depends_on:
      - webserver
      - scheduler
    volumes:
      - ./dags:/usr/local/airflow/dags
    environment:
      - REDIS_HOST=redis
      - REDIS_PORT=6379
      - POSTGRES_HOST=postgres
      - POSTGRES_PORT=5432
      - POSTGRES_USER=airflow
      - POSTGRES_PASSWORD=airflow
      - POSTGRES_DB=airflow
      - FERNET_KEY=${AIRFLOW_FERNET_KEY}
      - AIRFLOW_BASE_URL=http://localhost:8080
      - ENABLE_REMOTE_LOGGING=False
      - STAGE=dev
    command: worker

O docker-compose servirá para você poder rodar todo o ambiente em seu ambiente localhost! Ele permite com que você link todos os containers, permitindo que eles trabalhem da mesma forma que no ECS.

Tutorial continuará em breve, caso você queira ler sobre como fazer o deploy no ECS, clique aqui!