Cuando tenemos contenedores lxc en un servidor, estos suelen estar en una red diferente a la red donde esta huestro host anfitrión. En estas ocasiones, lxc crea un nat, y no podemos acceder directamente a estos contenedores desde fuera.
En este artículo vamos a poner un haproxy en el host anfitrion (de aquí en adelante server0), que se va a encargar de redirigir el trafico ssh que le entre a server0 por un determinado puerto, al puerto donde este escuchando el servicio ssh del contenedor lxc.
Lo primero que necesitamos es lxc y lxd en server0, así que vamos a comprobar si lo tenemos instalado con lxc version
athos@server0:~$ lxc version
2.0.11
Vemos que lo tenemos instalado, pero vamos a instalar la versión 3, para esto lo haremos así:
sudo apt install -t xenial-backports lxd lxd-client -y
athos@server0:~$ lxc version
If this is your first time running LXD on this machine, you should also run: lxd init
To start your first container, try: lxc launch ubuntu:18.04
Client version: 3.0.3
Server version: 3.0.3
Se nos advierte de que es la primera vez que ejecutamos LXD y que deberíamos ejecutar lxd init
. Lo hacemos y dejamos todas las opciones por defecto.
athos@server0:~$ lxd init
Would you like to use LXD clustering? (yes/no) [default=no]:
Do you want to configure a new storage pool? (yes/no) [default=yes]:
Name of the new storage pool [default=default]:
Name of the storage backend to use (btrfs, dir, lvm) [default=btrfs]:
Create a new BTRFS pool? (yes/no) [default=yes]:
Would you like to use an existing block device? (yes/no) [default=no]:
Size in GB of the new loop device (1GB minimum) [default=15GB]:
Would you like to connect to a MAAS server? (yes/no) [default=no]:
Would you like to create a new local network bridge? (yes/no) [default=yes]:
What should the new bridge be called? [default=lxdbr0]:
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
Would you like LXD to be available over the network? (yes/no) [default=no]:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:
Una vez hecho esto, vamos a levantar tres contenedores como se ve en la imagen superior.
lxc launch ubuntu:16.04 lxc0
lxc launch ubuntu:16.04 lxc1
lxc launch ubuntu:16.04 lxc2
athos@server0:~$ lxc list
+------+---------+-----------------------+-----------------------------------------------+------------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+---------+-----------------------+-----------------------------------------------+------------+-----------+
| lxc0 | RUNNING | 10.108.131.2 (eth0) | fd42:f96f:612f:6693:216:3eff:fe9c:a58a (eth0) | PERSISTENT | 0 |
+------+---------+-----------------------+-----------------------------------------------+------------+-----------+
| lxc1 | RUNNING | 10.108.131.206 (eth0) | fd42:f96f:612f:6693:216:3eff:fe8c:516 (eth0) | PERSISTENT | 0 |
+------+---------+-----------------------+-----------------------------------------------+------------+-----------+
| lxc2 | RUNNING | 10.108.131.167 (eth0) | fd42:f96f:612f:6693:216:3eff:feec:fa39 (eth0) | PERSISTENT | 0 |
+------+---------+-----------------------+-----------------------------------------------+------------+-----------+
Deberemos meter una clave publica en el authorized_keys de cada uno de los contenedores para poder acceder desde el cliente.
Y también instalaremos haproxy
sudo apt install haproxy -y
Bien, una vez instalado, deberemos configurar el archivo /etc/haproxy/haproxy.cfg
. De la configuración que viene por defecto, en la parte defaults he cambiado el modo de http a tcp. Luego ha añadido dos bloques para cada uno de nuestros contenedores, el frontend y el backend.
En el bloque frontend estamos definiendo desde que ips aceptamos trafico y por que número de puerto, y el backend al que lo redireccionaremos.
En este enlace hay una buena documentación de las opciones y directivas que tenemos para configurar el archivo haproxy.cfg
En el bloque backend estamos diciendo el tipo de balanceo que haremos y a que contenedor lxc vamos a redireccionar el tráfico.
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
mode tcp
#mode http
option tcplog
#option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
frontend lxc0
bind 0.0.0.0:2220
default_backend lxc0
backend lxc0
balance roundrobin
server lxc0 10.108.131.2:22 check
frontend lxc1
bind 0.0.0.0:2221
default_backend lxc1
backend lxc1
balance roundrobin
server lxc1 10.108.131.206:22 check
frontend lxc2
bind 0.0.0.0:2222
default_backend lxc2
backend lxc2
balance roundrobin
server lxc2 10.108.131.167:22 check
Si ahora nos intentamos conectar al server0 por el puerto 2220,2221 o 2222 nos redireccionará al contenedor lxc correspondiente.
athos@athos-Z97P-D3:~$ ssh -p 2220 root@192.168.1.121
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-174-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
0 packages can be updated.
0 updates are security updates.
New release '18.04.4 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Last login: Sat Feb 22 13:57:26 2020 from 10.108.131.1
root@lxc0:~#
athos@athos-Z97P-D3:~$ ssh -p 2221 root@192.168.1.121
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-174-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
0 packages can be updated.
0 updates are security updates.
New release '18.04.4 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Last login: Sat Feb 22 13:57:13 2020 from 10.108.131.1
root@lxc1:~#
athos@athos-Z97P-D3:~$ ssh -p 2222 root@192.168.1.121
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-174-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
0 packages can be updated.
0 updates are security updates.
New release '18.04.4 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Last login: Sat Feb 22 14:00:38 2020 from 10.108.131.1
root@lxc2:~#
Y esto es todo lo necesario. El post parece un poco largo para lo que hemos hecho.
El resumen es que instalamos haproxy, cambiamos el modo, y ponemos los bloques frontend y backend para cada contenedor.