Docker Run – Avançado

Olá pessoal,

Hoje vamos falar um pouco mais sobre as opções que talvez muitas pessoas não conhecem sobre o Docker run e que podem ajudar você diariamente a subir suas aplicações com mais segurança e também com mais praticidade. A ideia por trás desse post não é mostrar como criar um container, mas sim quais as opções novas e que podemos utilizar em nosso dia a dia.

PID settings (–pid)

Por padrão todos os containers possuem o PID namespace habilitado. O Namespace PID remove o ponto de vista dos processos do sistema e permite ids de processos para ser utilizado. Em alguns casos você pode querer rodar alguma ferramenta de depuração em seu container para que ele consiga visualizar os processos do seu host, então basta iniciar o container com a opção de –pid ativado:

docker run -it --rm --pid=host imagem

É possível também utilizar o –pid para depurar as informações de outro container, para isso vamos iniciar a execução de um container com mongoDB e depois um container para realizar a depuração

docker run --name mongo -d mongodb 
docker run --it --pid=container:mongo imagem

–dns

Por padrão os containers irão compartilhar os mesmos servidores de DNS que estão sendo utilizados em seu host, então na hora de criação de cada container você pode utilizar o parâmetro –dns=”8.8.8.8″ por exemplo.

–add-host

O docker ja cria dentro de cada container em /etc/hosts o arquivo com algumas configurações de rede, como:

172.17.0.2 02ed3f564f1b
127.0.0.1 localhost
fe00::0 ip6-localnet

Porem é possivel na hora da criação do container você adicionar mais uma entrada dentro do arquivo de hosts para isso basta colocar a opção –add-host em seu “docker run”

 docker run -it --add-host entrada:ip -d centos

–security-opt

Nas versões mais recentes do Docker é possível você limitar para que os comandos que exigem privilégios dentro do Docker não sejam mais executado, como: su ou sudo para isso basta executar:

docker run --security-opt no-new-privileges -d centos

–restart

Utilizando essa opção é possível realizar a reinicialização de containers a partir de determinados evento, são esses: on-failure, always, unless-stopped.

  • On-failure: Reinicia somente se o status de saída do container por diferente de 0, é possível limitar o numero de tentativas de reinicialização. O docker irá esperar 100ms na primeira vez que tentar reiniciar o container, caso vá para segunda vez então irá esperar 200ms e depois 400ms e assim dependendo do número de tentativas.
 docker run --restart=on-failure:3 centos
  • Always: Sempre reinicie o container independentemente do status de saída. Na reinicialização do servidor, o container irá subir automaticamente após o serviço do docker ser startado.
 docker run --restart=always centos
  • Unless-Stopped: Inicialize o container independentemente do status de saída, porem na reinicialização do servidor ou do serviço do Docker o container não irá subir automaticamente;
 docker run --restart=unless-stopped centos

O status de saída exibido pelo Docker no docker run pode ser visto utilizando a seguinte opção:

 docker run redis; echo $?

Existem alguns números já conhecidos, 125 (Problema com o docker daemon), 126 (Comando não pode ser invocado), 127 (Comando não pode ser encontrado).

–isolation

Essa opção é útil quando você executar Docker no Windows essa opção define qual tecnologia ira ser usada para o isolamento do container, no caso do linux é default e no Windows temos: process e Hyper-v.

docker run -d --isolation process busybox top

–device

Um dia poderá aparecer a necessidade para que você anexe um disco a seu container, então com essa opção você pode anexar diretamente um disco a seu container:

docker run --device=/dev/sdb:/dev/xvdc -d centos

–rm

Por padrão quando você cria um container sem passar a opção de “–rm” quando esse container acaba parando por algum motivo, ele não é removido do Docker e também nem o seu volume. Porem caso você deseja que remova o container você poderá passar o parâmetro na hora da criação do container.

docker run -it -v /home/container:/home --rm -d centos

Nesse modo de criação de container, quando o container por algum motivo parar o docker irá excluir-lo e também apagar o volume junto. Para que NÃO APAGUE O VOLUME você deve criar um volume com a opção de docker volume create.... e na hora da criação desse container passar o nome do volume.

docker run -it --rm -v volume:/home -d centos

Então ta pessoal, por hoje era isso, espero que tenham gostado, em breve faremos posts mais focados no baixo nível do Docker para que você possa saber como todas as opções funcionam e como utiliza-las. Já sabe, nos ajude divulgando o blog 😉

Dockerizando aplicações – Processos de administração

Seguindo a lista do modelo 12factor, temos “Processos de administração” como décima segunda e ultima boa prática desse modelo.

admin

Toda aplicação demanda administração, isso quer dizer que uma vez implantada é possível que ela precise receber determinados comandos para corrigir possíveis problemas ou simplesmente mudar de comportamento. Como exemplos temos migrações de banco de dados, execução de scripts diversos como backup, e também execução de um console para inspeção do serviço.

Essa boa prática recomenda processos de administração executados em ambientes idênticos ao utilizado no código em execução, ou seja, seguindo todas as práticas explicadas até então.

Usando Docker, é possível rodar esses processos usando a mesma imagem base no ambiente de execução que se desejar. Tudo isso podendo se beneficiar da comunicação entre os contêineres, uso de volumes que forem necessários e afins.

Para exemplificar essa boa prática criamos o arquivo reset.py:

from redis import Redis
import signal, os

host_redis=os.environ.get('HOST_REDIS', 'redis')
port_redis=os.environ.get('PORT_REDIS', '6379')

redis = Redis(host=host_redis, port=port_redis)

redis.set('hits', 0)

Ele é responsável por reinicializar o contado de visitas do Redis. Esse comando será dado usando um contêiner diferente a partir da mesma imagem docker. Primeiro vamos iniciar o ambiente. Baixe o repositório e acesse a pasta factor12 e execute o comando abaixo:

docker-compose up 

Acesse a aplicação em seu navegador. Caso esteja usando GNU/Linux ou Docker For MAC e Windows acesse o endereço 127.0.0.1, caso esteja usando Docker Toolbox será necessário usar o ip 192.168.99.100. Você verá a seguinte frase:

“Hello World! 1 times.”

Acesse a aplicação mais algumas vezes para o marcado aumentar bastante.

Depois vamos executar o comando de administração a partir do serviço worker:

docker-compose exec worker python reset.py

O comando “python reset.py” será executado dentro de um novo contêiner, mas usando a mesma imagem de um worker regular.

Acesse novamente a aplicação e verifique se o marcado iniciou a partir de 1 novamente.

Troubleshooting e dicas de Docker

Olá pessoal,

Já faz mais de 1 ano que criamos esse blog e hoje resolvemos fazer um post referente a como solucionar algumas dificuldades e problemas que tivemos no começo, visto que trabalhamos a mais de 2 anos já com Docker, tivemos muitos problemas que queremos demonstrar para vocês.

Instalando a versão mais recente

A maioria das pessoas que acabam por usar Ubuntu, Centos, RedHat ou qualquer outra distribuição utiliza seus próprios comandos para realizar a instalação do Docker, com yum ou apt-get. Mas a forma de utilizar as versões mais recentes são essas:

Versão oficial para se utilizar em produção:

curl -sSL https://get.docker.com/ | sh

Versão que se encontra ainda em fase de testes:

curl -fsSL https://test.docker.com/ | sh

Versão alpha que está em constante desenvolvimento:

curl -fsSL https://experimental.docker.com/ | sh

 Como remover todos os containers parados:

docker rm $(docker ps -a -q)

 Sincronizar o relógio do host com o container:

Isso é um dos principais problemas que as pessoas acabam encontrando as vezes.

Para Centos (Na hora de criar o container mapeia o diretório do host com o do container)

docker run -v /etc/localtime:/etc/localtime:ro centos date

Para Ubuntu (Na hora da criar o container passa como variável o timezone(tz)

docker run -e "TZ=America/Salvador" ubuntu date

 Comunicação entre containers:

Por padrão no Docker a comunicação entre os containers na mesma rede é liberado através de IP interno. Mas caso você queira que os containers não se comuniquem diretamente basta mudar na hora da criação da rede colocar icc=false.

docker network create -o com.docker.network.bridge.enable_icc=false rede_isolada

Montando volumes com services:

Quando criamos um container simples com docker run, existe a opção do -v onde podemos passar como parâmetro o nosso volume, porém com a implementação do services no Docker 1.12 ficou um pouco mais complicado na hora de passar um volume para o serviço:

Como você pode ver na opção “type” temos o “bind” que seria um diretório em nosso host:

docker service create --mount type=bind,source=/diretoriohost,target=/diretoriocontainer imagem

E também temos a opção volume que é passado o volume que é criado com “docker volume create…..

docker service create --mount type=volume,source=meuvolume,target=/diretoriocontainer imagem

 Docker commit e volume:

O comando “docker commit” gera uma imagem do nosso container, porém ele NÃO vai armazenar os dados do volume que estão atrelados a aquele container. Então o docker commit não irá servir de backup para os seus dados que estão no volume.

Não rode containers com –privileged

Com a opção de –privileged o container consegue facilmente acessar diversas áreas do seu host na qual podem ser cruciais caso alguém ache alguma brecha de segurança em sua aplicação.

Um processo para cada container.

Não instale pacotes desnecessários em seus containers, se você quer ter um container para apache, só instale o apache nele. Quer ter o PHP também? então suba outro container.

Cuidado com as regras de IPTABLES

Como o Docker trabalha com toda a sua parte de redes através de iptables, é bem provável que se você fizer alguma manutenção em seu firewall e editar alguma regra errada, toda a sua estrutura de Docker pode parar de funcionar por algum problema.

Coloque o diretório do docker em outro disco:

O docker utiliza o caminho “/var/lib/docker” para colocar todos os seus arquivos de instalação e também toda a sua estrutura de containers, volumes e mais outros recursos que ele utiliza. Então não deixe esse diretório no mesmo disco do seu SO.

Gostaram do post? Deixe seu feedback e novamente, nos ajudem divulgando o blog.

Grande abraço!

Dockerizando aplicações – Logs

Seguindo a lista do modelo 12factor, temos “Logs” como décima primeira boa prática.

logs

No desenvolvimento de código, gerar dados para efeitos de log é algo bastante consolidado, ou seja, não acredito que existam pessoas desenvolvendo software que não se preocupem com isso, porém o uso correto do log vai além de apenas gerar os dados.

Para efeito de contextualização, de acordo com o 12factor o log é um: “…fluxo de eventos agregados e ordenados por tempo coletados dos fluxos de saída de todos os processos em execução e serviços de apoio.”

Logs normalmente são armazenados em arquivos, com eventos por linha (pilhas de exceção podem ocupar várias linhas), mas essa prática não é indicada, ao menos não na perspectiva da aplicação. Isso quer dizer que sua aplicação não deveria se preocupar em qual arquivo deve guardar os logs.

Especificar arquivos implica em informar o diretório correto desse arquivo, que por sua vez resulta em uma configuração prévia do ambiente e tudo isso junto impacta negativamente na portabilidade da sua aplicação, pois será necessário que o ambiente que receberá sua solução deve seguir uma série de requisitos técnicos para suportar a aplicação, ou seja, com isso enterrando a possibilidade do “Construa uma vez, rode em qualquer lugar”.

Essa boa prática indica que as aplicações não devem gerenciar ou rotear arquivos de log, ou seja, eles devem ser depositados sem nenhum esquema de buffer na saída padrão (STDOUT). Assim uma infraestrutura externa à aplicação, plataforma, deve gerenciar, coletar e formatar a saída desses logs para futura leitura. Isso é realmente importante quando a aplicação está rodando em várias instâncias.

Com o Docker, essa tarefa fica bem mais fácil, pois Docker já coleta logs da saída padrão e encaminha para algum dos vários drivers de log. Esse driver pode ser configurado na inicialização do container de forma a centralizar os logs num serviço remoto de logs, por exemplo syslog.

O código exemplo que está nesse repositório, na pasta factor11 já se encontra pronto para testar essa boa prática, pois o mesmo já envia todas as saídas de dados para STDOUT e você pode conferir iniciando o nosso serviço com o comando abaixo:

docker-compose up

Depois de iniciar acesse o navegador e verifique as requisições da aplicação aparecendo na console do docker-compose.

Docker Service

Oi Pessoal,

Hoje queremos trazer em detalhes para vocês uma das features implementadas no Docker 1.12 (que foi lançado no último dia 29), e que já mencionamos aqui, que é o Docker Service. Para quem ainda não leu o nosso post sobre as novidades do Docker 1.12, o Docker Service é uma feature que foi incorporada pela engine Docker em sua última versão e que permite ao administrador criar e administrar sua stack de serviço dentro de um cluster Swarm, sem precisar utilizar uma segunda ferramenta para isso. Ela é parte integrante de uma série de melhorias que permitiram ao Docker 1.12 ter a camada de orquestração nativa em sua engine.

Mas afinal, como isso me ajuda? Bem, nas versões anteriores do Docker, para você ter algum tipo de orquestração você teria que utilizar uma série de ferramentas, como por exemplo: Docker Swarm, Docker Compose isso sem falar, que, se você quisesse provisionar isso em larga escala mesmo, o recomendado era utilizar Kubernetes, Mesos ou alguma outra forma de orquestração mais adequada. Agora está tudo dentro da própria engine do Docker, o que permite você ter maior controle sob o que está utilizando, e claro, permite você manipular esse ambiente de forma mais simples.

Para serviço especificamente, foi adicionado o sub-comando: docker service, e dentro dele alguns itens, veja:

  1. docker service create: Possibilita a criação de sua stack de serviço, é ele o que você mais vai ver hoje ;)
  2. docker service inspect: Verifica as informações sobre seu serviço e retorna informações sobre parametro utilizados para inicialização do mesmo, imagem utilizada, etc.
  3. docker service ls: Lista todos os serviços que você tem criado, e lhe retorna informações sobre nome, quantidade de replicas, etc.
  4. docker service rm: Remove o serviço desejado do cluster
  5. docker service ps: 2° comando mais útil, retorna para você o status de cada container que atende um serviço, é muito parecido com o docker ps, com a diferença de lhe trazer apenas informações sobre os container que fazem parte de um serviço criado, você pode ainda utilizar filtros para ter um retorno mais simplificado.
  6. docker service scale: Com o scale é possível realizar o escalonamento de seu serviço, é possível você aumentar a quantidade de containers que atenderão o seu serviço.
  7. docker service update: Comando que lhe permite realizar modificações no serviço criado, através dele é possível modificar informações sobre quantidade de memória, cpu, dentre muitas outras coisas em seu serviço.

Tudo certo com a teoria? Então vamos a prática :), nosso problema: Queremos criar uma stack para nosso ElasticSearch, nosso objetivo é escalar esse ambiente quantas vezes eu quiser e atualiza-lo de forma consistente.

Primeiro temos que criar nosso service:

docker service create --replicas 1 --update-delay 10s --update-parallelism 1 --name elasticsearch elasticsearch

O que isso quer dizer? Vamos lá:

  • Replicas – Número de containers que eu quero criar nesse momento, deve ser no mínimo um (por motivos óbvios);
  • Update-delay – Quando for realizado uma procedimento de atualização do ambiente, qual será a cadência de atualização dos containers.
  • Update-parallelism – Quantidade de containers que desejamos atualizar por vez
  • Name – Nome do serviço e por último a imagem que vamos utilizar para esse serviço.

O retorno do comando será algo parecido com isso:

docker-service1

Certo, meu serviço está criado, como escalono ele agora? Fácil, olha o print 🙂

docker-service2

Note que para escalar, basta executar o comando: docker service scale $(seu-servico)=numero. Agora vamos atualizar o nosso ambiente, certo? Muito fácil, basta executar o comando: docker service update, com ele é possível modificar diversos atributos do serviço, como por exemplo: Portas publicadas, limites de recursos, número de replicas, imagem, politica de escalonamento, etc.

