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.

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!

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 – 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!

 

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.

 

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!

E os logs?

Oi Pessoal, tranquilo?

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

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

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

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

Fluentd

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

docker run --log-driver=fluentd

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

Splunk

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

docker run --log-driver=splunk

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

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

Veja um exemplo prático:

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

AWS Logs

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

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

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

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

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

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

Abraço!