AKS – Azure Kubernetes Service – Parte 2.

Continuando nossa série de posts sobre o AKS, hoje vamos entender como o AKS cria os recursos no Azure. Se você não viu o post anterior mostrando como podemos criar um cluster de maneira rápida e fácil dentro do Azure, segue o link abaixo:

AKS – Parte 1

Quando você executa a criação de um cluster de Kubernetes no Azure, automaticamente a Microsoft cria diversos componentes, hoje vamos entender que componentes são esses criados pelo Azure e como eles se relacionam com o cluster de Kubernetes.

Estrutura

Na criação de um cluster simples igual foi criado no post anterior a Microsoft irá automaticamente no Azure criar recursos dos tipos: Load Balancer, Resource Group, Node Pools.

Na imagem acima é possível ver que em Resource Groups existem dois recursos, o resource_aks foi criado anteriormente, porem o MC_resource_aks_aksmundodocker_eastus é criado automaticamente pelo Azure e nesse momento não podemos renomear esse resource, então ele vai adicionar o prefixo: MC_{NOME DO RESOURCE GROUP}_{NOME DO CLUSTER}_{REGIÃO}. Dentro desse Resource Group é onde ficam os objetos criados especificamente para o cluster. Dentro do resource_aks você irá visualizar apenas um recurso do tipo Kubernetes Service, como na imagem abaixo:

Ao clicar em MC_resource_aks_aksmundodocker_eastus você poderá ver os recursos criados, se você copiou e colocou o exemplo de criação do post anterior, você deve ver algo parecido com isto:

É possível ver os tipos de recursos: Public IP address, Network security group, Route table, Virtual machine scale set, Virtual network e Load balancer. Por padrão são esses os tipos de recursos criados para um cluster de AKS.

Public IP address

Quando se cria um cluster de AKS padrão o endereço IP padrão para o Load Balancer é um IP público, então automaticamente o Azure cria um recursos do tipo Public IP address dentro do Resource group.

Network security group

O Networ security group (NSG) é um componente do Azure no qual é possível criar as regras para tráfego nas interfaces de rede, definindo assim se habilita o tráfego para determinado endereço ou recurso ou se habilita o mesmo.

Route table

O Route table como o nome já sugere é um recurso do Azure para definir a tabela de roteamento de alguns componentes.

Virtual machine scale set

Para conseguir realizar o dimensionamento de máquinas de maneira automática o Azure cria para o cluster de AKS um recurso do tipo Virtual machine scale set que faz com que o grupo de máquinas pode aumentar ou diminuir conforme a demanda de uso ou o agendamento criado.

Virtual network

Todo o cluster de AKS precisa ser criado dentro de uma Virtual network (VNET) ela pode ser criada automaticamente no momento de criação do cluster (Igual a gente fez) ou pode ser criada anteriormente e depois informada no momento da criação do cluster.

Load balancer

Dentro do Kubernetes existem 3 tipos de services: NodePort, ClusterIP e Load balancer. Quando o tipo de service Load balancer é criado o Azure atribui 1 IP da sua subnet para esse service e configura no recurso Load balancer um encaminhamento para esse service. Nos próximos posts a gente vai entender melhor e ver como essas regras são criadas.

Não sabe o que é service? da uma olhada em o que é service?

OBS* Os recursos criados pelo AKS de maneira automática não devem ser modificados ou excluídos por outras contas a não ser pela própria Azure, pois qualquer modificação pode fazer com que o recurso pare de funcionar e a Azure não de suporte a eles.

Os recursos acima são os criados de maneira default em um cluster simples no AKS. Agora que você aprendeu como funciona a estrutura do AKS e quais são os componentes básicos do cluster nos próximos posts você vai aprender como é possível realizar o deploy das aplicações, fazer integrações, monitoramento e obter o melhor desempenho para as suas aplicações em produção.

Ansible

Olá pessoal,

Hoje vamos falar sobre uma ferramenta que cada vez mais quem trabalha com Docker acaba utilizando que é o Ansible. A primeira vista muitas pessoas acham que ambas ferramentas fazem a mesma coisa, apresentando uma solução para gerenciamento de configurações através de meios diferentes. Na realidade a união das duas ferramentas torna o ambiente de implantações de softwares limpo, confiável e rápido.

Ansible

É uma ferramenta de automatização de tarefas semelhante a Puppet e Chef, porém muito mais poderosa e a queridinha do pessoal DevOps hoje. Com ela é possível fazer o deploy de aplicações, provisionando de servidores, automatizar tarefas, e outras funções.

O Ansible trabalha com arquivos YAML,  o principal arquivo de configuração é chamado de PLAYBOOK onde você coloca todas as tarefas que serão executadas “yum”,”mkdir”,”useradd” e no arquivo .ini você adiciona os servidores onde o Ansible irá executar esse PLAYBOOK. Cada Playbook possui roles que são as informações de provisionamento, após definir as roles você definirá em quais hosts essas roles serão executadas.

Dentro das roles existem as tasks, handlers, variaveis e templates:

       – Tasks: Tarefas de provisionamento que serão executadas

       – Handlers: Tarefas para manipular serviços e arquivos.

       – Templates: Arquivos para serem transformados em configurações dentro das máquinas.

       – Variaveis: Valores que são definidos para serem usados dentro das tasks, handlers e templates

O Ansible é uma ferramenta muito mais simples que seus concorrentes citados anteriormente, já que ele não precisa que seja instalado agents nos servidores na qual ele irá executar.

É possível utilizar Docker e Ansible em conjuntos para resolver duas situações: Implantação de Containers e Criação de Imagens.

Implantação de containers: É possível fazer toda a parte de orquestração, configuração e provisionamento com containers, sem precisar fazer a instalação de agents dentro dos containers

Criação de Imagens:

Exemplo de Playbook:

# Mysql service name for drupal application
mysqlservice: mysqld

# Mysql port for drupal application
mysql_port: 3306

# Database name for the drupal application
dbname: databasename

# Mysql Username for drupal application
dbuser: root  

Exemplo de Configuração do arquivo do Ansible:

[defaults]
inventory = /etc/ansible/inventory
host_key_checking = False
priva_key_file = ~/.sh/id_rsa
callback_plugins   = /opt/ansible-plugins/callbacks
connection_plugins = /opt/ansible-plugins/connections

Então tá pessoal, hoje fizemos apenas uma pequena introdução ao Ansible, em nossos próximos posts estaremos trazendo algo como Jenkins, Travis e também faremos um grande post mostrando como podemos criar um ambiente com Docker, Jenkins e Ansible. Obrigado

Referência: http://docs.ansible.com/ansible/playbooks_intro.html e http://ibm.com/developerworks/br/cloud/library/cl-provision-docker-containers-ansible/

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!

 

MundoDocker no DevOpsWeek

Oi Pessoal,

O Ano começou a todo vapor aqui para o MundoDocker, e hoje queremos convidar a todos para se inscreverem no DevOpsWeek, um dos maiores eventos sobre o assunto DevOps, Desenvolvimento/Infra ágil do Brasil.

Participaremos do evento com a apresentação: Deploy Integrado com Docker, é o assunto do momento, e o objetivo é tirar dúvidas e dar ideias de como o você pode usar Docker para automatizar suas rotinas, e claro acelerar seus processo de desenvolvimento.

Veja abaixo a chamada para o evento que gravamos, te liga:

Ficou interessado? Então te inscreve, o evento é online e gratuito!!! Acesse: http://devopsweek.com.br

 

Por hoje era isso, e fique atento pois teremos mais novidade aqui no Blog.

Grande abraço!

Docker multi-stage builds

Oi Pessoal,

Tivemos diversas novidades com o lançamento das versões 17.05 e 17.06 do Docker, que ocorreram nos últimos meses, nosso objetivo é trazer para vocês algumas dessas novidades, iniciaremos com o multi-stage builds, ou em português claro: construção em múltiplos estágios, vamos entender um pouco mais sobre esse conceito, como utiliza-lo e onde ele pode te ajudar no dia-a-dia.

Antes de mais nada, gostaríamos de nos desculpar pelo hiato na publicação de posts, mas garantimos que foi por alguns bons motivos

O que é?

O multi-stage build foi lançado na versão 17.05 e permite que um build possa ser reutilizado em diversas etapas da geração da imagem, deixando os Dockerfiles mais fáceis de ler e manter.

O estado da arte

Uma das coisas mais desafiadoras sobre a construção de imagens é manter o tamanho da imagem reduzido. Cada instrução no Dockerfile adiciona uma camada à imagem, e você precisa se lembrar de limpar todos os artefatos que não precisa antes de passar para a próxima camada. Para escrever um Dockerfile realmente eficiente, você tradicionalmente precisa empregar truques de shell e outra lógica para manter as camadas o mais pequenas possíveis e garantir que cada camada tenha os artefatos que ela precisa da camada anterior e nada mais.

Na verdade, era muito comum ter um Dockerfile para uso para o desenvolvimento (que continha tudo o que era necessário para construir sua aplicação), e outro para usar em produção, que só continha sua aplicação e exatamente o que era necessário para executá-la. Obviamente a manutenção de dois Dockerfiles não é o ideal.

Aqui está um exemplo de Dockerfile.build e Dockerfile exemplifica o caso acima:

Dockerfile.build:

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN go get -d -v golang.org/x/net/html 
  && CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

Observe que este exemplo também comprime artificialmente dois comandos RUN juntando-os com o parâmetro “&&” do bash, para evitar criar uma camada adicional na imagem. Isso é propenso a falhas e difícil de manter. É fácil inserir outro comando e esquecer de continuar a linha usando este parâmetro , por exemplo.

Dockerfile:

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app .
CMD ["./app"]  

Build.sh:

#!/bin/sh
echo "Building alexellis2/href-counter:build"

docker build --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy   
    -t alexellis2/href-counter:build . -f Dockerfile.build
docker create --name extract alexellis2/href-counter:build 
docker cp extract:/go/src/github.com/alexellis/href-counter/app ./app 
docker rm -f extract 

echo "Building alexellis2/href-counter:latest" docker build --no-cache -t alexellis2/href-counter:latest . 
rm ./app

Quando você executa o script build.sh, ele cria a primeira imagem com o artefato, a partir da qual cria-se um container que é utilizado para copiar o artefato, em seguida, ele cria a segunda imagem copiando o artefato para essa segunda imagem. Ambas as imagens ocupam espaço em seu sistema e você ainda tem o artefato em seu disco local também.

O que melhorou

Com o multi-stage, você usa várias instruções FROM no seu Dockerfile, cada instrução FROM pode usar uma base diferente, e cada uma delas começa um novo estágio da compilação. Você pode copiar artefatos de um estágio para outro, deixando para trás tudo que você não quer na imagem final. Para mostrar como isso funciona, vamos adaptar o Dockerfile anterior para usar multi-stage:

