LXC beginner

Configuration environnement local

mkdir ~/.config/lxc/
echo "lxc.include = /etc/lxc/default.conf" > ~/.config/lxc/defaults.conf
echo "lxc.id_map = u 0 100000 65536" > ~/.config/lxc/defaults.conf
echo "lxc.id_map = g 0 100000 65536" > ~/.config/lxc/defaults.conf
echo "lxc.lxcpath=/srv/containers/lxc" > ~/.config/lxc/lxc.conf

sudo mkdir -p /srv/containers/lxc
sudo chown 10000 /srv/containers/lxc
sudo chmod g+w /srv/containers/lxc

Creation container

TODO: voir comment faire un template local

lxc-create -t download -n lxc-debian

Les donnés du container seront dans /srv/containers/lxc/lxc-debian

Lancer une instance éphémère, c'est à dire qu'elle se supprime après le stop.

lxc-copy --name lxc-debian -N p1

Connaître les données de configuration de p1 (@IP ...)

lxc-ls --fancy

Se connecter à la machine en mode admin

lxc-attach --name p1

Arrêter la machine p1

lxc-stop --name p1

Exemple de workflow : créer un service web

On clone la base

lxc-copy --name lxc-debian -N lxc-webserver

On installe et configure le service web : DocumentRoot par défaut /var/www/html

lxc-start -n lxc-webserver
lxc-attach -n lxc-webserver
apt install nginx
exit

lxc-ls --fancy
NAME          STATE   AUTOSTART GROUPS IPV4       IPV6 
lxc-debian    STOPPED 0         -      -          -    
lxc-webserver RUNNING 0         -      10.0.3.250 -

# Test
curl http://10.0.3.250
# \o/

On crée les env de test

mkdir -p ${HOME}/src/LXC-CONF/web/site{1,2}
echo "site 1" > ${HOME}/src/LXC-CONF/web/site1/index.html
echo "site 2" > ${HOME}/src/LXC-CONF/web/site2/index.html

on lance une instance pour chaque site

lxc-copy -n lxc-webserver -e -m bind=${HOME}/src/LXC-CONF/web/site1:/var/www/html:ro -N site1
lxc-copy -n lxc-webserver -e -m bind=${HOME}/src/LXC-CONF/web/site2:/var/www/html:ro -N site2

lxc-ls --fancy
NAME          STATE   AUTOSTART GROUPS IPV4       IPV6
lxc-debian    STOPPED 0         -      -          -
lxc-webserver STOPPED 0         -      -          -
site1         RUNNING 0         -      10.0.3.250 -
site2         RUNNING 0         -      10.0.3.127 -


# tests
curl http://10.0.3.250
Site 1

curl http://10.0.3.127
Site 2
# \o/

Résolution de nom

Par défaut, lxc lance dnsmasq pour le réseau des conteneurs. Par défaut depuis le début c'est le réseau 10.0.3.0/24. L'adresse de l'hôte est 10.0.3.1. C'est à cette adresse que la résolution se fait. Si on souhaite résoudre les sites en dehors d'un conteneur, si rien n'est configuré, il faut donner explicitement le nom du serveur dns aux commandes de résolution :

host site1 10.0.3.1
Using domain server:
Name: 10.0.3.1
Address: 10.0.3.1#53
Aliases:

site1 has address 10.0.3.250

On voit que pour monter du site à la demande, il faut faire des ajustements : * du NAT/PAT ou bridge depuis le serveur hôte ou alors un mod_proxy * configurer le dns de l'hôte pour utiliser les noms des sites plutôt que leur @IP

Pour forcer les @IP des serveurs, soit on le fixe dans les conteneurs, soit on le fixe dans la configuration de dnsmasq.

Pour continuer, j'ai choisi la seconde solution plus flexible.Sur la Debian, il faut éditer le fichier /etc/default/lxc-net et dé commenter la ligne contenant la déclaration de la variable LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

Puis définir les @ip en fonction des noms de conteneurs

cat /etc/lxc/dnsmasq.conf
dhcp-host=site1,10.0.3.101
dhcp-host=site2,10.0.3.102

... et on relance le service réseau de lxc

systemctl restart lxc-net.service

En relançant les conteneurs site1 et site2, on vérifie bien que les @IP sont celles affectées dans le fichier de conf de DNSMASQ.

HAPROXY

Pour tester un mécanisme de HA avec les deux sites web, j'ai décidé de tester haproxy dans un conteneur.

Je décide de fixer l'@IP du conteneur :

echo "dhcp-host=haproxy,10.0.3.100" | sudo tee -a /etc/lxc/dnsmasq.conf'
sudo systemctl restart lxc-net.service

Comme pour les serveurs web, je fais une copie du conteneur lxc-debian en lxc-haproxy qui va me servir de modèle. Ce nouveau modèle doit être exécuté pour l'installation de haproxy.

lxc-copy -n lxc-debian -N lxc-haproxy
lxc-start -n lxc-haproxy
lxc-attach -n lxc-haproxy
apt install haproxy haproxyctl
exit

La configuration de haproxy se fait à l'aide du fichier de configuration /etc/haproxy/haproxy.cfg

Pur permettre une configuration en dehors du conteneur, on va créer un fichier de configuration dans l'environnement de tests et l'utiliser via un point de montage lors du lancement du conteneur.

mkdir -p ${HOME}/src/LXC-CONF/web/haproxy

Créer le fichier ${HOME}/src/LXC-CONF/web/haproxy/haproxy.cfg avec la configuration souhaitée (cf exemple en Annexes) puis lancer le service haproxy

 lxc-copy -n lxc-haproxy -e -m bind=${HOME}/src/LXC-CONF/web/haproxy:/etc/haproxy:ro -N haproxy

Test de bon fonctionnement:

lxc-ls --fancy
NAME          STATE   AUTOSTART GROUPS IPV4       IPV6
haproxy       RUNNING 0         -      10.0.3.100 -
lxc-debian    STOPPED 0         -      -          -
lxc-haproxy   STOPPED 0         -      -          -
lxc-webserver STOPPED 0         -      -          -
site1         RUNNING 0         -      10.0.3.101 -
site2         RUNNING 0         -      10.0.3.102 -


for i in $(seq 1 10); do curl http://10.0.3.100/; done
Site 1
Site 2
Site 1
Site 2
Site 1
Site 2
Site 1
Site 2
Site 1
Site 2

Test de failover

lxc-stop -n site2

for i in $(seq 1 10); do curl http://10.0.3.100/; done
Site 1
Site 1
Site 1
Site 1
Site 1
Site 1
Site 1
Site 1
Site 1
Site 1

Test de reprise

lxc-copy -n lxc-webserver -e -m bind=${HOME}/src/LXC-CONF/web/site2:/var/www/html:ro -N site2

/o\ le retour de Site2 ne fonctionne pas.

FIXME:

En se connectant (lxc-attach) au site 2, le tcpdump montre que les paquets
arrivent mais le sevrice nginx ne répond pas. arp -a ne montre aucune entrée
pour haproxy.
En faisant un ping vers haparoxy, la table arp est bonne et les flux sont ok.
=> Y'a un schmole dans la conf lxc ou est-ce un bug ?

TODO

  • configurer le syslog
  • configurer iptables

Annexes

Fichier de coonfiguration haproxy.cfg

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/
    # An alternative list with additional directives can be obtained from
    #  https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
    ssl-default-bind-options no-sslv3

defaults
    log global
    mode    http
    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 http-in
    bind *:80
      default_backend mybackend

      backend mybackend
      balance roundrobin
#     option forceclose
#      option tcp-check
      option httpchk GET /
      timeout check 1s
      default-server inter 1s fall 1 rise 1
      server srv1 10.0.3.101:80 check
      server srv2 10.0.3.102:80 check