Em nosso exemplo vamos atualizar a imagem que nosso serviço utiliza, veja que quando criamos, a imagem utilizada era a elasticsearch:latest, agora queremos testar a última versão do elasticsearch, que está em alpha (no dia da criação desse post) que é a 5.0, para isso basta executar: docker service update –image elasticsearch:5.0 elasticsearch, veja o que aconteceu:

docker-service3

Veja que nosso serviço não foi atualizado de uma vez só, esse processo foi sendo realizado conforme os containers iam sendo atualizados, isso devido a nossa politica de update que definimos na criação do serviço. Com o update você pode realizar diversas ações, veja mais em: docker service update –help, ele lhe mostrará todas as opções disponíveis.

Como removemos um serviço? Bem, você já deve ter imaginado como: docker service rm nome_do_servico.

Ahh, você se lembra que falamos aqui que no Docker 1.12 era possível criar um serviço distribuído dentro Swarm e acessá-lo de qualquer lugar? Pois bem, quando você criar um serviço você pode especificar qual será a porta publica dele, no exemplo acima não utilizamos isso, mas você pode definir (através do parâmetro -p) que a porta 8080 seja a porta de seu serviço, com isso todo o trafego enviado para a porta 8080 nos ips de seus nós do cluster de Swarm será redirecionado para os containers que atendam esse serviço. Lembrando que para você criar um serviço distribuído é necessário ter um cluster de Swarm ativo.

Gostaram do post? Deixe seu feedback e novamente, nos ajudem divulgando o blog.

Grande abraço!

 

Dockerizando aplicações – Paridade entre desenv/produção

Seguindo a lista do modelo 12factor, temos “Paridade entre desenvolvimento/produção” como décima boa prática.

Untitled Diagram (3)

Infelizmente na maioria dos ambientes de trabalho com software, existe um grande abismo entre o desenvolvimento e a produção. Esse grande buraco não é um mero acaso ou falta de sorte. Ele existe por conta de algumas diferenças entre as equipes de desenvolvimento e infraestrutura. De acordo com o 12factor elas manifestam-se nos seguintes âmbitos:

  • Tempo: Um desenvolvedor pode trabalhar em código que demora dias, semanas ou até meses para ir para produção.
  • Pessoal: Desenvolvedores escrevem código, engenheiros de operação fazem o deploy dele.
  • Ferramentas: Desenvolvedores podem estar usando um conjunto como Nginx, SQLite, e OS X, enquanto o app em produção usa Apache, MySQL, e Linux.

O 12factor pretende colaborar com base em suas boas práticas reduzir esse abismo entre as equipes e equalizar os ambientes em questão. Com relação aos âmbitos apresentados, seguem as respectivas propostas:

  • Tempo: um desenvolvedor pode escrever código e ter o deploy feito em horas ou até mesmo minutos depois.
  • Pessoal: desenvolvedores que escrevem código estão proximamente envolvidos em realizar o deploy e acompanhar seu comportamento em produção.
  • Ferramentas: mantenha desenvolvimento e produção o mais similares possível.

A solução de contêiner tem como um dos principais objetivos colaborar com essa portabilidade entre ambiente de desenvolvimento e produção, pois a ideia é que a imagem seja construída e apenas o seu status modifique para que ela seja posta em produção. O nosso código atual já está pronto para esse tipo de comportamento, sendo assim não há muito o que precise ser modificado para garantir essa boa prática, que será como um bônus pela adoção do Docker e o seguimento das outras boas práticas do 12factor.

Docker e Jenkins para build de aplicações

Olá pessoal,

Hoje queremos demonstrar para vocês como podemos utilizar Docker e Jenkins para o build de aplicações de forma rápida e fácil, primeiro vamos entender como é o ambiente de diversas empresas de TI hoje e você que estiver lendo este post possivelmente estará se identificando com isso.

Hoje diversas empresas utilizam a ferramenta Jenkins para build e deploy de aplicações, muitas vezes (Se não forem todas) essa maquina de Jenkins é compartilhada entre diversos times, Java, PHP, Python, Rails e NodeJS acabam utilizando. O que deixa essa máquina com ferramentas desnecessárias para as equipes, sobrecarregando o sistema e qualquer problema acaba parando todas as equipes.

Porém existem alguns casos mais organizados que a maquina onde irá ocorrer o build será uma máquina para cada equipe, o que torna o processo um pouco melhor, porém sempre que sair uma nova versões de softwares alguém precisa ficar atualizando essa máquina, o que pode acabar por muitas vezes impactando em prazos do projeto.

Então existe o que acreditamos que seja a melhor solução que seria a utilização de containers para o build de suas aplicações. mas porque usar containers?

  • Só dependências para aquela aplicação
  • Fácil manutenção
  • Ambiente de produção e local iguais.
  • Escabilidade

Então visto o porque que devemos utilizar containers para realizar o build, vamos mostrar como podemos utilizar essas duas ferramentas em sincronia.

Primeiramente vamos até as configurações do nosso repositório e clicar em “WebHooks & Services:4

Vamos até “Add Service” e adicionar o “Jenkins (Github Plugin)”
5
Agora em nosso servidor com Docker instalado, vamos iniciar o container que terá o Jenkins Master instalado.

############# SERVIDOR1 #################
docker run -p 8080:8080 -p 50000:50000 -d jenkins

Iniciado, agora vamos até o nosso browser e digitar http://ipserver:8080 e vamos fazer a configuração base do Jenkins.

1

Para pegar a senha você irá executar

docker exec idcontainer cat /var/jenkins_home/secrets/initialAdminPassword

Na pŕoxima página você pode escolher a opção de usar os plugins recomendados, então depois irá pedir para você criar um usuário.

2

Feito isso agora estamos na página inicial do jenkins.

3

Esse será nosso servidor de Jenkins Master que sera o responsável por avisar e mandar rodar alguns comandos no nosso servidor onde estará o Docker. Para isso, vamos acessar o servidor 2 e realizar a instalação do Jenkins:

############# SERVIDOR2 #################
sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
sudo rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key
sudo yum install jenkins -y
sudo yum install java -y 
sudo service jenkins start/stop/restart
sudo chkconfig jenkins on
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --zone=public --add-service=http --permanent
firewall-cmd --reload
sudo yum install java-1.7.0-openjdk -y

Após realizar a instalação do servidor2, vamos até o nosso servidor de Jenkins Master e adicionar o outro nó nele, colocando o IP e a forma pela qual o agente fosse instalado: Para isso você deve ir até “Gerenciar Jenkins” >> “Gerenciar nós”

6

Após isso você irá clicar em novo nó, colocar o ip desse novo servidor e clicar na opção de “Permanent” e OK. Após isso irá aparecer algo parecido com a tela abaixo então, você tera que fazer download do slave.jar, ir até o outro servidor e executar o comando do java que é mostrado na imagem abaixo, porem com as suas configurações.

7

Feito isso, vamos até a tela da esquerda na opção de configurações e configurar parecido com a imagem abaixo: A parte mais importante dessa tela é a configuração do “rótulo” que é o apelido que vamos dar a esse servidor, e também o “uso” que estamos dizendo que vamos executar esse servidor apenas como jobs.

8

Agora vamos até a página inicial do nosso jenkins e então criar o nosso build. Vamos até “Novo Build”

9

Após selecionar “Novo Build” vamos até a opção de configuração:

10

Vamos colocar o nome do nosso servidor de slave na opção de “Restringe onde este projeto pode ser executado”

11

Abaixo vamos colocar o nosso caminho do “GitHub” e também de qual branch irá baixar o código.

12

Vamos marcar  a opção de “Build when a change is pushed to github” e também a opção de quanto em quanto tempo vamos ir consultar o nosso “SCM”.

14

Em nosso ultimo passo, vamos colocar os comandos que iremos executar em nosso servidor. Vamos criar uma imagem a partir do Dockerfile que está em nosso GitHub e após isso vamos iniciar o container com essa imagem.

15

Então por hoje era isso pessoal, espero que tenham gostado do post e gostaríamos que vocês interagissem através de comentários propondo novos posts e arquiteturas que vocês gostariam que a gente fizesse com Docker. Em breve teremos mais posts nesse estilo.

Obrigado!

Referências: https://www.docker.com/sites/default/files/RA_CI%20with%20Docker_08.25.2015.pdf

: https://jenkins.io/solutions/docker/

: https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins

Dockerizando aplicações – Descartabilidade

Seguindo a lista do modelo 12factor, temos “Descartabilidade” como nona boa prática.

Quando falamos de aplicações web, espera-se que mais de um processo atenda a todo tráfego que é requisitado para esse serviço, porém tão importante quanto a habilidade de iniciar novos processos, é a capacidade de que um processo defeituoso termine na mesma velocidade que iniciou, pois um processo que demora para finalizar pode comprometer toda solução, uma vez que ela pode ainda estar atendemos requisições de forma defeituosa.

descartabilidade

Em resumo podemos dizer que aplicações web deveriam ser capazes de remover rapidamente processos defeituosos.

Com objetivo de evitar que o serviço prestado esteja muito dependente das instâncias que o servem, esta boa prática indica que as aplicações devem ser descartáveis, ou seja, que o fato de desligar uma de suas instâncias não afete a solução como um todo.

No Docker tem a opção de descartar automaticamente um contêiner após seu uso, no docker run utilize a opção –rm. Vale salientar que essa opção não funciona em modo daemon (-d), ou seja, só fará sentido utilizar essa opção em modo interativo (-i).

Outro detalhe importante nessa boa prática é viabilizar que seu código esteja preparado para se desligar “graciosamente” e reiniciar sem erros. Dessa forma, ao escutar um SIGTERM seu código deveria terminar qualquer requisição em andamento e então desligar o processo sem problemas e de forma rápida, permitindo também que seja rapidamente atendido por outro processo.

Entendemos como desligamento “gracioso” quando uma aplicação é capaz de auto finalizar sem causar danos a solução, ou seja, ao receber um sinal para desligar ela imediatamente deve recusar novas requisições e apenas finalizar as tarefas pendentes em execução no momento. O que está implícito nesse modelo é que as requisições HTTP sejam curtas (não mais que alguns poucos segundos) e nos casos de conexões mais longas que o cliente possa se reconectar automaticamente caso a conexão seja perdida.

Nossa aplicação teve a seguinte mudança para atender a especificação:

from flask import Flask
from redis import Redis
from multiprocessing import Process
import signal, os

host_redis=os.environ.get('HOST_REDIS', 'redis')
port_redis=os.environ.get('PORT_REDIS', '6379')

app = Flask(__name__)
redis = Redis(host=host_redis, port=port_redis)

@app.route('/')
def hello():
    redis.incr('hits')
    return 'Hello World! %s times.' % redis.get('hits')

if __name__ == "__main__":
    def server_handler(signum, frame):
        print 'Signal handler called with signal', signum
        server.terminate()
        server.join()
    
    signal.signal(signal.SIGTERM, server_handler)

    def run_server():
        app.run(host="0.0.0.0", debug=True)

    server = Process(target=run_server)
    server.start()

Como podem ver no código acima, adicionei um tratamento para quando receber um sinal de SIGTERM ele finalizar rapidamente o processo. Sem esse tratamento o código demoraria um pouco mais para ser desligado. Dessa forma podemos concluir que nossa solução já é descartável o suficiente, ou seja, podemos desligar e reiniciar os containers em outro docker host, e essa mudança não causará impacto na integridade dos dados.

Para fins de entendimento do que estamos trabalhando aqui, cabe falar um pouco sobre isso. De acordo com o Wikipedia, sinal é: “…uma notificação assíncrona enviada a processos com o objetivo de notificar a ocorrência de um evento.” E o SIGTERM é “…o nome de um sinal conhecido por um processo informático em sistemas operativos POSIX. Este é o sinal padrão enviado pelos comandos kill e killall. Ele causa o término do processo, como em SIGKILL, porém pode ser interpretado ou ignorado pelo processo. Com isso, SIGTERM realiza um encerramento mais amigável, permitindo a liberação de memória e o fechamento dos arquivos.”

Para realizar o teste de tudo que apresentado até então, realize o clone do repositório (https://github.com/gomex/exemplo-12factor-docker) e acesse a pasta factor8 (isso mesmo, a número 8, vamos demonstrar aqui a diferença pra o factor9), executando o comando abaixo para iniciar os contêineres:

docker-compose up -d

Depois execute o comando abaixo para finalizar os contêineres:

time docker-compose stop

Você verá que a finalização do worker demorará cerca de 11 segundos, isso porque o comportamento do docker-compose para finalizar é primeiro tentar um SIGTERM e esperar por 10 segundos que a aplicação finalize sozinha, caso contrário é enviado um SIGKILL que finalizar o processo mais bruscamente. Esse timeout é configurável. Caso deseje modificar basta usar o parâmetro “-t” ou “–timeout“. Vejam um exemplo:

docker-compose stop -t 5

Obs: O valor informado após o parâmetro deve ser considerado em segundos.

Agora para testar com o código modificado, basta mudar para a pasta factor9 e executar o seguinte comando:

docker-compose up -d

E depois solicitar seu término:

time docker-compose stop

Veja que o processo worker foi finalizar bem mais rápido, pois recebeu o sinal SIGTERM e a aplicação fez seu serviço de auto finalização e não precisou receber um sinal SIGKILL para ser de fato finalizado.

Docker no Windows 10

Oi pessoal!

Hoje o intuito é mostrar para vocês como instalar e utilizar o Docker for Windows no Windows 10 com apenas alguns cliques, com a ajuda do nosso amigo da Umbler, o Leo, estamos disponibilizando um vídeo com o passo-a-passo que deve ser seguido. Antes veja alguns requisitos que você precisa atender:

  1. Você deve ter o suporte a virtualização habilitado em seu computador;
  2. Seu Windows deve ser 64bits versão 1607 e build: 14393.0;
  3. Você deve habilitar o recurso do hyper-v;
  4. Baixe o Docker for Windows pelo link.

Basta você habilitar na Bios de seu computador o recurso de virtualização, para isso será necessário reiniciar seu computador. Em seguida habilite o recurso do hyper-v através do adicionar recursos do Windows (Painel de controle – programas – recursos do Windows). Execute o arquivo que você baixou lá do site do Docker e siga as instruções que aparecerem, logo em seguida aparecerá para você uma mensagem no canto inferior direito informando que o Docker está sendo iniciado, aguarde até a mensagem sair e pronto, o Docker estará instalado e configurado em seu computador.

Se você desejar, pode alterar as configurações dele pelo ícone que estará nos Ícones ocultos, por lá é possível parar e iniciar o serviço do Docker, assim como modificar o registry default, alterar configurações de rede, compartilhamento de volume, dentre outras opções.

Para usar é muito simples, abra o cmd e execute os comandos do Docker Cli, como se você estivesse em um terminal linux: docker ps -a, docker images, docker run xxx e assim por diante, note que a versão que ele instalará já é a 1.12 rc4, como você já viu nesse post, ela trás uma séria de melhorias e novas features, então bom divertimento :).

Esperamos que tenham gostado, e precisando nos enviem suas dúvidas para que possamos ajudar.

Grande abraço!

Dockerizando aplicações – Concorrência

Seguindo a lista do modelo 12factor, temos “Concorrência” como oitava boa prática.

Durante o processo de desenvolvimento de uma aplicação é difícil imaginar o volume de requisição que ela terá no momento que for colocada em produção. Por outro lado, ter um serviço que suporte grandes volumes de uso é algo esperado nas soluções modernas, pois nada é mais frustante do que solicitar acesso a uma aplicação e ela não estar disponível. Demonstra falta de cuidado e de profissionalismo na maioria dos casos.

Quando uma aplicação é colocada em produção normalmente ela é dimensionada para uma determinada carga esperada, porém é importante que o serviço esteja pronto para escalar, ou seja, a solução deve ser capaz de iniciar novos processo da mesma aplicação caso necessário, sem que isso afete negativamente o produto. A figura abaixo apresenta um gráfico de escalabilidade de serviços.

Untitled Diagram (2)

Com objetivo de evitar que exista qualquer problema na escalabilidade do serviço, esta boa prática indica que as aplicações devem suportar execuções concorrentes, tal que quando um processo está em execução deve ser possível instanciar um outro em paralelo e o serviço possa ser atendido sem perda alguma.

Para que isto aconteça, é importante dividir as tarefas corretamente. É interessante que os processos se atenham aos seus objetivos, ou seja, caso seja necessário executar alguma atividade em backend e depois retornar uma página para o navegador, é salutar que existam dois serviços que tratem as duas atividades de forma separada. O Docker torna essa tarefa mais simples, pois nesse modelo basta especificar um contêineres para cada função e configurar corretamente a rede entre eles.

Para exemplificar essa boa prática, usaremos a arquitetura demonstrada na figura abaixo:

Untitled Diagram (1)

O serviço web será responsável por receber a requisição e balancear entre os workers, os quais são responsáveis por processar a requisição, conectar ao redis e retornar uma tela de “Hello World” informando quantas vezes ela foi obtida e qual nome do worker que está respondendo essa requisição (Para ter certeza que está balanceando a carga), como podemos ver na figura abaixo:

Screen Shot 2016-07-25 at 11.18.25 PM

O arquivo docker-compose.yml exemplifica essa boa prática:

version: "2"
services:
  web:
    container_name: web
    build: web
    networks:
      - backend
    ports:
      - "80:80"

  worker:
    build: worker
    networks:
      backend:
        aliases:
          - apps
    expose:
      - 80
    depends_on:
      - web

  redis:
    image: redis
    networks:
      - backend

networks:
  backend:
      driver: bridge

Para efetuar a construção desse balanceador de carga, temos o diretório web contendo os arquivos Dockerfile (responsável por criar a imagem utilizada) e nginx.conf (arquivo de configuração do balanceador de carga utilizado).

Segue abaixo o conteúdo do DockerFile do web:

FROM nginx:1.9

COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Segue o conteúdo do arquivo nginx.conf:

user nginx;
worker_processes 2;

events {
  worker_connections 1024;
}

http {
  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  resolver 127.0.0.11 valid=1s;

  server {
    listen 80;
    set $alias "apps";

    location / {
      proxy_pass http://$alias;
    }
  }
}

No arquivo de configuração acima, foram introduzidas algumas novidades. A primeira é o “resolver 127.0.0.11“, que é o serviço DNS interno do Docker. Usando essa abordagem será possível efetuar o balanceamento de carga via nome, usando um recurso interno do Docker.

Para mais detalhes sobre o funcionamento do DNS interno do Docker, veja esse documento (https://docs.docker.com/engine/userguide/networking/configure-dns/) (apenas em inglês).

A segunda novidade é a função set $alias “apps”; que é responsável por especificar o nome “apps” que será usado na configuração do proxy reverso em seguida “proxy_pass http://$alias;“. Vale salientar que o “apps” é o nome da rede especificada dentro do arquivo docker-compose.yml. Nesse caso o balanceamento será feito para a rede, ou seja, todo novo contêiner que entrar nessa rede será automaticamente adicionado no balanceamento de carga.

Para efetuar a construção do worker temos o diretório worker contendo os arquivos Dockerfile (responsável por criar a imagem utilizada), app.py (que é a aplicação que usamos em todos os outros capítulos) e requirements.txt (descreve todas as dependências do app.py).

Segue abaixo o conteúdo do arquivo app.py modificado para essa prática:

from flask import Flask
from redis import Redis
import os
import socket
print(socket.gethostname())
host_redis=os.environ.get('HOST_REDIS', 'redis')
port_redis=os.environ.get('PORT_REDIS', '6379')

app = Flask(__name__)
redis = Redis(host=host_redis, port=port_redis)

@app.route('/')
def hello():
   redis.incr('hits')
   return 'Hello World I am %s! %s times.' % (socket.gethostname(), redis.get('hits'))
if __name__ == "__main__":
   app.run(host="0.0.0.0", debug=True)

Segue abaixo o conteúdo do requirements.txt:

flask==0.11.1
redis==2.10.5

E por fim o Dockerfile do worker tem o seguinte conteúdo:

FROM python:2.7
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . /code
WORKDIR /code
CMD python app.py

No serviço redis, não há construção da imagem, pois usaremos a imagem oficial para efeitos de exemplificação.

Para realizar o teste de tudo que apresentado até então, realize o clone do repositório (https://github.com/gomex/exemplo-12factor-docker) e acesse a pasta factor8, executando o comando abaixo para iniciar os contêineres:

docker-compose up -d

Acesse os contêineres através do navegador na porta 80 (se utilizar toolbox é 192.168.99.100, caso contrário acesse a localhost). Tente atualizar a página e veja que apenas um nome aparecerá.

Por padrão o docker-compose executa apenas uma instância de cada serviço explicitado em seu docker-compose.yml. Para aumentar a quantidade de contêineres “worker” de apenas um para dois execute o comando abaixo:

docker-compose scale worker=2

Atualize a página no navegador novamente e verá que o nome do host vai alternar entre duas possibilidades, ou seja, as requisições estão sendo balanceadas para ambos contêineres.

Nessa nova proposta de ambiente, o serviço web se encarregará de receber todas requisições HTTP e fazer o balanceamento de carga. Então o worker será responsável por processar essas requisições, que basicamente é obter seu nome de host, acessar o redis e obter a contagem de quantas vezes esse serviço foi requisitado e então gerar o retorno, para então devolvê-lo para o serviço web, que por sua vez responderá ao usuário. Como podem perceber, cada instância desse ambiente tem sua função bem definida e com isso será muito mais fácil escalá-lo.

Aproveito para dar os créditos ao capitão Marcosnils, que foi a pessoa que me mostrou que é possível balancear carga pelo nome da rede docker.

Um agradecimento especial para @glesio@JFCostta e bemanuel_pe que fizeram uma ótima revisão desse texto.

Docker 1.12 – O que vem por aí

Oi Pessoal,
Já vimos aqui no blog algumas ferramentas e soluções, como por exemplo: Docker Compose, Docker Swarm, SwarmkitDocker Network, dentre outros. Bom, o que você sabe sobre elas é essencial para entender a nova versão do Docker, que será lançada em agosto e que está em RC4 atualmente.

A grande novidade no Docker 1.12 é ter a orquestração nativa, sem a necessidade de ter duas ou mais ferramentas para criar seu cluster de Docker, basta apenas que você tenha a engine instalada e a partir dela poderá montar seu ambiente. Outra grande novidade é o conceito de serviço, esse conceito nós já tratamos em Swarmkit, e é algo que foi incorporado ao Docker para facilitar o deploy e escalonamento das aplicações. Vamos ver o que muda?

Orquestração:

Agora para você criar um cluster de Docker, basta rodar:

docker swarm init

Com isso você iniciará o primeiro nó do cluster, para adicionar mais nós ao cluster execute o seguinte comando em outro nó:

docker swarm join IP-DO-MANAGER:2377

Veja na imagem abaixo a sequência de comandos:

docker_swarm

Serviços:

No Docker 1.12 foi introduzido o conceito de serviço, que já existe no Kubernetes, e que agora possibilita a criação, atualização e escalonamento da sua camada de serviço (seja ela de frondend ou backend) de forma muito mais fácil. Por exemplo:

docker service create --replicas 1 --name servico1 alpine echo "Ola Mundo"

Dessa forma você estará criando um serviço com um container de Alpine, você pode aumentar a quantidade de containers que irão atender este serviço, para isso execute:
docker_service

Além de poder criar e escalonar, você pode ainda realizar a atualização de seu ambiente, basta utilizar o comando update, e pode ainda definir uma politica de atualização (por exemplo, executar a atualização em um container por vez, com isso ele removerá um container e iniciará um novo baseado na nova imagem). Você pode ainda, definir um bloco de rede para cada serviço, com isso você isola totalmente os ambientes, veja:

docker service create --replicas 3 --name webservers --network web --publish 80:80/tcp nginx

Dessa forma, serão criados 3 containers (caso você tenha colocar 2 ou mais hosts no cluster de Swarm, será criado um container por host). O mais interessante nesse ambiente é que, se você acessar a porta 80 de qualquer host que esteja no cluster Swarm, seu acesso será redirecionado ao serviço, independente se o container esteja nele ou não, isso por que o Docker garante que o serviço esteja acessível mesmo que um nó venha a falhar. E como o Docker faz isso? Simples, através da 3 feature adicionada nessa versão:

Roteamento:

Quando você criar um cluster via Docker Swarm, o Docker se encarregará de atribuir ao serviço um identificador único dentro do cluster, com isso, quando for solicitado acesso á porta exposta na criação do serviço, o acesso será roteado para o container que é responsável por aquele serviço (ou mais de um é claro), ele faz isso através do algoritmo de routing mesh que está presente na engine, ele identifica quem possuí o container que atende o serviço e redireciona o trafego para ele, por isso é importante que, quando você criar um novo serviço define uma rede também, pois reduzirá o tempo de processamento que a engine precisará para identificar onde encontra-se o container.

Segurança:

Por último e não menos importante, vem a questão de segurança. No Docker 1.12, toda a comunicação do cluster é realizada via tls, e quem garante o rotacionamento desses certificados (renovação e deploy) assim como a criação de certificados para novos nós é o nó manager, que é eleito baseado em uma série de parâmetros (disponibilidade e saúde), mas que de maneira geral é o primeiro nó onde você iniciou o cluster. Os certificados são rotacionados de tempos em tempos, e você pode modificar essa politica também.

Há mais coisas? Claro! Foi adicionado também um sub comando do comando docker plugin que permite você plugar de forma mais fácil os plugins do Docker, quando você realizar um docker plugin install nome_do_plugin, lhe será informado ao que exatamente aquele plugin terá acesso, e poderá assim permitir ou não sua instalação.

Bacana né? Se gostou nos ajude divulgando o blog e caso tenha dúvida nos avise 😉

Grande Abraço!

Olá Mundo v3, agora com Hugo

Novamente estamos aqui para mudar a tecnologia utilizada no blog.

Como tenho trabalhado muito com Docker comecei a querer aprender Go lang, a linguagem de programação do Google, que utilizaram para fazer o Docker e suas principais ferramentas.

Nos meus estudos descobri o Hugo https://gohugo.io/, um gerador de sites estáticos absurdamente rápido, e até um pouco mais simples e poderoso de usar que o Jekyll (IMHO).

A hospedagem que já tinha mudado de github pages para AWS permanece e o domínio vamos começar a trabalhar com .com.

E isso aí e até a próxima!

Escalando o MySQL com Docker e MaxScale

Oi Pessoal,

Não, hoje o post não é nosso :). Mas queremos divulgar um ótimo conteúdo criado por um de nossos parceiros, o MySQLBox, que é um dos maiores blogs sobre o SGBD MySQL e é mantido por um grande amigo nosso.

Então não deixe de ler o post: Escalando Mysql com Docker e Maxscale e veja como o Docker pode ajudar a escalar seu ambiente de banco de dados de forma fácil e rápida.

Grande abraço!

Docker Machine

Olá!

Umas das ferramentas mais interessantes do ecossistema Docker, e que é mantido pela própria Docker é o Docker Machine, com ele é possível você fazer deploy de seu ambiente na infra-estrutura que desejar, você pode portar sua aplicação do seu notebook para AWS, Digital Ocean, ou o que for. Veja no vídeo um exemplo prático disso:

Você pode ainda integrar com Docker Compose, e automatizar ainda mais essas tarefas, legal né? Espero que tenham gostado, tendo dúvidas nos contatem, estamos dispostos a sanar todas as dúvidas.

Abraço!

Dockerizando aplicações – Vínculo de portas

Seguindo a lista do modelo 12factor, temos “Vínculos de portas” como sétima boa prática.

É comum encontrar aplicações que são executadas dentro de contêineres de servidores web, tal como Tomcat, ou Jboss, por exemplo. Normalmente essas aplicações são implantadas dentro desses serviços para que possam ser acessadas pelos usuários externamente.

Ego_network

Essa boa prática sugere que o aplicativo em questão seja auto-contido e dependa de um servidor de aplicação, tal como Jboss, Tomcat e afins. O software sozinho deve exportar um serviço HTTP e lidar com as requisições que chegar por ele. Isso quer dizer que nenhuma aplicação adicional deveria ser necessária para que seu código possa estar disponível para comunicação externa.

Tradicionalmente a implantação de aplicações em serviços de aplicação web, tal como Tomcat e Jboss, exigem que seja gerado um artefato e esse deve ser enviado para o serviço web em questão, mas no modelo de contêiner docker a idéia é que o artefato do processo de implantação seja o próprio contêiner em sí.

O processo antigo de implantação do artefato em um servidor de aplicação normalmente não tinha um retorno rápido e isso aumentava demasiadamente o processo de implantação de um serviço, pois cada alteração demandava enviar o artefato para o serviço de aplicação web, sendo que esse tinha como responsabilidade de importar, ler e executar o novo artefato.

Usando Docker facilmente torna a aplicação auto-contida. Já construímos um Dockerfile que descreve tudo que a aplicação precisa:

FROM python:2.7
ADD requirements.txt requirements.txt
RUN pip install -r requirements.txt
ADD . /code
WORKDIR /code
CMD python app.py
EXPOSE 5000

As dependências estão descritas no arquivo requirements.txt e os dados que devem ser persistidos são geridos por um serviço externo (serviços de apoio) à aplicação.

Um outro detalhe desta boa prática é que a aplicação deve exportar o serviço através da vinculação a uma única porta. Como podemos ver no código exemplo, a porta padrão do python (5000) é iniciada, mas você pode escolher outra, caso julgue necessário. Segue o recorte do código que trata desse assunto:

if __name__ == "__main__":
  app.run(host="0.0.0.0", debug=True)

Essa porta 5000 pode ser utilizada para servir dados localmente em um ambiente de desenvolvimento ou através de um proxy reverso quando for migrada para produção, com um nome de domínio adequado a aplicação em questão.

Utilizando esse modelo de vinculação de portas torna o processo de atualização de aplicação mais fluído, uma vez que na utilização de um proxy reverso inteligente, é possível adicionar novos nós gradativamente, com a nova versão, e remover os antigos a medida que as versões atualizadas estão sendo executadas em paralelo.

Convém salientar que mesmo que o Docker permita a utilização de mais do que uma porta por contêineres, essa boa prática é enfática ao afirmar que você só deve utilizar uma porta vinculada por aplicação.

Origens da Infra Ágil

Após o lançamento do site infraagil.io algumas pessoas me perguntaram sobre suas origens e sobre as motivações que levaram a criação do site e desse modelo.

Esse texto foi parte da versão “alpha” do site infraagil.io, hoje ele não está mais lá, foi retirado para deixar o conteúdo mais objetivo, contudo, seu contexto cabe neste blog.

Origens

Em 2011 eu dividi uma palestra com o colega Daniel Sobral (a.k.a Gandalf) no CONSEGI em Brasília/DF, o tema central da palestra era a gerência de configurações e os benefícios deste modelo para o Governo Federal. Tivemos um excelente quórum e o tema começou a se espalhar pela Esplanada de Ministérios, muitos profissionais queriam saber mais deste conceito e das tecnologias envolvidas.

Creio que aquela foi a primeira oportunidade que eu tive para abordar o momento em que eu vivia como sysadmin. O movimento DevOps estava no início da formação de sua cultura, não fazia nem um ano que John Willis e Damon Edwards haviam criado o acrônimo CAMS, iniciativa que deu norte para a comunidade DevOps. Sem nem saber ou conhecer direito este modelo, o time em que eu trabalhava já havia começado a estudar e experimentar algumas técnicas e métodos ágeis na operação, algo inovador dentro do governo brasileiro e principalmente inovador para a organização que havia nos contratado.

Marco Zero

Naquela época trabalhei em um time fantástico, pude aprender muito com profissionais experientes como Fernando Ike (@fernandoike), José Eufrásio Júnior (@coredump), Daniel Capó Sobral (@dcsobral), Daniel Negri (@danielnegri), Douglas Andrade (@douglasandrade) dentre outros.

Nós estudávamos constantemente, estávamos sempre experimentando e compartilhando experiências dentro e fora dos times. O @FernandoIke trabalhava na integração de todos os times de TI da organização, focando na comunicação, no compartilhamento de responsabilidades, na garantia de entrega e na disponibilidade de recursos para o time devel trabalhar traquilo e entregar o que o cliente precisava. Ele era o escudo da TI e nos ajudava a manter o foco. O @Coredump era o líder do time de infra, seu foco era inovação e autonomia, graças a ele nosso time começou a estudar automação de infraestrutura no final de 2010, testamos e usamos ali versões primitivas do Puppet e Chef. No final dos testes acabamos optando pelo Puppet e fizemos a primeira implantação em escala de centenas de nós no governo brasileiro.

Em 2010 nós já estávamos trabalhando com infraestrutura como código, gerência de configuração, orquestração, pipeline de deploys e métricas avançadas, respirávamos inovação dia-a-dia, e tudo isso foi construído em uma curta janela de um ano e meio.

 Foi um período fantástico da minha vida em que aprendi muito com todo o time.

Após a conclusão do projeto, cada um seguiu um rumo diferente , alguns foram morar no exterior, outros mudaram de área, outros se tornaram empresários, a vida seguiu seus rumos. Acredito que aquela experiência marcou todos daquele time, no meu caso foi um divisor claro, eu era um sysadmin artesão e comecei a dar os primeiros passos para um modelo de trabalho mais eficiente e autônomo.

Novos caminhos, novas parcerias

Alguns anos depois desta experiência, no início de 2014, depois de muitas aventuras pelo Governo Federal, eu conheci pessoalmente o Miguel Di Ciurcio Filho (@mciurcio), outro desses profissionais que pensam bem a frente do seu tempo. Enquanto eu desbravava datacenters na esplanada dos ministérios entre 2010 e 2014, na mesma época Miguel atuava com startups e incubadoras na região de Campinas e Barueri no estado de São Paulo. Ele trabalhou com tecnologias modernas e inovadoras na área de automação, banco de dados e virtualização. Sua experiência com desenvolvimento, em especial no Google Summer of Code, no qual ele atuou com o projeto QEMU, lhe deram um olhar único relativo a administração e gestão de infraestrutura de TI das organizações em que passou.

Todos esses caminhos , interesses comuns, a participação nas mesmas comunidades, os projetos que acompanhamos, tudo isto foi importante para o início de nossa parceria na Instruct, empresa que ele fundou em 2011 e empresa na qual faço parte desde 2014 após o seu convite.

Trabalhando com ele o espaço e o alcance que tive para estudar e aprimorar este modelo - dentro da Instruct - foi inimaginável, afinal, ambos tivemos experiências muito parecidas, seguimos escolas similares como sysadmins e através da Instruct encontramos as empresas que podiam se beneficiar da soma de nossas experiências.

De lá para cá temos construído e evoluído juntos essa abordagem da infra ágil que organizamos no site infraagil.io.

Não estamos mais sozinhos neste projeto, nós convidamos alguns parceiros que tem nos ajudado (Alliance Members) a organizar e melhorar esse modelo. O objetivo é fazer com o modelo cresça e alcance aqueles profissionais que precisam de uma referência clara para começar a transformar seus times e sua infraestrutura.

[s]
Guto

DevOpsDays POA Resumo

‪Galera o #‎DevOpsDays de ‪#‎PortoAlegre‬ foi um dos melhores eventos que participei nos últimos anos, focado, com público alinhado, tinha apenas 130 pessoas presentes, todos muito interessados, o evento manteve um alto nível em todas as suas palestras, teve humor, ignites, open spaces, fishbowl, networking e muito compartilhamento. ‪

#‎Recomendo‬

[s]
Guto

Novo projeto infraagil.io

Durante o TDC fizemos o lançamento do site infraagil.io.

Este site organiza boas práticas para serem aplicadas no seu time de operação e infraestrutura.

Recomendo a visita!

[]s
Guto

Grupos de TI no Telegram

No Brasil o Telegram acolheu grupos de comunidades de TI que discutem diversas tecnologias, seu crescimento tem sido espantoso e formidável, tem aproximado pessoas e ajudado a diminuir a curva de aprendizado de muitas tecnologias.

As listas de discussão ainda continuam vivas mas não são orgânicas e dinâmicas como o Telegram, talvez esse seja o segredo de seu sucesso somado ao seu conjunto incrível de recursos.

Grupos no telegram que eu recomendo!

Tecnologias

https://telegram.me/puppetbr
https://telegram.me/gitlabbr
https://telegram.me/vagrantbr
https://telegram.me/dockerbr
https://telegram.me/ansiblebr
https://telegram.me/chefbr
https://telegram.me/rancherbr
https://telegram.me/openshiftbr

elastic-users-br
mac-users-brasil

Comunidades

devops-br
infraagil.io

Linguagens

https://telegram.me/go_br
https://telegram.me/rubybrasil
https://telegram.me/pythonbr
https://telegram.me/PyCoding

Participe!

[s]
Guto

E os logs?

Oi Pessoal, tranquilo?

Uma das coisas que atormentam tanto a vida do pessoal de Dev quanto de Ops é saber o que está acontecendo com o seu ambiente. Como se resolve isso? Existem duas formas, que devem sempre trabalhar juntas, são elas: Monitoramento, para saber que vai dar problema antes do problema ocorrer :), e Gerencia de logs, para saber, depois de ocorrer algum problema, o que aconteceu com sua aplicação ou ambiente que ocasionou o comportamento inesperado.

Essa mesma abordagem deve ser utilizada quando se trabalha com containers também, para monitoria você já viu aqui e aqui algumas formas de como pode ser feito esse monitoramento. Para a gerencia de logs você deve pensar antes qual será a criticidade dessas informações para o debug de sua aplicação e resolução de algum imprevisto, outro ponto é: como preciso ou como gostaria de visualizar essas informações. Tendo resolvido essas duas questões você pode então optar:

  • Utilizar o comando docker logs: Com isso você terá as informações do que está sendo enviando para a console do container, ou seja,somente irá visualizar aquilo que estiver passando na console, você deve fazer com que sua aplicação envie as informações necessárias para a console do container. Caso sua aplicação salve o debug em arquivo de log você não conseguirá visualizar de forma fácil essa informação.
  • Utilizar plugins de log: Utilizando plugins você pode fazer com que qualquer log do container seja enviado para um serviço externo, isso garante que você poderá ter acesso a qualquer informação (seja do container ou app) de um único lugar.

O que vamos ver hoje é como você pode utilizar alguns dos plugins de logs mais conhecidos, isso é claro na prática 🙂

Fluentd

Um dos drivers de log mais fácil de se utilizar, com ele você pode enviar tanto o stderr quanto o stout para o serviço de logs externo, para isso basta você rodar:

docker run --log-driver=fluentd

É claro que você precisa passar alguns parâmetros, como por exemplo: “–log-opt fluentd-address=” onde você define qual será o destino de seus logs, geralmente será um host onde estará rodando o servidor Fluentd ou o endereço que esse serviço lhe fornecer. Por padrão a tag de busca será o id do container, com isso, quando você precisar consultar algum log deverá faze-lo pelo id do container que desejar.

Splunk

O Splunk é talvez uma das ferramentas para gerenciamento de log mais completo que se pode ter, e da mesma forma que o Fluentd, você precisa apenas definir esse driver como sendo de log:

docker run --log-driver=splunk

Você precisa definir algumas coisas antes, veja a lista:

  • splunk-token: Token utilizado para autenticação do container na API http;
  • splunk-url: Endereço do servidor de Splunk disponível, seja ele local ou na solução de cloud da Splunk;
  • splunk-source: Origem do log (se não definido ele coletará tudo);
  • splunk-sourcetype: Tipo do log (app, debug, etc);
  • splunk-index: Índice para os logs;
  • splunk-capath: Caminho do certificado;
  • splunk-caname: Nome para validação do certificado, por padrão ele pega pelo nome do splunk-url;
  • splunk-insecureskipverify: Desativa a verificação ssl para o seu host Splunk;
  • tag: Identificação do log na base, no caso do Docker você pode definir qualquer informação do container como tag, por exemplo: ID, Nome, Região, etc;
  • labels: Facilita a consulta do log posteriormente, você pode por exemplo consultar logs do container x que pertence a região Sul;
  • env: Pode classificar por Dev, Test, Prod etc.

Veja um exemplo prático:

docker run --log-driver=splunk --log-opt splunk-token=SEUTOKENAQUI --log-opt splunk-url=https://servidor-splunk:8088 --log-opt splunk-capath=/etc/cert/cacert.pem --log-opt splunk-caname=SplunkDefaultCert --log-opt tag="{{.Name}}/{{.FullID}}" --log-opt labels=location --log-opt env=TESTE --env "TESTE=false" --label location=sul nginx

AWS Logs

Claro que não poderia faltar a opção de enviar seus logs para o CloudWatch da AWS, e é o mais simples de se utilizar, por um motivo: Basta você ter conta na AWS e ativar o CloudWatch, não é necessário contratar um serviço cloud de terceiro ou subir um servidor de log local. Veja como você pode utiliza-lo:

docker run --log-driver=awslogs --log-opt awslogs-region=sa-east-1

Você deve definir para qual grupo de log deseja enviar os logs do container, e tenha cuidado pois dependendo do tipo de logs e quantidade, pode prejudicar a visualização do mesmo, então preste atenção no formato de log que estará enviando:

docker run --log-driver=awslogs --log-opt awslogs-region=sa-east-1 --log-opt awslogs-group=MeuGrupodeLog nginx

A autenticação é bem simples, você montar o seguinte volume: aws:~/.aws, dentro dessa pasta deve ter um arquivo chamado credentials com o seu AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, e AWS_SESSION_TOKEN Lembre-se que o usuário utilizado para isso deve ter no mínimo as seguintes permissões: logs:CreateLogStream e logs:PutLogEvents.

Espero ter ajudado, tenho alguma dúvida pode nos enviar por e-mail ou deixe nos comentários. E nos ajude divulgando o blog 😉

Abraço!

Resumo TDC-SP

Passando para informar que foi um prazer participar do TCP SP na trilha infra ágil. Este ano além de ajudar a coordenadar a trilha eu palestrei e abri o evento na sexta-feira em parceira com o Miguel Filho. Aproveitamos para lançar o site infragil.io durante a palestra, foi intenso e o feedback do pessoal foi bastante positivo.

Palestras apresentadas:

1) Infra Ágil do conceito a prática (Guto e Miguel)
2) Equipes Ágeis de infraestrutura (Guto)
3) Gerência de Configuração vs Orquestração (Miguel)

Gostei bastante de participar de um evento tão plural e diverso.

#‎Recomendo‬

[s]
Guto

Dockerizando aplicações – Processos

Seguindo a lista do modelo 12factor, temos “Processos” como sexta boa prática.

Com advento da automatização, e uma devida inteligência na manutenção das aplicações, hoje é esperado que a sua aplicação possa atender a picos de demandas com inicialização automática de novos processos, sem que isso afete negativamente o comportamento da mesma.

download (1)

Essa boa prática indica que processos de aplicações 12factor são stateless (não armazenam estado) e share-nothing. Quaisquer dados que precise persistir deve ser armazenado em um serviço de apoio stateful(que armazena o seu estado), tipicamente uma base de dados.

O objetivo final dessa prática é não fazer distinção se a aplicação está sendo executada na máquina do desenvolvedor ou em produção, pois nesse caso o que mudaria seria a quantidade de processos iniciados para atender as suas respectivas demandas, ou seja, na máquina do desenvolvedor poderia ser apenas um e em produção um número maior.

O 12factor indica que o espaço de memória ou sistema de arquivos do servidor pode ser usado brevemente como cache de transação única. Por exemplo, o download de um arquivo grande, operando sobre ele, e armazenando os resultados da operação no banco de dados.

Vale a pena salientar que um estado nunca deve ser armazenado entre requisições, não importando o estado do processamento da próxima requisição.

É importante salientar que ao seguir essa prática, uma aplicação nunca assume que qualquer coisa armazenada em cache de memória ou no disco estará disponível em uma futura solicitação ou job – com muitos processos de cada tipo rodando, as chances são altas de que uma futura solicitação será servida por um processo diferente, até mesmo em um servidor diferente. Mesmo quando rodando em apenas um processo, um restart (desencadeado pelo deploy de um código, mudança de configuração, ou o ambiente de execução realocando o processo para uma localização física diferente) geralmente vai acabar com todo o estado local (por exemplo, memória e sistema de arquivos).

Algumas aplicações demandam de sessões persistentes, para armazenar informações da sessão de usuários e afins. Essas sessões são usadas em futuras requisições do mesmo visitante, ou seja, se armazenado junto ao processo isso é uma clara violação dessa boa prática. Nesse caso o mais aconselhável é usar um serviço de apoio, tal como redis, memcached ou afins para esse tipo de trabalho externo ao processo, com isso será possível que o próximo processo, independente onde ele esteja, conseguirá obter as informações atualizadas.

A aplicação que estamos trabalhando não guarda nenhum dado local, e tudo que ela precisa é armazenado no Redis. Dessa forma não precisamos fazer adequação alguma nesse código para seguir essa boa prática, como podemos ver abaixo:

from flask import Flask
from redis import Redis
import os
host_redis=os.environ.get('HOST_REDIS', 'redis')
port_redis=os.environ.get('PORT_REDIS', '6379')
app = Flask(__name__)
 redis = Redis(host=host_redis, port=port_redis)
@app.route('/')
def hello():
 redis.incr('hits')
 return 'Hello World! %s times.' % redis.get('hits')
if __name__ == "__main__":
 app.run(host="0.0.0.0", debug=True)

Para acessar o código dessa prática, acesse o nosso repositório e acesse a pasta “factor6“.

Dockerizando aplicações – Construa, lance, execute

Seguindo a lista do modelo 12factor, temos “Construa, lance, execute” como quinta boa prática.

Em um processo de automatização de infraestrutura de implantação de software, precisamos ter alguns cuidados para que o comportamento do processo esteja dentro das expectativas e que erros humanos causem baixo impacto no processo completo do desenvolvimento ao lançamento em produção.

release

Visando organizar, dividir responsabilidade e deixar o processo mais claro, o 12factor indica que o código base para ser colocado em produção deva passar por três fases:

  • Construa é quando o código do repositório é convertido em um pacote executável. Nesse processo é onde se obtém todas as dependências, compila-se o binário e todos os ativos desse código.
  • Lance é quando o pacote produzido pela fase de construir é combinado com sua configuração. O resultado é o ambiente completo, configurado e pronto para ser colocado em execução.
  • Execute (também como conhecido como “runtime”) é quando um lançamento (aplicação + configuração daquele ambiente) é colocado em execução, iniciado com base nas configurações especificas do seu ambiente requerido.

Essa boa prática indica que sua aplicação tenha separações explícitas nas fases de Construa, Lance e Execute. Assim cada mudança no código da aplicação é construída apenas uma vez na etapa de Construa. Mudanças da configuração não necessitam de uma nova construção, sendo apenas necessário passar pelas etapas de lançar e executar.

Dessa forma é possível criar controles e processos claros em cada etapa, ou seja, caso algo ocorra na construção do código, uma medida pode ser tomada e até mesmo abortado o lançamento do mesmo, para que o código em produção não seja comprometido por conta do possível erro.

Com a separação das responsabilidades é possível saber exatamente em qual etapa o problema aconteceu e atuar manualmente caso necessário.

Os artefatos produzidos devem sempre ter um identificador de lançamento único, que pode ser o timestamp do seu lançamento (como 2011-04-06-20:32:17) ou um número incremental (como v100).

Com o uso de artefato único é possível garantir o uso de uma versão antiga, seja para um plano de retorno ou até mesmo para comparar comportamentos após mudanças no código.

Para atendermos essa boa prática precisamos primeiro construir a imagem Docker com a aplicação dentro, ou seja, ela será nosso artefato.

Teremos um script novo, que aqui chamaremos de build.sh, nesse arquivo teremos o seguinte conteúdo:

#!/bin/bash

USER="gomex"
TIMESTAMP=$(date "+%Y.%m.%d-%H.%M")

echo "Construindo a imagem ${USER}/app:${TIMESTAMP}"
docker build -t ${USER}/app:${TIMESTAMP} .

echo "Marcando a tag latest também"
docker tag ${USER}/app:${TIMESTAMP} ${USER}/app:latest

echo "Enviando a imagem para nuvem docker"
docker push ${USER}/app:${TIMESTAMP}
docker push ${USER}/app:latest

Como podem ver no script acima, além de construir a imagem ele envia a mesma para o repositório de imagem do docker.

Lembre-se que o código acima e todos os outros dessa boa prática estão nesse repositório na pasta “factor5“.

O envio da imagem para o repositório é parte importante da boa prática em questão, pois isso faz com que o processo seja isolado, ou seja, caso a imagem não fosse enviada para um repositório, ela estaria apenas no servidor que executou o processo de construção da imagem, sendo assim a próxima etapa precisaria necessariamente ser executada no mesmo servidor, pois ela precisará da imagem disponível.

No modelo proposto a imagem estando no repositório central, ela estará disponível para ser baixada no servidor caso ela não exista localmente. Caso você utilize uma ferramenta de pipeline é importante você ao invés de utilizar a data para tornar o artefato único, utilize variáveis do seu produto para garantir que a imagem que será consumida na etapa de Executar seja a mesma construída no Lançar. Ex. no GoCD temos as variáveis GO_PIPELINE_NAME e GO_PIPELINE_COUNTER que podem ser usadas em conjunto para garantir isso.

Com a geração da imagem podemos garantir que a etapa Construir foi atendida perfeitamente, pois agora temos um artefato construído e pronto para ser reunido a sua configuração.

E etapa de Lançamento é o arquivo docker-compose.yml em si, pois o mesmo deve receber as configurações devidas para o ambiente que se deseja colocar a aplicação em questão, sendo assim o arquivo docker-compose.yml muda um pouco e deixará de fazer construção da imagem, pois agora ele será utilizado apenas para Lançamento e Execução (posteriormente):

version: "2"
services:
  web:
    image: gomex/app:latest 
    ports:
     - "5000:5000"
    volumes:
     - .:/code
    labels:
     - 'app.environment=${ENV_APP}'
    environment:
     - HOST_RUN=${HOST_RUN}
     - DEBUG=${DEBUG}
     - PORT_REDIS=6379
     - HOST_REDIS=redis
  redis:
    image: redis:3.2.1
    volumes:
     - dados:/data
    labels:
     - 'app.environment=${ENV_APP}'
volumes:
  dados:
    external: false

No exemplo docker-compose.yml acima usamos a tag latest para garantir que ele usará sempre a ultima imagem construída nesse processo, mas como falei anteriormente, caso utilize alguma ferramenta de entrega contínua (Ex. GoCD) faça uso das suas variáveis para garantir o uso da imagem criada naquela execução específica do pipeline.

Dessa forma, lançamento e execução sempre utilizarão o mesmo artefato, a imagem Docker, construída na fase de construção..

E etapa de execução basicamente é executar o docker-compose com o comando abaixo:

docker-compose up -d

Dockerizando aplicações – Serviços de Apoio

Seguindo a lista do modelo 12factor, temos “Serviços de Apoio” como quarta boa prática.

Para contextualizar, serviços de apoio é qualquer aplicação que seu código consome para operar corretamente (Ex. Banco de dados, serviço de mensagens e afins).

attached-resources

Com objetivo de evitar que seu código seja demasiadamente dependente de uma determinada infraestrutura, essa boa prática indica que você, no momento da escrita do software, não faça distinção se o serviço é interno ou externo, ou seja, seu aplicativo deve estar pronto para receber parâmetros que farão a configuração do serviço correto e assim possibilitem o consumo de aplicações necessárias da solução proposta.

A aplicação exemplo sofreu algumas modificações para suportar essa boa prática:

from flask import Flask
from redis import Redis
import os
host_run=os.environ.get('HOST_RUN', '0.0.0.0')
debug=os.environ.get('DEBUG', 'True')
host_redis=os.environ.get('HOST_REDIS', 'redis')
port_redis=os.environ.get('PORT_REDIS', '6379')
app = Flask(__name__)
redis = Redis(host=host_redis, port=port_redis)
@app.route('/')
def hello():
   redis.incr('hits')
   return 'Hello World! %s times.' % redis.get('hits')
if __name__ == "__main__":
   app.run(host=host_run, debug=True)

Como você pode perceber no código acima, sua aplicação agora pode receber variáveis de ambiente para configurar o hostname e porta do serviço Redis, ou seja, nesse caso é possível configurar um host e porta da redis que você deseja conectar. E tudo isso pode, e deve, ser especificado no docker-compose.yml, que também passou por uma mudança para se adequar a essa nova boa prática:

version: "2"
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
    labels:
     - 'app.environment=${ENV_APP}'
    environment:
     - HOST_RUN=${HOST_RUN}
     - DEBUG=${DEBUG}
     - PORT_REDIS=6379
     - HOST_REDIS=redis
  redis:
    image: redis:3.2.1
    volumes:
     - dados:/data
    labels:
     - 'app.environment=${ENV_APP}'
volumes:
  dados:
    external: false

Como podemos observar nos códigos já explicados, a grande vantagem de se utilizar dessa boa prática é o fato da possibilidade de mudança de comportamento sem a necessidade de mudança do código, mais uma vez é possível viabilizar que o mesmo código que foi construído em um momento, possa ser reutilizado de forma semelhante tanto no notebook do desenvolvedor, como no servidor de produção.

Fique atento para armazenamento de segredos dentro do docker-compose.yml, pois esse arquivo será enviado para o repositório de controle de versão, ou seja, é importante pensar em outra estratégia de manutenção de segredos.

Uma estratégia possível é a manutenção de variáveis de ambiente no docker host e dessa forma você precisaria usar variáveis do tipo ${variavel} dentro do docker-compose.yml pra pode repassar essa configuração ou utilizar outro recurso mais avançado de gerenciamento de segredos.

Dockerizando aplicações – Configurações

Seguindo a lista do modelo 12factor, temos “Configurações” como terceira boa prática.

Quando estamos criando um software aplicamos um determinado comportamento dentro do código e normalmente ele não é parametrizável, ou seja, para que essa aplicação se comporte de uma forma diferente será necessário mudar uma parte do código.

docker1

A necessidade de modificar o código para trocar o comportamento da aplicação inviabiliza que a mesma seja executa em sua máquina (desenvolvimento) da mesma forma que será usada para atender os usuários (produção) e com isso acabamos com toda possibilidade de portabilidade, e sem isso qual seria a vantagem de se usar contêineres, certo?

O objetivo dessa boa prática é viabilizar a configuração da aplicação sem a necessidade de modificar o código da mesma.

Como o comportamento da aplicação varia de acordo com o ambiente onde ela está executando, sendo assim, as configurações devem ser feitas baseadas nisso.

Seguem abaixo alguns exemplo:

  • Configuração de banco de dados que normalmente são diferentes entre os ambientes
  • Credenciais para acesso a serviços remotos (Ex. Digital Ocean ou Twitter)
  • Qual nome de DNS será usado pela aplicação

Como já falamos anteriormente, quando a configuração está estaticamente explícita no código, será necessário modificar manualmente e efetuar um novo build dos binários a cada reconfiguração do sistema.

Como demonstramos na boa prática codebase, usamos uma variável de ambiente para modificar qual o volume que usaremos no redis, ou seja, de certa forma já estamos seguindo essa boa prática, mas iremos um pouco além e mudaremos não somente o comportamento da infraestrutura, mas sim algo inerente ao código em si.

Segue abaixo a aplicação modificada:

from flask import Flask
from redis import Redis
import os
host_run=os.environ.get('HOST_RUN', '0.0.0.0')
debug=os.environ.get('DEBUG', 'True')
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
   redis.incr('hits')
   return 'Hello World! %s times.' % redis.get('hits')
if __name__ == "__main__":
   app.run(host=host_run, debug=debug)

Lembrando! Para acessar o código dessa prática basta clonar esse repositório e acessar a pasta “factor3“.

Como podemos perceber, adicionamos alguns parâmetros na configuração do endereço usado para iniciar a aplicação web, que será parametrizado com base no valor da variável de ambiente “HOST_RUN” e a possibilidade de efetuar ou não o debug dessa aplicação com a variável de ambiente “DEBUG“.

Vale salientar que nesse caso a variável de ambiente precisa ser passada para o contêiner, ou seja, não basta ter essa variável no docker host. Ela precisa ser enviada para o contêiner usando o parâmetro “-e” caso utilize o comando “docker run” ou a instrução “environment” no docker-compose.yml:

version: "2"
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
    labels:
     - 'app.environment=${ENV_APP}'
    environment:
     - HOST_RUN=${HOST_RUN}
     - DEBUG=${DEBUG}
  redis:
    image: redis:3.2.1
    volumes:
     - dados:/data
    labels:
     - 'app.environment=${ENV_APP}'
volumes:
  dados:
    external: false

Para executar o docker-compose, deveríamos fazer da seguinte maneira:

export HOST_RUN="0.0.0.0"; export DEBUG=True ; docker-compose up -d

Como podem perceber no comando acima ele usará as variáveis de ambiente “HOST_RUN” e “DEBUG” do docker host para enviar para as variáveis de ambiente com os mesmos nomes dentro do contêiner, que por sua vez será consumido pelo código python. Em caso de não haver parâmetros ele assume os valores padrões estipulados no código.

Essa boa prática é seguida com ajuda do Docker, pois o código é o mesmo e a configuração é um anexo da solução, que pode ser parametrizada de maneira distinta com base no que for configurado nas variáveis de ambiente.

Se aplicação crescer bastante, as variáveis podem ser carregadas em arquivo e parametrizadas no docker-compose.yml com a opção “env_file”.

Dockerizando aplicações – Dependências

Seguindo a lista do modelo 12factor, logo após o base de código que tratamos nesse artigo, agora temos “Dependência” como segunda boa prática.
Na maioria das vezes que buscamos portar uma aplicação para modelo de contêiner uns dos retornos esperados é a portabilidade, ou seja, a ideia que você possa construir sua aplicação apenas uma vez e ela executar sem problemas em qualquer infraestrutura.

download

Essa boa prática sugere a declaração de todas as dependências necessárias para executar seu código, ou seja, você nunca deve assumir que algum componente já estará previamente instalado no ativo responsável por hospedar essa aplicação.
Para viabilizar o “sonho” da portabilidade, precisamos gerenciar corretamente as dependências da aplicação em questão, isso indica que devemos também evitar a necessidade de trabalho manual na preparação da infraestrutura que suportará sua aplicação.
Automatizar o processo de instalação de dependência é o grande segredo de sucesso para atender essa boa prática, pois caso a instalação da sua infraestrutura não seja automática o suficiente para viabilizar a inicialização sem erros, o atendimento dessa boa prática estará prejudicada.
Automatizar esses procedimentos colabora com a manutenção da integridade do seu processo, pois o nome dos pacotes de dependências e suas respectivas versões estariam especificadas explicitamente em um arquivo localizado no mesmo repositório que o código, que por sua vez seria rastreado em um sistema de controle de versão. Com isso podemos concluir que nada seria modificado sem que se tenha o devido registro.
O Docker se encaixa perfeitamente nessa boa prática, pois é possível entregar um perfil mínimo de infraestrutura para essa aplicação, que por sua vez se fará necessária a declaração explícita de suas dependências para que a aplicação funcione nesse ambiente.
A aplicação que usamos como exemplo foi escrita em Python. Como podem ver na parte do código abaixo ela necessita de duas bibliotecas para funcionar corretamente:

 from flask import Flask
 from redis import Redis

Essas duas dependências estão especificados no arquivo requirements.txt e esse arquivo será usado como um parâmetro do pip.
“O PIP é um sistema de gerenciamento de pacotes usado para instalar e gerenciar pacotes de software escritos na linguagem de programação Python” (Wikipedia)
O comando pip é usado, juntamente com o arquivo requirements.txt, na criação da imagem como foi demonstrado no Dockerfile da boa prática anterior (codebase):

FROM python:2.7
ADD requirements.txt requirements.txt
RUN pip install -r requirements.txt
ADD . /code
WORKDIR /code
CMD python app.py

Perceba que um dos passos do Dockerfile é instalar as dependências explicitamente descritas no arquivo requirements.txt com o gerenciador de pacotes pip do Python. Veja o conteúdo do arquivo requirements.txt:

flask==0.11.1
redis==2.10.5

É importante salientar a necessidade de se especificar as versões de cada dependência, pois como no modelo de contêiner as suas imagens podem ser construídas a qualquer momento, é importante saber qual versão específica a sua aplicação precisa, caso contrário poderemos encontrar problemas com compatibilidade caso uma das dependências atualize e não esteja mais compatível com a composição completa das outras dependências e a aplicação que a está utilizando.

Para acessar o código descrito aqui, baixe o repositório e acesse a pasta “factor2“.
Um outro resultado positivo do uso dessa boa prática é a simplificação da utilização do código por outro desenvolvedor. Um novo programador pode verificar nos arquivos de dependências quais os pré-requisitos para sua aplicação executar, assim como executar facilmente o ambiente sem a necessidade de seguir uma extensa documentação que raramente é atualizada.
Usando o Docker é possível configurar automaticamente o necessário para rodar o código da aplicação, seguindo com isso essa boa prática perfeitamente.

Dockerizando aplicações – Base de código

Estamos evoluindo continuamente para entregar aplicações cada vez melhores, em menor tempo, replicáveis e escaláveis. Porém os esforços e aprendizados para atingir esse nível de maturidade muitas vezes não são simples de se alcançar.

Atualmente notamos o surgimento de várias opções de plataformas para facilitar a implantação, configuração e escalabilidade das aplicações que desenvolvemos. Porém, para aumentar nosso grau de maturidade não podemos apenas depender da plataforma, precisamos construir nossa aplicação seguindo boas práticas.

Visando sugerir uma série de boas práticas comuns a aplicações web modernas, alguns desenvolvedores do Heroku escreveram o 12Factor app, baseado em uma larga experiência em desenvolvimento desse tipo de aplicação.

12factor (1)

“The Twelve-Factor app” (12factor) é um manifesto com uma série de boas práticas para construção de software utilizando formatos declarativos de automação, maximizando portabilidade e minimizando divergências entre ambientes de execução, permitindo a implantação em plataformas de nuvem modernas e facilitando a escalabilidade. Assim, aplicações são construídas sem manter estado (stateless) e conectadas a qualquer combinação de serviços de infraestrutura para retenção de dados (Banco de dados, fila, memória cache e afins).

Nesse capítulo falaremos sobre criação de aplicações como imagens docker com base no 12factor app, ou seja, a ideia é demonstrar as melhores práticas de como se realizar a criação de uma infraestrutura para suportar, empacotar e disponibilizar a sua aplicação com alto nível de maturidade e agilidade.

O uso do 12factor com Docker é uma combinação perfeita, pois muitos dos recursos do Docker são melhores aproveitados caso sua aplicação tenha sido pensada para tal. Dessa forma, nesse texto daremos uma ideia de como aproveitar todo potencial da sua solução.

Como exemplo, usaremos a aplicação abaixo:

from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
   redis.incr('hits')
   return 'Hello World! %s times.' % redis.get('hits')
if __name__ == "__main__":
   app.run(host="0.0.0.0", debug=True)

É uma aplicação simples, que será usada apenas como exemplo. Através de um serviço HTTP, ela exibe quantas vezes foi acessada. Essa informação é armazenada através de um contador numa instância Redis.

Agora vamos às boas práticas!

Base de código

Com o objetivo de facilitar o controle das mudanças de código, viabilizando a rastreabilidade das alterações, essa boa prática indica que cada aplicação deve ter apenas uma base de código e, a partir do mesmo, uma aplicação pode ser implantada em distintos ambientes, mas a base precisa ser a mesma. Vale salientar que essa boa prática é necessária caso pretenda praticar o Continuous Integration (CI), ou seja, o mesmo código deverá ser consumido pelo processo de integração contínua e posteriormente implantado em desenvolvimento, teste e produção, mudando apenas parâmetros específicos ao ambiente em questão.

Para essa explicação, criei um repositório de exemplo.

Perceba que todo nosso código está dentro desse repositório, organizado por prática em cada pasta, para facilitar a reprodução. Lembre de entrar na pasta correspondente a cada boa prática apresentada.

O Docker tem uma infraestrutura que permite a utilização de variável de ambiente para parametrização da infraestrutura, sendo assim o mesmo código terá um comportamento distinto com base no valor das variáveis de ambiente.

Aqui usaremos o Docker Compose para realizar a composição de todo ambiente, fazendo com que a configuração dos distintos serviços e sua comunicação seja facilitada.

codebase-deploys

Posteriormente, mais precisamente na terceira boa prática Configuração desse compêndio de sugestões, trataremos mais detalhadamente sobre parametrização da aplicação, por hora apenas aplicaremos opções via variável de ambiente para a arquitetura ao invés de utilizar internamente no código da aplicação.

Para configurar o ambiente de desenvolvimento para o exemplo apresentado temos esse arquivo docker-compose.yml:

version: '2'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
    labels:
     - 'app.environment=${ENV_APP}'
  redis:
    image: redis
    volumes:
     - dados_${ENV_APP}:/data
    labels:
     - 'app.environment=${ENV_APP}'

O serviço redis será utilizado a partir da imagem oficial redis, sem modificação no momento e o serviço web será gerado a partir da construção de uma imagem Docker, que tem como base a imagem oficial do python 2.7. Criaremos nossa imagem através do seguinte Dockerfile:

FROM python:2.7
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD python app.py

Com posse de todos os arquivos na mesma pasta, iniciaremos o ambiente com o seguinte comando:

export ENV_APP=devel ; docker-compose -p $ENV_APP up -d

Como podemos perceber na configuração que acabamos de construir, a variável “ENV_APP” definirá qual volume será usado para persistir os dados que serão enviados pela aplicação web, ou seja, com base na mudança dessa opção teremos o serviço rodando com um comportamento diferente, mas sempre a partir do mesmo código, dessa forma seguindo perfeitamente a ideia dessa primeira boa prática.

SwarmKit

Oi Pessoal,

Hoje, você não pode pensar em utilizar Docker em produção em larga escala sem ter alguma forma de automação e orquestração dessa “coisa”, graças a comunidade e algumas empresas, temos ferramentas que podem nos auxiliar nessas tarefas, todas juntas ou em partes, é claro. Atualmente as ferramentas mais conhecidas para orquestração e scale em Docker são Kubernetes e Mesos, existem muitos projetos mantidos pela comunidade nesse sentido, mas nenhum deles com tanta representatividade quanto aos mencionados anteriormente. Para não ficar de fora desse mundo, a Docker vem trabalhando bastante em uma suite que atenda essa necessidade, e que futuramente seja incorporado ao Docker Data Center, o projeto chama-se Swarmkit, e hoje, aqui no MundoDocker, vamos ver um pouco mais sobre ele.

O Que é?

O Swarmkit é uma suite para escalonamento e orquestração para sistemas distribuídos, ele possui um sistema de descoberta de nós, agendamento de tarefas, e utiliza o raft-based consensus para coordenação do cluster.

O que tem de bom?

  • Como já mencionado, ele utiliza o raft-based consensus, isso garante uma melhor coordenação do cluster, eliminando assim o ponto único de falha.
  • Todo os nós do cluster Swarm conversam de forma segura, e para ajudar nisso o Swarmkit utiliza TLS para autenticação, autorização e transporte dos dados entre os nós.
  • Swarmkit foi projeto para ser simples, por isso ele é independente de base de dados externas, ou seja, tudo que você precisa para utiliza-lo já está nele.

Ele é composto basicamente de duas camadas: Worker e Manager nodes, para entender cada um:

Worker: Responsável por executar as tarefas utilizar um Executor, por padrão o Swarmkit vem com o Docker Container Executor, mas que pode ser trocado caso deseja.

Manager: Basicamente é o nó eleito pelo administrador para ser o ponto central de administração, lembrando que quanto você adiciona um nó no cluster de Swarm você define se esse nó será Manager ou não.

Como outras ferramentas, para o Swarmkit as tarefas são organizadas em serviços, e para esse serviço você define o que deseja fazer, por exemplo: Crie replicas desse serviço todo dia as 10h, ou: Atualize um container por vez baseado nessa nova imagem.

Features

  • Oquestração
  1. Estado desejado: O Swarmkit analise constantemente o cluster, garantindo que todos os serviços estejam de acordo com o pretendido pelo usuário, isso faz com que um serviço seja provisionado em outro nó caso algum falhe.
  2. Tipo de serviço: atualmente o Swarmkit suporta apenas 2 tipos: 1 – Replicas, onde você define quantas cópias daquele container deseja, e 2 – Global, onde você especifica o que deve ser executado em cada nó do cluster.
  3. Atualização: Você pode modificar a qualquer momento o estado de um serviço, seja para para-lo ou escala-lo, quando você atualiza um serviço, por padrão ele executa essa tarefa de atualização de uma vez só para todos os nós do cluster, mas você pode definir de outras duas formas essa atualização: 1 – Paralela, onde o administrador define quantas tarefas de atualização podem ser executadas por mês ou 2 – Delay, dessa forma o Swarmkit executará as tarefas de atualização de serviço de forma sequencial, ou seja, uma tarefa só será executada caso a anterior já tenha terminado.
  4. Politicas de restart: A camada de orquestração monitora o estado das tarefas e reage as falhas aplicando a regra definida pelo usuário, dentro dessas regras o administrador pode definir número máximo de tentativos de restart de um serviço, quanto tempo depois de uma falha esse serviço deve ser reiniciado, etc. Por padrão o Swarmkit reinicia o serviço dentro de outro nó disponível no cluster, isso garante que os serviços dos nós defeituosos sejam iniciados em outros nós o mais rápido possível.
  • Agendamento
  1. Recursos: O Swarmkit sabe, através das checagens constantes, como está a saúde de cada nó, com isso, quando um serviço precisa ser reiniciado ou realocado, por padrão essa tarefa será realizada no melhor nó do cluster;
  2. Restrições: O administrador pode limitar o reinicio de um serviço em determinados nós, isso pode ser feito através de labels, exemplo: node.labels.foo!=bar1
  • Gerenciamento de cluster
  1. State Store: Permite ter uma visão macro de todo o cluster, como suas informações ficam em memória, permite ao nó de gerenciamento tomar decisões de forma muito mais rápida e segura.
  2. Gerenciamento da topologia: O administrador pode alternar quais são os nós de gerenciamento e qual são os Workers através de chamadas de API ou CLI.
  3. Gerenciamento de nós: É possível definir um nó como pausado, por exemplo, com isso os serviços que estavam alocados neste nó serão iniciados nos demais nós, assim como a execução de novas tarefas permanece bloqueada.
  • Segurança
  1. TLS: Todos os nós se conversam através de TLS, e os nós de gerenciamento agem como autoridade certificadora de todos os demais nós, e são responsáveis pela emissão de certificados para os nós que entram no cluster.
  2. Politica de aceitação: O administrador pode aplicar regras de auto-aceitação, aceitação manual ou troca de chaves, isso claro na adição de novos nós ao cluster, por default o Swarmkit utiliza auto-aceitação.
  3. Troca de certificados: É possível definir a frequência com a qual serão alterados os certificados ssl utilizados para comunicação do cluster, por padrão o tempo é de 3 meses, mas pode-ser definir qualquer período maior que 30 minutos.

Vamos brincar?

Instalando

O Swarmkit foi desenvolvido em GO, então tenha todo o ambiente pré-configurado e claro, baixe os fontes para seu $GOPATH, você pode utilizar:

[root@docker1 ~]# go get github.com/docker/swarmkit/

Acesse o diretório, e execute:

[root@docker1 ~]# make binaries

Isso fará com que sejam instaladas as ferramentas para utilização do Swarmkit, em seguida você pode testar sua instalação:

[root@docker1 ~]# make setup
[root@docker1 ~]# make all

Agora adicione o swarmd e swarmctl ao seu $PATH e seja feliz utilizando ele, veja abaixo alguns exemplos.

Montando o Cluster

No primeiro nó, execute:

[root@docker1 ~]# swarmd -d /tmp/docker1 --listen-control-api /tmp/manager1/swarm.sock --hostname docker1

Nos demais nós, execute:

[root@docker2 ~]# swarmd -d /tmp/node-2 --hostname docker2 --join-addr 10.1.1.1:4242
[root@docker3 ~]# swarmd -d /tmp/node-3 --hostname docker3 --join-addr 10.1.1.1:4242

Você pode agora, utilizar outro host para administrar o cluster, no nosso exemplo utilizando o docker4, veja:

[root@docker4 ~]# export SWARM_SOCKET=/tmp/manager1/swarm.sock
[root@docker4 ~]# swarmctl node ls
ID             Name    Membership  Status  Availability  Manager status
--             ----    ----------  ------  ------------  --------------
6rj5b1zx4makm  docker1  ACCEPTED    READY   ACTIVE        REACHABLE *
91c04eb0s86k8  docker2  ACCEPTED    READY   ACTIVE        
nf6xx9hpf3s39  docker3  ACCEPTED    READY   ACTIVE        

Criando os serviços

Vamos começar devagar, veja como subir um ambiente em redis:

[root@docker4 ~]# swarmctl service create --name redis --image redis:3.0.5
6umyydpxwtzfs3ksgz0e

Listando os serviços:

[root@docker4 ~]# swarmctl service ls
ID                         Name   Image        Replicas
--                         ----   -----        ---------
6umyydpxwtzfs3ksgz0e      redis  redis:3.0.5  1

Inspecionando o serviço:

[root@docker4 ~]# swarmctl service inspect redis
ID                : 6umyydpxwtzfs3ksgz0e
Name              : redis
Replicass         : 1
Template
 Container
  Image           : redis:3.0.5

Task ID                      Service    Instance    Image          Desired State    Last State               Node
-------                      -------    --------    -----          -------------    ----------               ----
6umyydpxwtzfs3ksgz0e         redis      1           redis:3.0.5    RUNNING          RUNNING Up About an hour    docker1

Atualizando serviço:

Conforme mencionado anteriormente, podemos atualizar o status de um serviço, no nosso exemplo vamos aumentar o número de replicas dele, veja:

[root@docker4 ~]# swarmctl service update redis --replicas 6
6umyydpxwtzfs3ksgz0e

[root@docker4 ~]# swarmctl service inspect redis
ID                : 6umyydpxwtzfs3ksgz0e
Name              : redis
Replicas          : 6
Template
 Container
  Image           : redis:3.0.5

Task ID                      Service    Instance    Image          Desired State    Last State               Node
-------                      -------    --------    -----          -------------    ----------               ----
xaoyxbuwe13gsx9vbq4f         redis      1           redis:3.0.5    RUNNING          RUNNING Up About an hour     docker1
y8cu8nvl1ggh4sl0xxs4         redis      2           redis:3.0.5    RUNNING          RUNNING 10 seconds ago    docker2
ksv9qbqc9wthkrfz0jak         redis      3           redis:3.0.5    RUNNING          RUNNING 10 seconds ago    docker2
nnm9deh7t0op6rln3fwf         redis      4           redis:3.0.5    RUNNING          RUNNING 10 seconds ago    docker1
4ya5eujwsuc6cr7xlnff         redis      5           redis:3.0.5    RUNNING          RUNNING 10 seconds ago    docker3
9o4pmrz6q6pf9ufm59mk         redis      6           redis:3.0.5    RUNNING          RUNNING 10 seconds ago    docker3

Vamos atualizar a imagem do serviço?

[root@docker4 ~]# swarmctl service update redis --image redis:3.0.6
6umyydpxwtzfs3ksgz0e

[root@docker4 ~]# swarmctl service inspect redis
ID                : 6umyydpxwtzfs3ksgz0e
Name              : redis
Replicas          : 6
Template
 Container
  Image           : redis:3.0.6

Task ID                      Service    Instance    Image          Desired State    Last State                Node
-------                      -------    --------    -----          -------------    ----------                ----
xaoyxbuwe13gsx9vbq4f         redis      1           redis:3.0.6    RUNNING          RUNNING 5 seconds ago    docker3
y8cu8nvl1ggh4sl0xxs4         redis      2           redis:3.0.6    RUNNING          RUNNING 6 seconds ago    docker1
ksv9qbqc9wthkrfz0jak         redis      3           redis:3.0.6    RUNNING          RUNNING 5 seconds ago    docker2
nnm9deh7t0op6rln3fwf         redis      4           redis:3.0.6    RUNNING          RUNNING 6 seconds ago    docker1
4ya5eujwsuc6cr7xlnff         redis      5           redis:3.0.6    RUNNING          RUNNING 6 seconds ago    docker2
9o4pmrz6q6pf9ufm59mk         redis      6           redis:3.0.6    RUNNING          RUNNING 6 seconds ago    docker3

Por padrão todos os containers foram atualizados de uma única vez, isso tem suas vantagens e desvantagens, mas como explicado, você pode mudar essa execução para fazer em partes, veja:

[root@docker4 ~]# swarmctl service update redis --image redis:3.0.7 --update-parallelism 3 --update-delay 20s

Com isso, serão refeitos 3 containers por vez e entre eles terá um intervalo de 20 segundos.

Gerenciando nós

O Swarmkit monitora a saúde de cluster, e baseado nisso toma ações em cima dos serviços, você pode realizar ações manuais também, como por exemplo, retirar um nós do cluster, veja:

[root@docker4 ~]# swarmctl node drain docker1

[root@docker4 ~]# swarmctl node ls
ID             Name    Membership  Status  Availability  Manager status
--             ----    ----------  ------  ------------  --------------
6rj5b1zx4makm  docker1  ACCEPTED    READY   DRAIN         REACHABLE
91c04eb0s86k8  docker2  ACCEPTED    READY   ACTIVE        REACHABLE *
nf6xx9hpf3s39  docker3  ACCEPTED    READY   ACTIVE        REACHABLE

[root@docker4 ~]# swarmctl service inspect redis
ID                : 6umyydpxwtzfs3ksgz0e
Name              : redis
Replicas          : 6
Template
 Container
  Image           : redis:3.0.7

Task ID                      Service    Instance    Image          Desired State    Last State               Node
-------                      -------    --------    -----          -------------    ----------               ----
xaoyxbuwe13gsx9vbq4f         redis      1           redis:3.0.7    RUNNING          RUNNING 2 minute ago     docker2
y8cu8nvl1ggh4sl0xxs4         redis      2           redis:3.0.7    RUNNING          RUNNING 2 minute ago     docker3
ksv9qbqc9wthkrfz0jak         redis      3           redis:3.0.7    RUNNING          RUNNING 30 seconds ago    docker2
nnm9deh7t0op6rln3fwf         redis      4           redis:3.0.7    RUNNING          RUNNING 34 seconds ago    docker3
4ya5eujwsuc6cr7xlnff         redis      5           redis:3.0.7    RUNNING          RUNNING 28 minutes ago    docker2
9o4pmrz6q6pf9ufm59mk         redis      6           redis:3.0.7    RUNNING          RUNNING 29 seconds ago    docker3

O Swarmkit é uma ferramenta em desenvolvimento ainda, mas você pode utilizar ela em seus labs e entender um pouco melhor como pode trabalhar em cluster com Docker. Espero que tenham gostado, e nos ajude divulgando o blog 😉

Abraço!

Melhores praticas Dockerfile

Muitas pessoas pensam que construir uma imagem é apenas iniciar um container, realizar algumas alterações e assim realizar o commit da mesma. Ou até mesmo escrever um Dockerfile do jeito que quiser e pronto a imagem está pronta e agora é só colocar em produção. Com algumas técnicas na criação do Dockerfile é possível fazer o seu Build passar de 10 minutos para apenas 10 segundos.

Baseado nas dúvidas que o pessoal acaba tendo no dia a dia resolvemos a equipe do mundodocker.com.br resolveu dar algumas dicas referentes a como deixar o seu Dockerfile o mais otimizado possível.

Use o .dockerignore

O .dockerignore possui a mesma funcionalidade do .gitignore, fazendo com que você possa gerar a sua imagem excluindo alguns arquivos que estejam no diretório do seu Dockerfile.

Não instale pacotes desnecessários

Para reduzir o tamanho de sua imagem e o tempo de construção dela, não instale pacotes que você acha que poderá usar um dia, instale apenas o necessário para que sua aplicação possa rodar de forma integra e segura. Muitas vezes pacotes desnecessários possuem uma série de dependências o que pode acarretar um tempo maior de construção da imagem.

Construa o minimo de camadas possíveis

Cada comando “RUN”, “COPY”, “ADD” acaba adicionando uma camada a mais em sua imagem, então quanto mais comandos conseguir executar de uma vez só melhor.

Use tags

Quando você for realizar o docker build utilize o parâmetro -t para que você possa organizar melhor sua estrutura de imagens e no desenvolvimento ficará mais fácil para saber o qual release essa imagem representa.
docker build . -t php:56-0-4

apt-get

Nunca utilize apenas apt-get update utilize sempre apt-get update && apt-get install. Por exemplo você tem o seguinte Dockerfile:


FROM UBUNTU
apt-get update
apt-get install wget

Você executa isso e depois de algum tempo você altera o Dockerfile e coloca assim:


FROM UBUNTU
apt-get update
apt-get install wget vim

Ao executar o build o Docker não irá executar o apt-get update fazendo com que o vim esteja desatualizado no momento da instalação.

Nunca mapear a porta pública no Dockerfile

Você NUNCA deve mapear a porta do seu host em seu Dockerfile:


#Não faça isso
EXPOSE 80:8080

#Faça isso
EXPOSE 80

Deixe sempre o que mais será alterado para o final

Como o Dockerfile trabalha com camadas, então você sempre devera deixar para o final a parte que é mais dinâmica em seu Dockerfile, pois ao rodar o seu Dockerfile pela segunda vez, o Docker irá olhar onde foi modificado o arquivo e irá refazer as camadas abaixo da modificação. Então se você tem uma parte que demora algum tempo e você não irá precisar modificar ela constantemente então é melhor você deixar essa parte no topo.


FROM ubuntu
RUN apt-get install -y nodejs
RUN mkdir /var/www
ADD app.js /var/www/app.js

FROM ubuntu
RUN apt-get install -y nodejs
RUN mkdir /var/www
ADD package.json /var/www/package.json

Nessa alteração de Dockerfile o Docker irá apenas refazer a camada do ADD e não irá baixar novamente o node e criar o diretorio /var/www. Assim economizando tempo de Build e também tamanho em disco.

Então tá pessoal espero que tenham gostado desse post referente a dicas de como criar melhor o seu Dockerfile. Qualquer dúvida é só deixar um comentário que iremos reponder o mais rápido possível.

Vagas DevOps fazem sentido? Entenda!

Não, não fazem!

E quem diz isso são apenas os criadores do movimento DevOps e core members do DevOpsDays, dentre eles Patrick Debois, Damon Edwards, John Willis e outros.

Hoje o mundo está tomado por vagas Arquiteto DevOps, Engenheiro DevOps, Especialista DevOps e a informação sobre as vagas é muito ruim.

Como DevOps é essencialmente uma CULTURA, fica difícil você colocar anúncio para contratar uma cultura, um modelo, um movimento, uma metodologia.

No Brasil especialmente a confusão sobre DevOps é terrível, tem gente que acha que DevOps é um programador que sabe infra, ou que é um sysadmin que sabe programar. Alô, DevOps não é um cargo, não é uma pessoa, DevOps é uma CULTURA.

Também não existe time DevOps, se alguém usa esse termo para se referir ao seu time ele realmente não entendeu nada sobre DevOps.

Outra confusão que vejo com muita frequência é sobre CI (Continuous Integration) e CD (Continuos Delivery/Deployment) serem DevOps ou não.

Tem gente que fala:

- Amanhã vou em um evento DevOps, discutir CD em plataforma Java e .Net.

Ok, dentro da Cultura DevOps você pode sim utilizar CD e CI, certamente vai usar, mas isso é uma ferramenta/metodologia que a você traz para ajudar a resolver problemas culturais em uma organização, isso sozinho não pode ser considerado DevOps, na verdade é injusto pegar algo tão amplo, tão importante e reduzir a um simples pipeline de commit, build, test e deploy.

Sim, DevOps foi criado para entregar software melhor, mais rápido, com menor risco e de forma automatizada e controlada, ele é fundamentado nisso, mas antes disso tudo, a Cultura estabelece uma série de eixos para resolver os problemas internos da organização que a IMPEDEM de entregar softwares melhores, mais rápidos, com menor risco de forma automatizada. Antes da tecnologia vem o problema a ser assumido, resolvido, uma cultura a ser mudada para que todas as tecnologias e métodos possam ajudar.

CULTURA, guarde essa palavra.

Como contratar alguém que saiba essa cultura?

Mas eu preciso contratar uma pessoa seja um entusiasta da cultura DevOps, eu quero começar a transformar a minha organização, esse cara será o agente de mudanças, qual o nome dele?

CONSULTOR

Tá, mas eu quero alguém técnico para trabalhar já bebendo na fonte dessa cultura, e ai como divulgo?

Segue um exemplo:

Nome da vaga (sem devops no meio)

Estamos buscando um profissional que consiga trabalhar em times multidisciplinares, que tenha sólidos conhecimentos de programacao na plataforma/linguagem X, e bons fundamentos de sistemas operacionais e redes, que tenha condições de trabalhar com metodos ágeis, com processos e tecnologias de automação. Este profissional deve ter facilidade para adaptar metodos ágeis para uso interno do seu time e de suas atividades.

Procuramos essencialmente profissionais que consigam se relacionar bem com o seu time, que saibam fazer parte de um time, que respeitem o time, que saiba dividir e compartilhar responsabilidades com o time, que goste de estudar e aprender novas tecnologias e que goste de compartilhar o seu conhecimento.

Precisamos de profissionais que entendam que sua função é fazer com que o negócio da organização flua, ou seja, o foco do trabalho é oferecer suporte e sustentação as necessidades das pessoas que estão pensando, criando, escrevendo, desenvolvendo e publicando os produtos para atender aos clientes desta organização.

Nesta organização enxergamos a TI como uma unidade orgânica composta por pessoas, as pessoas são importantes para nós, nosso entendimento é que a TI é um time monolítico que compartilha seus sucessos e aprendizados.

Queremos que você agregue valor ao nosso time e a nossa organização, e queremos que a organização agrege valor a você.

Tecnologias com as quais trabalhamos:

  • Linguagens
  • Sistemas operacionais
  • Serviços
  • Plataformas de desenvolvimento
  • Plataformas de automação
  • Plataformas de monitoramento
  • Plataformas de segurança
  • Plataformas de nuvem e virtualização
  • Plataformas de armazenamento
  • Plataformas de rede

Métodos que utilizamos em nossos times:

  • Método A
  • Método B
  • Método C

O que esperamos de você?

  • Esperamos que nos ajude a identificar as melhores tecnologias que possam ser utilizadas por novos produtos
  • Esperemos que nos ajude a identificar tecnologias que possam melhorar a performance de produtos existentes
  • Esperamos que nos ajude a acompanhar a performance e o funcionamento das aplicações
  • Esperamos que nos ajude a melhorar nossos processos de provisionamento de vms e containers
  • Esperamos que nos ajude a melhorar e agilizar o processo e o tempo necessário para criação de novos ambientes
  • Esperamos que nos ajude a oferecer mecanismos de autoserviço entregando recursos diretamente aos desenvolvedores
  • Esperamos que nos ajude a automatizar e otimizar nossa infra ao máximo
  • Esperamos que nos ajude a registrar mudanças e eventos, gerando relatórios que possibilitem auditoria se preciso
  • Esperamos que nos ajude a manter e evoluir nosso processo de deploy para que possamos entregar sempre e entregar rápido
  • Esperamos que você possa ir além, propondo, criando, mudando, construindo e evoluindo junto conosco.

Se você acha que as características necessárias para participar de nossos projetos e de nosso time, entre em contato!

Veja que é muito mais simples e claro dizer o que você espera da pessoa, usando a cultura DevOps como referência, sem necessáriamente enfiar o nome DevOps no meio da vaga.

Antes que perguntem sobre sysadmin programar, sim, todo o profissional de TI deveria saber programar, isso não é exatamente Rocket Science, é uma qualidade fundamental para qualquer tipo de vaga de TI hoje em dia, principalmente se a organização se fundamenta pela cultura DevOps que tem automação como um dos seus pilares (CAMS/ICE).

É sempre bom lembrar que saber programar e ser um desenvolvedor ou engenheiro de software são coisas bem diferentes, normalmente não é isso que as pessoas estão buscando quando divulgam esse tipo de vaga.

Se precisa de um desenvolvedor, divulgar isso não tem mistério.

Puxa eu não preciso de nada disso, minha organização tem várias hierarquias, é bem vertical, engessada, tem vários silos, e a galera não vai topar isso ai, blá, blá, blá…. ok, então seu negócio não tem nada a ver com DevOps, talvez o que você esteja procurando seja um profissional de infra que use métodos ágeis, alguém que saiba aplicar métodos + automação em um silo como por exemplo uma equipe de operação ou infraestrutura, ele conseguirá nesse caso melhorar processos ali, naquele time, e fazer uma transformação naquela realidade local, isso também é possível.

A isso temos (Eu e Miguel Filho) dado o nome de infra ágil, que é uma necessidade e característica mais próxima do que temos visto no Brasil, seja em governo, seja em iniciativa privada.

Eu falarei mais disso em outro post ou em outro blog ;)

Espero ter ajudado.

[s]
Guto

DevOps in simple english

Abaixo coloco mais um vídeo bem simples para explicar DevOps feito pela Rackspace, muito bacana ;)

[s]
Guto

Cinco anos de DevOps

Duas palestras para demonstrar o atual estado do movimento e da cultura DevOps nos últimos 5 anos, uma do John Willis (criador da metodologia CAMS) e outra do Patrick Debois (criador do devopsdays).

Ambas dão uma noção de onde veio e como está o movimento hoje.

Enjoy!

[s]
Guto

Origens da cultura DevOps

Damon Edwards faz um excelente vídeo sobre as origens do DevOps, recomendo a todos que querem entender melhor esse movimento e cultura.

[s]
Guto

Puppet vs Ansible?

Essa é uma questão recorrente nas comunidades que participo e portanto vou registrar aqui no blog a minha visão para facilitar a resposta.

Definições

  1. O Puppet é uma ferramenta de gerência de configurações e estados que vem da escola de GCONF do Mark Burgess, criador do CFEngine e destes princípios que vem sendo contruídos desde os anos 90.

  2. O Ansible é uma ferramenta que faz o que chamamos de orquestração, ele não segue os princípios fundamentais de CCONF e o seu desenho não segue a escola do Mark Burgess.

1. Como funciona o Ansible

Imagine que você tem uma VM com o ansible instalado.

Nessa VM voce cria um playbook (código que vai executar alguma ação em um sistema operacional).

Você diz pro ansible a lista de máquinas em que ele vai se conectar para rodar aquele playbook.

A VM que roda o ansible converte aquele playbook em um código python e se conecta (faz o PUSH do código) em N máquinas utilizando sua rede para aplicá-lo. Na VM de destino é necessário ter o python e as python-libs exigidas pelo playbook.

O Ansible se conecta nestas máquinas utilizando o conhecido protocolo SSH, ele depende disso para funcionar, portanto é necessário ter credenciais de acesso ou chaves que te possibilitem chegar nestas VMs, se não houver serviço SSH rodando ou credenciais de acesso, não será possível fazer a orquestração.

Para se conectar as todas essas VMs, a máquina com Ansible tem que ter acesso a todas as redes em que as VMs estão rodando para poder orquestrá-las, portanto, você terá que fazer algumas regras de firewall para garantir o acesso a todos os pontos de sua infraestrutura.

Se você for aplicar um playbook em centenas ou milhares de máquinas paralelamente há de se tomar um cuidado extra pois ele pode gerar throughtput além das capacidades do seu switch/roteador no momento em que for tentar alcançar todos OSs simultâneamente ou dentro do paralelismo que você definir.

Nem tudo no Ansible tem controles rídigos ou é idempotente, algumas coisas são, outras não, idempotência não é uma pedra fundamental em seu desenho, além disto, ele não foi feito para gerar um relatório detalhado, garantir o sucesso ou ter um rídido controle da execução do playbook, no final ele executa o playbook onde você pede - o foco da orquestração é esse - mas a visibilidade é pequena, você não tem como saber de forma precisa se atingiu o seu objetivo ou se tudo o que você queria foi realizado em todas as VMs. No momento, ele não tem o melhor dos feedbacks para o administrador, mesmo assim, como orquestrador ele é uma ferramenta muito interessante e poderosa.

1.1 Orquestração em poucas palavras

Orquestração consiste em executar algo de forma paralela ou não em tempo real em um sistema operacional ou em um grupo de sistemas operacionais.

Quando falarem orquestração, pelo menos do ponto de vista de automação de infraestrutura, tenha em mente alguém que se conecta em N sistemas operacionais e executa algo, pontualmente, sem exigência rígidas ou grandes controles.

2. Como funciona o Puppet?

O puppet foi desenhado dentro dos conceitos fundamentais da “gerência de configurações”, e por isso não tem a característica PUSH. Esses conceitos foram criados em 1993 pelo Professor Mark Burgess da universidade de OSLO. Suas principais características são o drift, convergência, idempotência, gerência de estados e uso de agentes nos “nodes” (termo que usamos para descrever um sistema operacional com um agente instalado).

O conceito GCONF (Gerência de Configurações) foi estabelecido de forma mais concisa em 2004 com a criação da teoria Promisse do Mark Burgess que serviu de norte para a criação de todas as ferramentas modernas de CGCOF como Puppet, Salt, Chef e CFENGINE.

Na CGONF você define um estado desejado através de uma linguagem declarativa chamada DSL (Domain specific language), armazena isso em um local central (neste caso no puppetmaster). Nas pontas temos os agentes rodando nos nodes, esses agentes vão buscar essa configuração e aplicar no node.