Dockerfile:

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

Você só precisa do único Dockerfile, além de não precisar de um script de compilação separado, basta buildar sua imagem docker:

$ docker build -t alexellis2/href-counter:latest .

O resultado final é a mesma pequena imagem de produção que antes, com uma redução significativa na complexidade. Você não precisa criar nenhuma imagem intermediária e você não precisa extrair nenhum artefato para o seu sistema local.

Como funciona? A segunda instrução FROM inicia um novo estágio de compilação com a imagem base sendo alpine. A instrução “COPY –from=0”  copia apenas o artefato construído do estágio anterior para esta nova imagem, o Go SDK e quaisquer artefatos intermediários são deixados para trás e não são salvos na imagem final.

Deixando mais claro

Por padrão, as etapas não são nomeadas, e você referencia elas por seu número inteiro, começando por 0 na primeira instrução FROM. No entanto, você pode nomear seus estágios, adicionando a instrução “as <nome>” na mesma linha do FROM. O exemplo abaixo deixa mais claro isso e melhora a forma como manipulamos nossos builds nomeando as etapas e usando o nome na instrução COPY. Isso significa que, mesmo que as instruções no seu Dockerfile sejam reordenadas, a cópia do artefado não será interrompida.

FROM golang:1.7.3 as builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

 

Ficou fácil né? Essa feature auxilia ainda mais as equipes no momento de administrar seus builds, pois centraliza e deixa mais transparente cada passo na geração dos pacotes/artefatos de uma aplicação.

Gostaríamos de agradecer ao @alexellisuk pela contribuição a comunidade com os exemplos utilizados acima. Esperamos ter ajudado, e como sempre, se tiver dúvidas avisa ai que vamos te ajudar.

Grande abraço!

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!

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!

Iptables e Docker

Oi Gente!!

Iniciando 2019 e esse ano promete mudanças, em todos os aspectos, aqui no Blog também ;), esperamos que esse ano seja de grandes realizações, para todos nós.

Então, se você já trabalha com Docker, já deve ter passado por alguma situação onde as regras de iptables não são obedecidas, é, isso acontece :(.

Se você ainda não mexeu com Docker, recomendo este post aqui, que explica um pouco sobre o que é o Docker e como ele funciona, e te prepara pois o que mostraremos no post de hoje será bem útil para você.

O problema
Por padrão o Docker manipula regras no iptables, mas, por que ele faz isso? Porque quando você cria um container o Docker precisa criar algumas regras para encaminhamento de tráfego, isolamento, etc. É possível desabilitar esse comportamento, porém, você precisará garantir isso manualmente

Digamos que você tem seu iptables bonito, nele você libera apenas a porta 80 e 22, e bloqueia todo o resto, para isso é provável que você utilize as seguintes regras:

iptables -P INPUT DROP

iptables -A INPUT --dport 80 -j ACCEPT

iptables -A INPUT --dport 22 -j ACCEPT

Neste servidor você tem Docker rodando, e criou um container na porta 80 obviamente para responder as requisições que são feitas.

Ok, agora você teve a necessidade de criar outra container, este em outra porta, e neste container você terá o ambiente de homologação, como você já tem um container executando e utilizando a porta 80, você precisará criar na porta 8080, ok, sem problema, agora posso ir no meu iptables e liberar a porta 8080 APENAS para o meu ip, óbvio que funciona:

iptables -A INPUT -s 10.1.1.2 --dport 8080 -j ACCEPT

Não, não funciona. E a explicação para esse comportamento encontramos em um dos assuntos primordiais da existência de um Sysadmin Linux, o comportamento do iptables.

Para recapitularmos, o iptables é basicamente é um interpretador de regras gerando ações baseadas nessas regras. Dentro do iptables temos três tabelas, são elas: Filter, Nat e Mangle. A tabela mais utiliza de todas é a Filter, é nessa tabela que criamos nossas regras para bloqueio de portas/ips. Dentro dessa tabela encontramos outras três chains, são elas:

  • INPUT: Consultado para pacotes que chegam na própria máquina;
  • FORWARD: Consultado para pacotes que são redirecionados para outra interface de rede ou outra estação. Utilizada em mascaramento.
  • OUTPUT: Consultado para pacotes que saem da própria máquina;

Agora advinha em qual chain são criadas as regras do Docker? Sim, em uma chain de forward, isso por que o pacote não é destinado para o host e sim para a interface que o Docker cria. É importante saber disso, pois o fluxo dentro do iptables muda se o destino do pacote é local ou não.
Para ficar mais claro, dá uma olhada nessa imagem:
Isso quer dizer que aquele seu container que foi criado na porta 8080 ficará exposto, pois a regra de forward será executada antes daquela sua regra de input que bloqueia tudo ;). A chain utilizada neste caso chama-se DOCKER, e você pode visulizar as regras criadas utilizando o:

iptables -L -nv

“Oh, e agora quem poderá nos defender?”

A Solução

Até pouco tempo atrás havia basicamente uma solução, nem um pouco “elegante” de se resolver isso.

  • Desabilitar no daemon do Docker para ele não manipular de forma automatica essas regras, com isso você precisaria criar manualmente as regras;

Existiam outras formas? Sim, algumas mais complexas, outras mais baixo nível, mas de qualquer forma nada tão simples e muito menos fácil de se administrar, então, depois de vários pedidos e sugestões de solução no github do Docker, isso foi repensado e resolvido de uma forma mais inteligente.

Foi adicionado uma nova Chain, chamada DOCKER-USER, essa chain apesar de ser forward também, precede as chains utilizadas pelo Docker na criação de containers. Dessa forma, você pode utilizar ela para adicionar as suas regras personalizadas e garantir o bloqueio ou acesso aos containers.

Te lembra daquelas regra que não funcionava antes? Então, neste novo cenário, ficará dessa forma:

iptables -I DOCKER-USER -s 10.1.1.2 --dport 8080 -j ACCEPT

iptables -A DOCKER-USER --dport 8080 -j DROP

Bem mais simples do que manipular todas as regras do Docker manualmente, certo? Mas lembre-se, isso serve apenas para controlar o trafego externo aos containers, isso não é aplicado no contexto de INPUT, então tome cuidado achando que é nessa chain que deve ir todas as suas regras. Outro ponto positivo para essa abordagem é a simplicidade para automatizar, pois basta integrar essa mesma lógica em sua pipeline e você estará protegendo seus containers.

É possível ainda manter aquele seu script maroto de firewall, basta adicionar mais algumas regras liberando ou não o acesso a determinada porta (na qual quem responderá será um container).

Então era isso, se quiser saber mais, tirar alguma dúvida ou ainda ajudar, deixa ai nos comentários ou entre em contato por e-mail. Grande abraço e boa semana

Auto Complete para Docker

Olá!

Hoje o post será um pouco diferente dos que geralmente publicamos, queremos mostrar para vocês como é possível utilizar a funcionalidade de auto complete do shell para os comandos Docker. Mas para que isso? Simples, facilidade e agilidade na execução de comandos, quem aqui nunca apertou o tab depois de digitar ‘./conf’? Então, você deve sentir falta dessa facilidade quando se utiliza os subcomandos do docker, certo? Queremos mostrar pra vocês como resolver isso.

Como você já viu aqui, existem diversos subcomandos do docker, e cada um possui diversos parâmetros que podem ser utilizados, com o docker –help você poderá visualizar as opções disponíveis.

Mas isso é chato algumas vezes, é mais fácil começar a digitar docker run --vol...[tab][tab]e deixar o autocomplete fazer o trabalho:

$ docker run --volume
--volume         --volume-driver  --volumes-from

#vamosinstalar?

No Mac OS X

O processo é simples, estando no Mac OS X temos que instalar o auto completion usando o brew:

$ brew install bash-completion

