Category: AWS Partner Solutions Architect (SA) Guest Post


Simplificando a gestão de repositórios git com o AWS CodeCommit

Por Glauber Gallego e Angelo Carvalho, Partner Solution Architects

O AWS CodeCommit  é um serviço gerenciado pela AWS para hospedagem de repositórios git de forma segura, durável, escalável e que funciona com as ferramentas git que você já está acostumado. O AWS CodeCommit armazena seus arquivos em repositórios criptografados e utiliza roles IAM para controlar o acesso de desenvolvedores e administradores.

Para ganharmos experiência com o AWS CodeCommit, vamos espelhar o repositório oficial AWS-SDK-Javascript e operá-lo com as novas credenciais git com autenticação via HTTPS, funcionalidade lançada em 22 de dezembro de 2016. Com este método de autenticação, os desenvolvedores podem utilizar credenciais git diferentes de seus usuários IAM. Isso elimina a necessidade do AWS CLI instalado e configurado nas máquinas dos desenvolvedores, permite cache de credenciais com ferramental git nativo e facilita ainda mais o uso de IDEs como o Visual Studio e o Eclipse.

Neste post, vamos caminhar passo a passo na criação de um repositório AWS CodeCommit, gerar credenciais git (lembre-se, essas credenciais são diferentes de usuários IAM) e realizar o espelhamento de um repositório oficial da AWS. Dica: Para os impacientes, condensamos (quase) todos esses passos em um template de AWS Cloudformation, vá diretamente à sessão ‘Automação de espelhamento de repositórios com o AWS Cloudformation‘.

 

Instruções passo a passo para espelhamento de um repositório

 

Passo 1. Acesso a Conta

Abra o AWS Console e faça logon com um usuário IAM. Se você estiver utilizando um usuário root, siga estas instruções para criação de um usuário IAM Administrador e faça logon com ele.

imagem-0a

 

Passo 2. Acesse o serviço AWS CodeCommit

Escolha uma região que possua o serviço AWS CodeCommit, neste post iremos utilizar a região Virgínia. Selecione o serviço AWS CodeCommit.

imagem-0b

 

Passo 3. Crie um repositório

Crie um novo repositório com o nome aws-sdk-js.

Imagem-1

Após criar o repositório, você é automaticamente direcionado para a página com instruções de conexão ao repositório.

Nota: Se por algum motivo você saiu da página de instruções de acesso, é possível visualizá-la novamente ao clicar no botão “Connect” ao lado direito do repositório.

Imagem-2

Nota: Esta página contém as instruções de acesso com credenciais git via HTTPS apenas se você estiver logado como um usuário IAM.

 

Passo 4. Geração de credenciais git

Como comentamos, vamos gerar novas credenciais git com autenticação via HTTPS. Clique no link “IAM User” e seremos direcionados para o serviço IAM para criar as credenciais git.

imagem-3

Nota: Se você seguiu as instruções do passo 1, você estará logado como um usuário IAM Administrador. Este usuário é bastante poderoso e pode executar todo tipo de ação no console AWS. Para maior nível de segurança, recomendamos a criação de um usuário exclusivo para uso do git (ex: committer) com apenas as permissões “IAMSelfManageServiceSpecificCredentials” e “IAMReadOnlyAccess”. Essas permissões são o mínimo necessário para acesso ao AWS CodeCommit com credencias git via HTTPS. Para este post, seguiremos com o usuário IAM Administrador.

Para geração das credenciais, selecione a aba “Security credentials”, vá ao final da página e clique no botão “Generate” dentro da sessão “HTTPS Git credentials for AWS CodeCommit” e faça download das credenciais (Atenção: essa é a única oportunidade para visualizar ou baixar as credenciais).

Imagem-4

 

Passo 5. Obtenha a URL HTTPS do repositório

Volte para a página do serviço AWS CodeCommit e copie o link HTTPS para clonar o repositório.

Imagem-5

 

Passo 6. Clone o repositório

Vá ao terminal ou linha de comando e digite:

git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/aws-sdk-js

Quando requisitado, entre com as credenciais git (username e password) que você gerou anteriormente. Note que não é necessário ter o AWS CLI instalado em sua máquina, o único requisito é o cliente git (ou uma IDE como o Visual Studio ou o Eclipse).

 

Passo 7. Envie o conteúdo do repositório aws-sdk-js para o AWS CodeCommit

Neste ponto, seu repositório deverá está vazio. Para preenchê-lo com o conteúdo do repositório AWS-SDK-Javascript iremos clonar o repositório oficial em outro diretório (ex: TEMP-aws-sdk-js’), limpar os metadados do git (removendo o diretório .git) e enviar o conteúdo ao repositório do AWS CodeCommit. Note que neste método de espelhamento, perderemos todo o histórico, notas, tags e branches do repositório original, como nossa intenção é de experimentação com o serviço AWS CodeCommit essa é uma opção rápida e eficaz.

git clone https://github.com/aws/aws-sdk-js TEMP-aws-sdk-js
rm -rf TEMP-aws-sdk-js/.git/
cp -r TEMP-aws-sdk-js/* aws-sdk-js/
rm -rf TEMP-aws-sdk-js
cd aws-sdk-js/
git add *
git commit -m "First commit"
git push

Nota: Se você deseja realizar o espelhamento de repositórios incluindo o histórico do repositório original (ex: notas, refs, tags e branches), veja referencias do comando git clone / git push com a opção –mirror em https://git-scm.com/docs/git-clone#git-clone—mirror e https://git-scm.com/docs/git-push#git-push—mirror.

 

Passo 8. Acesso ao repositório via AWS Console

Pronto, seu repositório está preenchido, pronto para receber comandos git e pode ser visualizado diretamente no console AWS.

Imagem-6

 

O AWS CodeCommit possui um nível gratuito (e que não expira ao final de 12 meses) com repositórios ilimitados para até 5 usuários, 50GB de armazenamento e 10.000 requisições git/mês. Acima de 5 usuários o custo é de US$ 1 / mês. Se ainda assim você quiser remover seu repositório, acesse o repositório, clique em ‘Settings’ e em seguida em ‘Delete repository’ ao final da página.

imagem-7

 

Automação de espelhamento de repositórios com o AWS Cloudformation

 

Para facilitar sua experimentação com o AWS CodeCommit, criamos um template de AWS Cloudformation que automatiza (quase) todos os passos de 1-9 que vimos até aqui. A exceção é o passo 4, pois você precisará possuir credenciais git para acesso HTTPS. Note que se você já executou os passos de 1-9, você já possui as credencias e pode pular a geração descrita no próximo paragrafo.

Geração de credenciais git:

  • Acesse o serviço IAM e selecione um usuário com as permissões “IAMSelfManageServiceSpecificCredentials” e “IAMReadOnlyAccess” (se você estiver utilizando um usuário IAM Administrador ele já possui essas permissoes). Essas permissoes são necessárias para acesso ao AWS CodeCommit com credencias git via HTTPS.
  • Para geração das credenciais, selecione a aba “Security credentials”, vá ao final da página e clique no botão “Generate” dentro da sessão “HTTPS Git credentials for AWS CodeCommit” e faça download das credenciais (Atenção: essa é a única oportunidade para visualizar ou baixar as credenciais).
  • Veja o passo 4 com screenshots da geração das credenciais.

O template de AWS Cloudformation pode ser conferido aqui. Os recursos AWS criados pelo template são:

  • um repositório AWS CodeCommit;
  • uma função AWS Lambda (veja aqui) que será executada apenas durante a inicialização do repositório;

Para executá-lo, clique aqui.

launch_stack

E siga as instruções a seguir:

  1. Informe uma URL de um projeto do GitHub. Exemplo: https://github.com/aws/aws-sdk-php
  2. Informe um nome de repositório ainda não utilizado em seu AWS CodeCommit. Exemplo: aws-sdk-php
  3. Informe suas credenciais git com acesso https (username)
  4. Informe suas credenciais git com acesso https (password)

Imagem-8

 

Notas para todos os usuários:

  • O template de AWS Cloudformation utiliza AWS Lambda para espelhar o repositório, portanto está limitado a 5 minutos de execução e 512MB de espaço de repositório. Repositórios grandes ou com muitos objetos podem não terminar o espelhamento a tempo
  • Não é possível atualizar a stack de AWS Cloudformation para espelhar um novo repositório. Novos espelhamentos requerem novas stacks de AWS Cloudformation
  • ATENÇÃO: Remoção de stacks de AWS Cloudformation removem os repositórios AWS CodeCommit associados!

 

Notas para usuários avançados:

  • Vale a pena conferir o template de AWS Cloudformation (veja aqui), ele cria o repositório com o recurso AWS::CodeCommit::Repository e o inicializa via AWS Lambda com recursos customizados via AWS::CloudFormation::CustomResource
  • Vale a pena conferir o código AWS Lambda associado ao AWS Cloudformation (veja aqui), ele instala e configura um cliente git dentro do contexto de execução do AWS Lambda

 

O AWS CodeCommit possui um nível gratuito (e que não expira ao final de 12 meses) com repositórios ilimitados para até 5 usuários, 50GB de armazenamento e 10.000 requisições git/mês. Acima de 5 usuários o custo é de US$ 1 / mês. Se ainda assim você quiser remover seu repositório, delete a Stack de Cloudformation e todos os recursos associados (repositório AWS CodeCommit e função AWS lambda) serão removidos.

 

Automatizando o Start/Stop das suas Instâncias EC2

Por Angelo Carvalho e Glauber Gallego, Partner Solution Architects

Dentre as muitas vantagens da computação em nuvem, uma das principais é o provisionamento sob demanda. O cliente provisiona recursos, como servidores e storage, somente quando eles são realmente necessários, pagando somente pelo que utiliza. Na maioria dos casos, os ambientes de desenvolvimento e qualidade, só são necessários em horário comercial. Algumas vezes isso também é verdade para ambientes de produção. Um bom exemplo disso são os ERPs em empresas que não operam fora do horário de expediente.

Considerando que um mês tem em média 30.5 dias, chegamos a um total de 732 horas, sendo 192 horas úteis. Considerando que os seus servidores ficarão ligados somente em horário comercial, você poderia ter uma economia aproximada de até 73% com o custo dos servidores EC2, caso os mantenha desligados no momento em que não são necessários. Importante lembrar que esta economia é referente somente ao EC2. Os custos com o block storage (EBS) não param quando as suas instâncias EC2 são desligadas.

Existem várias maneiras de se agendar o ligar/desligar dos servidores. Alguns parceiros da AWS oferecem excelentes produtos para isso. Se você procura por uma solução mais completa, faça uma pesquisa na web ou consulte o nosso marketplace em: https://aws.amazon.com/marketplace.

Se você procura uma solução mais simples para fazer este agendamento, pode utilizar o AWS Lambda para isso. O AWS Lambda permite a execução de funções escritas em Java, Node.js, C#, e Python. Você pode usar o Lambda para criar, executar e agendar desde funções simples até aplicações completas. Estamos disponibilizando duas funções que podem ser utilizadas para agendar o start/stop dos seus servidores. Siga as instruções a seguir para criar e agendar a execução das funções:

1) Abra o AWS console e escolha uma região que possua o serviço AWS Lambda. Neste tutorial iremos escolher a Região Virgínia;
2) Clique no botão: “Create a Lambda Function”. Selecione o blueprint “Blank Function”;
3) Na tela “Configure Triggers”, simplesmente clique “Next”. Podemos configurar o agendamento mais tarde;
4) Dê um nome para a sua função. Vamos começar pela função que inicia as instâncias. Neste tutorial usaremos o nome “start_ec2_instances”;
5) Escolha Python 2.7 como Runtime;
6) Copie e cole o conteúdo da função abaixo;

import boto3
import sys, traceback
from datetime import datetime
from time import sleep

def start_ec2_instances():
    start_time = datetime.now()

    # starting ec2 client
    ec2_client = boto3.client('ec2')

    regions = ec2_client.describe_regions()

    for region in regions['Regions']:
        try:
            print("Region: " + str(region['RegionName']))
            ec2_client = boto3.client('ec2', region_name=region['RegionName'])
            instances = ec2_client.describe_instances()
            instanceIds = list()
            
            for reservation in instances['Reservations']:
                for instance in reservation['Instances']:
                    if instance['State']['Name'] == "stopped" and not instance['Tags'] is None : 
                        for tag in instance['Tags']:
                            try:
                                if tag['Key'] == 'ScheduledStartStop' and tag['Value'] == 'True'    :
                                    instanceIds.append(instance['InstanceId'])
                            except:
                                print "Not expected error: ", traceback.print_exc()
                      
            if len(instanceIds) > 0 : 
                print "Starting instances: " + str(instanceIds)
                ec2_client.start_instances(InstanceIds=instanceIds)                                                   
                                                            
        except:
            print "Not expected error:", traceback.print_exc()
                                                           
    end_time = datetime.now()
    took_time = end_time - start_time
    print "Total time of execution: " + str(took_time)    

def lambda_handler(event, context):
    print('Starting instances... ')
    start_ec2_instances()

 

7) No campo “Role”, selecione a opção “Create a Custom Role”;
8) Escolha a opção “Create a new IAM Role” para o campo “IAM Role” e dê um nome para a sua Role. Neste tutorial usaremos o nome “start_stop_instances” e vamos reutilizar posteriormente esta Role para a função que pára as instâncias;
9) Clique em “View Policy Document”, depois em “Edit”. Copie e cole o conteúdo da policy abaixo:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeInstances",
        "ec2:DescribeRegions",
        "ec2:StartInstances",
        "ec2:StopInstances"
      ],   
      "Resource": "*"
    }	
  ]
}

10) Altere o Timeout para 5 minutos;
11) Clique “Next”, e depois em “Create Function”;
12) Clique no botão “Test” para testar a função.
13) Se a função rodou sem erros, é hora de criar o agendamento;
14) Clique na aba “Triggers”, em em “Add Trigger”;
15) Selecione a opção “CloudWatch Events – Schedule”;
16) Dê um nome para a sua regra. Neste tutorial, usaremos o nome “Start_Instances”;
17) Coloque uma expressão cron no campo “Schedule expression” que represente os dias e horários que você deseja executar a sua função. Para rodar de segunda a sexta feira às 8 da manhã, use a expressão “cron(0 10 ? * MON-FRI *)”. Perceba que a expressão usa o fuso horário UTC. Como atualmente (horário de verão) temos uma diferença de duas horas, usaremos 10 em vez de 8 para representar a hora de início;
18) Clique em submit e pronto, a sua função já está agendada;
19) A função acima só atuará em instâncias que possuam a Tag “ScheduledStartStop” com o valor “True”. Logo, adicione esta tag nas instâncias que você deseja que sejam iniciadas/paradas automaticamente;

Agora que você já configurou a sua primeira função Lambda, basta repetir os passos acima e criar a função que pára as instâncias, mas usando o script abaixo e alterando o horário do agendamento:

import boto3
import sys, traceback
from datetime import datetime
from time import sleep

def stop_ec2_instances():
    start_time = datetime.now()

    # starting ec2 client
    ec2_client = boto3.client('ec2')

    regions = ec2_client.describe_regions()

    for region in regions['Regions']:
        try:
            print("Region: " + str(region['RegionName']))
            ec2_client = boto3.client('ec2', region_name=region['RegionName'])
            instances = ec2_client.describe_instances()
            instanceIds = list()
            
            for reservation in instances['Reservations']:
                for instance in reservation['Instances']:
                    if instance['State']['Name'] == "running" and not instance['Tags'] is None : 
                        for tag in instance['Tags']:
                            try:
                                if tag['Key'] == 'ScheduledStartStop' and tag['Value'] == 'True'    :
                                    instanceIds.append(instance['InstanceId'])
                            except:
                                print "Not expected error: ", traceback.print_exc()
                      
            if len(instanceIds) > 0 : 
                print "Stopping instances: " + str(instanceIds)
                ec2_client.stop_instances(InstanceIds=instanceIds, Force=False)                                                   
                                                            
        except:
            print "Not expected error:", traceback.print_exc()
                                                           
    end_time = datetime.now()
    took_time = end_time - start_time
    print "Total time of execution: " + str(took_time)    

def lambda_handler(event, context):
    print('Stopping instances... ')
    stop_ec2_instances()

Pronto! Agora é só aproveitar a economia na sua próxima fatura mensal da AWS!