Affichage des articles dont le libellé est DHCP. Afficher tous les articles
Affichage des articles dont le libellé est DHCP. Afficher tous les articles

mercredi 1 février 2017

Network Boot Raspberry Pi2

Voici un très court résumé de ce que nous allons devoir faire pour faire booter un Raspberry Pi 2 (RPi2) via le réseaux.

  1. sdcard + bootcode.ini
  2. DHCP/BOOTP
  3. TFTP
  4. NFSv2 (voir ce post)
  5. Brancher

Prérequis : Vous devez avoir un serveur DHCP configurable sur votre réseau.
Attention : Le serveur DHCP intégré dans les box des opérateurs internet n’est en général pas suffisamment configurable. 


1) Télécharger bootbin.bin  ici : https://github.com/raspberrypi/firmware/tree/master/boot
Mettre ce fichier sur une  carte micro SD vierge formatée en FAT32.
Mettre cette carte dans le RPi 2. (ne pas mettre en marche)


2) Configurer le serveur DHCP. Ici je donne la configuration du DHCP sur un switch Cisco.
A vous d'adapter à vos adresses ip.

ip dhcp excluded-address 192.168.0.1 192.168.0.100

ip dhcp pool CLUSTER
   network 192.168.0.64 255.255.255.192
   dns-server 8.8.8.8 
   option 43 ascii "Raspberry Pi Boot   "
   default-router 192.168.0.100 
   option 66 ascii 192.168.0.70

IMPORTANT : Il y a 3 espaces après Boot à la fin de "Raspberry Pi Boot   "

- network définit le (sous)réseaux dans lequel  les adresse ip sont allouées par le serveur dhcp.
Le « ip dhcp excluded-address exclue les ip  de 1 à 100. L’allocation aura donc lieu dans l’intervalle 101..126
- dns-server définit l’ip du résolveur dns. Ici celui de Google.
- default-router définit l'ip de la gateway (routeur)
- option 66 définit le nom du serveur TFTP, donné sous forme d’adresse IP.


3) Configuration du serveur TFTP  (ici configuration avec Centos 7)

yum install tftp-server tftp
systemctl start tftp 
systemctl enable tftp

Mettre tous les fichiers nécessaires au boot d’un RPi2 (ou d’un RPi3) dans la racine du serveur TFTP.
Par défaut le serveur TFTP sert  les fichiers qui sont dans /var/lib/tftpboot

Télécharger les dernière versions depuis  https://github.com/raspberrypi/firmware/tree/master/boot
ou prendre des version plus 'mature' sur la partition FAST d'une sdcarte carte. Cette partition est ensuite montée sous le nom de /boot.


bootcode.bin
On l’a déjà mis sur la carte de notre Rpi2, mais un Rpi3 sans sdcard peut le prendre directement sur le serveur TFTP.

Les 4 fichiers start*.elf
Celui utilisé dépendra de la répartition mémoire entre GPU et CPU
(Voir paramètre gpu_mem=... dans config.txt)
    start.elf
    start_cd.elf
    start_x.elf
    start_db.elf 

A chaque fichiers start*.elf correspond un fichier fixup*.dat
    fixup.dat  
    fixup_cd.dat 
    fixup_x.dat
    fixup_db.dat  

Le kernel ARM7 32 bits multi cores commun à RPi2 et RPi3
    kernel7.img

Les Device Tree
    bcm2709-rpi-2-b.dtb
    bcm2710-rpi-3-b.dtb

Créer les deux fichiers de configuration vide (on les remplira plus tard)
    config.txt
    cmdline.txt


4) Enfin, mettre le RPi sous tension.
Dans /var/log/message on doit trouver l’activité du serveur TFTP
   tftpd: Client 192.168.0.126 finished config.txt
   tftpd: Client 192.168.0.126 finished start.elf
   tftpd: Client 192.168.0.126 finished fixup.dat
   tftpd: Client 192.168.0.126 finished config.txt
   tftpd: Client 192.168.0.126 finished config.txt
   tftpd: Client 192.168.0.126 finished cmdline.txt
   tftpd: Client 192.168.0.126 finished kernel7.img
   tftpd: Client 192.168.0.126 finished bcm2709-rpi-2-b.dtb
   tftpd: Client 192.168.0.126 finished config.txt

Note: Le serveur TFTP ne montre que les transferts effectifs. Si on regarde avec tcpdump le trafic réseaux on découvre que le processus de boot teste l’existence de bien d'autres fichiers:

tcpdump -l -n -v -ttttt -i eth0 -s 1500 udp  | grep –line-buffered RRQ | awk ‘{print $6}’


   358bec05/start.elf 
   autoboot.txt 
   config.txt 
   recovery.elf 
   start.elf 
   fixup.dat 
   recovery.elf 
   config.txt 
   dt-blob.bin 
   recovery.elf 
   config.txt 
   bootcfg.txt 
   cmdline.txt 
   recovery7.img 
   recovery.img 
   kernel7.img 
   armstub7.bin 
   armstub.bin 
   kernel7.img 
   bcm2709-rpi-2-b.dtb 
   config.txt

Cette séquence varie en fonction des fichiers effectivement trouvés sur le serveur TFTP et en fonction du contenu de config.txt

Si tout se passe bien vous aurez au bout d'environ 5 ou 6 secondes la mire colorée, puis les info du chargement du kernel qui se terminera pas un message du type:

PANIC Unable to mount root fs. 

C'est normal ! L’étape suivante est de justement fournir ce root file system via NFSv2.

Si rien ne ce passe il faudra debugger le DHCP puis le TFTP avec tcpdump ou wireshark.
Pour voir tout le trafic il faudra utiliser un hub, pas un switch.
Quand le processus de boot échoue le led d’activité clignote 4 fois (parfois 7).
Si le RPi2 émet plusieurs requêtes DHCP alors que le serveur DHCP lui répond c'est que la réponse ne lui convient pas.


lundi 19 octobre 2015

Auto Configuration

Principe

Il n’est pas question de configurer à la main la carte micro-SD de chaque Raspberry Pi 2 du cluster. Nous allons plutôt construire une image unique, un master, que l’on dupliquera. A chaque boot le Rasperry Pi s’auto configurera pour fonctionner comme nœud du cluster. Ce système d’auto configuration devra donner une adresse IP unique, ainsi qu’un nom (hostname) unique, à chaque nœud.

L’affectation d’une adresse IP spécifique à chaque nœud se fera par DHCP. L’affectation du hostname pourrait aussi se faire via DHCP, mais tous les serveurs DHCP ne le permettent pas (en particulier ceux inclus dans les box des opérateurs internet). L’affectation du hostname unique se fera donc via un script exécuté sur le nœud à chaque fois qu’il recevra une adresse IP du serveur DHCP.

Concrètement

  • Les IP seront allouées dans le réseau privé 192.168.0.0/24
  • Sur la base de son adresse MAC, chaque nœud obtiendra du serveur DHCP une IP fixe spécifique, de la forme 192.168.0.XXX
  • Au moment de l’allocation de cette adresse IP un script extraira du fichier /etc/hosts le hostname associé a cette IP et l'affectera au système.
Le lien entre adresse MAC et adresse IP sera configuré une fois pour toutes dans le serveur DHCP. Donc, au lieu de configurer chaque carte micro-SD individuellement avec sa propre ip et son hostname, on configurera de manière centralisé le serveur DHCP.

Exemple :
    Adresse MAC envoyée au serveur DHCP: b8 27 eb c6 3f 77
    Adresse IP retournée par le DHCP: 192.168.0.105
    Hostname assigné: node05

PAS à PAS

Si rien n'est dit c'est qu'il faut faire la même chose avec Raspberian et avec CentOS.

a) Désactiver ipv6
Ajouter disable_ipv6=1 à la fin de l'unique ligne de /boot/cmdline.txt
et/ou ajouter au fichier /etc/sysctl.conf la ligne
net.ipv6.conf.all.disable_ipv6=1


b) Mettre à jour /etc/hosts

(on en profite pour enlever tout ce qui concerne ipv6)

> cat /etc/hosts
127.0.0.1       localhost
 

192.168.0.101   node01
192.168.0.102   node02
192.168.0.103   node03
 ...

192.168.0.115   node15
c) Configuration du daemon client dhcpcd (Raspbian)
Son vrai nom est dhcpcd5 bien que ce soit la version 6 !

> cat /etc/dhcpcd.conf
# debug
ipv4only
noarp
option domain_name_servers, domains_name
nohook lookup-hostname, hostname

TOUT le reste doit être supprimé ou mis en commentaire avec #

Pour CentOS rien à faire (le fichier /etc/dhcpcd.conf n'existe pas) et le client s’appelle dhclient.


d) interfaces (Raspbian)


cat /etc/network/interfaces
auto  lo eth0
iface lo   inet loopback
iface eth0 inet manual

Même si c’est dhcpcd qui configurera l’interface eth0 il ne faut pas utiliser ‘dhcp’ mais ‘manual’.

Pour CentOS toujours rien à faire, eth0 est par défaut configurée par dhcp.

