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.

 

MundoDocker – Eventos

Oi Pessoal,

Hoje o post é rápido, apenas para trazer a vocês nossa experiência no TcheLinux Caxias do Sul. Para quem nos acompanha nas rede sociais, ficou sabendo que iriamos participar de mais um edição do TcheLinux (um dos maiores eventos de tecnologia open source do Rio Grande do Sul), dessa vez em Caxias do Sul, na serra gaúcha.
O evento estava muito bem organizado, e o lugar não poderia ser melhor, com infraestrutura suficiente para atender os participantes, sem falar na localização. Com a ajuda de alguns amigos, conseguimos alguns registro fotográficos do evento, veja:

A nossa contribuição ao evento foi com uma palestra: Escalonando o mundo com Kubernetes, como o Google sobrevive. Essa apresentação teve como objetivo mostrar aos presentes como o Kubernetes funciona, como ele é utilizado dentro do Google e como você utiliza ele sem nem saber 🙂 . Compartilhamos a apresentação em nosso Slideshare, para você, que não estava no evento, possa ver um pouco sobre o que levamos ao evento:

http://www.slideshare.net/MundoDocker/escalonando-o-mundo-com-kubernetes

Gostaríamos de agradecer ao TcheLinux pela oportunidade e a Ftec que disponibilizou o local para o evento. Por hoje era isso, grande abraço! Ahhh e nos ajude divulgando o blog 😉

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:

ProtocoloPortaDescrição
udp4789Data plane (VXLAN)
tcp/udp7946Control 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çãoDescriçã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!

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/

Docker e Flannel

Oi Pessoal!

A intenção hoje é chamar a atenção para um dos recursos que está presente no Docker e que as vezes passa despercebido para muitos dos utilizadores dessa tecnologia, que é trabalhar com rede. Já vimos aqui no blog como trabalhar com Docker Network, mas com a ascensão do docker 1.12 ficou ainda mais fácil mudar a forma de como se utilizar rede, você pode integrar o Docker com diversos plugins e tecnologias de rede, hoje veremos como utilizar o Flannel para ser seu backend de rede.

Para quem não conhece, o Flannel é um projeto que foi inicialmente desenvolvido pela CoreOS, mas que atualmente é mantido, além da própria empresa, pela comunidade. Ele utiliza um serviço de chave-valor para persistir as informações sobre alocação de ip entre hosts e containers, por padrão ele utiliza o Etcd (que por coincidência é desenvolvido e mantido pela CoreOS também 🙂 ), veja abaixo algumas das características do Flannel e a diferença em relação ao Docker Network:

                             Flannel             Docker Overlay Network
Modelo                       VxLAN ou UDP                           VxLAN
Isolamento de aplicação                       CIDR Schema                     CIDR Schema
Protocolos suportados                             Todos                           Todos
Serviço de nome                               Não                             Não
Requer backend externo                               Sim                             Sim
Tipo de encriptação                               TLS                             Não
 vNIC por Container                               Não                             Sim
Restrição de subnet por container                               Não                             Sim

Como podem notar o Flannel tem algumas vantagens e desvantagens em relação ao Docker Network, destacam-se a comunicação encriptada que ele provê e não ter a possibilidade de criar subnet diferente por cliente, ou seja, todos os containers fazem parte da mesma rede. Se você está pensando em utilizar Kubernetes, leve em consideração o Flannel, pois é um dos plugins mais utilizados com esse orquestrador. Vamos colocar a mão na massa?

Instalação e dependências

Servidor Etcd

Nosso exemplo foi baseado no Centos 7 64 bits, mas você pode utilizar em outro S.O sem problema. Vamos lá, primeiramente você deve habilitar o repositório Extras do CentOS, para isso edite o CentOS-Base.repo e coloque habilite-o, veja:

# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client. You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the
# remarked out baseurl= line instead.
#
[base]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#released updates
[updates]
name=CentOS-$releasever - Updates
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=1
enable=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

Agora vamos instalar o backend do Flannel, que é o etcd (serviço de chave valor em memória), o etcd é utilizada para armazenar as informações sobre as redes que serão distribuídas entre os containers. Vamos lá:

[root@host-etcd ~]#  yum install etcd

Edite o /etc/etcd/etcd.conf alterando o ETCD_LISTEN_CLIENT_URLS, em nosso teste colocamos 0.0.0.0, ou seja, o etcd estará acessível através de qualquer ip do host, veja:

ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"

Cuide para que a porta 2389 esteja liberado no firewall desse host. Agora vamos aproveitar que estamos no host de etcd e vamos já deixar configurado a rede que será utilizada pelos hosts de Docker. Para isso, crie um arquivo, em nosso lab: rede.json e adicione o seguinte código:

{
 "Network": "192.0.0.0/16",
 "SubnetLen": 22,
 "Backend": {
 "Type": "vxlan",
 "VNI": 1
 }
}

Onde:

  • Network – Bloco de rede que será distribuída para os containers;
  • SubnetLen – Tamanho do bloco alocada para cada host, ou seja, cada host receberá um /22 do bloco 192.0.0.0/16, isso que dizer que poderíamos ter até 1000 containers em 1 host.
  • Type – Tipo do canal que será utilizado, lembra que no Flannel você pode escolher em vxlan ou udp, pois bem, é aqui que você configura isso, por experiência própria, recomendamos utilizar vxlan, pois há menos overhead.

O que faço com isso agora? Importe no etcd ;), lembrando que o etcd trabalha com chave=valor, então execute:

[root@host-etcd ~]# etcdctl set /mundodocker/network/config < rede.json

Onde:

  • /mundodocker/network/config – chave
  • rede.json – valor

Agora vamos ver se essas informações foram persistidas no etcd:

[root@host-etcd ~]#etcdctl get /mundodocker/network/config
{
 "Network": "192.0.0.0/16",
 "SubnetLen": 22,
 "Backend": {
 "Type": "vxlan",
 "VNI": 1
 }
}

 

Servidores Docker

Não esqueça, em todos os hosts temos que ativar o repositório de extras do CentOS, da mesma forma que foi feita acima. Vamos as instalações das dependências, o docker é claro:

[root@host-docker01 ~]# curl -fsSL https://get.docker.com/ | sh

Agora o Flannel:

[root@host-docker01 ~]# yum install flannel -y

Vamos as configurações agora, começamos pelo Flannel, para isso, edite o arquivo: /etc/sysconfig/flanneld, modificando as linhas:

FLANNEL_ETCD = Servidor do Etcd.
FLANNEL_ETCD_KEY = Key definida no Etcd.

Veja como deve ficar:

[root@host-docker01 ~]# cat /etc/sysconfig/flanneld | grep -v ^#
FLANNEL_ETCD="http://host-etcd:2379"
FLANNEL_ETCD_KEY="/mundodocker/network"

Agora inicie o serviço do Flannel:

[root@host-docker01 ~]# systemctl enable flanneld
[root@host-docker01 ~]# systemctl start flanneld

Note que ele criará uma interface de rede chamada flannel.1, que será utilizada para comunicação entre os hosts. Note também que será criado um arquivo dentro de: /run/flannel/subnet.env com as informações sobre a rede que o host assumiu, esse arquivo será utilizado daqui a pouco.

Agora vamos configurar nosso serviço de Docker para utilizar a rede Flannel configurada anteriormente, para isso, edite o arquivo: /lib/systemd/system/docker.service adicionando a linha: EnvironmentFile=-/run/flannel/subnet.env e alterando a forma como o Docker será iniciado, veja como deve ficar:

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket
 
[Service]
Type=notify
EnvironmentFile=-/run/flannel/subnet.env
ExecStart=/usr/bin/docker daemon -H fd:// $OPTIONS $DOCKER_STORAGE_OPTIONS --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU}
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
TimeoutStartSec=0
 
[Install]
WantedBy=multi-user.target

Agora basta iniciar/reiniciar o serviço do Docker:

[root@host-docker01 ~]# systemctl enable docker.service
[root@host-docker01 ~]# systemctl start docker.service

Não esqueça de fazer isso em todos os hosts de Docker que você quer colocar nessa rede.

 

Vamos testar?

Basta você criar um container em cada host, em nosso teste criamos um baseado na imagem do CentOS:

Host 1:

[root@host-docker01 ~]# docker run -it centos /bin/bash

Host 2:

[root@host-docker02 ~]# docker run -it centos /bin/bash

Agora basta você pingar de um container para o outro, ou se quiser fazer um teste mais real, você pode instalar um banco de dados ou servidor web em um dos containers e tentar acessar via ip da rede Flannel pelo outro container. Como você deve ter notado esse processo é bem simples e resolve grandes problemas com rede no Docker, como por exemplo a comunicação entre multi-host.

Por hoje era isso, espero que tenha ajudado, e como sempre, nos ajude divulgando o blog 😉

Abraço!

Docker Run – Avançado

Olá pessoal,

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

PID settings (–pid)

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

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

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

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

–dns

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

–add-host

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

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

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

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

–security-opt

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

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

–restart

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

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

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

 docker run redis; echo $?

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

–isolation

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

docker run -d --isolation process busybox top

–device

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

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

–rm

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

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

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

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

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