E em seguida adicionar as linhas em nosso arquivo de profile ($HOME/.bash_profile ou /Users//.bash_profile)

if [ -f $(brew --prefix)/etc/bash_completion ]; then
    . $(brew --prefix)/etc/bash_completion
fi

Você pode executar os seguintes comandos, que devem ser utilizados nesta sequência:

$ echo "if [ -f $(brew --prefix)/etc/bash_completion ]; then" | tee -a $HOME/.bash_profile
$ echo "    . $(brew --prefix)/etc/bash_completion" | tee -a $HOME/.bash_profile
$ echo "fi" | tee -a $HOME/.bash_profile

Atenção: Se não temos o homebrew instalado, veja em http://brew.sh/ mais informações de como instala-lo e utiliza-lo.

 
No Linux

No Linux, como sempre, é mais simples, basta instalar via gerenciador de pacotes da sua distribuição. Se for Debian like (Ubuntu, Mint, etc) usamos o apt-get:

$ sudo apt-get install bash-completion

Se for Red Hat like (RHEL, CentOS, Fedora, etc) então usamos yum:

$ sudo yum install bash-completion

Completion do Docker Engine

O arquivo está disponível em https://github.com/docker/docker/blob/master/contrib/completion/bash/docker portanto sempre que fizer uma atualização é recomendável que você baixe novamente esse arquivo para refletir os comandos e parâmetros novos disponibilizados pelo Docker.

Ao baixar devemos colocá-lo na pasta /etc/bash_completion.d/ se estivermos no Linux, se estivermos em um Mac OS X:  $(brew --prefix)/etc/bash_completion.d.

No Mac OS X
$ curl -L https://raw.githubusercontent.com/docker/docker/master/contrib/completion/bash/docker > $(brew --prefix)/etc/bash_completion.d/docker
No Linux
$ curl -L https://raw.githubusercontent.com/docker/docker/master/contrib/completion/bash/docker > /etc/bash_completion.d/docker

Completion do Docker Compose

De maneira similar o arquivo está disponível emhttps://github.com/docker/compose/blob/master/contrib/completion/bash/docker-compose . Reforçamos que sempre que fizer uma atualização é bom baixar novamente esse arquivo para refletir os comandos e parâmetros novos disponibilizados pelo Docker Compose.

Ao baixar também devemos colocá-lo na pasta /etc/bash_completion.d/ se estivermos no Linux ou devemos acrescentar a pasta do homebrew antes se estivermos em um Mac OS X: $(brew --prefix)/etc/bash_completion.d.

No Mac OS X
$ curl -L https://raw.githubusercontent.com/docker/compose/master/contrib/completion/bash/docker-compose > $(brew --prefix)/etc/bash_completion.d/docker-compose
No Linux
$ curl -L https://raw.githubusercontent.com/docker/compose/master/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose

Completion do Docker Machine

O processo é praticamente o mesmo porém o docker-machine possui 3 arquivos de auto complete. Os arquivos estão disponíveis em https://github.com/docker/machine/tree/master/contrib/completion/bash .

Como dito anteriormente devemos colocá-los na pasta /etc/bash_completion.d/ se estivermos no Linux ou devemos acrescentar a pasta do homebrew antes se estivermos em um Mac OS X: $(brew --prefix)/etc/bash_completion.d.

Como são mais arquivos recomendo utilizarmos um loop para baixarmos todos em sequência utilizando apenas um comando.

No Mac OS X
machineVersion=`docker-machine --version | tr -ds ',' ' ' | awk 'NR==1{print $(3)}'`
files=(docker-machine docker-machine-wrapper docker-machine-prompt)
for file in "${files[@]}"; do
  curl -L https://raw.githubusercontent.com/docker/machine/v$machineVersion/contrib/completion/bash/$file.bash > `brew --prefix`/etc/bash_completion.d/$file
done
unset machineVersion
No Linux
machineVersion=`docker-machine --version | tr -ds ',' ' ' | awk 'NR==1{print $(3)}'`
files=(docker-machine docker-machine-wrapper docker-machine-prompt)
for file in "${files[@]}"; do
  curl -L https://raw.githubusercontent.com/docker/machine/v$machineVersion/contrib/completion/bash/$file.bash > /etc/bash_completion.d/$file
done
unset machineVersion

Observe que:

  1. Se você utilizar alguma versão específica de uma dessas ferramentas basta baixar os arquivos da pasta correspondente.  Por exemplo o docker engine, da maneira que mostramos vamos pegar o arquivo que está na branch master, atualmente versão 1.12.1, para pegar na versão 1.11.0 por exemplo o arquivo fica em https://github.com/docker/docker/blob/v1.11.0/contrib/completion/bash/docker
  2. O Docker disponibiliza alguns arquivos de completion para outros shells. O Docker Engine disponibiliza bash, zsh, fish e powershell como podemos ver em https://github.com/docker/docker/tree/master/contrib/completion .
  3. O Docker Compose e o Docker Machine disponibilizam apenas para bash e zshcomo vemos nas urls https://github.com/docker/compose/tree/master/contrib/completionhttps://github.com/docker/machine/tree/master/contrib/completion .

E era isso por hoje pessoal, agradecimento especial ao @wsilva pela dica. Já sabe, ajude divulgando o blog, e tendo dúvidas ou sugestões deixa ai nos comentários

Abraço!

Fonte: http://dumpscerebrais.com/2016/09/auto-complete-para-docker-engine-machine-e-compose/

Segurança e hacking de containers Docker

Olá gente! Tudo bem?

Como vocês podem ter notado, meu nome é Fernando e este é o meu primeiro post aqui no blog, e minha contribuição será no sentido de esclarecer e ajudar vocês com algumas questões que pouca gente se preocupa, ou até mesmo implementa, mas que eventualmente pode prejudicar a sua aplicação ou seu negócio, sim, hoje falaremos sobre Segurança .

A alguns meses iniciei uma busca por informações sobre segurança relacionado a Docker, pois não via quase ninguém falar, na época até pensei que era porque eu estava por fora dos grupos de discussões, mas ao ir conversando com algumas pessoas bem envolvidas com a comunidade Docker fui vendo que em português temos bem pouco sobre este assunto. Então comecei a buscar por este assunto e fui encontrando materiais em inglês, assim fui montando um compilado de materiais sobre para tentar criar uma apresentação ou artigo. Conversando com o Cristiano do Mundo Docker, que é um membro muito ativo na comunidade Docker, recebi bastante incentivo pois ele também achou que o assunto é bem importante e pouco abordado, e nesta conversa surgiu a ideia de fazer uma pesquisa com a comunidade para saber de quem está usando Docker o que estão fazendo com relação a segurança.

Foi um questionário bem simples, com 3 perguntas  que foi realizado entre 14 e 25 de agosto 2017, com 36 participantes.

Primeira pergunta: Já utilizou Docker em produção?

Mais de 55 por cento das pessoas que participaram da pesquisa responderam que utilizam Docker em produção.

Segunda pergunta: Verifica vulnerabilidades nas imagens utilizadas?

Dos 36 participantes menos de 20 por cento faz algum tipo de verificação para tentar identificar vulnerabilidades nas imagens Docker utilizadas.

Terceira pergunta: Como verificar vulnerabilidades?

E na última pergunta a ideia era identificar se é utilizado algum tipo de ferramenta para fazer as verificações de vulnerabilidades. Dos 19.4% que responderam que fazem alguma verificação somente um respondeu que utilizava alguma tipo de ferramenta, os outros informaram fazer verificações manuais, analisando o dockerfile e suas dependências, verificando autenticação, permissões e qualquer tipo de comunicação com o host.

Com base nessa pesquisa eu passei a focar o desenvolvimento deste material em ferramentas que podem ajudar no dia-a-dia para verificação de vulnerabilidades, em imagens, container e host. E com isso também encontrei ferramentas para fazer hacking de containers Docker. Para se proteger nada melhor que saber como pode ser atacado, então acompanhem até o final que vamos ter bastante dicas e ferramentas bacanas.

Mas para começarmos a utilizar as ferramentas primeiro precisamos estar ciente de algumas preocupações e práticas de segurança  ao usar Docker.

Preocupações com segurança ao usar Docker

Kernel exploits (exploração do kernel)

Ao contrário de uma VM, ao usar containers o kernel é compartilhado entre todos os containers e o host, aumentando a importância de qualquer vulnerabilidade que explore o kernel.

Denial-of-service attacks (ataque de negação de serviço)

Como todos os containers compartilham  recursos do kernel, se um container pode monopolizar o acesso a certos recursos, incluindo memória, ou até IDs de usuário (UIDs), pode faltar recursos para outros containers, resultando em uma negação de serviço (DoS).

Container breakouts (invasão de container)

Um invasor que tem acesso a um container não pode ter acesso a outros containers ou ao host. Se você usa root no container, você será root no host.

Poisoned images (imagens “envenenadas”)

Como você sabe que as imagens que você está usando são seguras, não foram adulteradas, e vêm de onde elas afirmam vir?

Application secrets (segredos de aplicações)

Quando um container acessa um banco de dados ou serviço, provavelmente exigirá credenciais, como um token ou mesmo usuário e senha. Se um invasor tiver acesso ao container terá acesso a estes dados.

Práticas de segurança

No tópico anterior foi levantada algumas preocupações de segurança que devemos ter ao usar containers, agora vamos ver algumas possíveis soluções para tentar resolver estes problemas.

Inicio este tópico com uma pergunta.

Como devemos armazenar dados sensíveis, como senhas, chaves privadas, tokens, chaves de APIs?

Para começar a responder esta pergunta, eu acho mais fácil e direto responder como não devemos armazenar dados sensíveis.

Não use variáveis de ambiente ou incorpore na imagem de container. É uma dica meio óbvio mas acontece e muito. Se quiserem ler sobre um caso, de utilização de credenciais incorporadas na imagem e que vazou,  tem um consideravelmente conhecido que aconteceu com a IBM: IBM Data Science Experience: Whole-Cluster Privilege Escalation Disclosure.

Mas como então devemos armazenar nossas credenciais de acesso quando usamos containers? Uma ótima solução é utilizar o Docker Secrets Management.

Docker Secrets Management

O Docker Secrets funciona como um cofre onde você pode colocar coisas sensíveis lá e só quem tem a chave do cofre consegue utilizar, no caso essa chave é designada aos nós dos serviços que a chave for atribuída. Mais de como funciona pode ser visto no blog Mundo Docker – Docker Secrets.

Outras dicas de segurança menciono abaixo em forma de tópicos:

Proteja seu host

  • Certifique-se de que seu host e a configuração do Docker engine sejam seguras
  • Mantenha seu SO atualizado
  • Impor controle  de acesso para evitar operações indesejadas, tanto no host como nos containers, usando ferramentas como SecComp, AppArmor ou SELinux

Redução dos privilégios

  • Tomar cuidado ao executar como root
  • Crie namespaces isolados
  • Limitar privilégios ao máximo
  • Verifique se o container é confiável (verifique a imagem)

Alto uso de recursos do container

  • Limite os recursos no kernel ou no container
  • Fazer testes de carga antes de pôr em produção
  • Implemente monitoramento e alertas

Autenticidade da imagem

  • De onde veio?
  • Você confia no criador?
  • Quais políticas de segurança está usando?
  • Identificação do autor
  • Não use se não confia na fonte
  • Use um servidor Docker Registry próprio
  • Verifique a assinatura da imagem

Vulnerabilidades de segurança presentes na imagem

  • Inspecionar as imagens
  • Atualize para pegar novos patches de segurança
  • Utilize uma ferramenta de scanner de vulnerabilidades
  • Integre esse scanner como etapa do seu CI/CD

Ferramentas de análise de segurança e hacking

Até aqui vimos algumas preocupações que devemos ter e algumas soluções relacionadas a segurança quando usamos containers, agora vamos ver algumas ferramentas que podem nos auxiliar e muito no nosso dia-a-dia.

Docker Security Scanning

Anteriormente conhecido por Projeto Nautilus, a solução fornece um perfil de segurança detalhado das imagens Docker com objetivo de tornar o ambiente em conformidade com as melhores práticas. A ferramenta faz uma varredura das imagens antes de serem utilizadas e monitoramento de vulnerabilidades. Esta ferramenta está disponível no Docker Hub, Store e Cloud.

No Docker Hub por exemplo está disponível para as imagens oficiais e pode ser visto o nível de vulnerabilidade destas imagens ao acessar as tags.

Ao clicar em uma das tags é possível identificar em qual camada está esta vulnerabilidade.

Abaixo algumas ferramentas separadas por projetos Open Source e Aplicações Web gratuitas ou pagas. São ferramentas que podem auxiliar no dia-a-dia na verificação de vulnerabilidades.

Ferramentas Web

  • Anchore – anchore.io – Descubra, analise e certifique as imagens e containers
  • Image Layers – imagelayers.io – Inspeciona as imagens dos containers e seus metadados
  • Micro Badger – microbadger.com – Inspeciona as imagens dos containers e seus metadados
  • Quay – quay.io – Constrói, analisa e distribui imagens de containers
  • Twistlock – twistlock.com – Segurança para containers Docker, Kubernetes e mais
  • Aqua – aquasec.com – Plataforma de segurança para containers

Ferramentas Open Source

  • Docker Bench for Security – https://dockerbench.com/ – O Docker Bench for Security é um script que verifica dezenas de melhores práticas comuns em torno da implantação de containers Docker na produção.
  • Open Scap – open-scap.org – Esta ferramenta faz revisão de imagens e containers para identificar vulnerabilidades.
  • Docke Scan – github.com/kost/dockscan – Esta ferramenta faz scanner de imagens Docker para identificar vulnerabilidades.
  • Docker Scan – github.com/cr0hn/dockerscan – Esta ferramenta faz scanner de imagens Docker para identificar vulnerabilidades e também possui funcionalidade para injetar vulnerabilidades.

Isso é tudo por enquanto, mas se você conhece outras dicas ou ferramentas que não são mencionadas aqui, deixe um comentário abaixo. Obrigado pela leitura e um grande abraço!

 

Docker – Device mapper

Olá pessoal,

No primeiro post da série falamos sobre AUFS e hoje vamos falar um pouco sobre Device Mapper.

Origem

No começo o Docker era suportado apenas em distribuições Ubuntu, Debian e usavam AUFS para o seu armazenamento. Depois de algum tempo o Docker começou a se popularizar e as pessoas começaram a querer utilizar Docker com RedHat, porêm o AUFS era suportado apenas em sistemas (Debian,Ubuntu).

Então os engenheiros da Redhat baseados no código do AUFS decidiram desenvolver uma tecnologia própria de armazenamento baseado no já existente “Device mapper”. Então os engenheiros da RedHat colaboraram com o “Docker inc” para contribuir com um novo driver de armazenamento para containers. Então o Docker foi reprojetado para fazer a conexão automática com o dispositivo de armazenamento baseado em Device Mapper.

Layers

O Device Mapper armazena cada imagem e container em seu disco virtual, esses discos virtuais são dispositivos do tipo Copy-on-Write no nível de bloco e não a nível de arquivo. Isso significa que ao invés do Device Mapper copiar todo um arquivo para o seu dispositivo, ele vai copiando por blocos o que o torna muito rápido comparado ao AUFS. No processo de criação de uma imagem com o Device Mapper é criado um pool e em cima desse pool é criado um dispositivo base que é a partir dele que as imagens são construídas, a partir dai temos as imagens base do Docker que a cada modificação vão criando camadas de snapshots a cima da camada anterior. Conforme a imagem abaixo:

https://docs.docker.com/engine/userguide/storagedriver/images/two_dm_container.jpg

Read

Quando um container deseja ler algum arquivo que está nas camadas anteriores o Device Mapper cria um ponteiro na camada do container referenciando a camada da imagem onde possui esses dados colocando transferindo esse bloco para a memória do container.

Write

Quando o Docker faz uma alteração no arquivo utilizando Device Mapper esse arquivo é copiado apenas o que sera modificado cada bloco de modificação copiado é de no máximo 64KB. Por exemplo na escrita de um arquivo de 40KB de novos dados para o container o Device Mapper aloca um único bloco de 64KB para o container, caso a escrita seja de um arquivo maior que 64KB então o Device Mapper aloca mais blocos para realizar essa gravação.

O Device Mapper já é padrão nas em algumas distribuições do linux como:

  • RedHat/Centos/Fedora
  • Ubuntu 12.04 e 14.04
  • Debian

Docker e Device Mapper

O Device Mapper atribui novos blocos para um container por meio de uma operação chamada “Allocate-on-Demand”, isso significa que cada vez que uma aplicação for gravar em algum lugar novo dentro do container, um ou mais blocos vazios dependendo do tamanho de gravação terão que ser localizados a partir do pool mapeado para esse container. Como os blocos são de 64KB então muitas gravações pequenas podem sofrer com problemas de performance, pois acaba causando lentidões nas operações. Com isso aplicações que gravam arquivos pequenos sequencialmente podem ter performance piores com Device Mapper do que com AUFS.

Legal né? Se gostou nos ajude divulgando o blog.

Grande abraço!

 

Amazon EKS – Parte 1

Eai gente,

Bora falar de facilidades? Então, o objetivo deste post é trazer uma introdução ao uso da Amazon EKS (Elastic Kubernetes Service), vamos entender melhor o que é essa ferramenta e como você pode começar a “brincar” com ela de forma simples e rápida.

Ahhh mas antes, você sabe o que é Kubernetes? Caso ainda não esteja familiarizado recomendo que leias os posts que fizemos sobre o assunto Segue os links:

Kubernetes Parte 1

Kubernetes Parte 2

Kubernetes Parte 3

O que é o EKS

O Elastic Kubernetes Service nada mais é do que uma forma de você poder ter um cluster (ou mais) de Kubernetes sob demanda e sem a necessidade de administração dos managers (que para muitos é o mais complexo e oneroso dentro do Kubernetes), ou seja, a Amazon mais uma vez disponibiliza mais uma facilidade e tira um peso de quem precisa gerenciar o ambiente, é claro que isso gera outros pontos de atenção, como é o caso do vendor lockin, porém, se bem pensado, pode ser uma decisão que valha a pena.

Como Funciona

O objetivo da Amazon é disponibilizar para você uma infraestrutura completa, inclusive, no caso do EKS, tendo o gerenciamento dos manager sendo realizado pela própria Amazon. 

Fonte: https://aws.amazon.com/pt/eks/

Temos então basicamente três pontos principais nessa arquitetura:

     

Manager

Você não terá acesso a essa estrutura, toda a gerencia e configuração fica por conta da AWS mesmo, então, menos um ponto para se preocupar.

Workers:

São os nós do cluster onde você poderá executar todos os seus conteirners, ou seja, quando você instanciar um novo pod, ele será provisionado em um desses hosts.

Client:

Você precisa ter o binário do kubectl no host para poder geranciar o cluster, e ai que vem um ponto bem legal, você gerencia o cluster de forma transparente, da mesma forma como se fosse um Kubernetes on premise.

Mãos a obra?

A criação do master pode ser realizado utilizando a console da AWS mesmo, CloudFormation ou via CLI, o que veremos hoje será via CLI pois é o mais simples, para isso, você deve ter configurado em seu computador o awscli, para isso, siga os passos: https://docs.aws.amazon.com/pt_br/cli/latest/userguide/cli-chap-install.html, para resumir, se seu host for linux, siga a sequência:

Instale o Python 3:

apt-get/yum install python3

Baixe o pip para instalar o aws cli:

curl -O https://bootstrap.pypa.io/get-pip.py

Instale o pip:

python get-pip.py --user ou python3 get-pip.py --user

Adicione um novo caminho em seu path:

export PATH=~/.local/bin:$PATH
source ~/.bash_profile

Instale o AWS Cli:

pip3 install awscli --upgrade --user

Verifique a instalação:

aws version

Feito isso, você precisa configurar o cli para as credenciais da AWS, para isso, execute os passos:

aws configure

Informe os dados conforme for sendo lhe solicitado e pronto, basta seguir para o próximo passo.

Você precisará configurar o aws-iam-authenticator, para isso, siga:

curl -o aws-iam-authenticator 
https://amazon-eks.s3-us-west-2.amazonaws.com/1.12.7/2019-03-27/bin/linux/amd64/aws-iam-authenticator
chmod +x ./aws-iam-authenticator
mkdir -p $HOME/bin && cp ./aws-iam-authenticator $HOME/bin/aws-iam-authenticator && export PATH=$HOME/bin:$PATH
echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc

Além desses binários, você precisará também ter configurado no host o eksctl, então siga os passos abaixo:

Baixe o eks:

curl --silent --location "https://github.com/weaveworks/eksctl/releases/download/latest_release/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp

mv /tmp/eksctl /usr/local/bin/

Verifique se o eksctl está ok:

eksctl version

Certo, agora você precisará baixar o client do Kubernetes, o kubectl, você pode seguir os passos:

curl -o kubectl.sha256 https://amazon-eks.s3-us-west-2.amazonaws.com/1.13.7/2019-06-11/bin/linux/amd64/kubectl.sha256

chmod +x ./kubectl

mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$HOME/bin:$PATH

echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc

Feito, basta verificar se está ok, execute:

kubectl version --short --client

E agora José?

Agora bora subir esse cluster ai que o pessoal ta louco pra ver funcionando :).

Pra isso, você pode executar o eksctl da seguinte forma:

eksctl create cluster 
--name prod
--version 1.13
--nodegroup-name workers
--node-type t3.medium
--nodes 3
--nodes-min 1
--nodes-max 4
--node-ami auto

Dessa forma o eksctl criará toda a escrutura necessária para o funcionando do cluster, desde VPC até regras de security group, esse novo cluster será formado com 3 instâncias t3.medium. O retono do comando será algo parecido com este:

[ℹ]  using region us-west-2
[ℹ]  setting availability zones to [us-west-2b us-west-2c us-west-2d] 
[ℹ]  subnets for us-west-2b - public:192.168.0.0/19 private:192.168.96.0/19 
[ℹ]  subnets for us-west-2c - public:192.168.32.0/19 private:192.168.128.0/19 
[ℹ]  subnets for us-west-2d - public:192.168.64.0/19 private:192.168.160.0/19 
[ℹ]  nodegroup "standard-workers" will use "ami-0923e4b35a30a5f53" [AmazonLinux2/1.12] 
[ℹ]  creating EKS cluster "prod" in "us-west-2" region 
[ℹ]  will create 2 separate CloudFormation stacks for cluster itself and the initial nodegroup 
[ℹ]  if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=us-west-2 --name=prod' 
[ℹ]  building cluster stack "eksctl-prod-cluster" 
[ℹ]  creating nodegroup stack "eksctl-prod-nodegroup-standard-workers" 
[✔]  all EKS cluster resource for "prod" had been created 
[✔]  saved kubeconfig as "/Users/ericn/.kube/config" 
[ℹ]  adding role "arn:aws:iam::111122223333:role/eksctl-prod-nodegroup-standard-wo-NodeInstanceRole-IJP4S12W3020" to auth ConfigMap 
[ℹ]  nodegroup "standard-workers" has 0 node(s) 
[ℹ]  waiting for at least 1 node(s) to become ready in "standard-workers" 
[ℹ]  nodegroup "standard-workers" has 2 node(s) 
[ℹ]  node "ip-192-168-22-17.us-west-2.compute.internal" is not ready 
[ℹ]  node "ip-192-168-32-184.us-west-2.compute.internal" is ready 
[ℹ]  kubectl command should work with "/Users/ericn/.kube/config", try 'kubectl get nodes' 
[✔]  EKS cluster "prod" in "us-west-2" region is ready

Ahh mas eu quero personalizar… Não se preocupe amigo, o eksctl permite você definir qual VPC vai usar, quais subnet, security group, imagem (desde que homologada pela AWS), chave, dentre outras opções.

Depois de criado o cluster, bem, agora ficou fácil, basta você administrar da mesma forma como se fosse um cluster de Kubernetes instalado ai, nas suas máquinas locais ;).

Valide se tudo está ok com o cluster executando os comandos para verificar os nós do cluster:

kubectl get nodes

Você pode visualizar se foi criado o serviço default também, para isso:

kubectl get svc

O retorno será algo parecido com este:

NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
svc/kubernetes ClusterIP 10.100.0.1 443/TCP 1m

Legal, e agora?

Bem, agora a sua imaginação é limite, encare o EKS como um cluster normal, neste sentido, o deploy de suas apps seguirá o mesmo processo, e caso você queria, pode utilizar outras facilidades da AWS para agilizar a publicação, mas isso é conto para outro post.

Queremos ainda, falar sobre monitoramento no EKS, Logs, e claro, vamos criar e fazer deploy de alguns serviço neste cluster, vamos ver como ficam as questões de segurança, ingress de serviço, dentre outros pontos.

Eai, curtiu? Então manda para alguém que talvez tenha interesse, e claro, fique a vontade para conversamos
Grande Abraço!

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://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

Docker Compose V3

Olá pessoal, tudo bem?

 

Conforme falamos em um post anterior o Docker lançou uma nova versão a 1.13 e nessa nova versão tivemos diversas melhorias e com a entrada dessa nossa versão também tivemos a criação de uma nova versão no Docker Compose que é a v3. Essa nova versão é totalmente compatível com o Docker Swarm que hoje é nativo na mesma engine no Docker, então agora com Docker Compose podemos gerenciar nossos serviços através do Docker Swarm.

Agora com a V3 existe opção chamada deploy que é responsável por realizar as implantações e execução de serviços. Dentro dessa opção temos as seguintes funções:

  • Mode
    • Onde é possível escolher a opção “Global” (Um container por nó de swarm) ou “Replicated” (Onde posso escolher a quantidade de réplicas que estarão distribuídas entre os nós). O padrão é replicated.
    • Replicas
      • replicas: x
    • Global
  • Placement
    • Especifica restrições de posicionamento são elas:
      • node.id = idworker
      • node.hostname = nomeworker
      • node.role = manager ou worker
      • node.lables = nome
      • engine.labels = Sistema Operacional ou Driver
  • Update_config
    • Configura como devem ser as opções de atualizações dos serviços.
    • Parallelism: 5 #O Numero de containers que vão ser atualizados em paralelo.
    • delay: 10s #O tempo entre cada grupo de containers será atualizado
    • failure_action: pause ou continue #O que irá acontecer se a atualização falhar. O padrão é pause.
    • monitor: 0s # Duração após cada atualização para monitorar a falha. O padrão é 0s.
    • max_failure_ratio: #Taxa de falha para atualizar.
  • resources
    • Configura a restrição de recursos
      • limits:
        • cpus: ‘0.5’ # 0.5 representa 50% de um núcleo, porem pode ser 1 ou 1.5 ou 2….
        • memory: ‘512M’ #apenas especificar o prefixo M, G, K….
  • Restart_policy
    • Configura como reiniciar os containers quando eles derem exit.
      • condity: none on-failure any #Por padrão é any
      • delay: 0s #Tempo entre as tentativas de reiniciar o containers #Por padrão é 0s
      • max_attempts: 0 #Quantas vezes irá tentar subir o container antes de desistir #Por padrão é nunca desistir.
      • window: 0s #Quanto tempo demora para decidir se um reinicio foi bem sucedido  #Por padrão é imediatamente,

 

Alem dessas opções, com a entrada da V3 foram descontinuadas as seguintes opções do Docker Compose: volume_driver, volumes_from, cpu_shares, cpu_quota, cpuset, mem_limit, memswap_limit

Agora vamos demonstrar um exemplo de como ficaria o docker-compose.yml com essas opções que mostramos acima.

version: "3"
services:

  redis:
    image: redis
    ports:
      - "6379"
    deploy:
      placement:
        constraints: [node.role == manager]
  nginx:
    image: nginx
    ports:
      - 80:80
    depends_on:
      - redis
    deploy:
      mode: replicated
      replicas: 2
      placement:
        constraints: [node.role == manager]
      resources:
        limits:
          memory: 512M
      restart_policy:
        condition: on-failure
        delay: 10s

Executando o comando docker deploy --compose-file docker-compose.yml nomedastack criamos a stack mencionada acima em nossa estrutura. Após executar esse comando é possível dar um docker stack ls e você poderá ver que a sua stack foi criada, com o nome da sua stack você pode executar o docker stack services nomedastack e poderá ver os serviços criados e qual o seu status.

Então ta pessoal, por hoje era isso, espero que tenham gostado e qualquer dúvida é só deixar um comentário que estaremos felizes em lhe ajudar, nos ajude divulgando o blog obrigado!

 

Docker AUFS

Olá pessoal,

AUFS foi o primeiro controlador de armazenamento em uso com Docker, como beneficio tem uma história longa com Docker. É muito estável, tem grandes implementações no mundo real e possui forte apoio da comunidade, o AUFS possui diversas características que acabam o tornando uma boa escolha para uso com Docker. Entre elas estão:

  • Tempo de inicialização do container rápido
  • Uso eficiente de armazenamento
  • Uso eficiente de memória

Apesar de ter uma ampla capacidade de caracteristicas com Docker, algumas distribuições não possuem suporte ao AUFS, pois ele não está incluído na linha principal do Kernel Linux, no caso do RHEL não é suporte AUFS.

Os tópicos seguintes demonstram algumas características do AUFS e como ele se relaciona com o Docker:

 

Layers de Imagens:

AUFS é um sistema de unificação de arquivos, isso quer dizer que ele leva vários diretórios em um único host linux, colocando um sobre o outro e fornece uma visão unificada desses arquivos para conseguir isso o AUFS usa uma união de montagem.

O AUFS driver de storage do Docker implementa Layers de imagens utilizando usando a união do sistema montado. Abaixo podemos ver um exemplo de Layers, onde para o cliente é apresentado a união de todas elas:

 

layer1

 

Utilizando arquivos:

O Docker utiliza a tecnologia de “AUFS CoW”  para conseguir compartilhar a imagem e minimizar o uso de disco. Como o AUFS trabalha em nível de arquivos então todos os dados são copiados por inteiros para a camada superior mesmo que modificando uma pequena parte do arquivo, isso faz com que dependendo do tamanho de arquivo que será copiado acabe penalizando um pouco o desempenho do container, pois um arquivo muito grande demorará algum tempo para que seja copiado. Ou também a imagem possui uma grande quantidade de camadas e o arquivo que você deseja utilizar está na primeira camada da imagem.

A ordem de procura é de cima para baixo, então caso seja a primeira vez que o usuário irá utilizar aquele arquivo, então o Docker vai procurar esse arquivo nas suas camadas abaixo e copiar todo o seu conteúdo para a camada gravável do container. Porém o arquivo só é copiado na primeira vez, após isso o esse arquivo já está na ultima camada então todas as demais operações são rápidas.

Deletando arquivos:

O driver do AUFS exclui um arquivo de dentro do container colocando um arquivo whiteout na camada gravável do container. O arquivo whiteout obscurece a existência do arquivo nas camadas inferiores de imagem:

 

 

layers2

 

 

Você pode adicionar o driver AUFS no seu daemon docker editando o arquivo de conf do docker e adicionando:

DOCKER_OPTS="--storage-driver=aufs"
systemctl restart docker

 

Então ta pessoal esse é nosso primeiro post dessa série que vai mostrar para vocês os drivers de armazenamento nativos do Docker.

 

Docker Stack e Deploy

Oi Pessoal,

Nós já conversamos sobre o Docker 1.13 aqui, agora vamos explorar um pouco mais sobre essa funcionalidade que saiu do modo experimental e tornou-se parte da engine estável do Docker, sim estamos falando do docker stack/deploy. Mas antes, recomendo fortemente você ler este post aqui sobre docker compose v3, ele é muito, mas muito importante mesmo para os exemplos que veremos neste post.

Agora com o Docker 1.13 é possível você portar suas aplicações do compose para o Swarm, e isso graças a funcionalidade de deploy disponível na engine. Seu funcionamento é bem simples, basta você informar na execução do comando o diretório de onde está o seu arquivo compose, e o nome da aplicação, se lembra que falei que era muito importante olhar esse post? Pois bem, não adianta você ter um compose escrito para a versão 2 e tentar utilizar aqui, será necessário você se altere para as novas regras da versão 3 para que seja possível a criação de sua stack pelo docker deploy. Mas digamos que você já tem seu arquivo pronto na versão 3, vamos pegar o exemplo do outro post, basta executar:

$ docker deploy --compose-file docker-compose.yml app

O retorno desse comando será

$ docker deploy --compose-file docker-compose.yml app
Creating network app_default
Creating service app_nginx
Creating service app_redis

Dessa forma foram criados uma rede e dois serviços, o mesmos definidos no arquivo compose. Para obter mais informações da stack, você pode executar os comandos:

$ docker stack ls
NAME SERVICES
app 2

Com o stack ls, será retornado todas as stacks que você criou, neste caso retornou apenas a “app” e informa também quantos serviços existem para essa stack, com este comando:

$ docker stack ps app
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
xb02xrua71db app_redis.1 redis:latest node1 Running Running 7 minutes ago
lm7k8obhncyl app_nginx.1 nginx:latest node1 Running Running 7 minutes ago
jh65f9scx0cq app_nginx.2 nginx:latest node1 Running Running 7 minutes ago

Você visualizará mais informações sobre a stack, como por exemplo o id de cada container, imagem utilizada, nome do container, nó onde está executando e claro o estado de cada container. Você pode ainda, executar o comando:

$ docker stack services app
ID NAME MODE REPLICAS IMAGE
g3i4f4erympf app_nginx replicated 2/2 nginx:latest
s11w093eraxz app_redis replicated 1/1 redis:latest

Para ter a visualização de sua stack no mesmo formato dos serviços (docker service ls).

O que fizemos até aqui foi portar uma stack do docker-compose para o cluster de swarm.

 

“Ahh mas como assim?”

Bom se você pegar esse mesmo arquivo de compose e executar: docker-compose up -d, ele funcionará também, sem erro, sua stack iniciará e ficará disponível para uso, MAS, não em cluster :), você continuará utilizando o docker-compose da mesma forma que antes, sem os benefícios do Swarm. Apenas com o docker deploy é que você poderá fazer o deploy e gerenciamento de sua stack dentro do cluster de swarm.

“Ok, entendido, mas como eu escalo agora a minha stack? Antes eu executava: docker-compose scale app=3, como faço isso com o docker stack?”, não se preocupe, você continuará tendo a possibilidade de escalar a sua stack, vamos lá: Já sabemos que o docker deploy criar todos os serviços necessários para a stack, certo? Pois bem, para escalar algum componente da sua stack, basta você escalar o serviço, da mesma forma como se você estivesse manipulando um serviço dentro do swarm, veja:

$ docker service ls
ID NAME MODE REPLICAS IMAGE
cnnabnpqkjvy app_redis replicated 1/1 redis:latest
pcn4urntqn8l app_nginx replicated 2/2 nginx:latest

Agora vamos escalar o serviço de nginx da minha stack app:

$ docker service scale app_nginx=4
app_nginx scaled to 4

E o resultado é:

$ docker service ls
ID NAME MODE REPLICAS IMAGE
cnnabnpqkjvy app_redis replicated 1/1 redis:latest
pcn4urntqn8l app_nginx replicated 4/4 nginx:latest

Ou seja, escalei apenas o nginx.

 

“Ok, muito bonito, mas como eu acesso a minha stack?”

Boa pergunta, mas é claro que há uma resposta, e é aqui que vem a parte mais legal ;).

Vamos voltar ao docker-compose.yml que usamos para criar essa stack, veja essas linhas:

nginx:
    image: nginx
    ports:
        - 80:80

Preste atenção no parâmetro: ports, ali você define em qual porta o serviço vai ouvir, neste caso, o nginx estará trabalhando na porta 80, ou seja, o serviço no cluster de swarm estará disponível para acesso através da porta 80, e todos os nós do cluster, quando receberem alguma requisição na porta 80 encaminharão para o container que atende este serviço (utilizando uma das funcionalidade do docker swarm que é a rede de serviço em mesh).
Quando escalamos um serviço, dizemos ao docker para adicionar mais containers para atender as requisições que estarão sendo feitas para o mesmo, ou seja, teremos diversos containers atendendo um único recurso que é o serviço, e o swarm se encarrega de distribuir os acessos para todos os containers.

 

“Ta bom, me convenceu, mas como removo tudo agora pra fazer direito?”

Muito fácil, da mesma forma que o docker service, basta você executar:

$ docker stack rm app
Removing service app_redis
Removing service app_nginx
Removing network app_default

E serão removidos todos os serviços, containers e rede que tenham sido criadas pela sua stack.

Interessante não? Esperamos que tenha sido útil, se ficou com dúvida nos avisa que ajudamos. Por hoje era isso, nos ajude divulgando o blog e fique atento, teremos mais novidades em breve ;).

Abraço!

 

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!

Cluster Mongo em Docker

Opa!

Hoje o post será mais prático, e queremos trazer para vocês uma forma de criar um cluster de MongoDB utilizando Docker. O próprio Docker tem um tutorial de como você pode criar a sua imagem de mongo e executá-lo dentro do Docker, para quem não viu ainda, segue o link. Para quem não conhece, MongoDB é um tipo de banco de dados orientado a documentos ou seja, utiliza o conceito de dados e documentos auto contidos e auto descritivos, e isso implica que o documento em si já define como ele deve ser apresentado e qual é o significado dos dados armazenados na sua estrutura.

O MongoDB também é chamado de banco de dados NoSql, mas isso é outro assunto . O que veremos neste artigo é como você pode montar um cluster de instâncias do mongo utilizando como backend containers Docker. Isso é possível pois o existe na “caixa” do mongo algumas formas de se construir um cluster, uma delas é utilizando o método de replica set, que consiste em ter instâncias  para onde a informação será replicada, e dessa forma garantir a persistência das informações, abaixo segue uma imagem ilustrativa de como isso funciona:

Dessa forma garantimos a persistência e tolerância a falha dos dados que estão sendo armazenados. Neste post mostraremos como utilizar essa abordagem, não entraremos em detalhes mais fundos do Mongo pois não é este o objetivo.

Vamos lá?

Antes de tudo, é recomendável que os servidores possam ser acessíveis via nome, caso não seja possível, você pode adicionar nos hosts os endereços para que isso seja temporariamente possível.

Em seguida precisamos criar o diretório no host onde será persistido os dados do banco:

$ mkdir /opt/mongo
$ mkdir /opt/mongo/data $ cd /opt/mongo

É importante lembrar que essas pastas devem estar criadas em todos os nós, para que dessa forma seja possível persistir os dados em todos os nós.

Agora você precisa gerar uma chave que será utilizada para realizar a sincronia entre as replicas, e garantir que os dados além de trafegar de forma segura, estejam replicados entre todos os nós, essa chave deve ser copiada para todos os nós também.

$ openssl rand -base64 741 > mongodb-keyfile $ chmod 600 mongodb-keyfile $ chown 999 mongodb-keyfile

Configurado este arquivo, precisamos subir um container para realizar algumas tarefas administrativas, para depois subir o cluster propriamente dito:

$ docker run --name mongo -v /opt/mongo/data:/data/db -v /opt/mongo:/opt/keyfile --hostname="node1" -p 27017:27017 -d mongo:2.6.5 --smallfiles

Vamos as configurações agora:

$ docker exec -it mongo /bin/bash
root@node1:/# mongo
> use admin
db.createUser( {
     user: "admin",
     pwd: "SENHA_DE_ADMIN",
     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
   });

db.createUser( {
     user: "root",
     pwd: "SENHA_DE_ROOT",
     roles: [ { role: "root", db: "admin" } ]
   });
> exit
root@node1:/# exit

Remova o container para que possamos agora subir o ambiente todo:

$ docker stop mongo
$ docker rm mongo

Agora sim vamos subir o ambiente:

$ docker run --name mongo -v /etc/hosts:/etc/hosts -v /opt/mongo/data:/data/db -v /opt/mongo:/opt/keyfile --hostname="node1" --add-host node1.db:${node1} --add-host node2.db:${node2} --add-host node3.db:${node3} -p 27017:27017 -d mongo:2.6.5 --smallfiles --keyFile /opt/keyfile/mongodb-keyfile --replSet "rs0"

Acesse este container para inicializar o cluster:

$ docker exec -it mongo /bin/bash
root@node1:/# mongo
> use admin
> db.auth("root", "SENHA_DE_ROOT");
> rs.initiate()
{
         "info2" : "no configuration explicitly specified -- making one",
         "me" : "node1.db:27017",
         "info" : "Config now saved locally.  Should come online in about a minute.",
         "ok" : 1
}

> rs0:PRIMARY> rs.conf()
{
        "_id" : "rs0",
        "version" : 1,r
        "members" : [
              {
                  "_id" : 0,
                  "host" : "node1.db:27017"
              }
        ]
}

Nos demais nós, suba os containers da seguinte forma:

Servidor 2

$ docker run --name mongo -v /etc/hosts:/etc/hosts -v /opt/mongo/data:/data/db -v /opt/mongo:/opt/keyfile --hostname="node2" -p 27017:27017 -d mongo:2.6.5 --smallfiles --keyFile /opt/keyfile/mongodb-keyfile --replSet "rs0"

Servidor 3

$ docker run --name mongo -v /etc/hosts:/etc/hosts -v /opt/mongo/data:/data/db -v /opt/mongo:/opt/keyfile --hostname="node3" -p 27017:27017 -d mongo:2.6.5 --smallfiles --keyFile /opt/keyfile/mongodb-keyfile --replSet "rs0"

Volte até o servidor 1, acesse o container de mongo e execute os comandos:

$ docker exec -it mongo /bin/bash
root@node1:/# mongo
> use admin
> db.auth("root", "SENHA_DE_ROOT");
> rs0:PRIMARY> rs.add("node2.db") 
> rs0:PRIMARY> rs.add("node3.db") 
> rs0:PRIMARY> rs.status()

O status devem ser algo parecido com este retorno:

rs0:PRIMARY> rs.status()
{
 "set" : "rs0",
 "date" : ISODate("2017-05-16T15:43:30Z"),
 "myState" : 1,
 "members" : [
 {
 "_id" : 0,
 "name" : "node1:27017",
 "health" : 1,
 "state" : 1,
 "stateStr" : "PRIMARY",
 "uptime" : 578713,
 "optime" : Timestamp(1494371417, 1),
 "optimeDate" : ISODate("2017-05-09T23:10:17Z"),
 "electionTime" : Timestamp(1494371963, 1),
 "electionDate" : ISODate("2017-05-09T23:19:23Z"),
 "self" : true
 },
 {
 "_id" : 1,
 "name" : "node2.db:27017",
 "health" : 1,
 "state" : 2,
 "stateStr" : "SECONDARY",
 "uptime" : 577454,
 "optime" : Timestamp(1494371417, 1),
 "optimeDate" : ISODate("2017-05-09T23:10:17Z"),
 "lastHeartbeat" : ISODate("2017-05-16T15:43:29Z"),
 "lastHeartbeatRecv" : ISODate("2017-05-16T15:43:29Z"),
 "pingMs" : 0,
 "syncingTo" : "node1:27017"
 },
 {
 "_id" : 2,
 "name" : "node3.db:27017",
 "health" : 1,
 "state" : 2,
 "stateStr" : "SECONDARY",
 "uptime" : 577354,
 "optime" : Timestamp(1494371417, 1),
 "optimeDate" : ISODate("2017-05-09T23:10:17Z"),
 "lastHeartbeat" : ISODate("2017-05-16T15:43:29Z"),
 "lastHeartbeatRecv" : ISODate("2017-05-16T15:43:29Z"),
 "pingMs" : 0,
 "syncingTo" : "node1:27017"
 }
 ],
 "ok" : 1
}
rs0:PRIMARY>

Caso tenha ocorrido algum erro na sincronização das informações, você poderá visualizar através deste retorno, e claro terá informações para realizar a correção do caso. Existem muitas maneiras de realizar esse tipo de configuração de cluster, algumas mais complexas e outras mais simples, em nosso teste esta foi a forma onde tivemos mais objetividade e assertividade na configuração, baseado nessas informações você pode montar/adaptar os passos que atendem a sua demanda.

Um ponto muito importante nesse ambiente é a forma como ocorre a recuperação em caso de desastre, pois você pode parar o master (primário) e você poderá ver através do rs.status(); o comportamento do cluster elegendo um novo master, ou seja, dessa forma seu cluster ficará quase que 100% a prova de falhas ;).

Esperamos ter ajudado, e se tiver alguma dificuldade ou dúvida com relação a este ambiente por favor entre em contato conosco para que possamos ajudar o/. E como sempre, nos ajude divulgando o blog, isso é muito importante para nós.

Grande abraço!

Oito dicas sobre Docker

Oi Gente!

Sendo este o primeiro post com conteúdo sobre Docker para o ano de 2017, tivemos a ideia de trazer a vocês algumas dicas e informações que consideramos de muita importância. Para isso fizemos um com uma apresentação sobre essas dicas, explicando cada uma dela e contando um pouco sobre como elas resolvem ou ajudam em determinadas situações. Vamos ao vídeo?

 
Para você que não conseguiu ver o vídeo, disponibilizamos também a apresentação em nosso canal no slideshare, acompanhe:

 

Viu, não deixamos passar nada

Aguarde pois este ano teremos diversas novidades aqui no blog, garanto que vocês vão gostar.

 

Grande abraço!

Docker 1.13 – O que vem por ai

Eai gente!

Você que é leitor do blog já está acostumado a ver por aqui as principais novidades sobre o Docker e tecnologia associadas, e hoje não será diferente. Queremos trazer uma preview sobre as novas features que serão lançadas na versão 1.13 do Docker, como todos os sabem, o ciclo de desenvolvimento dentro do Docker é algo fora da curva, e a cada nova versão alguma novidade aparece, é possível acompanhar esse ritmo pelo próprio github deles.

Mas se você não quiser esperar a versão estável para brincar com as novidades, pode utilizar a versão experimental do Docker, que obviamente não é recomendado para se colocar em produção, mas que pode ser usada para lab sem problema. Para isso, basta você instalar o Docker com o seguinte comando: curl -sS https://experimental.docker.com | sh, com isso você terá acesso a engine com as modificações mais atuais mas em fase de desenvolvimento ainda.

Bom, chega de papo, vamos a uma pequenas lista das novidades do Docker 1.13:

 

Docker stack

Para quem usa docker-compose ou docker service sabe das diferenças entre essas duas “ferramentas”, e como de certa foram eles deveriam se complementar, não é mesmo? E Essa é uma situação que vinha sendo trabalhada pelos engenheiros do Docker a algum tempo, essa função intermediária vinha sendo testada através do comando docker stack que possibilita criar um serviço dentro do swarm baseado em uma estrutura do docker-compose, ou seja, você conseguirá portar para o cluster de swarm um serviço baseado no docker-compose, isso facilita em muito a administração de seu serviço e claro no deploy do mesmo, pois garante que o serviço esteja rodando independente do nó onde ele está.

Nas versões de teste você tinha que gerar um arquivo .dab (distributed application bundle ou pacote de aplicação distribuída) baseado em seu docker-compose.yml e depois sim você conseguiria fazer deploy dessa stack utilizando o docker. Agora no docker 1.13 isso não é mais necessário, basta você chamar o arquivo docker-compose.yml diretamente no deploy da stack, algo como isso:

# docker stack deploy --compose-file ./docker-compose.yml minhastack

Muito mais simples e rápido não?

 

Gerenciamento de senha

Ou gerenciamento de segredos, essa é uma função básica dentro de qualquer orquestrator, o Kubernetes já possuía esse conceito e aplicação á algum tempo já, e agora o docker também implementa essa funcionalidade.
Mas afinal, onde vou usar isso? Sua aplicação usa senha não usa? Seja para banco, API, etc, qualquer aplicação usa senha de acesso a algum serviço em algum momento, e com você faz hoje com Docker? Provavelmente via variável de ambiente ou compartilhando um arquivo com o container, existem outras formas, como ferramentas as a service de gerenciamento de identidade.

Agora no docker 1.13 você pode definir uma secret que pode ser utilizada pelo seu serviço dentro do swarm, exatamente da mesma forma que o Kubernetes usa. Para isso foram adicionados quatro comandos novos, são eles:

  • docker secret create
  • docker secret inspect
  • docker secret ls
  • docker secret rm

Veja um exemplo de como criar uma secret para ser utilizada dentro de seu serviço

# echo "123456" | docker secret create senha-banco

Agora um exemplo de como utilizar essa secret em seu serviço:

# docker service create --name app --secret senha-banco ubuntu

Dentro do container será criado um arquivo em /run/secrets/senha-banco com a informação da senha, isso é claro apenas dentro do container, sem precisar mapear nada do host para o container.

# docker exec -it app cat /run/secrets/senha-banco
123456

Um detalhe muito importante é: As secrets podem ser utilizadas apenas dentro de serviços, se você criar um container com o docker run, vão não poderá utilizar essa funcionalidade.

 

Novo parâmetro de rede no Swarm

Essa talvez seja uma das melhorias mais importante no core do docker, pois permite que você adicione uma rede do Swarm mesmo se o container for criado fora de um serviço, ou seja, criado da forma tradicional com o docker run.... Mas afinal, por que isso é importante? É importante porque agora é possível adicionar um container a mesma rede do serviço criado no Swarm, isso é muito útil para debugs ou até mesmo testes de ambiente.

E como fica agora então? Simples, veja:

# docker network create --driver overlay --attachable rede-plugavel

Com o comando acima nós criamos uma rede overlay do Swarm, e a diferença agora é o parâmetro –attachable, que permite que essa rede seja plugada em qualquer container criado, e no comando abaixo nós plugamos um container a essa rede:

# docker run --rm -it --net rede-plugavel centos ping google.com

 

Plugins

Finalmente alguns plugins que estavam sendo testados e aprimorados foram disponibilizados como estáveis dentro da engine do Docker. Dentre ele podemos destacar o Flocker e o Weave, que agora tem integração total com docker.

 

Docker Daemon –experimental

Até então para você poder utilizar comandos e opções em desenvolvimento/teste do docker, você teria que instalar a versão experimental ou test da engine, mas agora basta você iniciar o daemon do docker com a opção –experimental, com isso será habilitado em momento de execução as opções da versão experimental, veja:

 

Melhorias no docker service

Essas, na verdade, são algumas das melhorias que a comunidade pediu ao longo do meses, uma delas tem relação com o update da imagem no update do serviço, para quem não notou, quando um serviço é atualizado (até então) você precisava executar um update com alguns parâmetros a mais para poder atualizar o serviço com uma nova imagem, na nova versão esse processo pode ser feito passando o parâmetro –force junto, o docker service update já verificará se há uma versão mais recente da imagem e atualizará o serviço baseado nisso.

 

Novo parâmetro no docker service

Além das melhorias no docker service, foi acrescentado também um novo parâmetro. Hoje nós acessamos um serviço através da porta exposta do mesmo, que você pode definir com o parâmetro –publish, no docker 1.13 será possível você definir de forma mais detalhada essa regra, isso deve-se ao novo parâmetro –port, que, da mesma forma que o –mout, tem sintaxe parecida com csv, onde você define item=valor,item=valor… Veja um exemplo:

# docker service create --name servico_web --port mode=ingress,target=80,published=8080,protocol=tcp

Dessa forma você tem, de forma mais clara, as definições de porta do serviço.

 

Outras novidades

Dentre outras novidades do docker 1.13 podemos destacar ainda algumas que tem bastante relevância para quem o utiliza, como por exemplo:

  • Cache de Layer para o Build: Para que gera muitas imagens, sabe que esse era um problema a ser resolvido, exemplo: geramos um imagem agora com o docker build, caso tenha que modificar essa imagem todas as layers anteriores a alteração não eram buildadas novamente, o docker build usava o cache para elas. Agora digamos que mandamos essa imagem para outro host e queremos fazer outra modificação nela, o que ocorre? Exatamente, todas as layers são buildadas novamente, isso pelo fato do docker não ter naquele host o cache de build dessa imagem. Parece ser trivial, mas quando se quer ganhar tempo, não é. No docker 1.13 você pode especificar na hora do build de onde o docker poderá buscar o cache de build, como por exemplo:
    docker pull imagem:v1.0
    docker build --cache-from imagem:v1.0 -t imagem2:v1.1 .
    

    Dessa forma o build da nova imagem utilizará o cache da imagem original, compilando assim apenas as layers diferentes.

  • A instrução MAINTAINER  foi removida do Dockerfile, agora essa informação deve ser utilizada através de label;
  • Foi adicionado um novo comando, ainda experimental, que é o docker service logs para visualizar os logs do serviço e não do container em si.
  • Outra adição do docker service foi o parâmetro –rollback que tem por objetivo realizar o update do serviço através de uma versão anterior a atual;
  • Remoção de container velhos através do docker system (ainda não há mais informações sobre como esse comando funcionará para remoção de containers antigos, então ficamos ligados no lançamento)

 

Ok Cristiano, e quando será lançada? Não há uma data 100% definida, o que se sabe é que será lançada até inicio de Janeiro de 2017, então pode ser que seja lançada hoje mesmo . Pode haver mais modificações? Claro, sempre há e com certeza as novidades que trouxemos hoje serão melhor explicadas após o lançamento oficial, então o jeito é ficar ligado aqui no blog e claro no site do ofiical do docker.

 

Grande abraço!

 

 

Docker Overlay

Oi Pessoal,

Como vimos nesse post, é possível utilizar plugins diversos para resolver o desafio da rede, e mostramos nesse post um pouco da teoria de como usar o driver de overlay, hoje queremos mostrar isso na prática, e para isso, nada melhor do que colocar a mão na massa, certo?  Claro, mas antes precisamos entender um pouco de teoria, e lá vamos nós.

Se você estiver utilizando o Swarm, não é necessário configurar um serviço de chave-valor externo, pois o próprio Swarm faz o controle e persistência das informações de rede que você utiliza. E você deve ter cuidado, pois se quiser utilizar o Overlay com um serviço externo de chave-valor, o modo de cluster via Swarm fica impossibilitado.

Veja abaixo uma tabela com algumas informações relevantes sobre o funcionamento do Overlay:

Protocolo Porta Descrição
udp 4789 Data plane (VXLAN)
tcp/udp 7946 Control plane

Ou seja, você deve cuidar para que em seus firewalls essas portas estejam liberadas, caso contrario a comunicação entre os nós não ocorrerá, o que impossibilitará o funcionando do Overlay.

Veja abaixo os principais parâmetros que você deve ter atenção:

Opção Descrição
--cluster-store=PROVIDER://URL
Endereço do seu servidor/serviço de chave-valor
--cluster-advertise=HOST_IP|HOST_IFACE:PORT
IP ou interface do host que será utilizado para comunicação do cluster
--cluster-store-opt=KEY-VALUE OPTIONS
Configuração opicional, onde é possível definir regras de monitoramento dos hosts e validação TLS

Ok Cristiano, entendi tudo isso, mas como vamos testar, qual será o ambiente de laboratório que vamos seguir? Vamos lá, para exemplificar como será o ambiente que vamos montar, segue abaixo uma imagem onde ilustra o funcionamento do Docker com o serviço de chave-valor, todos os hosts consultam esse serviço para identificar quais redes existem e qual bloco/ip deve ser alocado por container. Veja:

Engine on each host

Vamos colocar a mão na massa?

Dependências/Configuração

Você deve ter um serviço de chave valor, no qual o Docker persistirá as informações de rede que você criar, em nosso lab utilizamos o Consul dentro de um container Docker, rodando em um server a parte dos que participarão do ambiente multi-host, para isso executamos:

[root@consul ~]# docker run -d  -p "8500:8500"  -h "consul"  progrium/consul -server -bootstrap

Dessa forma iniciamos um container com Consul, mapeando a porta 8500 do host para o container, ou seja, para ter acesso ao serviço do Consul basta acessar ip-do-host:8500. Agora vamos ao nosso ambiente de Docker.

Nos hosts de Docker (obviamente você já tem o Docker instalado, mas se quiser saber como instalar, veja esse post ) você precisará configurar o daemon para consultar o Consul e buscar as informações de rede, em nosso laboratório utilizamos o CentOS, com isso, o arquivo a ser modificado é o: /lib/systemd/system/docker.service, e deixamos da seguinte forma:

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock --cluster-advertise=eth0:2376 --cluster-store=consul://ip-do-consul:8500
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process

