# Criando um deploy automatizado com GitHub Actions, AWS e Docker
## AWS IAM
### Introdução
O IAM faz o gerenciamento da parte de identificação e acesso aos serviços da AWS. Para o correto funcionamento de todas as funcionalidades do deploy, vamos criar duas funções do IAM, uma para o CodeDeploy acessar o EC2, e outra para o EC2 utilizar o SSM (que concede acesso ao System Manager) e possibilitar a comunicação com o CodeDeploy. Pot último, vamos criar um usuário do IAM, para o GitHub acessar posteriormente o CodeDeploy.
### Função para o CodeDeploy
Acesse o IAM, clique em Funções e em sequência Criar Função. Agora vamos executar as etapas:
- **Etapa 1 - Confiança**
* **Selecionar tipo de entidade confiável**: Serviço da AWS
* **Escolha um caso de uso**: EC2
- **Etapa 2 - Permissões**
* **Attach políticas de permissões**: devem ser selecionadas as seguintes políticas:
- *AdministratorAccess*
- *AmazonEC2FullAccess*
- *AmazonEC2RoleforAWSCodeDeploy*
- *AWSCodeDeployRole*
* **Definir limite de permissões**: Criar role sem limite de permissões
- **Etapa 3 - Tags**
* **Adicionar tags**: não é obrigatório, mas pode ser utilizado para facilitar a identificação e agrupamento da função na AWS.
- **Etapa 4 - Revisar**
* **Nome da função**: CodeDeployRole
* **Descrição da função**: Permite o acesso à EC2 a partir do CodeDeploy para execucao de todas etapas do deploy
* **Entidades confiáveis**: Serviço da AWS: ec2.amazonaws.com
* **Políticas**: *AdministratorAccess*, *AmazonEC2FullAccess*, *AmazonEC2RoleforAWSCodeDeploy*, *AWSCodeDeployRole*
* **Limite de permissões**: Limite de permissões não definido
Por ultimo clique em *Criar a função*.
Na sequência abra a função criada, clique na aba *Relações de confiança* e em *Editar Relações de confiança*. No campo documento da política, insira o seguinte código:
```
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "codedeploy.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
```
E por último, *Atualizar política de confiança*.
### Função para o EC2
Acesse o IAM, clique em Funções e em sequência Criar Função. Agora vamos executar as etapas:
- Etapa 1 - Confiança
* **Selecionar tipo de entidade confiável**: Serviço da AWS
* **Escolha um caso de uso**: EC2
- Etapa 2 - Permissões
* **Attach políticas de permissões**: devem ser selecionadas as seguintes políticas:
- *AmazonEC2RoleforAWSCodeDeploy*
- *AmazonEC2RoleforSSM*
* **Definir limite de permissões**: Criar role sem limite de permissões
- Etapa 3 - Tags
* **Adicionar tags**: não é obrigatório, mas pode ser utilizado para facilitar a identificação e agrupamento da função na AWS.
- Etapa 4 - Revisar
* **Nome da função**: EC2CodeDeployRole
* **Descrição da função**: Permite o acesso ao CodeDeploy e ao agente SSM a partir da EC2
* **Entidades confiáveis**: Serviço da AWS: ec2.amazonaws.com
* **Políticas**: *AmazonEC2RoleforAWSCodeDeploy*, *AmazonEC2RoleforSSM*
* **Limite de permissões**: Limite de permissões não definido
Por ultimo clique em *Criar a função*.
Na sequência abra a função criada, clique na aba *Relações de confiança* e em *Editar Relações de confiança*. No campo documento da política, insira o seguinte código:
```
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
```
E por último, *Atualizar política de confiança*.
### Usuário para o GitHub
Acesse o IAM, clique em Usuários e em sequência Criar Usuário. Agora vamos executar as etapas:
- Etapa 1 - Detalhes
* **Nome do usuário**: GitHubCodeDeployUser
* **Tipo de acesso**: Acesso programático
- Etapa 2 - Permissões
* **Definir permissões**: Anexar políticas existentes de forma direta, e selecionar a política *AWSCodeDeployFullAccess*.
* **Definir limite de permissões**: Criar user sem limite de permissões
- Etapa 3 - Tags
* **Adicionar tags**: não é obrigatório, mas pode ser utilizado para facilitar a identificação e agrupamento da função na AWS.
- Etapa 4 - Revisar
* **Detalhes do usuário**:
- **Nome de usuário**: GitHubCodeDeployUser
- **Tipo de acesso AWS**: Acesso programático: com uma chave de acesso
- **Limite de permissões**: Limite de permissões não definido
* **Resumo de permissões**:
- **Política gerenciada**: AWSCodeDeployFullAccess
Por ultimo clique em *Criar o usuário*.
Na tela que segue, anote o ID da chave de acesso e a Chave de acesso secreta, para ser utilizado posteriormente no GitHub. Pode ser utilizado o botão *Fazer download .csv* para salvar os dados.
## AWS Parameter Store
### Introdução
Utilizaremos essa ferramenta para guardar os parâmetros da aplicação, para serem injetados no .env da aplicação durante o deploy, evitando que qualquer dado sensível fiquei exposto no código fonte da aplicação.
### Criando os parâmetros
Busque por Parameter Store na AWS, ele é um subserviço do AWS System Manager. Ao abrir clique em criar parâmetro.
Na criação do parâmetro existem vários campos para serem informados:
- **Nome**: informe o nome do parâmetro. Deixe ele igual a como seria no seu arquivo .env.
- **Descrição**: aqui pode ser informada uma descrição para o parâmetro.
- **Nível**: utilize o padrão para não gerar cobranças.
- **Tipo**:
* *String*: um valor qualquer.
* *StringList*: vários valores que podem ser separados por vírgula.
* *SecureString*: um valor qualquer que fica criptografado dentro do sistema usando chave KMS. Este tipo pode ser usado em dados muito sensíveis, como senhas e tokens.
- **Tipo de Dados**: para escolher o tipo de dados. Pode deixar selecionado text, ele serve para qualquer valor, seja texto ou numérico.
- **Valor**: o valor do parâmetro.
- **Tags**: pode ser informado tags para facilitar a localização e agrupamento dos parâmetros dentro da AWS.
## AWS EC2
### Introdução
Utilizaremos essa ferramenta para criação da uma instância Linux que será o servidor da nossa aplicação.
### Criando uma Instância
Acesse a guia Instâncias do EC2, e na tela de listagem que abriu, selecione *Executar instâncias*. Na tela que se segue, teremos um passo a passo para criação da Instância:
- **Etapa 1 - Selecione a AMI**
* Selecione uma imagem Linux.
- **Etapa 2 - Escolher tipo de instância**
* Escolha um tipo de instância adequada para o seu servidor.
- **Etapa 3 - Configurar instância**
* **Número de instâncias**: 1
* **Opção de compra**: deixar desabilitado
* **Rede**: selecione uma VPC
* **Sub-rede**: selecione uma Subnet ou deixe sem preferência
* **Auto-assign Public IP**: Usar configuração de sub-rede (Habilitar)
* **Grupo de posicionamento**: deixar desabilitado
* **Reserva de capacidade**: Nenhuma
* **Diretório de ingresso em domínio**: Nenhum diretório
* **Função do IAM**: EC2CodeDeployRole
* **Comportamento de desligamento**: Encerrar
- **Etapa 4 - Adicionar armazenamento**
* Esolha um tipo/quantidade de armazenamento adequado para o seu servidor.
- **Etapa 5 - Adicionar Tags**
* Adicione uma Tag para identificar a instância poteriormente, no CodeDeploy. Coloque como chave EC2CodeDeploy.
- **Etapa 6 - Configure o security group**
* **Atribuir um grupo de segurança**: selecione um existente ou crie um novo.
- **Etapa 7 - Análise**
* Revise os dados da sua instância, garantindo que seja criada a tag EC2CodeDeploy, para que encontremos essa instância posteriormente no CodeDeploy.
- **Etapa 8 - Executar**
* Será solicitado para utilizar um par de chaves existente ou criar um novo. Escolha qual é a melhor opção para você.
### Configuração Básica
Assim que criada a instância, precisamos fazer algumas configurações na mesma para funcionar o deploy. Conecte a sua instância via SHH e executando o seguinte comando para atualizar o repositório de pacotes:
```
sudo apt update
```
E na sequência para executar o upgrade dos pacotes no sistema:
```
sudo apt upgrade -y
```
### Instalando o CodeDeploy Agent
Agora iremos instalar o agente do CodeDeploy. Para o mesmo funcionar, precisaremos instalar o Ruby na nossa instância:
```
sudo apt install ruby -y
```
Em seguida, caso não esteja instalando, o WGET:
```
sudo apt install wget -y
```
Agora vamos copiar o instalador do agente. Ele fica armazenado no bucket S3 da região da sua instância. Vamos usar como exemplo a região de São Paulo (sa-east-1):
```
wget https://aws-codedeploy-sa-east-1.s3.sa-east-1.amazonaws.com/latest/install
```
Torne o arquivo baixado executável:
```
chmod +x ./install
```
Execute o instalador:
```
sudo ./install auto
```
Em seguida, configure o serviço para sempre iniciar com o sistema:
```
sudo systemctl enable codedeploy-agent
```
E inicie o serviço:
```
sudo systemctl start codedeploy-agent
```
### Instalando o AWS Cli
Precisaremos também do AWS Cli para acessar o S3 e outros serviços da AWS.
Baixe a versão mais recente:
```
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
```
Descompacte:
```
unzip awscliv2.zip
```
E por fim instale:
```
sudo ./aws/install
```
### Instalando o Docker
Agora iremos instalar o Docker. Após a instalação, iremos configurar um grupo de usuário dele para poder executar o Docker sem o uso de super usuário.
Instale as ferramentas necessárias para rodar o Docker:
```
sudo apt install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release -y
```
Adicione a chave GPG oficial:
```
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
```
Agora vamos configurar um repositório para atualização estável:
```
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
Atualize o repositório de pacotes:
```
sudo apt update
```
E por ultimo, instale o Docker:
```
sudo apt install docker-ce docker-ce-cli containerd.io
```
Agora vamos alterar as configurações de usuário para executar o Docker sem ser super usuário:
Vamos criar o grupo docker:
```
sudo groupadd docker
```
E adicionaremos o usuário atual ao grupo:
```
sudo usermod -aG docker $USER
```
Agora, vamos aplicar as alterações:
```
newgrp docker
```
Por ultimo, vamos configurar para o Docker sempre iniciar com o sistema:
```
sudo systemctl enable docker.service
```
### Instalando o Docker Compose
Para a instalação do Docker Compose, só precisamos baixar o binário do mesmo na versão desejada (aqui usaremos a 1.29.2) e alterar suas permissões de acesso.
Para baixar o binário, execute:
```
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
```
E alterar suas permissões de acesso:
```
sudo chmod +x /usr/local/bin/docker-compose
```
## AWS Code Deploy
### Introdução
Utilizaremos essa ferramenta para fazer a implantação da aplicação, depois de ser feito algum commit no GitHub.
Podemos observar o workflow do CodeDeploy a seguir:
Vamos fazer a configuração de cada etapa.
### Aplicativo
Acessa o CodeDeploy e clique em *Criar aplicativo*. Feito isso será abert uma tela de configuração de aplicativo, onde deverá ser preenchido os seguintes campos:
- **Nome do aplicativo**: GitDeployAutomated
- **Plataforma de computação**: EC2/On-premises
### Grupo de Implantação
Para criação de um grupo de implantação, abra o aplicativo criado na etapa anterior e clique em *Criar grupo de implantação*. Será aberta uma tela de criação do grupo, onde deverá ser preenchido os seguintes campos:
- **Nome do grupo de implantação**: GitDeployAutomatedGroup
- **Função de serviço**: CodeDeployRole
- **Tipo de implantação**: No local
- **Configuração do ambiente**: Instâncias do Amazon EC2
* **Grupo de tags 1**: informe na chave, a tag da instância que configuramos anteriormente, *EC2CodeDeploy*.
- Configuração do agente com o AWS Systems Manager
* **Instalar o agente do AWS CodeDeploy**: *Agora e programar atualizações*.
* **Programador Básico**: configure 10 dias.
- **Configurações de implantação**: selecione *CodeDeployDefault.OneAtATime*.
- **Load balancer**: não selecione *Habilitar balanceamento de carga*.
Agora clique em *Avançado - opcional*, e preencha a seguinte opção:
- **Reversões**: habilite Reverter quando uma implantação falhar
Finalize clicando em *Criar grupo de implantação*.
### Implantação
**ATENÇÃO**: execute esta etapa somente após executar a próxima etapa, *Configuração do Projeto*.
Agora vamos criar uma implantação que é a etapa que efitivamente copia o código fonte para a EC2 e executa as operações do deploy. Para tal, vamos acessar o grupo de implantação *GitDeployAutomatedGroup* recém criado. Ao abrir ele, vamos clicar em *Criar implantação*, onde iremos validar e preencher os campos:
- **Aplicativo**: GitDeployAutomated.
- **Grupo de implantação**: GitDeployAutomatedGroup.
- **Plataforma de computação**: EC2/On-premises.
- **Tipo de implantação**: No local.
- **Tipo de revisão**: selecione *Meu aplicativo está armazenado no GitHub*.
- **Nome do token do GitHub**: preencha com um nome para identificar seu repositório. preencha com GitHubActionsDeploy e clique em *Conectar ao GitHub*. Na tela que abre, confirme a ação.
- **Nome do repositório**: o nome do seu repositório no GitHub.
- **ID de confirmação**: preencha com o hash gerado no ultimo commit do seu repositório. Ele pode ser encontrado no seu histórico de commit, ao lado direito do seu último commit (tem um ícone de "copiar", pode clicar nele para copiar o hash completo).
- **Descrição da implantação**: informe uma descrição para essa implantação.
O restante dos campos deve ser deixado como está. Algumas configurações já vem pro padrão configuradas a partir do próprio grupo. Ao final, clique em *Criar implantação* para criar a primeira implantação manual.
Onde podemos verificar que o deploy está funcionando corretamente
## Configuração do Projeto
Agora iremos criar um projeto e criar os arquivos e scripts necessários para integração com o *CodeDeploy*.
O projeto terá a seguinte estrura: