Fala dataholics, espero que todos tenham tido uma ótima virada de ano, vamos começar 2024 a todo vapor, no ano de 2023 tive a oportunidade de trabalhar bastante com Azure Function, ter bastante contato com AWS Lambda e estudar um pouquinho sobre GCP Cloud Functions, estarei iniciando uma série de posts para quem quer sair do zero com Azure Function e começar a implementar na prática, veremos que Azure Function não é só para aplicações, podemos também usar para os nossos pipelines de dados.
Mas não ficaremos só hello world não, vamos ver como ingerir dados e gravar direto nas nossas tabelas no Delta Lake sem precisar de Spark (WTF como assim?!), sim, isso vai te ajudar a reduzir custos e deixar seu ambiente mais dinâmico e escalável.
Serão uma média de 10 artigos não sequenciais, então fica ligado aí, tentarei abortar os seguintes tópicos:
Introdução a Azure Function (veremos nesse post)
Triggers: HTTP, Timer, Azure SQL e outros eventos
Bindings e integrações
Function App com várias functions
Manipulando Delta Lake sem Spark
Ingestão de APIS
Orquestração com Azure Data Factory
Precificação e escalabilidade
Redução de custos na ingestão de dados
Integração com esteiras CICD
Monitoramento com Aplication Insights
Integração com Kubernetes
Configurations, Secrets, Managed Identities e ConnectionStrings
Pipeline de ponta a ponta com Azure Function
... Ideias? Manda aí.
O que veremos nesse post?
Introdução Azure Function
O que é Azure Function
O que é Serverless
Quais linguagens suportadas
Concorrentes
Azure Function vs Azure Logic App
Hosting - Tiers da Azure Function
Criando sua primeira Azure Function
Lendo e escrevendo dados no Azure Blob Storage
Quanto custou?
Resumo
Ao final deste post, entederemos o que é Azure Function, quais suas concorrentes em outras Clouds, onde ela pode ser utilizada e faremos uma demo (demonstração rs) lendo e gravando arquivos no Blob Storage.
Introdução Azure Function
Estamos muito acostumados a ver Azure Function nos contextos de arquiteturas de aplicação, como no desenho abaixo, então fica a impressão que Azure Function é coisa de desenvolvedor.
Mas pera, um Data Engineer também não é um desenvolvedor?! Obviamente, são contextos diferentes, mas ambos acabam usando as mesmas metodologias de desenvolvimento e trabalham boa parte do seu dia debruçados em códigos, no caso dos Data Engineers estamos muito mais focados em Python e SQL.
O Azure Function é usado para diversas coisas, sempre no contexto de arquiteturas Event-Driven, sendo arquitetura baseada em eventos, que está muito conectado no contexto de microsserviços, ambas andam em conjunto.
Imagem: https://learn.microsoft.com/en-us/azure/architecture/web-apps/serverless/architectures/web-app
Em alguns contextos, o Azure Function pode ser o próprio microsserviço, ou ela pode ser apenas um intermediário, escutando eventos em real time e disparando outros fluxos, ou seja, ela é extremamente dinâmica e pode ser acoplada em qualquer parte da sua arquitetura, inclusive funcionando tambem como uma API.
Quer saber mais sobre Event-Driven:
Afinal, o que é Azure Function?
Resumindo com minhas palavras, é um serviço de cloud para você rodar códigos sem servidor, ou seja, você cria um código e ao invés de ficar rodando na sua máquina ou em algum servidor, você publica o código nesse serviço e ele é executado sem a necessidade de dedicar uma máquina virtual (a qual é muito mais caro).
Em resumo, você cria suas funções na sua linguagem de programação preferida e hospeda seu código na nuvem, executando em um serviço gerenciado pela Cloud, sem necessidade de configurar servidor ou capacidade do recurso, simplemente se preocupa com seu código.
O porquê é chamada de serviço sem servidor ou serverless?
Basicamente porque você não precisa configurar nenhuma infraestrutura para ela rodar, obviamente ela rodará em algum servidor interno da cloud, mas não precisamos saber qual e onde, você só se preocupa com o seu código e se ele precisar de mais capacidade ela escala automaticamente.
É ótimo para aplicações que precisam de escalabilidade, mas não possuem previsão de consumo, imagine que esta lançando um App novo, você não sabe se esse Aplicativo será baixado 100 vezes ou 1 milhão de vezes, logo você precisa pensar em colocar seu App em um serviço escalável, sem precisar pagar enquanto seu app está parado, isso é Cloud na prática.
O conceito de serverless está aí faz muito tempo e muita gente acaba confundindo outros serviços que operam como PaaS como sendo serverless, exemplos:
Azure Function no plano Consumption é considerado Serverless, pois, não informamos nada sobre capacidade de processamento, ela escala automaticamente conforme a necessidade
Azure SQL Database no plano Standard 10 DTUs não é considerado serverless, mesmo que não configuramos nada de servidor para esse serviço, você precisa configurar a capacidade. (Azure SQL possui uma configuração de serverless)
Logo, é comum ter essa confusão do que é serverless de fato, mas basta considerar: Estou configurando uma capacidade para o serviço? Se sim, possivelmente ele não é serverless, embora, isso não é uma regra.
Dito isso, então qual a vantagem de pegar meu bloco de código e rodar em uma Azure Function e não em uma infraestrutura dedicada ou serviço de Kubernetes?
Primeiro ponto é custo, no Azure function pagaremos por utilização, diferente de um serviço dedicado que estamos pagando o tempo todo, e a escalabilidade automática e fácil implementação e utilização.
Mesmo quando comparado com serviços como Kubernetes, aqui você ganha na complexidade, com Azure Function você não precisa gerenciar nada de infraestrutura, embora, veremos casos onde rodar em um serviço como Kubernetes valerá mais a pena.
Falando de preço em comparação com Kubernetes vs Azure Function tende a ser uma comparação muito complexa e veremos alguns detalhes de outros planos no post de precificação.
Em resumo, utilizar Azure Function pode ser muito mais fácil e mais barato para muitas arquiteturas de aplicação e de dados.
Com Azure Function você cria o seu código na sua linguagem de programação e coloca ele para rodar em minutos num serviço totalmente gerenciado pela Cloud, as linguagens que podem ser utilizadas atualmente são:
C# - Para fãs de dotnet
JavaScript
Python - A nossa preferida
Java
PowerShell
TypeScript
Go/Rust
Azure Function vs Lambda vs Cloud Functions
O recurso Azure function é realmente sensacional e obviamente ele é exclusivo do Azure (Não entrarei no tema sobre ARC), contudo, as concorrentes AWS e GCP não ficam para trás e possuem suas plataformas de execução de código serverless assim como o Azure Function, na AWS temos o famoso Lambda e no GCP o Cloud Functions.
Todas as três tem suas vantagens e desvantagens, e claro que as vantagens de cada uma está muito ligado as suas próprias Clouds, a integração com os serviços da sua Cloud são muito mais simples, exemplo Azure Function com o ecossistema do Azure como SQL Server, Blob Storage, Event Hub, etc.
Todas possuem o modelo serverless com pagamento por consumo, possuem várias linguagens em comum e IDEs em comum, exemplo, você pode usar a linguagem Python e VSCODE para qualquer uma delas.
Cada uma tem suas particularidades, integrações, planos de preços diferentes, o principal fator ao escolher uma delas é onde está hospedado a sua infraestrutura de dados, se você esta na AWS não faz sentido usar Azure Function e vice-versa. Embora, pode ser usado para integrar e escalar serviços e plataformas multi-cloud, mas esse não é o tópico aqui.
Azure Logic App vs Azure Functions
Você que já conhece o Azure Logic App pode estar se perguntando, qual a relação entre elas?
Ambas são plataformas serverless, o Logic App está mais focado em fluxos, enquanto o Azure Function esta focado em arquiteturas Event-Driven (reagir sobre eventos). O Logic App você cria seus fluxos via interface gráfica, no Azure Function programaremos em uma linguagem de programação.
O Logic App possui centenas de conectores prontos, enquanto no Azure Function você precisa criar essa conexão utilizando os drivers existentes, exceto para o ecossistema Azure, onde podemos usar os bindings.
Embora ambos possam criar fluxos complexos e possuem diversos tipos de triggers, para ter maior controle e dinamicidade nos projetos, Azure Function tende a ser mais prático para o nosso dia a dia e na construção de pipelines customizados.
Aqui no Blog tem um post sobre Logic App que mostra como ele também é sensacional:
Aqui uma tabela de comparação rápida entre as duas:
Temos um item de escalabilidade que não é mencionado, no Azure Function temos outros planos que nos proporcionam uma escalabilidade e performance para códigos complexos e mais pesados.
Hosting - Tiers da Azure Function
O objetivo aqui não é entrar em detalhes do funcionamento interno da Azure Function, porém, algumas configurações são importantes termos conhecimento.
Basicamente temos 3 planos para execução de uma Azure Function e cada um deles pode definir o desempenho e escalabilidade da sua aplicação.
Consumption - Esse é o modelo Serverless, onde temos escala automática, mas podemos sofrer do famoso Cold Start (Um delay para escalar nossa function, que pode dar a sensação de lentidão levando alguns casos a timeout).
Premium Plan - Aqui podemos definir capacidade da infraestrutura por detrás dos planos, já não se enquadra mais como serverless, aqui temos alguns benefícios como não sofrer mais do Cold Start e termos controle do quanto vamos pagar baseado no tier escolhido.
Dedicaded - Aqui você usa um App Service Plan, podendo ter sua infraestrutura dedicada, inclusive podendo rodar em um Kubernetes, você tem previsibilidade de custo, pois, tem uma infra dedicada.
Outro detalhe extremamente importante que muitos não conhecem quando vão criar uma Azure Function, ainda mais se você usara no mundo de Analytics para ingestão de dados.
No plano Consumption o tempo máximo de Timeout é de 10 minutos, isso quer dizer que se você esta consumindo uma origem e ela levar mais de 10 minutos para processar os dados, sua execução irá falhar e não há nada que possa fazer sem ser mudar o plano ou otimizar a origem para responder mais rápido.
Chega de falar, faremos na prática.
No exemplo de hoje criaremos uma Azure Function bem simples que lê um arquivo no Storage, imprime o valor dele na tela e atualiza o valor de volta para o arquivo no Storage.
Essa Azure Function será disparada de minuto em minuto com uma trigger de tempo (timerTrigger) e faremos uma estimativa de custo.
Obs: Não usaremos bindings nessa primeira Function.
Para essa demostração criaremos e usaremos:
1x Function App (Azure Function), é como um workspace que podemos agrupar várias funções, esse é um tópico bem importante que abordaremos nos próximos posts, pois, pode impactar na sua arquitetura.
1x Storage Account, obrigatório ter um Storage vinculado em cada Function App, pois, armazena todos os metadados, recomendo deixar um storage dedicado pra isso
VSCODE para programarmos e publicarmos nossa Function local para a Function App
É muito difícil colocar todos os detalhes da criação de uma Azure Function em um único post, pois, de fato, são vários detalhes, tentarei focar nos pontos principais e mais interessantes e deixarei o código e referências disponíveis.
Aqui são os passos macros que executaremos:
Criação e codificação da function em Python
Testes locais com emulador
Publicar Function para o Function App no Azure
Requisitos importantes:
Estar com VSCode Atualizado
Se atentar a versão do Python, aqui estou usando a versão 3.9.6
Instalar as seguintes bibliotecas: azure-cli, logging, azure-functions, azure.identity, azure-storage-blob
Instalar as extensões de Azure no seu VScode: Azure Account, Azure Functions, Azure Resources, Azurite
Obs: Pode estar faltando alguma biblioteca ou você pode ter algum problema durante a instalação e preparação do primeiro ambiente, ainda mais quando se trata de VSCode, Python, extensões e bibliotecas, conflitos podem acontecer, ai você precisa se diferenciar e ir atrás, famoso "se virá", não da para mapear 100% dos detalhes, ainda mais quando tem dependências do SO, pois, também pode depender do seu S.O aqui estou usando MacOS.
Após instalado todas as dependências, vamos para a criação da nossa function localmente.
O seu VSCode precisa estar parecido com essa visão, se você já tiver instalado as extensões.
Vamos criar nossa Function:
Selecione a linguagem desejada (usaremos Python) e tecle Enter. Na sequência, na próxima tela, selecione Model V2.
Selecione a trigger desejada, para esse exemplo usaremos uma Timer Trigger.
Na próxima tela será solicitado o nome da sua Trigger, aqui você pode colocar o nome que quiser, a nossa vai se chamar storage_timertrigger, tecle enter.
A última tela solicitará um schedule no formato CRON, para nossa demo, rodaremos de minuto em minuto, então ficará assim:
0 */1 * * * *
Reginaldo, não faço ideia como funciona a sintaxe CRON, bom, não sofra, tem vários sites que montam isso, eu pedi pro Bard montar.
Pronto, sua function esta criada e você tera uma estrutura parecida com essa:
functionignore - Não publica os arquivos informados nessa lista
gitinore - Quando publicado para um repositório remoto ignora os arquivos dessa lista
function_app.py - Arquivo onde ficara o código da sua function, por enquanto trabalharemos com apenas 1 arquivo Python para facilitar.
host.json - Arquivo de configuração da function, como versão, logs e outras customizações e parâmetros
local.settings.json - Informações para debug local, como Storage, você pode usar o Azurite para emular um storage local
requirements.txt - Dependências para sua App rodar, esse arquivo é necessário, caso não tenha na sua pasta, pode criar manualmente e adicionar as linhas das bibliotecas
requirements.txt
local.settings.json
host.json - O bloco em vermelho é para customizar a saida de logs na tela
function_app.py
Aqui está todo o nosso código, bem simples.
Estamos usando a biblioteca logging para printar as infos na tela
Estamos usando logging.warning e ignorando os logging.info, para ficar mais limpo
Na seta estamos instanciando a conexão com o Blob Storage utilizando a ConnectionString disponibilizada na aba de Access Keys do seu Storage, em outros posts veremos outras maneiras.
No primeiro bloco vermelho, estamos baixando um arquivo TXT e printando as informações
No segundo bloco, estamos incrementando o contador e gravando novamente no Storage
Vamos depurar localmente antes de publicar para o portal, se tudo estiver certo nas suas configurações, basta clicar em Start Debugging.
Um emulador local será iniciado, como se estivesse rodando na Azure Function literalmente, podemos fazer ajustes em tempo de execução sem mesmo precisar parar o Debug, é muito útil para ganhar tempo e evitar ficar publicando para o portal antes de estar 100%.
Aqui é nossa Function funcionando localmente (Já posso dizer que na minha máquina funciona!).
Note que estamos lendo um arquivo TXT num Blob Storage, pegando o valor da primeira linha, dando um split, incrementando o valor que veio no arquivo e depois gravando nele novamente.
Veja que o retorno do 'helloworld,{}' vai mudando a cada minuto.
Bom, mas não queremos deixar isso rodando na nossa máquina, vamos publicar agora para o Function App no Azure.
Vamos criar nossa Function App, selecione seu resource group, de um nome único e selecione a runtime Python, essas informações não são alteráveis depois.
Na parte de Hosting, vamos usar o plano de Consumption.
Na aba Storage, crie um novo storage ou selecione um já existente, depois mantenha as configurações padrão para essa demo.
Pronto, Function App criada.
Agora vamos publicar nossa Function local que já está funcionando para rodar no Azure Function App (um namespace de funções, aqui poderemos colocar outras funções).
La no VSCode, selecione a opção Deploy to Function App...
Se sua conta já estiver conectada, suas Function Apps serão listadas, selecione a criada recentemente.
Aqui é importante ressaltar que o deploy vai sobrescrever toda a Function App com as suas functions locais, então tome muito cuidado em qual Function vai publicar, nos posts futuros falaremos sobre CICD e integração com Azure Devops.
Apenas confirme a operação, note que tem o aviso conforme informei.
Após aparecer a mensagem de conclusão, vamos conferir no portal do Azure.
Agora acompanharemos os logs no portal, selecione sua Function, vá na aba Monitor, vamos ver os logs de execução.
Selecionei apenas o Log Level Warning.
Na aba Code + Test, podemos ver o código da nossa function, porém, não é possível alterar pelo portal, somente visualizar.
Temos o botão Test/Run que podemos forçar uma execução da nossa Function, seja ela com trigger de Timer ou HTTP, isso é bem útil para você não precisar esperar um evento acontecer, imagine se nossa trigger fosse com um timer de 1 vez ao dia, iria demorar muito para disparar automaticamente.
Referências:
Quanto vai custo essa brincadeira pra gente?
Extrapolando, se fizermos 100 mil execuções no mês e cada execução leve 30 segundos, não pagaremos nada.
Isso para este exemplo, pode mudar se tiver outros conectores envolvidos.
Ah, mas Reginaldo, isso não espelha a realidade, vamos para algo mais palpável.
1 execução por hora que leva 5 minutos.
Continua de graça.
Note que temos um aviso que o primeiro milhão de execução ou até 400.000 GB/s é free, somente após isso começara a cobrança.
Em resumo, para alguns cenários é muito barato.
Mas calma, falaremos mais sobre precificação e limitações.
Resumo
Esse é um tema bem extenso e em alguns contextos bem complexos, no post de hoje conhecemos a Azure Function e criamos uma função básica agendada com um Timer e lendo e escrevendo em um Storage Account, nos próximos posts vamos avançando em configurações especificas até chegarmos no Delta Lake, orquestração e configurações avançadas.
Espero que tenha gostado.
Fique bem e até a próxima.
Link para o Github:
Referências:
Comments