Gestión de jails en FreeBSD con Iocage


Iocage es un gestor de contenedores(jails) que hace uso de las mejores funcionalidades y tecnologías que nos ofrece FreeBSD. Este nos facilitará la gestión en todo el ciclo vida del jail, creación, destrucción y actualización.

El primer paso será instalar el software:

pkg install py37-iocage-1.2_5

Podemos indicarle que nos muestre colores:

export IOCAGE_COLOR=TRUE

Para que sea permanente habrá que exportar la variable en la shell que utilicemos, en mi caso se trata de bash:

vi .bashrc
export IOCAGE_COLOR=TRUE

Si se trata de un servidor que contendrá muchos jails debemos montar el sistema de ficheros de descriptores de ficheros, de este modo el acceso será mas rápido:

mount -t fdescfs null /dev/fd

Para que sea permanente:

vi /etc/fstab
fdescfs                 /dev/fd fdescfs rw              0       0

Si tenemos mas de un zpool debemos indicarle a Iocage cual queremos utilizar:

zpool list
NAME      SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
storage   928G  35.8G   892G        -         -     1%     3%  1.00x  ONLINE  -
zroot     109G  16.0G  93.0G        -         -     3%    14%  1.00x  ONLINE  -

En mi caso zroot:

iocage activate zroot

Nos bajamos la versión de FreeBSD que actuará como base de las jails:

iocage fetch
Press [Enter] to fetch the default selection: (12.1)
ENTER

Creamos nuestra jail:

iocage create -r LATEST -n test boot=on

Comprobamos que esté:

iocage list
+-----+---------+-------+--------------+--------------+
| JID |  NAME   | STATE |   RELEASE    |     IP4      |
+=====+=========+=======+==============+==============+
+-----+---------+-------+--------------+--------------+
| 5   | test    | up    | 12.1-RELEASE | -            |
+-----+---------+-------+--------------+--------------+

Podemos acceder a la consola con el comando console:

iocage console test
root@test:~ # hostname
test
exit

Iocage viene con varias jails listas para ser utilizadas, las llaman plugins, con el comando list --plugins --remote podemos ver que jails hay disponibles:

iocage list --plugins --remote

Algunas de las mas populares son:

+-------------------+-------------------+-------------------+------------------+
|       NAME        |    DESCRIPTION    |        PKG        |       ICON       |
+===================+===================+===================+==================+
| Bacula-server     | Manage, backup,   | bacula-server     | https://www.true |
+-------------------+-------------------+-------------------+------------------+
| GitLab            | DevOps lifecycle  | gitlab            | https://www.true |
+-------------------+-------------------+-------------------+------------------+
| Jenkins           | Open source build | jenkins           | https://www.true |
+-------------------+-------------------+-------------------+------------------+
| Nextcloud         | Suite of client-  | nextcloud         | https://www.true |
+-------------------+-------------------+-------------------+------------------+
| Zoneminder        | Closed-circuit    | zoneminder        | https://www.true |
+-------------------+-------------------+-------------------+------------------+

En cuanto a la asignación de direcciones ip Iocage soporta dos modos sharedIP/Vnet, pero este último es considerado inestable por lo tanto nos centraremos en sharedIP.

Debemos asignar cada una de las ips de las jails al host padre mediante alias:

vi /etc/rc.conf
ifconfig_nfe0="inet IP_PADRE netmask 255.255.255.0"
ifconfig_nfe0_alias0="inet IP_JAIL netmask 255.255.255.0"
defaultrouter="GW_RED"

Reiniciamos la interfaz de red y el routing:

service netif restart
service routing restart

Nos aseguramos de que la jail no tenga Vnet activada:

iocage get vnet test
0

Le asignamos la ip del alias:

iocage set ip4_addr="nfe0|IP_JAIL/24" test
iocage list
+-----+---------+-------+--------------+--------------+
| JID |  NAME   | STATE |   RELEASE    |     IP4      |
+=====+=========+=======+==============+==============+
+-----+---------+-------+--------------+--------------+
| 5   | test    | up    | 12.1-RELEASE | IP_JAIL      |
+-----+---------+-------+--------------+--------------+

Comprobamos que la jail conozca su ip:

iocage exec test ifconfig
nfe0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
    options=8210b<RXCSUM,TXCSUM,VLAN_MTU,TSO4,WOL_MAGIC,LINKSTATE>
    ether 00:22:19:eb:c7:e9
    inet IP_JAIL netmask 0xffffff00 broadcast 192.168.69.255
    media: Ethernet autoselect (1000baseT <full-duplex,master>)
    status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
    options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
    groups: lo
ipfw0: flags=8800<SIMPLEX,MULTICAST> metric 0 mtu 65536
    groups: ipfw

Iocage permite definir dependencias entre jails, de este modo hasta que no arranquen las dependencias no arrancará la jail en cuestión:

iocage set depends="dep1 dep2" test

Una de las funcionalidades mas interesantes son los snapshots, para crearlos ejecutaremos:

iocage snapshot -n testJail00 test
iocage snapshot -n testJail01 test

Para ver los snapshots de una jail:

iocage snaplist test
+-----------------+-----------------------+-------+------+
|      NAME       |        CREATED        | RSIZE | USED |
+=================+=======================+=======+======+
| testJail00      | Sun Mar 29 14:06 2020 | 92K   | 60K  |
+-----------------+-----------------------+-------+------+
| testJail00/root | Sun Mar 29 14:06 2020 | 1.33G | 264K |
+-----------------+-----------------------+-------+------+
| testJail01      | Sun Mar 29 14:14 2020 | 92K   | 0    |
+-----------------+-----------------------+-------+------+
| testJail01/root | Sun Mar 29 14:14 2020 | 1.33G | 220K |
+-----------------+-----------------------+-------+------+

Si queremos revertir primero paramos la jail:

iocage stop test

Acto seguido realizamos el rollback:

iocage rollback -n testJail00 test

NOTA: Si no revertimos al último snapshot los snapshots intermedios serán borrados, en mi caso tenía los snapshots testJail00 y testJail01, al revertir al testjail00, testjail01 ha sido eliminado:

iocage snaplist test
+-----------------+-----------------------+-------+------+
|      NAME       |        CREATED        | RSIZE | USED |
+=================+=======================+=======+======+
| testJail00      | Sun Mar 29 14:06 2020 | 92K   | 0    |
+-----------------+-----------------------+-------+------+
| testJail00/root | Sun Mar 29 14:06 2020 | 1.33G | 0    |
+-----------------+-----------------------+-------+------+

Para eliminar snapshots ejecutaremos:

iocage snapremove -n testJail00 test

Es posible instalar de forma automática ciertos paquetes en una jail cuando es creada tan solo debemos preparar la lista en formato json:

vi pkgs.json
{
    "pkgs": [
    "ngrep",
    "tcpdump"
    ]
}

Arrancamos la jail:

iocage create -r LATEST -p pkgs.json -n test ip4_addr="nfe0|JAIL_IP/24"

La funcionalida de importar en Iocage está bugeada, consume toda la RAM+SWAP del sistema, como workaround se puede exportar de forma normal, pero la importación la tendremos que hacer mediante comandos de ZFS manualmente:

iocage export test
scp /zroot/iocage/images/test_2020-03-28.zip REMOTE_SERVER:/zroot/iocage/images/test_2020-03-28.zip

En el servidor receptor:

unzip /zroot/iocage/images/test_2020-03-28.zip
zfs recv -F zroot/iocage/jails/test < zroot/iocage/images/test_2020-03-28
zfs recv -F zroot/iocage/jails/test/root < zroot/iocage/images/test_2020-03-28_root

Si queremos montar directorios externos dentro de la jail utilizaremos el comando fstab de Iocage, en mi caso monto el directorio /storage dentro de la jail en /mnt/storage:

iocage console test
mkdir /mnt/storage
iocage fstab -a test "/storage /mnt/storage nullfs rw 0 0"

Podemos consultar los puntos de montaje con:

iocage fstab -l test
+-------+-------------------------------------------------------------------------------------------+
| INDEX |                                        FSTAB ENTRY                                        |
+=======+===========================================================================================+
| 0     | /storage        /zroot/iocage/jails/test/root/mnt/storage       nullfs  rw      0       0 |
+-------+-------------------------------------------------------------------------------------------+

Otra opción muy útil es poder ver que recursos están ocupando cada jail:

iocage df     
+---------+-------+------+------+-------+-------+
|  NAME   |  CRT  | RES  | QTA  |  USE  |  AVA  |
+=========+=======+======+======+=======+=======+
| test    | 1.04x | none | none | 396K  | 84.1G |
+---------+-------+------+------+-------+-------+

Iocage soporta varios tipos de jails.

Clone: iocage create -r [RELEASE] -b

Es el tipo de jail por defecto, cuando se crea una jail de este tipo esta es clonada del snapshot de la RELEASE, consume poco espacio ya que la base es compartida entre jails y solo se guardan los datos que se cambian en su interior, cada jail de este tipo debe ser actualizada de forma independiente. Como consecuencia de su base compartida no es posible eliminar la RELEASE mientras haya jails dependeintes de esta.

Base: iocage create -r [RELEASE] -b

Se trata de una jail generada a partir de una copia completa de la RELEASE pero hay ciertos directorios de la RELEASE que son montados dentro de la jail mediante nullfs, este tipo de jail ocupa menos espacio que las thick pero mas que las clone. Es el tipo ideal para parchear de forma masiva ya que mediante iocage update sobre una de las jails estaremos actualizando todas las que compartan RELEASE con esta. También se pueden actualizar todas las jails de esa RELEASE ejecutando iocage fetch RELEASE de nuevo.

Thick: iocage create -T -r 11.2-RELEASE

Se realiza una copia entera de la RELEASE ocupando mas espacio que los demás tipos, es una jail totalmente independiente de las demás, cada jail de este tipo debe ser actualizada de forma independiente.

Template

Los templates son jails retocadas para servir como plantilla de despliegue rápido de otras. Para generar un template a partir de una jail existente:

iocage stop test
iocage set template=yes test

Podemos consultar los templates locales:en

iocage list -t
+-----+------+-------+--------------+--------------+
| JID | NAME | STATE |   RELEASE    |     IP4      |
+=====+======+=======+==============+==============+
| -   | test | down  | 12.1-RELEASE | JAIL_IP      |
+-----+------+-------+--------------+--------------+

Para crear una jail a partir de un template:

iocage create -t test -n newtest

El proceso de conversión a template se puede revertir mediante el parámetro template:

iocage set template=no test

Empty: iocage create -e

Son jails pensadas para testing o funcionalidades no soportadas, ideales para experimentar con RELEASES no soportadas o Linux-jails.


Las actualizaciones de la base de las jails se realizará mediante Iocage, según el tipo de jail tendremos que ejecutar el comando para cada una de las jails o en una sola. El resto de software(binarios/ports/código fuente del SO) se actualizará desde dentro de la jail como si de una máquina física se tratase.

Si nos mantenemos dentro de la misma versión bastará con:

iocage update JAILNAME

Para pasar de una versión a otra seguimos la guía y consultamos la última RELEASE disponible.

Si es una minor update, ej: 12.0 -> 12.1:

iocage upgrade JAILNAME -r 12.1-RELEASE
iocage update JAILNAME

Si es una major update ej: 12.1 -> 13.0, además de los pasos de una minor update debemos reinstalar los paquetes binarios/ports:

pkg-static upgrade -f

Los programas intalados desde ports también, en este artículo se indica como gestionar instalaciones mixtas de paquetes binarios/ports.

Terminamos la instalación:

iocage update JAILNAME

NOTA: Las actualizaciones mediante Iocage realizan de forma automática un snapshot en cada actualización de este modo si algo saliese mal se podría revertir sin problemas.


Como nota final debemos tener en cuenta que todas las reglas de firewall deben definirse en el host padre, cuando se haga referencia a "me" son todas las ips de los alias, por lo tanto las reglas genéricas se configurarán utilizando "me" y las mas específicas de cada servicio indicando la ip origen y destino de la jail.

Algunas recomendaciones son:

  • Es mas eficiente reiniciar las jails mediante iocage restart -s que hacer un stop/start
  • Cada cierto tiempo realizar limpieza de los snapshots antiguos sobretodo de las jails cuyos datos cambien muy a menudo.
Si te ha gustado el artículo puedes invitarme a un redbull aquí.
Autor: kr0m -- 29/03/2020 16:51:37