e) Attribution du hostname (Raspbian)

Dans le répertoire /lib/dhcpcd/dhcpcd-hooks créer le fichier 99-set-hostname

cat /lib/dhcpcd-hooks/99-set-hostname
get_hostname()
{

    [ -z "$new_ip_address" ] && return 1
    local h="$(/usr/bin/getent hosts $new_ip_address)"
    if [ $? = 0 ]; then
        echo "$h" | sed 's/[^ ]* *\([^ ]*\).*/\1/'
        return 0
    fi
    return 1
}

if $if_up ; then
    if [ -z "$new_host_name" -a -z "$new_fqdn_name" ]; then
        export new_host_name="$(get_hostname)"
        hostname $new_host_name
    fi
fi
Ce script utilise l'adresse ip assignée par le serveur DHCP pour trouver le hostname dans le fichier /etc/hosts et l'assigner au système. (c'est du reverse DNS sans DNS)

Note: dans ce même répertoire les deux scripts 29-loopup-hostname et 30-hostname ont été désactivés dans /etc/dhcpcd.conf par la commande :
nohook lookup-hostname, hostname
e) Attribution du hostname (CentOS 7.x)

A chaque changement dans la config réseau le NetworkManager exécute les scripts qui sont dans /etc/NetworkManager/dispatcher.d Dans ce répertoire il y a déjà le script 11-dhclient qui source  les scripts xxxx.sh qui sont dans  le répertoire /etc/dhcp/dhclient.d et invoque la fonction xxxx_config quand interface devient  ‘up’, ou xxxx_restore quand une interface passe ‘down’. Les variables d’environnement donnant les info sur l’interface concernée (ip, netmask, gateway ..)
On va donc mettre notre script sethostname.sh dans /etc/dhcp/dhclient.d

cat /etc/dhcp/dhclient.d/sethostname.sh

function sethostname_config {
  local ip_addr=127.0.0.1
  if [ -n "$IP4_ADDRESS_0" ]; then
    ip_addr="$(echo "$IP4_ADDRESS_0" | /usr/bin/cut -d'/' -f1)"
  else
    ip_addr=$DHCP4_IP_ADDRESS
  fi
  local h="$(/usr/bin/getent hosts $ip_addr)"
  if [ $? = 0 ]; then
    export new_hostname=$(echo "$h" | /usr/bin/awk '{print $2}')
    /usr/bin/hostnamectl --static set-hostname $new_hostname
    echo "Set my hostname to '$new_hostname' "
  else
    echo "ERROR: Cannot find $ip_addr in /etc/hosts"
  fi
}

function sethostname_restore {
  : # nothing todo

}

Note: Suivant la version du client dhcp ce sont les variables $IP4_* ou $DHCP4_* qui sont utilisées. D'où le test en début de script pour initialiser $ip_addr. Si le nom de host est 'localhost' c'est que aucune des deux variables n'existe, ou que le fichier /etc/hosts n'est pas à jour.

Ne pas oublier:

chmod +x /etc/dhcp/dhclient.d/sethostname.sh


f) Configurer le serveur DHCP
Se loguer sur chaque Raspberry Pi 2 pour noter l’adresse MAC de son interface Ethernet. Le plus simple est de faire cela via la console (HDMI/clavier usb), sans câble réseau. Ne pas être connecter au réseau évitera des problèmes de cache DHCP.

Une fois connecté à la console du Raspberry taper la commande :

cat /sys/class/net/eth0/address


Note : L’adresse MAC (Media Access Control Address) est constituée de 6 octets. Les 3 octets de poids fort dépendent du fabriquant. Pour Raspberry ces 3 octets sont toujours : b8 27 eb. Les 3 octets de poids faible identifient l’interface. Dans le cas des RPi ce sont les 3 octets de poids faible du numéro de série que l’on peut voir avec la commande : cat /proc/cpuinfo


Pour chaque adresse MAC ajouter une entrée dans la configuration du serveur DHCP. (voir la doc de cotre serveur DHCP. Exemple ci-contre)

La routine à répéter 15 fois est donc :
- se loger a un Raspberry en console et sans câble réseau
- noter l'adresse mac afficher par cat /sys/class/net/eth0/address
- mettre à jour le serveur DHCP (adresse mac, adresse ip)
- brancher le réseau
- rebooter le RPi (alt-ctrl-del)
- Au boot on doit avoir l'IP et le hostname voulus.
- shutdown
- deplacer la carte micro-sd au raspberry suivant
répéter...


Patience, ne dupliquez pas encore cette carte.
A SUIVRE...