[Install]
WantedBy=multi-user.target

Feito isso, basta reiniciar o serviço e seguirmos para o próximo passo.

Utilização/Testes

Agora que você já definiu um serviço de chave-valor a ser consultado, basta você criar a sua rede com o driver Overlay, para isso:

[root@docker01 ~]# docker network create --driver overlay rede1

Você pode definir ainda qual o bloco de ip que deseja para essa rede, caso não faça essa definição, o Docker associará um bloco automaticamente para você. Fácil certo? Basta testarmos, para isso vamos validar em todos os hosts se ambos estão visualizando a mesma rede, execute esse comando em qualquer outro host:

[root@docker01 ~]# docker network ls

Será retornando algo como isso:

NETWORK ID          NAME                DRIVER
64507d0be843f        rede1               overlay
d0bdae8fbe7bd        bridge              bridge
1c0eb8f68962d        none                null
3412c2496d0eb        host                host
697102a22e8d2        docker_gwbridge     bridge

 Vamos utilizar essa rede, crie os containers em pelo menos 2 hosts, informando essa nova rede, veja:

[root@docker01 ~]# docker run -it --net=rede1 centos /bin/bash

Agora basta pingar ou acessar os serviços entre os containers que estão nessa mesma rede.

Dessa forma você pode definir uma rede diferente por grupo de containers, e pode ainda isolar essas redes utilizando o método VXLAN, para isso deve passar como parâmetro na criação da rede o seguinte argumento: –opt “com.docker.network.driver.overlay.vxlanid_list=257″, esse parâmetro fará com que essa rede receba uma vlan, ou seja, todo o trafego direcionado a essa rede receberá uma identificação, impossibilitando que outros containers que não estejam nessa vlan tenha acesso a esse trafego. 

Legal né? Se gostou nos ajude divulgando o blog.

Grande abraço!

Kubernete parte III

Olá pessoal,

 

Depois de algum tempo sem falar sobre Kubernetes hoje vamos mostrar como podemos criar um ambiente altamente disponível de servidores web.

Conforme comentado nos posts anteriores, podemos criar um service Web e dentro desse service eu posso ter milhões de containers, onde o Kubernetes fará toda a parte de Balanceamento de carga com o que chamamos de Replication Controller.

Vamos criar então o Replication Controller:

 

vim web-rc.yml

apiVersion: v1
kind: ReplicationController 
metadata:
 name: web-controller
spec:
 replicas: 2
 selector:
   name: nginx
 template:
   metadata:
     labels:
       name: nginx
   spec:
     containers:
       - name: nginx
         image: nginx
         ports:
           - containerPort: 80

kind: É o tipo de objeto que o Kubernetes ira criar, nesse caso ele vai criar

Replicas: Quantos pods dessa imagem sempre deve existir, caso exista um número menor que o indicado, o Kubernetes irá criar outros pods até chegar ao número determinado em replicas.

 

Para criar o Replication Controller execute:

kubectl create -f web-rc.yml

 

Você poderá ver RC criado com o comando:

kubectl get replicationcontrollers

 

Agora vamos criar o Service que é aquele que faz com que o usuário consiga criar a aplicação:

 

vim web-service.yml

kind: Service
apiVersion: v1
metadata:
  name: web-service
spec:
  selector:
    name: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
kubectl create -f web-service.yml

Feito isso você pode executar o comando abaixo e verá que existe 2 pods de Nginx rodand:

kubectl get pods

Com tudo isso pronto você pode pegar e testar executando um curl no ip do seu servidor, no meu caso estou executando a partir do minion1, então vou acessar o minion2 e executar:

curl -qa http://seuip

E a página inicial do nginx será mostrada, você pode pegar e parar um pod e notará que o Kubernetes irá criar outro, pois no Replication Controller colocamos como 2 replicas.

Então tá pessoal por hoje era só, continue ligado em nosso canal e em breve estaremos fazendo um vídeo mostrando mais sobre o Kubernetes.

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/ 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.

Traefik e Docker Swarm

Opa!

Acreditamos que um dos maiores desafios quando se trabalha com alguma tecnologia de cluster, é a forma como você vai disponibilizar o conteúdo para seu usuário/cliente, obviamente isso pode ser feito de diversas maneiras, e cada uma delas atender a uma necessidade e objetivo.

A intenção hoje é trazer à vocês uma forma simples de se disponibilizar conteúdo web (site, api, etc.) e que tem como backend o Docker Swarm, sim, hoje falaremos do Traefik, um poderoso proxy web dinâmico. Antes disso, temos que responder a seguinte dúvida: Por que diabos preciso de um proxy reverso dinâmico? Simples, por que as implementações atuais de Apache, Haproxy e Nginx foram desenvolvidas para serem estáticos, necessitando de intervenções para que as modificações sejam aplicadas. É claro que existem iniciativas que tratam isso, e são boas alternativas também, como é o caso do docker-flow-proxy e jwilder/nginx mas são presas ao que as tecnologias base oferecerem. No caso do traefik, a situação é bem diferente, ele é um proxy arquitetado e desenvolvimento para ser totalmente dinâmico e orientado a micro-serviços, além disso, ele suporta nativamente diversos tipos de backend, como é o caso do Docker Swarm, Kubernetes, Mesos, Docker apenas, Consul, dentre muitos outros.

Features

Algumas features/benefícios do Traefik, incluem:

  • Veloz.
  • Sem dependência, ele é um binário escrito em go.
  • Existe imagem oficial para Docker.
  • Fornece uma API Rest.
  • Reconfiguração sem a necessidade de reiniciar o processo.
  • Metricas (Rest, Prometheus, Datadog, Statd).
  • Web UI em AngularJS.
  • Suporte a Let’s Encrypt (Com renovação automática).
  • Alta disponibilidade em modo cluster (beta).

O Traefik foi desenvolvido para atender a demanda de requisições web, então ele pode ser utilizado para fazer o roteamento das conexões de um site ou api para o container ou serviço que foi criada para isso. A imagem abaixo é clássica, e explica bem esse comportamento:

Fonte: https://docs.traefik.io

Como pode ser visto, o traefik fica “ouvindo” as ações que ocorrem no orquestrador (independente de qual for) e baseado nessa ações se reconfigura para garantir o acesso ao serviço/container criado. Dessa forma basta você apontar as requisições web (seja http ou https) para o servidor onde o traefik está trabalhando.

Mãos a massa?

Em nosso lab, vamos montar esse ambiente utilizando o Docker Swarm como nosso orquestrador, para isso, tenha pelo menos três hosts, inicialize o Swarm em um deles, e em seguida adicione os demais ao cluster.

Feito isso, precisamos criar um rede do tipo overlay, que será utilizada pelo traefik para enviar o trafego web:

docker network create -d overlay net

Depois de inicializada a rede overlay, basta criar o serviço do traefik:

docker service create --name traefik --constraint 'node.role==manager' --publish 80:80 --publish 8080:8080 --mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock --network net traefik:camembert --docker --docker.swarmmode --docker.domain=mundodocker --docker.watch --logLevel=DEBUG --web

Com este comando, será criado um serviço mapeando o socket do Docker para que o traefik possa monitorar o que acontece neste cluster, além disso são expostas as porta 80 (para acesso dos sites/apis) e 8080 (página administrativa do traefik), caso preciso da 443, basta adicionar a lista.

Ok, até agora o que fizemos foi criar o serviço do traefik no cluster para que monitore e se reconfigure baseado nos eventos do cluster. Agora precisamos criar nossos serviços web e ver se tudo funcionará como deveria. Vamos lá:

Blog:

Vamos criar agora uma nova aplicação web, que será responsável por um blog, o processo de criação é bem simples:

docker service create --name traefik --label 'traefik.port=80' --label traefik.frontend.rule="Host:blog.mundodocker.com.br;" --network net ghost

Criamos um serviço com nome de blog, utilizando uma imagem do WordPress e adicionamos na rede “net”, essa mesma rede onde o traefik está, agora vamos detalhar os novos parâmetros:

  • traefik.port = Porta onde a aplicação vai trabalhar, nos caso do wordpress, será na porta 80 mesmo.
  • traefik.frontend.rule = Qual será o virtual host que este serviço atende, com isso o traefik consegue definir que, quando chegar uma requisição para: blog.mundodocker.com.br, encaminhará as requisições para o serviço correto.

Agora basta apontar no DNS a entrada blog.mundodocker.com.br para o servidor do traefik e a mágica estará feita.

Site:

Para ver como é difícil, tudo que você precisa fazer é executar este comando:

docker service create --name site --label 'traefik.port=80' --label traefik.frontend.rule="Host:mundodocker.com.br;" --network net tutum/apache-php

Dessa vez criamos um novo serviço, na mesma rede, mas com alguns parâmetros diferentes, como é o caso do traefik.frontend.rule, onde especificamos um novo endereço, e claro a imagem que vamos utilizar, que agora é a tutum/apache-php.

URLs:

Outra feature muito legal do traefik é a possibilidade de redirecionar URLs para backends diferentes. O que isso quer dizer? Quer dizer que podemos enviar partes de uma aplicação para serviços diversos, por exemplo, na aplicação existe um /compras e um /categoria, podemos enviar essas URLs para serviços distintos, isso apenas informando o traefik, veja:

docker service create --name categoria --label 'traefik.port=3000' --label traefik.frontend.rule="Host:mundodocker.com.br; Path: /categoria/" --network net node

Note que agora temos um novo parâmetro, o “Path” onde especificamos qual URL este serviço vai atender, o resto é semelhante, informamos a porta e imagem que este serviço vai utilizar. Para criar um serviço especifico para outra URL, basta:

docker service create --name compras --label 'traefik.port=3000' --label traefik.frontend.rule="Host:mundodocker.com.br; Path: /compras/" --network -net node

E pronto, sua aplicação estará “quebrada” entre vários serviços, e o mais legal é que você não precisou editar um arquivo de configuração se quer. Além dessas facilidades, o traefik ainda disponibiliza uma interface para visualizar como está a saúde das url, em nosso lab você acessará pela porta 8080, e você visualizará algo assim:

Neste dashboard você poderá visualizar como estão configuradas as suas entradas no proxy. Na aba health você poderá visualizar como está o tempo de resposta das url e saber se está tudo certo com o trafego, veja:

Bonito né? E além de tudo, extremamente funcional , em posts futuros veremos um pouco mais sobre como funciona a API do traefik, como configurar o let’s encrypt, e alguns outros pontos, por enquanto, como post introdutório, era isso que gostaria de trazer a vocês.

Esperemos que tenham gostado, qualquer dúvida/sugestão nos avise

Grande abraço, até mais!