Continuos Delivery – AWS Code Pipeline + Jenkins
No processo de DevOps é comum encontramos alguns termos para representar o processo de deploy automático de aplicações, entre eles, um que se destaca é o Continuos Delivery.
Este termo é usado para descrever o processo de liberação da aplicação em algum ambiente do seu ciclo de desenvolvimento. Não estamos falando aqui necessariamente do ambiente de produção, pode ser um ambiente de QA para validação manual dos usuários ou mesmo um ambiente de desenvolvimento que não seja a máquina do desenvolvedor.
Eu não me alongarei aqui sobre esse desenvolvimento, recomendo que você consulte o artigo para um melhor entendimento de todo o processo. O meu objetivo é mostrar um exemplo prático do processo de entrega contínua em um ambiente da Amazon ELB com AWS Code Pipeline e Jenkins. (o AWS CodeBuild poderia ser usado também, mas esse serviço não está disponível na região de São Paulo [sa-east-1]).
O objetivo desse manual é montar um exemplo prático usando AWS Code Pipeline + Jenkins, não se preocupe, vamos fazer tudo do início ao fim e eu vou guiar você por cada etapa desse processo. Para isso, eu criei vários scripts que vão ajudá-lo – é só seguir as orientações para validar o passo a passo.
Se você ainda não tiver, vai precisar das seguintes ferramentas e arquivos:
Todos os fontes usados nesse exemplo você encontra no seguinte repositório do GitHub.
Crie uma nova pasta no seu computador e execute todos os comandos a partir dela, caso contrário, você terá que apontar diretamente para os arquivos de configuração e pode acontecer alguma confusão no meio das etapas.
Configurar interface de comando da AWS
Caso você ainda não tenha feito, precisa configurar o usuário de linha de comando da AWS. Para fazer isso, você pode seguir os passos descritos nesse artigo.
Abra um prompt de comando e digite o seguinte comando para iniciar a configuração do console:
[code language=”text”]aws configure
[/code]Entre com informações necessárias para autenticação do usuário e região padrão. Agora é hora de começar a criar sua instância do EC2.
Criar um par de chaves para a instância EC2 do Jenkins
Você vai precisar de um par de chaves para se conectar a uma instância do EC2 via SSH, para isso, digite o seguinte comando no prompt de comando:
[code language=”text”]aws ec2 create-key-pair –key-name ec2-jenkins > ec2-jenkins.json
[/code]O resultado do comando será armazenado no arquivo ec2-jenkins.json, se você acessar o console do EC2 vai observar que agora tem o seguinte par de chaves na lista.
Nós vamos usar para esse exemplo o grupo de segurança padrão da sua assinatura. Para verificar o id do grupo de segurança padrão, digite o comando abaixo no prompt e guarde o valor da propriedade GroupId. A partir desse momento, sempre que aparecer o termo , você deve informar o valor dessa propriedade.
[code language=”text”]aws ec2 describe-security-groups –filters Name=group-name,Values=default
[/code]Bom, agora que você já possui o par de chaves e o ID do grupo de segurança, vamos criar a instância do EC2 e instalar o Jenkins.
Criar instância do EC2 para o Jenkins
Você pode usar o comando abaixo para criar uma instância do EC2 na faixa gratuita da AWS, observe o valor o parâmetro –image-id, ele é uma imagem padrão da AWS para um máquina virtual com Amazon Linux, você pode usar o comando describe-images para uma listagem de todas as máquinas virtuais disponíveis.
[code language=”text”]aws ec2 run-instances –image-id ami-87dab1eb –count 1 –instance-type t2.micro –key-name ec2-jenkins –security-group-ids <sg-group-id>
[/code]O resultado desse comando será um JSON com as informações da nova instância do EC2, navegue até o consolo do EC2 na AWS e observe a nova instância criada.
Guarde as informações Public DNS (IPv4) e Instance ID, a partir desse momento, sempre que o termo [public-dns] e [instance-id] aparecerem, substitua-os pelo valor das propriedades respectivamente.
Agora temos que abrir as portas 22 e 8080 para os serviços da máquina, a primeira porta é a padrão do SSH e será usada para conectar na instância via Putty, a segunda porta será usada para acesso ao Jenkins de um navegador conectado a internet.
Ainda no prompt de comando, digite os seguintes comandos:
[code language=”text”]aws ec2 authorize-security-group-ingress –group-id <sg-group-id> –port 22 –protocol tcp –cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress –group-id <sg-group-id> –port 8080 –protocol tcp –cidr 0.0.0.0/0
Como resultado do comando, as portas 22 e 8080 devem estar abertas para acesso remote. A partir desse momento, é hora de gerar a chave privada e conectar a instância do EC2.
Formatar chave privada e conectar a instância do EC2
Se você abrir o arquivo ec2-jenkins.json, vai reparar nas propriedades KeyMaterial e KeyFingerprint, essas são as informações necessárias para conectar a sua nova instância do EC2, o processo aqui é basicamente formatar a chave privada (remover as quebras de linhas do arquivo) e importar no Putty. Execute os seguintes passos para isso:
Abra um prompt de comando do Powershell e navgue até a pasta de trabalho, execute o seguinte comando no powershell:
[code language=”powershell”]$rsakey = (Get-Content ‘ec2-jenkins.json’) | ConvertFrom-Json
$rsakeyString = New-Object System.IO.StringReader($rsakey.KeyMaterial)
$line = $rsakeyString.ReadLine()
$line | Out-File "ec2-jenkins.pem" -Encoding default
while($true) {
$line = $rsakeyString.ReadLine()
if ($line -ne $null) {
$line | Out-File "ec2-jenkins.pem" -Encoding default -Append
} else {
break
}
}
$rsakeyString.Dispose()
O resultado desse comando será um novo arquivo chamado ec2-jenkins.pem, se você abrir esse arquivo em um editor de texto, vai reparar que agora a chave privada está formatada, com as informações de BEGIN e END em linhas separadas do arquivo.
Abra o PuttyGEN, que foi instalado juntamento com o Putty, e clique em Load, selecione o arquivo ec2-jenkins.pem e clique em Open.
Após a importação do arquivo, clique em Save private key e salve o arquivo como ec2-jenkis.ppk, esse é o arquivo que será usado pelo Putty para conectar a instância do EC2.
Abra o Putty e no menu lateral clique em Session, informe no campo Host Name o valor ec2-user@[public-dns]. No menu lateral, clique em SSH e em seguida Auth, na area Authentication Parameters, clique em Browse e selecione o arquivo ec2-jenkins.pem.
Clique em Open para abrir a conexão com a instância do EC2, clique em Yes para confirmar que confia no certificado do novo servidor.
Agora que você possui conexão com a sua instância, é hora de iniciar a instalação do Jenkins.
Instalar e configurar Jenkins
Para instalar o Jenkins, execute os seguintes comandos no servidor a partir do Putty:
[code language=”text”]sudo su –
yum update
yum install java-1.8.0
yum install java-1.8.0-openjdk-devel
Como resultado dos comandos acima, você agora possui o Java 1.8.0 instalado no servidor, para configurar a versão do java padrão, utilize o comando abaixo e selecione a nova versão como padrão.
[code language=”text”]update-alternatives –config java
[/code]Agora é hora de instalar o Jenkins, execute os seguintes comandos para instalar o Jenkins:
[code language=”text”]wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo
rpm –import http://pkg.jenkins-ci.org/redhat-stable/jenkins-ci.org.key
yum install jenkins
service jenkins start
A partir desse momento, abra o endereço [public-dns]:8080 por um navegador conectado a internet e o Jenkins deve solicitar a senha de administrator para iniciar a configuração, volte ao Putty e digite o seguinte comando para obter a senha de administrator.
[code language=”text”]cat /var/lib/jenkins/secrets/initialAdminPassword
[/code]Informe o resultado do comando como senha de administrator e clique para continuar a configuração do Jenkins, cancele o wizard de configuração clicando no X do lado superior direito da tela e aguarde o carregamento da página inicial do Jenkins.
O próximo passo é desabilitar a configuração de segurança do Jenkins, digite o seguinte comando para abrir o arquivo de configuração do Jenkins.
[code language=”text”]vim /var/lib/jenkins/config.xml
[/code]No arquivo, altere a configuração da tag security para false, execute o comando abaixo para reiniciar o processo do Jenkins.
[code language=”text”]service jenkins restart
[/code]A partir desse momento, se você acessar o endereço [public-dns]:8080, você vai acessar a página inicial do Jenkins. Agora é hora de configurar os plugins do Jenkins.
Instalar plugins do Jenkins
Para a execução do exemplo, é necessário habilitar no Jenkins os seguintes plugins:
Execute os seguintes comandos a partir do Putty para instalar os plugins no Jenkins, ao final dos comandos, reinicie o processo do Jenkins para atualizar o servidor:
[code language=”text”]wget http://localhost:8080/jnlpJars/jenkins-cli.jar
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin aws-codepipeline
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin maven-plugin
service jenkins restart
Você também vai precisar do Apache Maven instalado no servidor para compilar os projetos do Java, para isso, e ainda no Putty, execute os seguintes comandos no servidor:
[code language=”text”]wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
sed -i s/\$releasever/6/g /etc/yum.repos.d/epel-apache-maven.repo
yum install -y apache-maven
Uma vez instalado, você deve configurar o Apache Maven no Jenkins, acesse a interface do Jenkins pela url [public-dns]:8080 e clique em Manage Jenkins. Em seguida clique em Global Tools Configuration.
Na área Maven, clique em Add Maven e configure as opções como a imagem abaixo.
Clique em Save para salvar as configurações.
Agora que você já instalou e configurou o Jenkins, é hora é configurar as permissões necessárias para a integração do AWS Code Pipeline com a sua instância do Jenkins.
Configurar e associar o instance profile com o EC2
O primeira passo é criar o que chamamos de Instance Profile, você pode obter mais informações por esse link .
O que acontece aqui é que a sua instância do EC2 deve possuir permissão para publicar artefatos e consultar jobs no AWS Code Pipeline. Para isso, a sua instância deve ser capaz de se conectar ao AWS Code Pipeline com algum tipo de credencial, a forma mais recomendada nesses casos é usar o instance profile, porém, se você preferir, pode colocar diretamente as chaves do IAM no projeto do Jenkins.
Para configurar o instance profile, execute os seguintes comandos no prompt de comando do Windows (não no Putty):
[code language=”text”]aws iam create-role –role-name RoleForJenkinsServer –assume-role-policy-document file://trustedpolicy.json
aws iam put-role-policy –role-name RoleForJenkinsServer –policy-name JenkinsCodePipeline –policy-document file://permissionspolicy.json
aws iam create-instance-profile –instance-profile-name JenkinsServer
aws iam add-role-to-instance-profile –role-name RoleForJenkinsServer –instance-profile-name JenkinsServer
Esses quatro comandos criam um IAM role chamado RoleForJenkinsServer, a sua instância do EC2, quando associada a esse role, assume uma identidade com permissões no AWS Code Pipeline.
Para associar a sua instância ao IAM role, execute o seguinte comando:
[code language=”text”]aws ec2 associate-iam-instance-profile –instance-id [instance-id] –iam-instance-profile Name=JenkinsServer
[/code]Além disso, também é necessário criar um IAM role para o seu projeto no AWS Code Pipeline, nesse caso, é para permitir que o AWS Code Pipeline publique os projetos compilados no Jenkins em um Amazon S3, ou em um Amazon ELB por exemplo. Você pode criar essa role através dos seguintes comandos:
[code language=”text”]aws iam create-role –role-name RoleForCodePipeline –assume-role-policy-document file://trustedpolicy-codepipeline.json
aws iam put-role-policy –role-name RoleForCodePipeline –policy-name JenkinsCodePipeline –policy-document file://permissionspolicy-codepipeline.json
Como resultado dos comandos, se você acessar o console do IAM, deve ter agora as seguintes roles configurados na sua assinatura:
Agora que você configurou as permissões necessárias para execução, é hora de adicionar a ação de Build no AWS Code Pipeline.
Configurar ação de compilação no AWS Code Pipeline
Agora é hora de configurar uma ação customizada no AWS Code Pipeline, isso é necessário para o estágio de compilação do código, o AWS Code Pipeline vai enviar os artefatos para o Jenkins, que vai compilar o fonte e enviar o resultado de volta para o AWS Code Pipeline. Antes de criar efetivar a criação da ação de build, abra o arquivo codepipeline-build.json e modifique as propriedades entityUrlTemplate e executionUrlTemplate, informe nesses campos o dns público da sua instância do EC2.
Após a modificação, salve o arquivo e digite o seguinte comando para criar a ação customizada no AWS Code Pipeline:
[code language=”text”]aws codepipeline create-custom-action-type –cli-input-json file://codepipeline-build.json
[/code]Agora é hora de criar o seu ambiente do ELB para testar o deploy da aplicação, continue que que está quase acabando, você não quer desistir agora né.
Criar uma nova aplicação no Elastic Beanstalk
Para criar uma nova aplicação no Amazon ELB, digite o comando abaixo:
[code language=”text”]aws elasticbeanstalk create-application –application-name HelloWorldApplication –description "Site de exemplo com um site HelloWorld"
[/code]Como resultado, uma nova aplicação foi criada na sua assinatura da AWS, acesse o console do ELB e você deve encontrar uma tela parecida com essa abaixo.
Agora você deve criar um novo ambiente nessa aplicação, execute o seguinte comando para criar um ambiente de exemplo com Tomcat.
[code language=”text”]aws elasticbeanstalk create-environment –application-name HelloWorldApplication –environment-name dev-environment –cname-prefix dev-helloworld –solution-stack-name "64bit Amazon Linux 2017.03 v2.6.0 running Tomcat 8 Java 8" –option-settings file://elb-options.json
[/code]A partir de agora, você deve ter um ambiente de exemplo na sua aplicação da Amazon ELB, ao acessar a sua aplicação, e após o fim da configuração, a seguinte tela deve ser exibida.
Ufa, quase lá, agora é hora de criar o seu projeto no Jenkins.
Criar projeto de compilação no Jenkins
Nesse momento, vamos criar um novo projeto no Jenkins e configurar o plugin do AWS Code Pipeline para compilar o projeto, para isso, você deve copiar o arquivo helloworldmvc-blogiteris.xml para o servidor do EC2, você pode usar o WinSCP para realizar a cópia do arquivo.
Com o arquivo no servidor, execute o seguinte comando para criar o projeto no Jenkins.
[code language=”text”]java -jar jenkins-cli.jar -s http://localhost:8080 create-job helloworldmvc-blogiteris < helloworldmvc-blogiteris.xml
[/code]*Não se preocupe se o primeiro build falhar, em todos os meus testes o build disparado do Jenkins sempre vai falhar, ele deve iniciar pelo plugin do AWS Code Pipeline.
Agora chegou a hora de configurar o AWS Code Pipeline, enfim, chegou o momento.
Configurar o AWS Code Pipeline
Acesso o console do AWS Code Pipeline, e clique em Get Started para iniciar a configuração. Quando solicitado, entre com o nome helloworldmvc-blogiteris no campo Pipeline name.
Clique em Next step para continuar, em source location, selecione o repositório do GitHub (será necessário vincular sua conta do GitHub ao AWS) que contém os arquivos fontes. Selecione a branch (será criado um hook na branch para atualização automática a cada commit).
Clique em Next step para continuar, nas intruções de build, selecione o provider Compilar-Maven-Jenkins e informe o nome do projeto no Jenkins no campo ProjectName.
Clique em Next step para continuar, nas configurações de Deploy, informe os dados da sua aplicação no Amazon ELB.
Clique em Next step para continuar, quando solicitado, informe o nome do IAM role RoleForCodePipeline.
Clique em Next step para finalizar a configuração do AWS Code Pipeline. Deve iniciar uma nova entrega após a finalização. Se tudo foi configurado corretamente, você deve observar que o pipeline marca de verde as actions que foram realizadas com sucesso.
Navegue até o Jenkins e veja o console output da compilação, no log do Jenkins deve estar a informações da compilação realizada com sucesso.
Durante a entrega, você pode observar que a sua aplicação no Amazon ELB é atualizada com um nova versão do fonte (alterada a cada entrega).
Ao acessar o site do Amazon ELB, o seu resultado final deve ser o seguinte.
E assim finalizamos a configuração de um processo de entrega contínua, espero que este artigo te ajude nas configurações do seu ambiente.
Caso tenha alguma dúvida ou se alguma etapa não ficou totalmente clara, deixe seu e-mail e comentário e, assim que possível, atualizarei o artigo com as sugestões e respostas.