Este post é sobre o LXD, uma forma de criar “máquinas virtuais” que residem em directorias na nossa máquina, sem mais intermediários (hypervisors). Para quem usa docker podem ver mais info sobre o projecto e como se comparam os 2: https://www.ubuntu.com/containers/lxd.
Fica já a nota que o docker e o lxd são concorrentes, mas talvez sejam mais complementares. O docker isola componentes, o lxd isola sistemas operativos. Terão por isso vantagens e desvantagens muitas vezes simétricas. E ambos são similares na tecnologia de base que usam (lxc e chroot + cgroups). Basicamente, usam capacidades do kernel linux para isolar componentes (é por isso que só podemos “virtualizar” componentes linux e não windows ou mac). Na verdade, e para ser tecnicamente menos incorrecto, não se criam máquinas virtuais, mas sim containers. Mas para simplicidade, no resto do texto quando falo de containers ou VM’s é tudo o mesmo… containers.
Aquilo que me entusiasma no LXD é a simplicidade de uso, com muito poucos comandos, e a facilidade de gerir sistemas que integram vários componentes, como geralmente acontece numa plataforma SIG (qgis, postgresql, geoserver, etc.). Como o LXD virtualiza um SO inteiro, é natural e fácil usá-lo para conter sistemas aplicacionais inteiros.
As máquinas LXD podem ser criadas em directorias no nosso servidor Ubuntu, e podem conter diversos sistemas operativos. E é muito fácil clonar, fazer snapshots, parar e iniciar estes contentores de SO. Já cópias de segurança obrigam a alguma ginástica, mas estão a trabalhar num método simplificado.
Também é fácil limitar os recursos usados por cada VM, quer na memória máxima, quer no processador (cores, % de tempo, etc.), e vários outros recursos. Podem ver info completa aqui: https://stgraber.org/2016/03/26/lxd-2-0-resource-control-412/.
A existência do LXD vem baixar a complexidade da virtualização baseada em containers, deixando de usar hypervisors como o KVM, OpenVZ, VMWare, VirtualBox, e HyperV.
Podemos instalar o Ubuntu directamente na máquina física, e criar VM’s usando comandos LXD. Os seus defensores indicam ganhos de desempenho, ou mais correctamente menos perda de desempenho, e por isso potencial maior densidade de VM’s. Não posso confirmar nem desmentir porque não testei nada disto. Mas parece-me algo lógico.
Só mais um detalhe – o LXD suporta nested virtualization, ou seja, dentro de uma VM Ubuntu podemos usá-lo para criar VM’s, que estão dentro da nossa VM inicial… confuso? Cuidado, que o OpenVZ não suporta lxd… portanto ao comprarem uma VPS assegurem-se que é baseada em KVM.
Nested Virtualization… whaaat?
Instalar o LXD
Instalar o LXD é muito simples – já vem incluído no Ubuntu.
É preciso no entanto iniciá-lo uma primeira vez e definir a sua configuração, que principalmente define o tipo storage usado pelas máquinas a criar (baseadas em directorias ou pools zfs), e a configuração da rede que dirá se as VM’s são acessíveis do exterior, e se poderão comunicar entre si.
O tutorial que usei como base foi este da Digital Ocean: https://www.digitalocean.com/community/tutorials/how-to-set-up-and-use-lxd-on-ubuntu-16-04.
A diferença é que escolhi usar directorias para mais simplicidade, em vez de ZFS. Embora ZFS seja a opção recomendada pela Canonical, fabricante do Ubuntu, envolve uma complexidade que seria contraproducente para mim – o objectivo é ter simplicidade máxima e o menor número de pontos de falha. Mais info aqui: https://insights.ubuntu.com/2016/02/16/zfs-is-the-fs-for-containers-in-ubuntu-16-04/.
Então, a sessão de configuração do lxd foi assim (o meu user é dncpax e as respostas estão a negrito):
$ sudo usermod --append --groups lxd dncpax $ sudo lxd init Do you want to configure a new storage pool (yes/no) [default=yes]? y Name of the storage backend to use (dir or zfs) [default=dir]: dir Would you like LXD to be available over the network (yes/no) [default=no]? no Do you want to configure the LXD bridge (yes/no) [default=yes]? yes
Como se vê escolhi sempre os defaults.
Neste ponto, o lxd lança um wizard de configuração da rede em modo texto (podemos usar num terminal). Se respondermos sempre com defaults, vamos ter no final uma rede interna gerida pelo LXD, do tipo 10.0.0.X.
Desta forma, as VM’s poderão contactar a máquina “mãe” e outras VM’s, e também a Internet. Mas não receberão tráfego exterior, ou seja, ninguém conseguirá aceder às nossas VM’s.
(Para permitir o acesso do “exterior” às nossas VM’s LXD vamos ter de usar algum tipo de router/firewall (IPTables) ou reverse proxy (NGinx ou HAProxy). Eu escolhi usar o HAProxy, que veremos noutro artigo.)
Durante o wizard, vai ser configurada uma rede IPv4, e opcionalmente uma rede IPv6. Eu usei sempre os defaults, mas não configurei a rede IPv6:
A minha rede foi configurada como 10.70.99.X, e assim todas as VM’s terão um IP deste tipo.
Utilizar LXD
A partir daqui temos os comandos do lxd ao dispor. Parte são baseados em lxc e outros em lxd. (lxc é o componente de base do lxd.)
Por exemplo, ver as VM’s criadas (não há ainda) – lxc list:
$ lxc list +------+--------+------+------+------+-----------+ | NOME | ESTADO | IPV4 | IPV6 | TIPO | SNAPSHOTS | +------+--------+------+------+------+-----------
Nota: se tiverem um erro de permissão negada, é porque o vosso novo grupo lxd não está ainda “activo”. Podem fechar a sessão e abrir uma nova com o mesmo login e continuar o trabalho, ou executarem “newgrp lxd”.
Ver a configuração do lxd – lxc info:
$ lxc info config: {} api_extensions: - id_map - id_map_base - resource_limits api_status: stable api_version: "1.0" auth: trusted auth_methods: [] public: false environment: addresses: [] architectures: - x86_64 - i686 certificate: | -----BEGIN CERTIFICATE----- MIIFWzCCA0OgAwIVK3ESSSDQAIgte5p8cNcFQHJo0byAjiQD2YkT/sXr+3mf5U bla bla bla bla hTuelEv1+SWzBsN2nDbF7ZUDhw4cioBS59fkWidNrg== -----END CERTIFICATE----- certificate_fingerprint: 85ab3c61 bla 6d2bae driver: lxc driver_version: 2.0.8 kernel: Linux kernel_architecture: x86_64 kernel_version: 4.4.0-109-generic server: lxd server_pid: 3276 server_version: 2.0.11 storage: dir storage_version: ""
Então o que temos por agora? Um deamon lxd que coordenará a existência e o isolamento das VM’s a criar. Podemos ver o seu estado actual com systemctl (notem a memória ocupada):
systemctl status lxd ● lxd.service - LXD - main daemon Loaded: loaded (/lib/systemd/system/lxd.service; indirect; vendor preset: ena Active: active (running) since Qui 2018-01-18 21:35:36 WET; 14min ago Docs: man:lxd(1) Process: 3315 ExecStartPost=/usr/bin/lxd waitready --timeout=600 (code=exited, Process: 3277 ExecStartPost=/usr/lib/lxd/profile-config (code=exited, status=0 Process: 3265 ExecStartPre=/usr/lib/x86_64-linux-gnu/lxc/lxc-apparmor-load (co Main PID: 3276 (lxd) Tasks: 9 Memory: 7.5M CPU: 438ms CGroup: /system.slice/lxd.service └─3276 /usr/bin/lxd --group lxd --logfile=/var/log/lxd/lxd.log Jan 18 21:35:35 ubuntumin systemd[1]: Starting LXD - main daemon... Jan 18 21:35:36 ubuntumin lxd[3276]: lvl=warn msg="CGroup memory swap accounting Jan 18 21:35:36 ubuntumin systemd[1]: Started LXD - main daemon.
Criar e gerir VM’s
Trabalhar com VM’s ou containers LXD é muito fácil, e basicamente limita-se a estes passos:
- Criar o container com o OS escolhido
- Aceder ao container na nossa shell ou por ssh
- Configurar alguns limites se quisermos (de memória p.e.)
- Parar ou reiniciar um container
- Ver os detalhes de um container, incluindo memória ocupada
A melhor página que conheço sobre gestão de containers LXD é esta: https://insights.ubuntu.com/2016/03/22/lxd-2-0-your-first-lxd-container/
Então para criar uma VM de Ubuntu dentro do nosso Ubuntu 😉 usamos o comando lxc launch. O sistema operativo que queremos usar pode ser escolhido de uma lista já extensa que pode ser consultada aqui: https://us.images.linuxcontainers.org/.
Antes de instalar uma máquina novinha vamos antes ver como temos a memória:
$ free -m
total used free shared buff/cache available
Mem: 2000 47 1501 3 451 1795
Como se vê, estamos só com 47MB usados e 451MB em cache.
Para instalar a nova vm chamada “wordpress1” (como é a 1ª vez, a imagem é descarregada do repositório online):
$ lxc launch ubuntu:16.04 wordpress1 A criar wordpress1 A iniciar wordpress1
E pronto. Temos um novo ubuntu fresquinho. Podemos ver na lista de containers com lxc list:
$ lxc list
+------------+---------+---------------------+------+-------------+-----------+
| NOME | ESTADO | IPV4 | IPV6 | TIPO | SNAPSHOTS |
+------------+---------+---------------------+------+-------------+-----------+
| wordpress1 | RUNNING | 10.70.99.165 (eth0) | | PERSISTENTE | 0 |
+------------+---------+---------------------+------+-------------+-----------+
Podemos ver a lista dos containers, se estão iniciados, e os endereços IP internos.
Para vermos a configuração de um container, incluíndo a memória usada:
$ lxc info wordpress1 Nome: wordpress1 Remote: unix:// Arquitetura: x86_64 Criado: 2018/01/18 22:20 UTC Estado: Running Tipo: persistente Perfis: default Pid: 4426 Ips: eth0: inet 10.70.99.165 vethWJS19I eth0: inet6 fe80::216:3eff:fef3:793c vethWJS19I lo: inet 127.0.0.1 lo: inet6 ::1 Recursos: Processos: 27 Memory usage: Memória (atual): 31.77MB Memória (máxima): 152.54MB Network usage: lo: Bytes recebidos: 0B Bytes enviados: 0B Pacotes recebidos: 0 Pacotes enviados: 0 eth0: Bytes recebidos: 195.18kB Bytes enviados: 7.45kB Pacotes recebidos: 138 Pacotes enviados: 90
Até agora a memória ocupada variou entre 31 e 157 MB…
Para aceder podemos usar ssh ou um comando do lxc (exec):
$ lxc exec wordpress1 -- sudo --login --user ubuntu To run a command as administrator (user "root"), use "sudo <command>". See "man sudo_root" for details. ubuntu@wordpress1:~
Estamos agora “dentro” da nova máquina wordpress1, com o login ubuntu… podemos ver os seus processos de forma isolada, sem acesso à máquina mãe:
$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 37596 5616 ? Ss 22:20 0:00 /sbin/init
root 55 0.0 0.1 41724 3284 ? Ss 22:20 0:00 /lib/systemd/sy
root 57 0.0 0.1 35280 3228 ? Ss 22:20 0:00 /lib/systemd/sy
root 232 0.0 0.0 16000 856 ? Ss 22:20 0:00 /sbin/dhclient
daemon 318 0.0 0.1 26048 2164 ? Ss 22:20 0:00 /usr/sbin/atd -
syslog 324 0.0 0.1 186904 3288 ? Ssl 22:20 0:00 /usr/sbin/rsysl
root 326 0.0 0.0 20104 1208 ? Ss 22:20 0:00 /lib/systemd/sy
root 327 0.0 0.2 272872 5960 ? Ssl 22:20 0:00 /usr/lib/accoun
root 328 0.0 0.2 65524 5476 ? Ss 22:20 0:00 /usr/sbin/sshd
message+ 329 0.0 0.1 42896 3828 ? Ss 22:20 0:00 /usr/bin/dbus-d
root 341 0.0 0.1 26072 2528 ? Ss 22:20 0:00 /usr/sbin/cron
root 342 0.0 1.2 158844 26576 ? Ssl 22:20 0:00 /usr/lib/snapd/
root 350 0.0 0.4 277184 8260 ? Ssl 22:20 0:00 /usr/lib/policy
root 378 0.0 0.0 12848 1784 ? Ss+ 22:20 0:00 /sbin/agetty --
root 441 0.0 0.1 59508 4032 ? Ss 22:25 0:00 sudo --login --
ubuntu 442 0.0 0.2 23012 5064 ? S 22:25 0:00 -bash
ubuntu 459 0.0 0.1 37764 3276 ? R+ 22:26 0:00 ps aux
A partir daqui podemos instalar o que quisermos da forma habitual. Podemos aceder ao exterior, mas não o inverso – do exterior aceder ao nosso container. E isso será para resolver noutro post.
Por agora, deixem-me terminar com um pequeno teste de desempenho. Uso sempre o 7zip para testes rápidos de cpu. Portanto vamos instalar o 7zip no container testar o cpu com só 1 thread, e depois fazer o mesmo na máquina mãe, para vermos neste caso a quebra de rendimento.
$ sudo apt-get update Hit:1 http://archive.ubuntu.com/ubuntu xenial InRelease bla bla Fetched 24.6 MB in 10s (2276 kB/s) Reading package lists... Done $ sudo apt-get install 7zip-full bla bla Setting up p7zip-full (9.20.1~dfsg.1-4.2) ... $ 7z b -mmt1 7-Zip [64] 9.20 Copyright (c) 1999-2010 Igor Pavlov 2010-11-18 p7zip Version 9.20 (locale=C.UTF-8,Utf16=on,HugeFiles=on,2 CPUs) RAM size: 2000 MB, # CPU hardware threads: 2 RAM usage: 419 MB, # Benchmark threads: 1 Dict Compressing | Decompressing Speed Usage R/U Rating | Speed Usage R/U Rating KB/s % MIPS MIPS | KB/s % MIPS MIPS 22: 3917 100 3811 3810 | 41983 100 3791 3790 23: 3735 100 3806 3806 | 39076 100 3578 3577 24: 3337 100 3589 3588 | 39359 100 3652 3652 25: 3339 100 3812 3812 | 39856 100 3748 3748 ---------------------------------------------------------------- Avr: 100 3755 3754 100 3692 3692 Tot: 100 3723 3723
Portanto, dentro do container temos um total de 3723 MIPS de compressão. Vamos sair do container e fazer o mesmo exercício:
ubuntu@wordpress1:~$ exit logout dncpax@ubuntumin:~$ dncpax@ubuntumin:~$ 7z b -mmt1 7-Zip [64] 9.20 Copyright (c) 1999-2010 Igor Pavlov 2010-11-18 p7zip Version 9.20 (locale=pt_PT.UTF-8,Utf16=on,HugeFiles=on,2 CPUs) RAM size: 2000 MB, # CPU hardware threads: 2 RAM usage: 419 MB, # Benchmark threads: 1 Dict Compressing | Decompressing Speed Usage R/U Rating | Speed Usage R/U Rating KB/s % MIPS MIPS | KB/s % MIPS MIPS 22: 3815 100 3712 3711 | 41670 100 3762 3762 23: 3696 100 3767 3766 | 41115 100 3765 3764 24: 3557 100 3825 3825 | 40444 100 3753 3753 25: 3408 100 3891 3891 | 40016 100 3764 3763 ---------------------------------------------------------------- Avr: 100 3799 3798 100 3761 3761 Tot: 100 3780 3779
Temos então na máquina LXD 3780 MIPS de compressão.
Ou seja, 3723/3780 = 98% de desempenho no container! Sim, é um teste simplista, e não representa uma avaliação real, mas é óptimo indicador.
E pronto, acabo por aqui. O próximo post da série será dedicado a coisas mais sérias, como ter várias máquinas LXD a comunicar com o exterior, e ver como limitar os recursos usados por uma delas. Até breve.
One thought on “LXD o virtualizador ubuntu”