= Installation d'un serveur OpenVZ - ma version de l'histoire = Objectif: laisser des traces de ma propre expérience de la mise en place d'un serveur openvz et les soucis particuliers que j'ai rencontrés. == Installation == === Fiche serveur === * Sur le noeud physique: * '''Services''': openssh, openvz (noyau) * '''Sécurité''': sudo, Logcheck, tripwire, iptables * '''Suivi/Outils''': Git/etckeeper, mtr, netdiag, iptraf, tcpdump, dnsutils, nmap, tcpdump, vim * Sur chaque serveur virtuel * '''Services''': ssh, ntp (au minimum) + services spécifiques au serveur * '''Sécurité''': sudo, Logcheck, tripwire, iptables * '''Suivi/Outils''': Git/etckeeper, mtr, netdiag, iptraf, tcpdump, dnsutils, nmap, tcpdump, vim === Schéma de partitionnement === * voir la page [[http://wiki.auf.org/wikiteki/Partitionnement || Partitionnement]] === Configuration réseau === * 2 interfaces actives: * 1 interface d'administration: elle est configurée complètement * 1 autre pour le pont ethernet laissée non configurée. === Tâches supplémentaires à exécuter === * corriger le fichier /etc/apt/sources.list: utilisation des dépôts locaux. * mise à jour du système (notamment les mises à jour de sécurité). * Editer le fichier /etc/hostname * Editer le fichier /etc/resolv.conf * Editer le fichier /etc/hosts et supprimer les fichiers /etc/hosts.allow et /etc/hosts.deny * Installer le noyau correspondant le mieux à l'architecture du serveur et supprimer la version antérieur (après redémarrage bien sûr). === Installation des logiciels === ==== Sudo ==== {{{ # aptitude install sudo # visudo -f /etc/sudoers # /etc/sudoers ... # User privilege specification root ALL=(ALL) ALL nacer ALL=(ALL) ALL }}} ==== SSH ==== Suivre la démarche décrite [[http://wiki.auf.org/wikiteki/SSH| ici]]. Ajouter le compte d'administration (ici nacer) au groupe ssh: {{{ $ sudo usermod -a -G ssh nacer }}} Copier ma clé publique sur le serveur, à partir d'une clé usb par exemple: {{{ $ sudo mount -t vfat /dev/sda1 /mnt/ $ mkdir .ssh $ cat /mnt/id_dsa.pub >> .ssh/authorized_keys $ chmod u=rw,go=r .ssh/authorized_keys }}} Tester la configuration en essayant de se connecter à partir du poste d'administration. ==== tripwire ==== ==== ntp (client) ==== * Installation: {{{ $ sudo aptitude install ntp }}} * Configuration (fichier /etc/ntp.conf): {{{ ... #Paramètres du serveur: server ntp.cm.refer.org #Restreindre le type d'accès: restrict default notrust nomodify nopeer # configuration de l'hôte local restrict ntp.cm.refer.org restrict 127.0.0.1 ... }}} * Relancer le service: {{{ $ sudo invoke-rc.d ntp restart }}} * Corriger l'heure de l'horloge matérielle: {{{ $ sudo hwclock --systohc }}} * Vérifier avec quel(s) serveur(s) on est synchronisé: {{{ $ ntpdc -p remote local st poll reach delay offset disp ======================================================================= *192.168.100.2 10.45.0.242 14 64 77 0.00027 0.004907 0.43616 }}} la colonne '''reach''' > 0. ==== Logcheck ==== '' to do '' ==== Nmap ==== '' to do: tutoriel '' ==== Tcpdump ==== '' to do: tutoriel '' ==== Git ==== Voir [[http://wiki.auf.org/wikiteki/Git/SuiviDeConfiguration| ici]] == Création le template (image de base) OpenVZ == * Voir la [[http://wiki.openvz.org/Debian_template_creation#Squeeze_.28current_Debian_stable.29 | documentation de référence ]]. * Une fois l'image de base configurée à son goût, organiser le réseau. Voir les explications de la [[http://wiki.auf.org/wikiteki/OpenVZ/OrganisationR%C3%A9seau| méthode pont ethernet]]: {{{ # aptitude install bridge-utils }}} * mise en place de l'interface veth: vérifier que les modules correspondant sont bien chargés: {{{ # lsmod | grep vzeth vzethdev 12480 0 vzmon 38152 5 vzethdev,vznetdev,vzrst,vzcpt vzdev 3620 4 vzethdev,vznetdev,vzmon,vzdquota }}} * et sinon: {{{ # modprobe vzethdev }}} * Rendre persistante la configuration du pont * indiquer un script personnalisé à lancer au démarrage du serveur virtuel, comme par exemple: {{{ #!/bin/bash # /usr/local/sbin/vznetaddroute # a script to bring up virtual network interfaces (veth's) in a VE ETH=$3 BRIDGE=vz1 # je fixe le nom du bridge, mais penser à standardiser les noms des interfaces # afin de pouvoir écrire un script plus généraliste CONFIGFILE=/etc/vz/conf/$VEID.conf . $CONFIGFILE VZHOSTIF=`echo $NETIF |sed 's/^.*host_ifname=\(.*\),.*$/\1/g'` # je laisse les contrôles pour les messages fort utiles s'il y a un problème if [ ! -n "$VETH_IP_ADDRESS" ]; then echo "According to $CONFIGFILE VE$VEID has no veth IPs configured." exit 1 fi if [ ! -n "$VZHOSTIF" ]; then echo "According to $CONFIGFILE VE$VEID has no veth interface configured." exit 1 fi for IP in $VETH_IP_ADDRESS; do echo "Adding interface $VZHOSTIF and route $IP for VE$VEID to CT0" /sbin/ifconfig $VZHOSTIF 0 #echo 1 > /proc/sys/net/ipv4/conf/$VZHOSTIF/proxy_arp -- la valeur par défaut de /etc/sysctl.conf suffit #echo 1 > /proc/sys/net/ipv4/conf/$VZHOSTIF/forwarding -- déjà fait dans /etc/sysctl.conf #/sbin/ip route add $IP dev $VZHOSTIF -- ce n'est plus correct /sbin/ip route add $IP dev $BRIDGE # parce que j'ai pas configuré d'adresse sur vz1 done /usr/sbin/brctl addif $BRIDGE $ETH exit 0 }}} * et le rendre exécutable {{{ # chmod 0500 /usr/sbin/vznetaddbr }}} '''Note: le script proposé ici, pris dans la documentation officielle de openvz et personnalisé, à l'avantage de faire un peu de logging, ce qui n'est pas mal quand il y a des soucis.''' * ajuster le lien vers ce script: {{{ # cat /etc/vz/vznet.conf EXTERNAL_SCRIPT=/usr/local/sbin/vznetaddroute }}} * Configurer les interfaces sur l'hote physique (eth1 est l'interface ethernet associée au pont sur le noeud physique et eth0 l'interface d'administration): {{{ # echo 0 > /proc/sys/net/ipv4/conf/eth0/forwarding }}} * Configurer la table de routage sur l'hote physique (normalement effectué par le script. si c'est pas le cas redémarrer vz) == Création d'une machine virtuelle OpenVZ == * Créer la machine virtuelle à partir du modèle (image) crée précédemment: {{{ # sudo vzctl create 101 }}} pas besoin d'indiquer le template ici, car on a déjà configuré le template par défaut comme étant celui que nous avons précédemment crée. * éditer le fichier de configuration du serveur virtuel /etc/vz/conf/xxx.conf * supprimer toutes entrée IP_ADDRESS afin d'éviter la création seulement du périphérique de type VENET dans l'environnement virtuel * ajouter les entrées (en prévision du script à utiliser. Voir la note qui suit). {{{ VZHOSTBR="vethxxx.0" VETH_IP_ADDRESS=XXX.XXX.XXX.XXX }}} * éventuellement charger les modules iptables nécessaires. Exemple: {{{ IPTABLES="ip_tables iptable_filter ipt_multiport ip_conntrack ipt_conntrack ipt_state " }}} * lier l' interface eth0 de la machine virtuelle à l'interface virtuelle vethxxx.0 de l'hôte physique. Exemple pour la VE 240: {{{ # vzctl set 240 --netif_add "eth0,,veth240.0,,vz1" --save }}} Ici les macs ne sont pas indiquées, elles seront auto générées. * Configurer les interfaces et la table de routage dans le VE. Par exemple, pour la VE 240: {{{ # vzctl start 240 # vzctl enter 240 # cat /etc/network/interfaces ... auto eth0 iface eth0 inet static address 10.45.0.240 netmask 255.255.254.0 gateway 10.45.0.254 ... }}} * Relancer la machine virtuelle et voilà! == Quelques problèmes rencontrés == * Problèmes de routage * J'ai créé une machine virtuelle (et donc son espace privé /var/lib/vz/private/xxx) et ensuite j'ai créé des partitions lvm pour différentes sous arborescence du système de fichiers de cette VE. J'ai migré les données de sorte à monter les partitions aux points correspondants (/var/log, /var/spool, / et /tmp). Voici ma situation: {{{ virtual1:~# cat /etc/fstab ... /dev/mapper/serveurs-var--vz /var/lib/vz ext3 defaults 0 3 /dev/mapper/serveurs-root--asterisk /var/lib/vz/private/101 ext3 defaults,userquota 0 4 /dev/mapper/serveurs-log--asterisk /var/lib/vz/private/101/var/log ext3 defaults 0 5 /dev/mapper/serveurs-spool--asterisk /var/lib/vz/private/101/var/spool ext3 defaults 0 6 /dev/mapper/serveurs-temp--asterisk /var/lib/vz/private/101/tmp ext3 defaults 0 7 ... }}} On peut y voir les quatres partitions (asterisk) correspondants à ma VE. Mais après cette manipulation (et montage de ces partitions), à chaque tentative de démarrage de la VE j'obtiens le message suivant:"vzquota : (error) Quota on syscall for 101: Device or resource busy" * pour résoudre ce problème, j'ai désactivé ls quotas ('''heureusement j'en avais pas besoin sur ce serveur là, puisque celui-ci est complètement isolé sur une partition à part''') dans le fichier /etc/vz/conf/101.conf (en le modifiant dans le fichier /etc/vz/vz.conf, on interdit carrément l'usage des quotas disque pour toutes les machines virtuelles). L'autre alternative pour résoudre ce problème aurait été de réinitialiser les quotas pour cette machine en faisant (en prenant les paramètres DISKSPACE, DISKINODES et QUOTATIME du fichier /etc/vz/conf/101.conf): {{{ # vzquota init 101 -b 1048576 -B 1153024 -e 0D -i 200000 -I 220000 -n 0D -p /var/lib/vz/private/101 }}} * Problème de montage des partitions Après avoir mis en place le schéma de partitionnement présenté ci-dessus, je me suis rendu compte que tout se passait comme si les "sous" partitions (/tmp, /var/log, /var/spool) n'étaient pas pris en compte (dans la VE, /var/log était vide par exemple). Pour certaines VE, le répertoire /usr était vide, ce qui rendait un grand nombre de commandes indisponibles. La raison vient de la façon dont les montages sont gérés. Voici une solution (merci JC): * Ajouter la partition principale (/) dans le fichier /etc/fstab: {{{ # cat /etc/fstab ... /dev/donnees/root-asterisk /var/lib/vz/private/101 ext3 defaults 0 4 ... }}} Pour toutes les autres partitions qu'on souhaite affecter à la VE, on créera deux fichier, $VEID.mount et $VEID.umount. Voici le contenu des miens: {{{ virtual1:/etc/vz/conf# cat 101.mount #!/bin/bash NAME=asterisk RACINE=/var/lib/vz/root/101 for vol in `ls /dev/donnees | grep $NAME` do part=`echo $vol | sed s/-$NAME// | tr "-" "/"` if [[ $part != "root" ]] then mount -o noatime /dev/donnees/$vol $RACINE/$part fi done exit 0 }}} et {{{ virtual1:/etc/vz/conf# cat 101.umount #!/bin/bash NAME=asterisk RACINE=/var/lib/vz/root/101 for vol in `ls /dev/donnees | grep $NAME` do part=`echo $vol | sed s/-$NAME// | tr "-" "/"` if [[ $part != "root" ]] then mountpoint -q $RACINE/$part && umount $RACINE/$part fi done exit 0 }}} Ces scripts sont assez génériques. Pour d'autres VE, il me suffit de changer les variables NAME et RACINE. Pour cela, j'utilise la une convention de nommage des volumes logiques que je crée. Par exemple, pour le serveur asterisk, je cree une partition pour le /var/log et je le nomme var-log-asterisk. Pour /tmp, je nommerai le volume tmp-asterisk. Pour le root, je mets root-asterisk, de sorte que les scripts ne gèreront pas ce volume lors des montages/démontages. Voici les résultats: après démarrage de la VE: {{{ virtual1:/etc/vz/conf# vzctl start 101 virtual1:/etc/vz/conf# cat /proc/mounts ... /dev/donnees/vz /var/lib/vz ext3 rw,data=ordered 0 0 /dev/donnees/root-asterisk /var/lib/vz/private/101 ext3 rw,data=ordered 0 0 /var/lib/vz/private/101 /var/lib/vz/root/101 simfs rw 0 0 /dev/donnees/tmp-asterisk /var/lib/vz/root/101/tmp ext3 rw,noatime,data=ordered 0 0 /dev/donnees/var-log-asterisk /var/lib/vz/root/101/var/log ext3 rw,noatime,data=ordered 0 0 /dev/donnees/var-spool-asterisk /var/lib/vz/root/101/var/spool ext3 rw,noatime,data=ordered 0 0 ... }}} Après arrêt de la VE: {{{ virtual1:/etc/vz/conf# vzctl stop 101 virtual1:/etc/vz/conf# cat /proc/mounts ... /dev/donnees/vz /var/lib/vz ext3 rw,data=ordered 0 0 /dev/donnees/root-asterisk /var/lib/vz/private/101 ext3 rw,data=ordered 0 0 ... }}} = Maintenance = == Je reçois via logcheck des messages du genre '''Mar 12 12:14:43 vz-bac kernel: [1795653.115214] Orphaned socket dropped (130,520 in CT0) ''' == '''Voir:''' http://forum.openvz.org/index.php?t=msg&goto=25080&&srch=Orphaned+socket#msg_25080 et http://forum.openvz.org/index.php?t=msg&goto=3895&&srch=Orphaned+socket#msg_3895 et pour qui lit l'espagnol, il y a un bon résumé à l'adresse http://www.rubenortiz.es/2009/04/06/orphaned-socket-dropped-ii/. Ce message apparaît pour deux raisons: - soit le nombre de sockets orphelins d'un VE est supérieur au 1/4 * numtcpsock.barrier - soit le nombre de sockets orphelins d'un VE est supérieur au paramètre sysctl net.ipv4.tcp_max_orphans. Ce message représente t il un problème: '''non'''. Un socket orphelin est un socket qui, parce qu'il contient des données ou pour autre raison, n'a pas pu être fermé immédiatement et doit continuer à exister encore quelques temps. C'est notamment le cas si le client d'une connexion au VE cesse de répondre, par exemple parce qu'il a crashé. == Un paramètre a le champ failcnt > 0 == Dans le cas d'espèce, je constate que le failcnt du paramètre tcprcvbuf = 87. '''Ce que je fais:''' {{{ vz-bac:~# vzctl set 106 --tcprcvbuf 7979232:7979232 --save ;; je passe la valeur du paramètre TCPRCVBUF de 5319488:6804288 à 7979232:7979232 et j'enregistre vz-bac:~# vzcfgvalidate /etc/vz/conf/106.conf Warning: tcprcvbuf.lim-tcprcvbuf.bar should be > 1484800 (currently, 7979232-7979232=0) ;; je passe la valeur du paramètre TCPRCVBUF à 7979232:9464032 vz-bac:~# vzctl set 106 --tcprcvbuf 7979232:9464032 --save vz-bac:~# vzcfgvalidate /etc/vz/conf/106.conf Validation completed: success }}} ---- CatégorieVirtualisation