Primeiro o agente verifica o estado atual do node, compara com o estado desejado, se houver divergência ele converge o node para o estado desejado. Todo esse processo gera um relatório robusto que registra todas as mudanças e eventos daquela drift/convergência.

Em resumo se alguém alterar algo que o puppet está gerenciando, o puppet detecta e corrige sem necessidade de intervenção humana, é o que chamamos de auto-healing.

Quaisquer ações ou recursos utilizados no Puppet tem como premissa a idempotência e o rídigo controle durante a aplicação, esse é um princípio fundamental do seu desenho. O agente roda como serviço no sistema operacional, portanto, a cada N minutos ele acorda e executa essa checagem em todo o sistema para garantir o compliance e o estado desejado, essa é sua missão, ele é o guardião dos estados e da integridade do node.

O servidor nunca se conecta nos nós, apenas os nós de conectam no servidor. O servidor que contém as configurações pode ser facilmente replicado e colocado atrás de um balanceador. Você difícilmente tem problemas com throughput em sua rede como aqueles que podem acontecer com orquestradores e praticamente não precisa de preocupar com regras firewall, os nodes precisam se conectar à porta 8140 TCP do master ou do seu LB, apenas isto.

O Puppet não depende de serviços de terceiros como SSH para funcionar, ele utiliza seu próprio agente e a comunicação ocorre através de uma API REST que é utilizada pelo agente para se comunicar com o master.

Toda a comunicação é criptografada ponta-a-ponta e o custo disso para rede é baixíssimo se comparado com outros médotos.

Outra grande vantagem desse modelo é que mesmo que o servidor esteja fora, os agentes continuam funcionando e aplicando a última configuração recebida.

2.1 Gerência de configurações em poucas palavras

Ferramentas de gerência de configuração funcionam em arquitetura agente e servidor, o servidor armazena as configurações dos nodes. O agente que roda no node, busca as configurações e aplica localmente.

O agente funciona com o conceito de gerência de estados. Você usa uma linguagem declarativa para descrever os estados desejados nos nodes de sua rede.

Idempotência é uma princípio fundamental do agente. Há um robusto sistema de relatórios e registro de eventos e mudanças. O servidor nunca se conecta nos nós, apenas os nós se conectam ao servidor.

3. Conclusão

No final ambas são ferramentas de gerência, o Puppet faz a gerência de configurações e estados e o Ansible faz gerência por orquestração. Tais ferramentas atuam de formas distintas e tem objetivos e usos diferentes.

Acima de tudo é importante entender que elas não são concorrentes.

É bom ter as duas no seu cinto de utilidades, dependendo do projeto você terá uso para uma ou para outra.

[s]
Guto

Criação de um Loadbalancer com Haproxy e containers Docker

1. Introdução Segue uma stack utilizando o Loadbalancer HAproxy e containers Docker, portanto este tutorial irá abordar a criação de um Loadbalancer com HAProxy e balanceamento de carga entre containers Docker. 2. Pré-requisitos Docker instalado – Tutorial instalação do Docker. Comunicação entre containers – Todos os containers precisam se comunicar, o ping tem que funcionar […]

Plugins que uso no ATOM

Sempre me perguntam quais plugins eu uso no ATOM para desenvolvimento Puppet, segue a lista:

De linguagem:

  • language-puppet do atom
  • language-yaml do atom
  • language-ruby do tom

De linter:

  • linter do atom-community
  • linter-puppet-lint do atom-community
  • linter-puppet-parser do asquelt
  • linter-ruby do atomcommunity

De align:

  • aligner do adrianlee44
  • aligner-puppet do bigbrozer
  • aligner-ruby do adrianlee44

Outros:

  • file-icons do DanBrooker
  • git-control do jacogr
  • open-recent do zren
  • minimap do atom-minimap
  • remote-edit do sveale

Normalmente monto - via sshfs - o diretório com o código que está em alguma VM de desenvolvimento e trabalho no conforto do ATOM.

Meus alunos preferem que eu mostre o código no ATOM e eles sempre falam muito bem do linter.

#ficaadica

Se você tiver dica de plugins pro ATOM manda nos comentários ;)

[s]
Guto

Estarei no DevOpsDays 2016 em Porto Alegre

Galera fui convidado para apresentar alguns cases de automação de infraestrutura no DevOpsDays de Porto Alegre, será no dia 09 de julho de 2016. Ainda não sei o horário, mas fica a dica do evento.

Faça sua inscrição!

http://www.devopsdays.org/events/2016-portoalegre/welcome/

Vejo vocês lá!

[s]
Guto

Estarei no TDC SP 2016 :)

Fui convidado para ajudar a coordenar a trilha de “Infra Ágil” no “The Developers Conference São Paulo” que vai acontecer em Julho de 2016.

Devo apresentar uma palestra de nome homônimo no evento. A trilha deve acontecer no dia 08 de Julho, ainda não está definido o horário, aviso por aqui assim que souber.

A chamada de trabalhos ainda está aberta, mande sua proposta até o dia 4 de Junho.

http://www.thedevelopersconference.com.br/tdc/2016/saopaulo/call4papers

Vejo vocês lá!

[s]
Guto

Resultado do Meetup Puppet DF 20160518

O Meetup foi execelente, tivemos cerca de noventa inscritos, compareceram cerca de sessenta pessoas, se contarmos a turma da organização e os palestantres acho que tivemos umas setenta pessoas presentes.

Meus agradecimentos à faculdade evangélica, em especial do Prof. Maurício e ao Prof. Dirceu que cederam espaço e nos ajudaram na logística do encontro.

Não conseguimos apresentar do jeito que queríamos o último trabalho (Integração de GitLab com Puppet) devido ao tempo que ficou apertado, mas conseguimos avançar com conteúdo de Puppet para a comunidade local.

A experiência nos mostrou que é melhor reduzir os temas nos próximos encontros, portanto, o próximo meetup terá tema específico, seja desenvolvimento de módulos, seja testes, seja pcp, apenas um tema que iremos desenvolver do início ao fim.

Agradeço aos palestrantes Adriano, Taciano, Rafael e Dirceu pelo tempo que investiram no encontro e por terem compartilhado experiência e conhecimento conosco.

Estamos estudando fazero próximo agora em junho, aguardo sugestões de temas, ideias e quem sabe uma nova parceria para hospedar o Meetup.

Fotos

Acesse as fotos no link abaixo:

https://www.flickr.com/photos/puppet-br/albums/72157666275683673

Slides

Os slides estão no speakerdeck:

  1. https://speakerdeck.com/gutocarvalho/meetup-puppet-br-20160518-intro-puppet

  2. https://speakerdeck.com/gutocarvalho/meetup-puppet-br-20160518-integracao-entre-puppet-e-vagrant

  3. https://speakerdeck.com/gutocarvalho/meetup-puppet-br-20160518-projeto-pcp

  4. https://speakerdeck.com/gutocarvalho/meetup-puppet-br-20160518-desenvolvendo-modulos-e-fatos-puppet

  5. https://speakerdeck.com/gutocarvalho/meetup-puppet-br-20160518-testes-de-codigo-puppet

[s]
Guto

Alpine – Faça você mesmo

Oi Pessoal,

O MundoDocker trás hoje para você um pequeno tutorial de como é possível criar uma imagem enxuta, somente com o que você precisa e utilizando menos espaço possível. Para isso será necessário utilizar uma das duas imagens mais limpas do Docker, são elas: Alpine ou BusyBox, nesse tutorial vamos focar na Alpine, uma das mais buscadas atualmente.

Para que não conhece, a Alpine é uma distribuição construída com musl libc e BusyBox, que é conhecida como canivete suíço, pois combina versões minúsculas de muitos utilitários comuns no UNIX em um único pequeno executável. Algumas características de Alpine:

Pequena

Enquanto a menor imagem para Docker precisa de cerca de 130MB de espaço em disco, a Alpine precisa de no máximo 8MB, isso faz com que, mesmo você montando todo o seu ambiente, ele nunca terá o mesmo tamanho do que se montando em um imagem tradicional, isso é ótimo, pois deixa o ambiente ainda mais enxuto e simples de migrar.

Simples

Você tem apenas aquilo que é necessário para o funcionamento de sua aplicação, se precisar de mais alguma biblioteca, é só instalar, você não precisa se preocupar em desativar ou remover lixos, eles simplesmente não existem.

Segura

Alpine foi desenvolvida pensando em segurança, e para garantir isso os desenvolvedores se preocuparam aprimorar os recursos de segurança do kernel como grsecurity/PaX, além disso, todos os binários foram compilados em executáveis independente de posição, isso previne alguns uso problemas relacionados a buffer overflow e outros tipos de ataques envolvendo estouro de pilha.

Mãos a obra?

Nosso exemplo consistirá em montarmos uma imagem de com Alpine e Nodejs, e vamos comparar o tamanho da nova imagem que montamos com Alpine e outras distros disponíveis.

A Aplicação:

Será algo bem simples, apenas uma aplicação olá mundo:

var http = require('http');
http.createServer(function(req,res) {
 res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
 res.end('Exemplo Node.js Mundo Docker!');
}).listen(8080);

Colocamos o nome de app.js, não esqueça de criar o package.json com as dependências da aplicação:

{
"name": "docker_web_app",
"version": "1.0.0",
"description": "Node.js on Docker",
"author": "First Last <first.last@example.com>",
"main": "app.js"
}

Agora criamos nosso Dockerfile:

FROM alpine:3.1
# Update
RUN apk add --update nodejs
# Cria a pasta da app
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Instala as dependencias da app
COPY package.json /usr/src/app/
RUN npm install
# copia a app
COPY . /usr/src/app
EXPOSE 8080
CMD ["node", "/usr/src/app/app.js"]

 

Não é nada muito complexo, basta você informar qual imagem base utilizará, e a diferença está no instalador de dependências, que para o Alpine é o apk. Agora vamos gerar a imagem:

docker build -t alpineteste .

Será gerado uma nova imagem com o nome de alpineteste, agora vamos comparar o tamanho dessa imagem com outras:

Alpine

Lembrando, que utilizamos a imagem base de cada distribuição e em cima dela instalamos o node e subimos essa aplicação, note que a diferença é exorbitante, isso por que a Alpine tem apenas o que é necessário para essa aplicação rodar, nada além disso.

Como podem ver, utilizando essa abordagem seu ambiente fica ainda mais escalável, e claro ainda mais portável, pois quanto menos a sua imagem, melhor é para transitar ela entre os hosts (não é necessário baixar megas e megas da imagem no primeiro deploy por exemplo) .

Gostou? nos ajude divulgando o Blog 😉

Grande abraço!

ProjectAtomic.io

Olá pessoal,

Com o passar dos anos as tecnologias vem evoluindo cada vez mais rápido, surgem novos conceitos porém muitos morrem e poucos acabam se tornando tendência. No passado muito se falou sobre “Máquinas Virtuais” muitas empresas apareceram no mercado de virtualização porém apenas algumas se destacaram que é o caso de Microsoft, VMWare e Oracle.

Agora chega a hora da tendência de containers (Sim, LXC existe há um grande tempo já) que cada vez mais vem se popularizando e com isso surgem diversas empresas no mercado oferecendo integrações, plataformas, contentores e entre outros produtos. Com essa gama de ofertas decidi realizar uma série mostrando as empresas que acreditamos que serão as grandes donas do mercado de containers nos próximos anos.

O ProjectAtomic: É um sistema operacional desenvolvido pela RedHat, foi projetado para a execução de aplicações em containers docker. O Project Atomic depende de vários projetos de código aberto as várias distribuições Linux específicas. A comunidade Atomic vai trabalhar para o desenvolvimento do projeto atômico de forma inclusiva, contribuindo para os projetos upstream relacionados, resolvendo problemas de integração nas diversas distribuições sendo usado e desenvolver as ferramentas de gestão específicas necessárias para atualizações de gestão e de sistema. As principais ferramentas utilizadas foram:

– Docker – Implementação dos aplicativos

– Kubernetes – Orquestração

– rpm-ostree – Atualizações

– systemd – Gerencia de serviços

O Project Atomic possui uma ferramenta Web chamada Cockpit para realizar o gerenciamento de containers e hosts, com o Cockpit você pode:

– Visualizar os recursos utilizado pelos containers.

– Limitar recursos dos containers.

– Iniciar, parar, salvar e realizar o commit dos containers.

– Executar e excluir imagens.

– Administrar o host.

– Configurar serviços no host e outras funcionalidades.
cockpit-screenshot

Exemplo de imagem do Cockpit

Aqui possui o link para o download da imagem do sistema operacional http://www.projectatomic.io/download/

Por hoje era isso, espero que tenham gostado e tendo dúvidas nos avisem, e claro ajudem divulgando o http://mundodocker.com.br

Abraço!

Foi liberado o PCP 1.0.2

O projeto PCP está em casa nova e com nova versão. Movemos o projeto para a organização Puppet-BR no github para facilitar a contribuição. Agora a documentação está toda em inglês o que facilita o uso para pessoas de qualquer parte do mundo.

Já fizemos a homologação das versões mais recentes do puppet nesta release:

  • Puppet Server 2.3.2
  • Puppet Agent 1.4.2
  • Mcollective 2.8.8
  • PuppetDB 4.0.2
  • PostgreSQL 9.4.6
  • Puppet Explorer 2.0.0
  • ActiveMQ 5.13.2

Agradeço por todas as ideias e por todas as contribuições recebidas no GitHub, agradeço pela turma que participou do Meetup PCP em Brasília e por todos que ajudaram a testar a nova versão. [s]
Guto

Meetup Puppet-BR em BSB no dia 18-05

Foi marcado um Meetup Puppet-BR em Brasília no dia 18 de Maio, será no edifício Parque Cidade Corporate, vai começar às 18:30.

Este será o terceiro encontro técnico do ano, foco nas atividades práticas.

Faça sua inscrição, temos apenas 50 vagas.

http://www.meetup.com/pt-BR/puppet-br/events/230816720/

Programação:

1. Intro CGONF & Puppet 4

Palestrante: Rafael Sales & Guto Carvalho
Tempo: 40 min

  • Introdução rápida a gerência de configurações;
  • Introdução ao Puppet 4.

2. Projeto PCP

Palestrante: Taciano Tres & Guto Carvalho
Tempo: 20 min

  • Apresentação do projeto PCP;
  • Demo de instalação do PCP.

3. Oficina de desenvolvimento de módulos e fatos Puppet

Palestrante: Rafael Sales & Guto Carvalho
Tempo: 40 minutos

  • Demo de desenvolvimento de módulos;
  • Demo de desenvolvimento de fatos.

4. Integração do Puppet com Vagrant

Palestrante: Taciano Tres
Tempo: 20 minutos

  • Introdução rápida ao Vagrant;
  • Uso do Provider Puppet Apply;
  • Uso do Provider Puppet Agent;
  • Demo de integração de Puppet com Vagrant.

5. Testes de código Puppet

Palestrante: Adriano Vieira & Guto Carvalho
Tempo: 30 minutos

  • Porque testar?
  • Puppet Parser Validate
  • Puppet Lint
  • Entendendo teste unitário;
  • Entendendo teste de aceitação;
  • Introdução rápida ao Rspec-Puppet;
  • Introdução rápida ao ServerSpec;
  • Introdução rápida ao Beaker;
  • Demo de desenvolvimento de teste unitário para o módulo que criamos;
  • Demo de desenvolvimento de teste de aceitação.

6. Integração do Puppet com GitLab

Palestrantes: Douglas Andrade e Guto Carvalho

  • Introdução rápida ao GitLab;
  • Demo de instalação do GitLab;
  • Demo GitLab CI;
  • Integrações com Puppet (VCSREPO);
  • Integrações com Puppet (R10k).

[s]
Guto