quinta-feira, 21 de julho de 2016

AWS - CloudFormation - Uma outra abordagem

Mais uma tentativa de tirar poeira desse blog. Inclusive pretendo tirá-lo do Blogger e migrar para o S3 com Jekyll, mas isso será motivo de uma nova postagem.

A motivação para essa postagem é a pouca cobertura que o tema (Cloudformation) tem em português. Em inglês temos diversas postagens, e temos os modelos (update: também disponíveis em português) que a Amazon nos oferece, mas eles em geral possuem arquivos gigantes que desanimam quem está tentando aprender. Então lá vai:

Definição oficial de CloudFormation:

"O AWS CloudFormation oferece aos desenvolvedores e administradores de sistemas uma maneira fácil de criar e gerenciar um grupo de recursos relacionados à AWS, e fornecê-los e atualizá-los de uma forma organizada e previsível"

Definição não-oficial:

Infrastructure-as-a-code

Por que usar:
  • Versionamento de Infra
  • Agilidade no deploy
  • Controle de dependências
  • Sem erro nas repetições
  • Outputs

Como Funciona:

O CloudFormation é um serviço da AWS que permite que você crie (através de arquivos no formato JSON ou do AWS Cloudformation Designer) um template com todos os recursos AWS que você precisa.  Ele trata as dependências, relações, ordens e caso algum recurso falhe para ser criado ou provisionado, ele cancela toda a criação.

Você não precisa saber a ordem de provisionamento dos serviços da AWS ou os detalhes para as dependências funcionarem. O CloudFormation cuida disso para você. Após a implantação dos recursos da AWS, você pode modificá-los e atualizá-los de uma forma controlada e previsível, efetivamente aplicando o controle de versão à sua infraestrutura na AWS da mesma forma que faz com o seu software.

Também traz uma maneira segura de undeploy, caso você precise remover ele se encarregará de "desprovisionar" todos os recursos relacionados à aquele CloudFormation.

Não há custo para o uso, somente o custo dos recursos que ele provisionar serão faturados.


Sugestão de abordagem:

Uma das dificuldades no aprendizado do cloudformation é que todas as documentações possuem enormes arquivos JSON com uma pilha completamente configurada. Para alguns casos essa abordagem é interessante, mas para aprendizado sugerimos uma abordagem dividida.

Ao invés de um arquivo contendo todos os recursos, vamos utilizar mais de um arquivo.

Vantagens:
  • Simplicidade
  • Reuso de código
  • Diversas equipes subindo itens em um ambiente já provisionado
Desvantagens:
  • Falta de dependências (falaremos mais sobre isso)
  • Tendência para perda de controle do ambiente
Mão na massa:

Como falado anteriormente, o cloudformation utiliza o formato JSON e no nosso exemplo criaremos um VPC em um arquivo. E depois, em um arquivo adicional, criaremos uma instância EC2.

O primeiro arquivo pode ser baixado aqui e o segundo aqui.

Faça download do primeiro arquivo e no console da amazon acesse:

Cloudformation -> Create Stack -> Upload a template do Amazon S3 -> selecione o arquivo -> next

Nessa tela preencha o nome da sua Stack. Algumas já estão preenchidas, caso queira pode mudar, caso contrário pode clicar em next -> next -> Create

Em alguns instantes você terá um VPC novo e configurado com o seguinte:

  • Internet Gateway
  • Duas subnets públicas com route table para o Internet Gateway
  • Duas subnets privadas
  • Security Group liberando somente as subnet publicas para acesso
  • Security Group liberando porta 22, 3389 e ICMP do IP da sua empresa

Vamos para o segundo arquivo:

Escolha chave SSH, Subnet (alguma das criadas anteriormente) e Security group (algum dos criados anteriormente) que serão utilizados.


Pronto! Temos uma instância EC2 rodando dentro do VPC na Subnet desejada.
Selecione a sua stack e vá até a aba outputs, você deve ter algo semelhante a isso:


Um pouco de teoria:
Os nossos arquivos CloudFormation são compostos por 4 sessões (clique nos nomes, para acessar a documentação):

  1. Parameters: São as informações que precisamos que sejam informados pelo usuário, no nosso caso os endereços de rede de VPC e a chave SSH são alguns exemplos.
  2. Mappings: São as constantes condicionais que estarão presentes. No nosso caso, temos para a instância EC2 o mapeamento da AMI que queremos, para cada região que a instância pode ser lançada.
  3. Resources: Recursos que serão criados pelo template, no nosso caso temos desde a instância em si, até tabela de roteamento e security group
  4. Outputs: Retorno que queremos para acesso, documentação ou automações (Cloudformation também funciona em CLI ;) ).
Casos de uso:

Nesse exemplo podemos ter uma equipe de infra que criou o VPC e dentro dele, outras equipes podem lançar seus EC2, sem impactar no que foi feito pela equipe de infra e seguindo um padrão, previamente definido.

Porém este cenário é didático, para o dia-a-dia um arquivo monolítico pode ser mais seguro. Imagina nesse caso que alguém resolver remover o cloudformation do VPC. Ele vai tentar apagar tudo, mas não conseguirá pela existência de instâncias rodando. Mas pela característica do CloudFormation ele vai conseguir apagar o Internet Gateway antes de perceber isso. Logo suas instâncias ficarão sem conectividade.

Assim é preferível para o cotidiano um arquivo só e as alterações podem ser feitas no Cloudformation, consulte a documentação para ver se haverá algum tipo de indisponibilidade na sua alteração.

Comentando a sessão resources do EC2 (estamos desconsiderando as chaves):
  1. "Ec2Instance" - Nome do recurso que pode ser referenciado em outros recursos e nos Outputs.
  2. "Type" : "AWS::EC2::Instance - Tipo do recurso 
  3. "Properties" : - Propriedades
  4. "ImageId" : { "Fn::FindInMap" : [ "RegionMap", { "Ref" : "AWS::Region" }, "AMI" ]} - Imagem que vai ser usada, ele verifica a região que você está usando (no console ou na CLI), para verificar qual AMI deve ser utilizada.
  5. "KeyName": { "Ref": "KeyName"  - Chave escolhida pelo usuário, na sessão parameters
  6. "InstanceType" : "m1.small" - Tamanho da instância, neste caso padronizamos m1.small
  7. "NetworkInterfaces" : - Sub sessão networkInterfaces
  8. "GroupSet" : [{ "Ref" : "SecurityGroupIds" }] - Security Group escolhido pelo usuário, na sessão parameters
  9. "DeviceIndex" : "0", - Ordem que a interface de rede será anexada. Neste caso será a primeira placa de rede
  10. "DeleteOnTermination" : "true" - Será removida quando a máquina for terminada
  11. "SubnetId" : { "Ref" : "SubnetId" } - Subnet escolhida pelo usuário, na sessão parameters
É isso. Espero que esse exemplo sirva de inspiração para que você comece a utilizar Cloudformation na sua conta AWS. Fique a vontade para copiar e para tirar dúvidas aqui nos comentários.











Nenhum comentário: