Asignar una dirección IP estática en contenedores LXD

La mayoría de las aplicaciones en Superadmin funcionan sobre contenedores LXD. La seguridad y la escalabilidad son los principales motivos por los que nos decidimos por esta tecnología, así como la facilidad de permitir la conexión externa a los contenedores ya sea a través de un proxy inverso o configurando el propio bridge de LXD.

Generalmente, usando el bridge existen dos opciones para configurar una IP pública a un contenedor:

  • Agregar la IP pública al Host y luego hacer NAT sobre la IP interna del contenedor.
  • Enrutar el tráfico de la IP pública al bridge y configurar la IP pública en el propio contenedor.

En este artículo veremos la última opción, que es la recomendable ya que permite mover contenedores y sus ips entre distintos hosts sin necesidad de hacer ajustes adicionales.

1. Configurar el host

Hasta la versión 2.1 de LXD la gestión de la red era sencilla: LXD montaba el bridge lxdbr0 sobre el que poder realizar la configuración de red de cualquier contenedor en el propio Host con herramientas como bridge-utils.

Sin embargo, esta forma de trabajar dificulta la gestión remota de la red de los contenedores. Por eso a partir de la versión 2.3 de LXD se abandona la gestión desde el Host y se hace a través del nuevo comando: lxc network.

El comando lxc network permite crear nuevos bridges y establecer una configuración de red diferente a cada uno.

El modo de empleo del comando es:

# lxc network set <network> <key> <value>

Para configurar cada aspecto de la configuración se emplea un sistema de clave/valor. Las claves están divididas en espacios de nombres siendo los principales:

  • bridge
  • fan
  • tunnel
  • ipv4
  • ipv6
  • dns

Aquí encontrarás todas las opciones de configuración de lxc network.

Enrutar el tráfico de una IP pública al bridge

Entre las claves disponibles, encontramos ipv4.routes que permite enrutar todo el tráfico de una dirección IP pública al bridge ejecutando el comando:

# lxc network set lxdbr0 ipv4.routes 1.1.1.1/32

Donde —1.1.1.1— es la dirección IP pública y que no debe estar configurada en el Host.

Para revisar que la nueva configuración del bridge ejecutamos:

# lxc network show lxdbr0
config:
  ipv4.address: 10.0.0.1/24
  ipv4.nat: "true"  
  ipv4.routes: 1.1.1.1/32
...

2. Configurar la IP en el contenedor

Una vez enrutado el tráfico al bridge, el segundo paso consiste en añadir la dirección IP pública en el propio contenedor.

En Ubuntu Xenial (16.04)

Para asignar la dirección IP a la interface de red usamos el comando ip del siguiente modo:

# ip -4 addr add dev eth0 1.1.1.1/32

De este modo, ya es posible acceder al contenedor a través de la nueva dirección IP, sin embargo el tráfico saliente lo hará a través de la dirección del Host a menos que establezcamos la dirección pública como predeterminada:

# ip -4 addr add dev eth0 1.1.1.1/32 preferred_lft 0

Atención, esta configuración no es persistente y se perderá tras un reinicio del contenedor. Para evitarlo hay que añadir un hook script a /etc/network/interfaces para que reconfigure la IP pública cada vez que la red levante la conexión:

auto eth0
iface eth0 inet dhcp
    post-up ip -4 addr add dev eth0 1.1.1.1/32 preferred_lft 0

Ahora, el contenedor tendrá dos direcciones IP:

  • Una local obtenida por DHCP.
  • La nueva dirección IP pública.
# lxc list
+----------------+---------+------------------------ // ...
|      NAME      |  STATE  |              IPV4       // ...
+----------------+---------+------------------------ // ...
|       c1       | RUNNING | 1.1.1.1 (eth0)          // ...
|                |         | 10.0.0.2 (eth0)         // ...
+----------------+---------+------------------------ // ...

Configuración de red estática

Si únicamente queremos configurar la dirección IP pública y no permitir conexiones desde la red privada configuraremos de red de forma estática:

# The loopback network interface
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
  address 1.1.1.1
  netmask 255.255.255.255
  gateway 10.0.0.1 
   
  pre-up ip -4 route add dev eth0 10.0.0.1/32

Donde —10.0.0.1— es la dirección del gateway del bridge que podemos averiguar consultando la clave ipv4.address en la propia configuración del bridge:

# lxc network show lxdbr0

config:
  ipv4.address: 10.0.0.1/24
  ipv4.nat: "true"  
description: ""
name: lxdbr0
type: bridge
used_by:
- /1.0/containers/c1
- /1.0/containers/c2
managed: true
status: Created
locations:
- none

En Ubuntu Bionic (18.04)

Ubuntu Bionic utiliza Netplan para configurar la red que no tiene soporte para hook scripts. Es posible usar networkd-dispatcher para configurar hooks post-up pero no tiene soporte para scripts pre-up.

Así, en el caso de querer una configuración completamente estática hay que eliminar netplan, volver a ifupdown y crear un nuevo fichero interfaces para configurar la red:

$ lxc exec c1 -- bash

$ apt-get update 
$ apt-get install ifupdown

# Crear el fichero de configuración de red.
$ cat << EOF >> /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
  address 1.1.1.1
  netmask 255.255.255.255
  gateway 10.0.0.1 

  pre-up ip -4 route add dev eth0 10.0.0.1/32

EOF

$ systemctl unmask networking
$ systemctl enable networking
$ systemctl restart networking

Eliminar netplan en el contenedor:

$ systemctl stop \
	systemd-networkd.socket \
	systemd-networkd \
	networkd-dispatcher \
	systemd-networkd-wait-online

$ systemctl disable \
	systemd-networkd.socket \
	systemd-networkd \
	networkd-dispatcher \
	systemd-networkd-wait-online

$ systemctl mask \
	systemd-networkd.socket \
	systemd-networkd \
	networkd-dispatcher \
	systemd-networkd-wait-online

$ apt-get --assume-yes purge nplan netplan.io"

Por último reiniciar el contenedor:

$ exit 
$ lxc restart c1

y comprobar la configuración:

# lxc list
+----------------+---------+------------------------ // ...
|      NAME      |  STATE  |              IPV4       // ...
+----------------+---------+------------------------ // ...
|       c1       | RUNNING | 1.1.1.1 (eth0)          // ...
+----------------+---------+------------------------ // ...

En este artículo hemos visto como enrutar el tráfico de una IP pública al bridge LXD y así configurar una IP pública en uno de sus contenedores. LXD es la tecnología que usamos en Superadmin para que los sitios de nuestros clientes destaquen sobre la competencia con un rendimiento y velocidad superiores.

César Maeso


Creative Commons License

Esta obra está bajo una licencia de Creative
Commons Reconocimiento-NoComercial-CompartirIgual
4.0 Internacional
.