fesousa / dataops-lab4

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DataOps - Laboratório 4

Coleta de Dados com Lambda, Eventos e implantação com Github e Jenkins

As instruções do laboratório estão em português. Para alterar o idioma, procure a opção na barra inferior do console AWS.

Objetivos

  • Configurar Jenkins para construir a aplicação e implantar na AWS
  • Utilizar Github para integrar e implantar com Jenkins
  • Criar uma função Lambda para coleta de dados, disparada por um evento agendado
  • Implantar uma Função Lambda utilizando AWS SAM, Jenkins e Github

Arquitetura da solução

Função Lambda para coletar dados

  1. No seu ambiente do Cloud9, crie uma nova pasta lab4 e dentro dela uma outra pasta app. Dentro da pasta app crie um arquivo lambda_function.py

  2. Coloque o seguinte código no arquivo

Este código faz o download do arquivo de um arquivo de vacinação disponível aqui e copie para o bucket criado no Laboratório 1 (nome sugerido foi dataops-dados-nomesobrenome, sendo que nomesobrenome deve ser seu nome e sobrenome; ou entáo coloque o nome do bucker que criou no Laboratório 1 , se for diferente)

import requests, boto3, asyncio, math

async def upload_s3_async(init, end, i, url, bucket, key, s3, mpu):
    print(f'Upload {i}')
    # download do pedaço do arquivo
    r = requests.get(url,  headers={'Range':f'bytes={init}-{end}'})    
    #upload para o S3
    return s3.upload_part(Bucket=bucket, Key=key, PartNumber=i, UploadId=mpu['UploadId'], Body=r.content)

async def upload_s3(url, bucket, key, s3, mpu):
    # separar arquivo em pedaços de 50 MB
    b = 52428800
    t = int(requests.head(url).headers['Content-Length'])
    parts, tasks = [], []
    for i in range(math.ceil(t/b)):
        init = i*b if i == 0 else i*b + 1
        end = min((i+1)*b, t)
        if t-end < 6291456: end = t        
        tasks.append(asyncio.ensure_future(upload_s3_async(init, end, i+1, url, bucket, key, s3, mpu)))

    # executar coleta dos pedaços do arquivo
    return await asyncio.gather(*tasks)

def lambda_handler(event, context):
    # url que virá pelo parâmetro
    url = event['url']
    # nome do bucket para upload
    bucket = 'dataops-dados-nomesobrenome'
    #nome do arquivo que será salvo no bucket
    key = f'input/vacinas_{event["uf"]}.csv'
    #Concexão com s3
    s3 = boto3.client('s3')
    # iniciar upload multipart
    mpu = s3.create_multipart_upload(Bucket=bucket, Key=key)

    #fazer download do arquivo por partes    
    parts = asyncio.get_event_loop().run_until_complete(upload_s3(url, bucket, key, s3, mpu))
            
    # finalizar upload
    part_info = {'Parts': 
        [{'PartNumber': i+1, 'ETag': p['ETag']} for i, p in enumerate(parts)]    
    }
    s3.complete_multipart_upload(Bucket=bucket, Key=key, UploadId=mpu['UploadId'], MultipartUpload=part_info)

    return True
  1. Criar função Lambda no Console AWS

    3.1. No console da AWS procure pelo serviço Lambda

    3.2. Na tela do serviço, clique em

    3.3. Na próxima tela, preencha os seguintes campos:

        a. Nome da função: dataops-coleta-vacinas

        b. Tempo de execução: Python 3.7

        c. Abra a seção

        d. Selecione

        e. Em selecione

        O lambda precisa de permissão para usar o S3. A função (IAM Role) selecionado da essa permissão

        f. Clique em

  2. Você será redirecionado para a tela da função criada. Agora é preciso configurá-la

    4.1. Na seção remova o conteúdo do arquivo que está aberto e cole o código do arquivo lambda_function.py criado no Cloud9 .

    4.2. Clique em

    4.3. Selecione a aba

    4.4. Nas opções da esquerda, selecione

    4.5. Clique em para alterar o tempo máximo de execução da função e a quantidade de memória

    4.6. Em coloque 512 MB

    4.7. Em coloque 15 minutos

    4.8. Clique em

  3. Testar a função

    5.1. Selecione a aba

    5.2. Na caixa de texto onde está a string JSON, troque pelo seguinte, para coletar os dados de vacina do Acre:

    Pegue um link de arquivo de vacinação aqui: https://opendatasus.saude.gov.br/dataset/covid-19-vacinacao/resource/5093679f-12c3-4d6b-b7bd-07694de54173. Clique com o botão direito em um dos arquivos do Acre e clique em "Copiar endereço do link". Coloque este link no lugar de LINK no JSON abaixo.

    {
      "url":"LINK", 
      "uf":"ac"
    }

    O evento de teste ficará assim:

    5.3. Clique em

    5.4. Espera a função terminar de executar

    5.5. Expanda para ver os resultados. Você deve ver a mensagem true na área branca. Se não vir, verifique o log mais abaixo e verifique o nome do bucket

    5.6. Abra o seu bucket de dados (dataops-dados-nomesobrenome, ou o nome criado no lambda_function.py ) e verifique o arquivo baixado

Template SAM para a função lambda

  1. No Cloud9 crie um novo arquivo template.yaml na pasta lab4

  2. Coloque o seguinte código no arquivo. Veja os comentários para entender o que cada declaração faz. Lembre-se de pegar uma nova URL de dados de vacina (como fez para testar a função lambda anteriormente) e substituir em LINK (valor da url no json em Input)

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Coleta de dados.
Resources:
  # Criar função lambda agendada
  lambdafunction:
    Type: 'AWS::Serverless::Function'
    Properties:
      FunctionName: dataops-coleta-vacinas-ci-cd # nome da função
      Handler: lambda_function.lambda_handler # nome do arquivo e método de onde está a função
      Runtime: python3.7 # ambiente de execução
      CodeUri: ./app # local onde estarão os arquivos da função
      Description: Coletar dados de vacinas.
      MemorySize: 512 # memória utilizada pela funçãop
      Timeout: 900 # tempo máximo de execução, em segundos
      Role: !Sub arn:aws:iam::${AWS::AccountId}:role/LabRole # IAM role da função para permissões a outros recursos da AWS
      Events: # Evento agendado para execução
        ScheduledFunction:
          Type: Schedule
          Properties:
            Schedule: cron(15 00 * * ? *) # executa todo dia às 10:15
            Name: dataops-agenda-coleta-vacina
            Input: '{
              "url":"LINK", 
              "uf":"ac"
            }' # evento com parâmetros que serão enviados para a função lambda
            # OBS: Pegue um link de arquivo de vacinação aqui: https://opendatasus.saude.gov.br/dataset/covid-19-vacinacao/resource/5093679f-12c3-4d6b-b7bd-07694de54173. Clique com o botão direito em um dos arquivos do Acre e clique em "Copiar endereço do link". Coloque este link no lugar de LINK (valor da url no JSON acima).
  1. Crie um repositório dataops-lab4 no seu GitHub e adicione a pasta lab4 nesse repositório.

    3.1. Veja o Laboratório 3 e o material de aula para lembrar como vincular a pasta no repositório e autenticar no Github

Configurar Jenkins para fazer CI/CD da função lambda

  1. Inicie seu ambiente da AWS como fez nos laboratórios anteriores

  2. Ainda na tela do laboratório no AWS Academy, clique em

  3. Clique em para baixar a chave SSH para acessar as instâncias EC2

  1. Acesse o console da AWS

  2. Verifique se a instância EC2 criada na no Laboratório 3 está ligada. Se não, inicie a instância. A instância deve ficar parecida com a imagem abaixo:

  1. Na barra superior, clique em para abrir um console de linha de comando do AWS CloudShell e espere iniciar

  1. Faça o upload da chave SSH que acabou de baixar (labsuser.pem) para o CloudShell

    7.1. Clique em

    7.2. Selecione a opção

    7.3. Procure e selecione o arquivo labsuser.pem que baixou

    7.5. Espere o arquivo ser carregado. Aparecerá a seguinte mensagem no canto inferior direito

    7.6. No terminal do CloudShell digite ls e verifique a presença do arquivo

  2. Ainda no terminal, digite o seguinte comando para mudar a permissão de acesso à chave SSH:

chmod 400 labsuser.pem
  1. Acesse a instância EC2 do Jenkins pela linha de comando

    9.1. Volte ao console da AWS, no serviço do EC2

    9.2. Selecione a instância ec2-jenkins criada na aula anterior

    9.3. No painel inferior, em copie o clicando em

    9.4. Volte à tela do AWS CloudShell e digite o seguinte comando para acessar a instância EC2. Troque <IP-INSTANCIA> pelo IP copiado no passo anterior

    ssh -i labsuser.pem ec2-user@<IP-INSTANCIA>

    9.5. Confirme a conexão digitando yes

    9.6. Se a conexão deu certo, você verá a linha de comando iniciando com ec2-user

  2. Conectado na instância, precisamos recuperar a senha de administrador do Jenkins

    10.1. Na linha de comando digite:

    sudo cat /var/lib/jenkins/secrets/initialAdminPassword

    10.2. Copie e guarde o valor alfanumérico que aparecer no terminal

  3. Em uma nova aba do navegador, acesse o Jenkins escrevendo <IP-INSTANCIA>:8080. Por exemplo: 12.345.6.789:800. O IP é o mesmo utilizado para conectar na instância pelo terminal

  4. Coloque a senha do administrador no campo de texto e clique em

Essa é a senha do administrador. Quando acessar o Jenkins novamente, será solicitado o usuário e senha. Utilize o usuário “admin” e a senha que acabou de copiar

  1. Na tela de customização, clique em Instalar as extensões sugeridas e aguarde a instalação ser finalizada

  1. Assim que instalação terminar, na nova tela clique em Pular e continuar como administrador

  1. Na próxima tela clique em Gravar e concluir

  1. Por fim, clique em Começar a o Jenkins

Configurar credenciais do Github

  1. No seu repositório, clique no seu perfil no canto superior direito e depois em Settings

  1. No menu lateral procure por (última opção)

  2. No novo menu lateral clique abra Personal access tokens e clique em Token (classic)

  1. Clique na opção Generate new token e depois em Generate new token (classic)

  2. Preencha um nome no campo Note

  3. Defina a data de expiração (Expiration) para 90 dias

  4. Em Select scopes selecione as opções conforme imagem abaixo:

  1. Clique em Generate token

  2. Na página seguinte será mostrado o personal access token gerado, no campo com fundo verde. Ele funciona como uma senha para acessar o github a partir de aplicações. Guarde esse token, o github não mostra mais ele. Se perder, terá que gerar outro e reconfigurar tudo que usa o token.

Criar pipeline no Jenkins

  1. Volte ao Jenkins. Na página inicial do Jenkins clique em Gerenciar Jenkins no menu lateral

  2. Clique em Tools - Configurar ferramentas, suas localizações e instaladores automáticos.

  1. Procure pela seção Git installations

    3.1. Remova a opção Git, clicando no X

3.2. Clique no botão `Add Git` e depois em `JGit`
  1. Clique em Save

  2. Volte à pagina inicial do jenkins e clique em no menu lateral

  3. Clique em Credentials - Configure credentials

  1. Clique em (global)

  1. Clique no botão

  2. Na próxima tela coloque seu usuário do github no campo Username, o token gerado anteriormente no campo Password e clique em Create

  1. Volte a tela inicial do Jenkins e clique em Novo tarefa

  1. Configure o nome da tarefa para DataOpsDeployColeta

  2. Selecione a opção Pipeline

  3. Clique em Tudo certo

  1. Na tela de configuração do pipeline, procure pela seção Build Triggers e selecione

  1. Aida na mesma tela, procure pela seção Pipeline

  2. Em Definition selecione Pipeline script from SCM e configure conforme a imagem abaixo. Troque os seguintes valores pelas suas configurações:

    • Repository URL: URL do seu repositório do lab 4

    • Credentials: selecione a credencial criada anteriormente

    • Branch Specifier (blank for 'any'): Coloque a sua branch principal (provavelmente main)

  3. Clique em Aplicar e depois em Salvar

Configurar webhook no Github

  1. Volte ao Github e abra seu repositório do Lab4

  2. Clique em no menu superior e depois em Webhooks no menu lateral

  3. Clique em Add webhook E CONFIGURE O SEGUINTE:

    • Payload URL: http://{IP_JENKINS_EC2}:8080/github-webhook/ Troque {IP_JENKINS_EC2} pelo IP da sua instância EC2. Repare na barra no final da URL

    • Content type: application/json

  4. Clique em Add webhook

  1. Quando voltar a lista de webhooks você deve ver um check ao lado do webhook. Atualize a página caso não veja o check. Se aparecer um alerta, verifique as configurações do webhook.

Executar pipeline Jenkins

  1. No Cloud9, crie o arquivo Jenkinsfile na pasta lab4 com o seguinte conteúdo. Na configuração S3_BUCKET, troque o valordataops-deploy-nomesobrenome-accountID-regiao pelo bucket criado no Laboratório 2
pipeline {
  agent any
 
  stages {
    stage('instalar sam-cli') {
      steps {
        sh 'python3 -m venv venv && venv/bin/pip install aws-sam-cli'
        stash includes: '**/venv/**/*', name: 'venv'
      }
    }
    stage('deploy') {
      environment {
        STACK_NAME = 'dataops-coleta-vacinas-stack'
        S3_BUCKET = 'dataops-deploy-nomesobrenome-accountID-regiao'
      }
      steps {
        unstash 'venv'        
        sh 'venv/bin/sam build'
        stash includes: '**/.aws-sam/**/*', name: 'aws-sam'
        unstash 'aws-sam'
        sh 'venv/bin/sam package --region us-east-1 --s3-bucket $S3_BUCKET'
        stash includes: '**/.aws-sam/**/*', name: 'aws-sam'
        sh 'venv/bin/sam deploy --stack-name $STACK_NAME --region us-east-1 --capabilities CAPABILITY_IAM --s3-bucket $S3_BUCKET'
      }
    }   
  }
}
  1. Envie os arquivos para o github e acompanhe a execução no Jenkins. Se não executar automaticamente, abra a o pipeline criado no Jenkins e clique em Construir agora. As próximas alterações no repositório devem iniciar o pipeline automaticamente. Faça alguma alteração em algum arquivo do lab4, envie para o github e veja a execução automática do pipeline.

  2. Acompanhe a execução no Jenkins e espere completar com sucesso

  1. Verifique se a função lambda dataops-coleta-vacinas-ci-cd foi criada

  2. Verifique no serviço EventBridge o evento criado e o horário de execução

    14.1. Esse evento irá executar automaticamente no horário definido no template e disparar a função AWS

    14.2. No EventBridge, acesse Regras no menu lateral esquerdo para abrir as regras de execução automática.

    14.3. Clique na regra “dataops-agenda-coleta-vacina”

    14.4. Nos detalhes da regra, clique em

    14.5. Vá até a seção e na caixa de seleção ao lado de selecione a opção para ver qual a próxima execução no horário de Brasília

    14.6. Se o horário já passou ou ainda está longe (pode ser que seja só amanhã), altere no template do SAM na propriedade Schedule dentro de Events a hora da execução para daqui 10 minutos, envie para o repositório e espere a atualização da função pelo pipeline. O horário da AWS fica 3 horas adiantando ao horário atual. Então no agendamento coloque 3 horas a mais do horário atual. Por exemplo, se for 21:00 no seu relógio, coloque a execução para às 00:10 (cron(10 00 * * ? *) – o primeiro número são os minutos e o segundo são as horas). Assim o evento passa a executar todos os dias as 21:10.

© 2022 Fernando Sousa

Last update: 2023-09-03 13:29:35

About

License:MIT License


Languages

Language:Python 74.6%Language:Shell 25.4%