Oi, pessoal!
A intenção hoje é chamar a atenção para um dos recursos que está presente no Docker e que às vezes passa despercebido para muitos dos utilizadores dessa tecnologia, que é trabalhar com rede. Já vimos 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 SO 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 é utilizado 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 liberada no firewall desse host. Agora vamos aproveitar que estamos no host de etcd e vamos já deixar configurada 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 alocado 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; lembre 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 ás 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 às 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 se 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 a comunicação entre multi-host.
Por hoje era isso, espero que tenha ajudado.
Abraço!