lundi 20 juin 2016

Créer une SD carte master pour RPi

Voici comment dupliquer 'intelligemment' une carte mémoire d'un Raspberry pi.
L'image de la certe peut ensuite etre archivé, et etre utiliser comme 'master'.

'Intelligemment' veut dire que l'on ne va pas dupliquer tout le support physique si ce n'est pas nécessaire.

Étape 1 : Évaluer la taille utile sur la carte micro SD

Depuis le RPi que le font dupliquer taper :

# fdisk  -l

Disk /dev/mmcblk0: 15.9 GB, 15931539456 bytes, 31116288 sectors
        Device Boot  Start     End  Blocks   Id  System

/dev/mmcblk0p1        2048  616447  307200    c  W95 FAT32 (LBA)
/dev/mmcblk0p2      616448 1665023  524288   82  Linux swap
/dev/mmcblk0p3     1665024 5859327 2097152   83  Linux

On voit que le support physique (/dev/mmcblk0) fait 31116288 secteurs (donc ~ 14.8 Go)  alors que la dernière partition (/dev/mmcblk0p3)  s’arrête au secteur 5859327 (~ 2.8 Go). Il suffit donc de faire une image des 5859328 premiers secteurs. Un secteur faisant 512 octets cela fait 2929664 ko à sauvegarder. Soit encore 183104 x 16 k.

Étape 2 : Créer le fichier image

Depuis une autre machine ayant suffisamment d’espace disque, on peut aller pomper l’image d’un des raspberry du cluster en utilisant dd au travers de ssh :

# ssh root@rbpi09 "dd if=/dev/mmcblk0 count=183104 bs=16k" > /tmp/rpi.img
183104+0 records in
183104+0 records out
2999975936 bytes copied, 328.288 s, 9.1 MB/s


Étape 3: Vérifier / retoucher l’image

La commande ‘file’ va indiquer si le fichier est reconnaissable

# file rpi.img
rpi.img: x86 boot sector;
 
partition 1: ID=0xc, starthead 32, startsector 2048, 614400 sectors;
partition 2: ID=0x82, starthead 94, startsector 616448, 1048576 sectors;
partition 3: ID=0x83, starthead 163, startsector 1665024, 4194304 sectors, code offset 0xb8

Avec la commande fdisk -l rpi.img on retrouve les même info.

On peut monter les partitions fat32 et Linux, à condition de donner leur offset de début dans le fichier à l’octet prêt, c’est-à-dire offset = 512  * Secteur de démarrage.
Pour la partition FAT32 offset = 512 * 2048 = 10315776
Pour la partition Linux  offset = 512 * 1665024 = 852492288

 # mkdir /mount/img
 # mount -o loop,offset=852492288 rpi314.img2 /mnt/img
On peut même aller modifier les fichiers dans /mnt/img (pour vider des log par exemple)
On termine par : umount /mnt/img

Si on veut manipuler les partitions (changement de taille, tester le file system) on ne peut pas le faire si le fichier image est montée avec 'mount'. Il faut à la place créer une interface loopback avec la commande 'losetup' :

 # losetup -o offset -f --show rpi.img 

remplacer offset par l'offset de début de la partition (comme avec mount)
Grace à l'option --show losetup affiche sur quelle interface la partition a été montée. (En général /dev/loop1)

On peut alors utiliser cette interface comme on le fait
# fsk /dev/loop1
e2fsck 1.42.9 (28-Dec-2013)
/dev/loop1: clean, 68537/131072 files, 341154/524288 blocks

Terminer avec ' losetup -D'  pour détacher toutes les interfaces loopback.
Le fichier image peut être compressé pour être archivé, ou être utilisé pour créer d'autre cartes micro SD.

Étape 5 : Graver l'image


mercredi 18 mai 2016

OpenMP vs OpenMPI vs MPICH

Dès que l’on s’intéresse à la programmation parallèle on rencontre ces trois acronymes OpenMP, Open MPI et MPICH dont les noms entretiennent la confusion
  • OpenMP = Open Multi-Processing
  • Open MPI = Open Message Passing Interface
  • MPICH = Message Passing Interface over CHameleon
Les trois fonctionnent avec C/C++ et Fortran et sont supportés  par gcc et les principaux compilateurs. Leur but commun est de permettre le développement de programmes parallèles.



OpenMP est principalement implémenté au travers d’extensions du compilateur C/C++ ou Fortran. Des directives sont données au compilateur au travers de #pragma (ou de !$ pour Fortran) afin qu’il génère des blocs  de code s’exécutant en parallèle sur des architectures multiprocesseurs à mémoire partagée. Typiquement une machine Linux ou Windows avec un i5 ou i7 ou un Raspberry Pi avec un ARM7 ou ARM8. 

L'avantage de OpenMP est d’être très peu intrusif et de rendre la parallélisation d'un programme plus naturelle. Pour apprendre OpenMP la chaine OpenMP sur YouTube est excellente!


Open MPI  et MPICH sont deux implémentations du standard  MPI (Message Passing Interface). Leur but est de produire un programme qui s’exécute en parallèle sur les ordinateurs d’un réseau. Le partage de donnée ne se fait pas via la mémoire comme avec OpenMP mais via le réseau. C’est plus lent mais plus extensible et c'est le seul moyen de faire travailler des centaines ou milliers de processeurs ensemble. Les performances et la fiabilité du réseau sont donc critiques dans les applications MPI mais

Les principaux supports de Open MPI sont Cisco, Intel, Nvidia et les principaux supports de MPICH sont Cray, IBM, Intel, Microsoft. Fin 2015 MPICH est utilisé sur 9 des 10 plus puissants ordinateurs du monde.

Tout un écosystème d’applications gravite autour de MPI. Les programmes s’exécutant sur des clusters d’ordinateurs  il faut des  logiciels pour administrer/superviser  le cluster.

Tout langage qui peut s'interfacer avec une librairie C peut utiliser MPI : Python, Perl ...

TRÈS IMPORTANT : Rien n’empêche d’utiliser OpenMP en même temps que OpenMPI ou MPICH. Par contre on n’utilise jamais ensemble OpenMPI et MPICH.

mercredi 20 avril 2016

Rasberry Pi2 vs Pi3

Faut-il remplacer les Raspberry Pi2 B de  notre cluster par des  Raspberry Pi3 ?

Voici 3 réflexions:

1) La première est que l’utilisation de 64 bits (ARMv8)  induit automatiquement l’utilisation de plus de mémoire aussi bien pour le code que les données. Le classique index de boucle
for (int i=0 ; i<1000 ; i++) { … } 
prenait 32 bits (alors que 16 suffisaient largement) maintenant il en faudra 64 sans aucun gain. Sur un serveur avec 16 Go de RAM on ne s’inquiète pas de ce genre de détail, mais sur une RPi avec seulement 1 Go (dont une partie est prise par la vidéo) on fait beaucoup plus attention. 

Notez que :
- Avec des pointeurs sur 32 bits on peut adresser 4 Go. Donc 32 bits sont largement suffisant pour un RPi.
- Si on écrit "for ( int16 i=0 …)" c’est le code qui est plus lent.
- Cette inflation des besoins en mémoire induite par le passage de 16 à 32 puis à 64 bits coûte tellement cher pour les applications embarquées qu’ARM a développé un jeu d’instructions 16 bits (Thumb et Thumb-2).


2) Le deuxième réflexion est que, pour le moment, on n’a pas de distributions Linux 64 bits (aarch64) utilisant le nouveau jeu d’instruction de ARMv8.  Or ce qui fait l’intérêt de l’architecture ARMv8 c’est que son jeu d’instructions a été conçu sans la contrainte de compatibilité avec le jeu d’instructions 32 bits. La performance ne vient pas des 64 bits mais de ce design moderne et sans compromis. (Le travail est en cours avec CentOS-7)

3) Comparaison des vitesses de calcul:

Note: Chaque RPi2 de notre cluster est légèrement over-clocké (1GHz) sans jamais avoir de plantages (mais alimenté en 5.2V) . Dans le fichier /boot/config.txt on a :

arm_freq=1000
core_freq=600
sdram_freq=500
over_voltage=2
over_voltage_sdram_p=4
over_voltage_sdram_i=0
over_voltage_sdram_c=0


Pour faire cette comparaison entre RPi2 à 1GHz et RPi3 à 1.2GHz (et avec un Intel i7) on va utiliser la commande “openssl speed rsa -multi x” où x est le nombre de threads à utiliser.
On devrait avoir un gain de 20% en faveur du RPi3.


Voici les résultats obtenue avec openssl 1.0.1


**** Résultats sur un RPi3 ****

[rpi3 ~]# openssl speed rsa -multi 1
================= RPi3 1x1.2Ghz ====================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000775s 0.000067s   1290.0   15000.4
rsa 1024 bits 0.003928s 0.000198s    254.6    5038.5
rsa 2048 bits 0.024988s 0.000704s     40.0    1419.6
rsa 4096 bits 0.172203s 0.002684s      5.8     372.6


[rpi3 ~]# openssl speed rsa -multi 4
================= RPi3 4x1.2Ghz ====================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000195s 0.000019s   5115.2   53333.3
rsa 1024 bits 0.001344s 0.000073s    744.3   13746.1
rsa 2048 bits 0.009693s 0.000283s    103.2    3535.3
rsa 4096 bits 0.071341s 0.001157s     14.0     864.3



**** Résultats sur un des RPi2 du cluster ****

[rpi2 ~]# openssl speed rsa -multi 1
================= RPi2 1x1Ghz ======================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.001373s 0.000109s    741.4    9259.0
rsa 1024 bits 0.006555s 0.000340s    152.5    2940.4
rsa 2048 bits 0.043712s 0.001256s     22.9     797.4
rsa 4096 bits 0.312812s 0.004840s      3.2     206.6


[rpi2 ~]# openssl speed rsa -multi 4
================= RPi2 4x1Ghz ======================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000342s 0.000027s   2923.9   36613.4
rsa 1024 bits 0.001644s 0.000085s    608.1   11721.2
rsa 2048 bits 0.010966s 0.000315s     91.2    3179.8
rsa 4096 bits 0.078496s 0.001213s     12.7     824.4



On constate que le RPi3 apporte bien un gain de vitesse souvent de plus de 20% sur le calcul pur. Donc avec un Linux 32 bits (ARMv7) on a l'avantage de la vitesse sans avoir besoin de plus de mémoire. Il n'est donc pas sur qu'un linux 64 bits (ARMv8) soir vraiment utile. 
Le gain en calcul pur est malheureusement noyé dans le fait que tout le reste est à la même vitesse sur un RPi2 et RPi3. On aurait plus besoin de 2 Go de RAM et d'un port Giga Ethernet. (Comme sur le ODROID-C2). 

Donc, si on devait faire un upgrade ce serait plus pour un odroid-c2 qu'un RPi3 !


**** Résultats sur un intel i7 3.1Ghz ****

[i7 ~]# openssl speed rsa -multi 1
================= i7-4770S 1x3.1Ghz ================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000041s 0.000003s  24187.4  297005.8
rsa 1024 bits 0.000162s 0.000009s   6158.7  114694.3
rsa 2048 bits 0.000980s 0.000029s   1020.9   34625.3
rsa 4096 bits 0.007335s 0.000108s    136.3    9241.4



[i7 ~]# openssl speed rsa -multi 4
================= i7-4770S 4x3.1Ghz ================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000012s 0.000001s  86956.5 1000000.0
rsa 1024 bits 0.000046s 0.000003s  21831.1  400000.0
rsa 2048 bits 0.000273s 0.000008s   3659.7  120320.9
rsa 4096 bits 0.002098s 0.000032s    476.6   31564.4



[i7 ~]# openssl speed rsa -multi 8
================= i7-4770S 8x3.1Ghz ================
                  sign    verify    sign/s  verify/s
rsa  512 bits 0.000011s 0.000001s  93570.5 1089285.7
rsa 1024 bits 0.000047s 0.000003s  21498.2  400000.0
rsa 2048 bits 0.000276s 0.000008s   3617.7  125000.0
rsa 4096 bits 0.002074s 0.000030s    482.1   33773.2


Pour voir la fréquence d'horloge en temps réel:
cat /sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq


Benchmarks officiels: https://www.raspberrypi.org/magpi/raspberry-pi-3-specs-benchmarks/

mardi 16 février 2016

Efficacité d'un cluster

Les plus vieux se rappellent du livre « The mythical man-month » de F.P. Brooks. Dans cet ouvrage Brooks montrait pourquoi ajouter 2 développeurs à une équipe de 2 développeurs ne divisait pas le temps de développement par deux. Aujourd’hui ceci est admis, mais à l’époque (1972) cela ne coulait pas de source et a valu beaucoup de déboires y compris aux plus gros comme IBM chez qui Brooks travaillait.  

Loi de Brooks
: Ajouter des développeurs à un projet en retard ne fait que le retarder.

Quand on travaille dans un environnement multiprocesseurs il faut garder à l’esprit cette histoire car pour des raisons similaires ajouter 2 processeurs à 2 processeurs ne divise pas forcement le temps de calcul par deux. Le gain de temps peut varier suivant l’organisation du code (ce qui est contrôlable) mais aussi suivant les données (c’est moins facile à anticiper).


Communication : C’est la clef du problème. Scinder un programme résolvant une tâche complexe en plusieurs petits programmes s’exécutant chacun sur un processeur indépendant sous-entend un minimum de communication entre ses petits programmes. Les ressources consommées par cette communication s’ajoutent aux ressources strictement requises par la tâche principale. Pour certains problèmes les communications deviennent si complexes que l’on dédit des processeurs à la gestion des communications. Il faudra trouver un équilibre entre la granularité de répartition de la charge et le cout des communications induites.

Il existe une métrique simple pour vérifier l’efficacité de la parallélisation d’une tache :

Soit ‘T1’ le temps réel pris pour résoudre le problème avec 1 processeur.
Soit ‘Tn’ le temps réel pris pour résoudre le problème avec ‘n’ processeurs.
Le temps théorique avec n processeurs est Tn’ = (T1/n).

En pratique on a cette relation : T1 > T2 > … > Tn > Tn’ > 0

Le rapport (Tn’/Tn) = T1 / (n * Tn) donne l’efficacité de la parallélisation dans son ensemble (hardware + software).

Exemple 1::
T1=60s, n=10 processeurs, T10=7, T10’ = 60/10 = 6s
Efficacité = 6/8 = 0.86

Exemple 2:
T1=60s, n=20 processeurs, T20=4, T20’ = 60/20 = 3s
Efficacité = 4/5 = 0.80

L’augmentation (10 ==> 20) de 100% du nombre de processeurs a permis de diminuer le temps de calcul (7s ==> 4s) de ~43% mais l’efficacité a chuté de ~6%.

Bien sur une efficacité de 1 (100%) n'est possible que s'il y a strictement aucun 'overhead' dû à la parallèlisation du traitement et donc aucune communication entre les n process.


Notes: Ici j’ai pris comme mesure le temps de calcul, mais on peut utiliser d’autres paramètres comme la consommation électrique, la mémoire etc…


mardi 12 janvier 2016

Centos 7 pour Raspberry Pi 2


Un SIG (Special Interest Group) a porté CentOS 7 sur plateforme ARMv7 (32 bits), et pour Raspberry Pi 2 en particulier.

Les fichiers image compressés sont ici : http://mirror.centos.org/altarch/7/isos/armhfp/

Note: L'image compressée fait environ 255Mo, l'image finale fait exactement 3Go (3,221,225,472 octets) et rentre donc sans problème sur n'importe qu'elle carte 4Go.

En trois commandes on a une carte SD bootable sur RPi2:

wget http://mirror.centos.org/altarch/7/isos/armhfp/CentOS-Userland-7-armv7hl-Minimal-1611-RaspberryPi2.img.xz


ATTENTION: pour moi la carte est en /dev/sde , à adapter à votre situation!

xzcat CentOS-Userland-7-armv7hl-Minimal-1511-RaspberryPi2.img.xz | dd of=/dev/sde bs=4M

(patienter ~5 a 6 minutes)

sync; sync

Mettre la carte dans un RPi2 et booter. 

rpi2 login: root
Password: centos

CLAVIER FRANCAIS
On passe vite en clavier français
- de manière temporaire avec: loadkeys fr
- de manière permanente avec: localectl set-keymap fr


RESOLUTION TEXTE DE LA CONSOLE
Si vous voulez augmenter la résolution de la console texte (24x80 par défaut)
il faut éditer  /boot/config.txt  et ajouter par exemple :
hdmi_group=2
hdmi_mode=16
ce qui donnera 45x120 au prochain reboot.
Plus d'info ici: http://elinux.org/RPiconfig


[root@rpi2 ~]# uname -a
Linux rpi1 4.4.45-v7+ #954 SMP Fri Jan 27 19:06:40 GMT 2017 armv7l armv7l armv7l GNU/Linux


Comme l'image est une version minimale, il faut pratiquement tout installer. Allons y ...

yum update
yum install wget 
yum install vim
yum install perl
yum install nfs-utils  rpcbind
yum group install "Development Tools"
...
Error: Package: systemtap-devel-2.8-10.el7.armv7hl (base)
           Requires: kernel-devel
 

Il semble que le package kernel-devl ne soit pas dans les repositories définit dans /etc/yum.repos.d

En fait, par défaut, les repositories définit dans /etc/yum.repos.d/ sont commun à plusieurs systèmes à base d’ARM. Les parties spécifiques à chaque système résident dans un repository spécifique à chaque système. Pour le RPi2 il faut ajouter ce fichier a /etc/yum.repo.d

cat /etc/yum.repo.d/CentOS-rpi2-kernel.repo
# CentOS-rpi2-kernel.repo
[rpi2-kernel]
name=rpi2 kernel repo for CentOS 7 userland
baseurl=http://mirror.centos.org/altarch/7/kernel/armhfp/kernel-rpi2/
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-AltArch-Arm32


Maintenant  yum group install "Development Tools"  fonctionne.

NTP

Si on tape "date" juste après le boot d'un Raspbery Pi 2 utilisant l’installation minimale de CentOS on obtient :
Thu Jan  1 00:00:21 UTC 1970

Il est donc urgent d'installer le service ntp !

  yum update
  yum install ntp



On demande une mise de la date :
  ntpdate pool.ntp.org
  14 Jan 01:08:26 ntpdate[1278]: step time server 212.47.239.163 offset 1452733476.784032 sec


On vérifie:
  date
  Thu Jan 14 01:08:07 UTC 2016


Ok. Tout marche on peut planifier le démarrage de ntpd à chaque boot:
  systemctl enable ntpd
  systemctl start  ntpd
  systemctl status ntpd


  reboot
  ...

  date
  Thu Jan 14 01:10:32 UTC 2016

OK!

MPICH



Cette librairie dédiée au calcul parallèle est disponible sur la plupart des plateformes Unix, y compris sur CentOS pour ARM.

yum install  mpich  mpich-devel  mpich-autoload  mpich-doc

La version dans ce repository n’est pas la toute dernière. Pour cela il faut aller chez Fedora:

wget http://kojipkgs.fedoraproject.org/packages/mpich/3.2/2.fc24/armv7hl/mpich-xxxx
yum install  mpich-xxxx

On peut aussi télécharger les sources ici https://www.mpich.org/downloads/ et compiler.


Voir aussi: https://wiki.centos.org/SpecialInterestGroup/AltArch/Arm32
 

mercredi 6 janvier 2016

NFS

Il y a plusieurs  raisons pour installer un serveur NFS dans notre cluster de Rasberry Pi 2:
•    Pour suppléer aux faiblesses des cartes SD liées au rapport cout / fiabilité-capacité-vitesse.
•    Il peut être plus facile aux nœuds d’échanger des données  via un espace disque commun  plutôt que via des sessions TCP (même si  NFS repose sur du réseau).
•    Pour simplifier le management/configuration/backup du cluster il peut être pratique d’avoir un espace disque partagé par tous les nœuds.
•    Pour booter via NFS et non via la carte SD. Cette dernière  restera nécessaire mais son contenu sera minimaliste et plus facile à maintenir.


Tout ce qui suit s’effectue avec l’utilisateur root.

1 NFS coté serveur

Le serveur que nous utilisons ici est une machine utilisant centos 7, donc pas un Raspberry . Dédier un Raspberry à cette tâche est possible à condition d’utiliser un disque externe, sinon on perd sur tous les tableaux.

Installation serveur NFS (centos)

yum install nfs-utils nfs-utils-lib

(depuis Centos 7.2 nfs-utils-lib n'existe plus car inclu dans nfs-utils)

systemctl enable rpcbind
systemctl enable nfs-server
systemctl start rpcbind
systemctl start nfs-server


Si les services nfs-lock et nfs-idmap sont requis voir la fin de ce post.

Vérifier l’installation
ps -e | grep rpc
    2152 ?        00:00:00 rpcbind
    2323 ?        00:00:00 rpciod
    2337 ?        00:00:00 rpc.statd
    2338 ?        00:00:00 rpc.mountd
    2339 ?        00:00:00 rpc.idmapd

ps -e | grep nfs
    1254 ?        00:00:00 nfsd4_callbacks
    1260 ?        00:00:00 nfsd
    1261 ?        00:00:00 nfsd

    ...
    2001 ?        00:00:00 nfsiod

cat /proc/filesystems | grep nfs
    nodev   nfsd
    nodev   nfs

    nodev   nfs4

rpcinfo -p | sort | grep nfs

   program vers proto   port  service
    100003    3   tcp   2049  nfs
    100003    3   udp   2049  nfs
    100003    4   tcp   2049  nfs
    100003    4   udp   2049  nfs
    100227    3   tcp   2049  nfs_acl
    100227    3   udp   2049  nfs_acl

Notez que pour chaque version de nfs (3 ou 4) les deux protocoles (udp et tcp) sont supportés sur le même numéro de port (2049).


Créer les répertoires à exporter
On va créer un répertoires par nœud et deux répertoires d'usage commun.
Le répertoire rpi-fs servira pour le network-boot (DHCP/BOOTP + TFTP)

mkdir -pv /var/nfs/node{01..15} /var/nfs/common /var/nfs/rpi-fs

chown  nfsnobody.nfsnobody        /var/nfs/*
chmod  a=rx,ug+w                  /var/nfs/*


ls –l /var/nfs
drwxrwxr-x 2 nfsnobody nfsnobody  common
drwxrwxr-x 2 nfsnobody nfsnobody  node01
...
drwxrwxr-x 2 nfsnobody nfsnobody  node15

drwxrwxr-x 2 nfsnobody nfsnobody  rpi-fs

Créer la liste des exports


vi /etc/exports

/var/nfs/common 192.168.0.0/24(rw,sync,root_squash,all_squash,no_subtree_check)
/var/nfs/node01 192.168.0.101(rw,sync,root_squash,all_squash,no_subtree_check)
...
/var/nfs/node15 192.168.0.115(rw,sync,root_squash,all_squash,no_subtree_check)
/var/nfs/rpi-fs 192.168.0.0/24(rw,sync,no_root_squash,no_all_squash,no_subtree_check)

Attention : Pas d’espace entre l’IP et la parenthèse ouvrante.
Adapter les noms des nœuds (ici nodexx) et les IP (ici 192.168.0.1xx) à la configuration de votre cluster.
192.168.0.0/24 désigne n’importe quelle machine du réseau 192.168.0.0
L'option no_root_squash pour le partage /var/nfs/rpi-fs utilisé plus tard pour le network boot est importante.


Exporter

exportfs –rav

Vérifier
exportfs -v


NFS v2 

Activer la version 2 de NFS est obligatoire si on veut booter via le réseau. Si ce n'est pas votre but vous pouvez ignorer cette partie.

Normalement la commande
    cat /proc/fs/nfsd/versions
indique avec un '+' les versions acceptées par le serveur nfsd. Par exemple:
   -2 +3 +4 +4.1 +4.2
signifie que la versions 2  n'est pas acceptées par nfsd.

On peut aussi vérifier avec la commande ci-dessous quelles versions sont acceptées :
    rpcinfo -p

Pour booter un Raspberry Pi2 via nfs (network boot) if faut que le serveur nfsd accepte la version 2 de nfs. Pour forcer l'usage de nfsv2 il faut éditer le fichier :
  /etc/sysconfig/nfs
et remplacer la ligne
    RPCNFSDARGS=""
par
    RPCNFSDARGS="-V 2"
et redémarrer nfs avec:
  systemctl restart nfs
  systemctl restart nfs-config

Mais avec nfs il y a tellement de services en jeux que rebooter est plus sûr...

Vous devriez alors obtenir:

cat /proc/fs/nfsd/versions
+2 +3 +4 +4.1 +4.2

et rpcinfo doit montrer
  portmapper en version 2, 3, 4
  mountd en version 1, 2, 3  (c'est bien 1, 2, 3)
  nfs en version 2, 3, 4

2 NFS coté client

Ici on est bien sur un Raspberry (sur celui qui servira à faire la carte SD master).

Installation client NFS  (rasperian)

apt-get install  nfs-common  rpcbind

update-rc.d rpcbind enable
service     rpcbind start


Installation client NFS  (CentOS 7.x)

yum install nfs-utils rcbind

systemctl enable rpcbind
systemctl start  rpcbind


Vérifier l’installation (toute versions)
cat /proc/filesystems | grep nfs
rpcinfo -p            | grep portmap


Tester
Depuis le noeud #10 (qui a l'ip 192.168.0.110) taper
mkdir -pv /mnt/nfs_home /mnt/nfs_common
mount  192.168.0.100:/var/nfs/node10 /mnt/nfs_home
mount  192.168.0.100:/var/nfs/common /mnt/nfs_common

192.168.0.100 est l’ip du serveur NFS (le serveur centos dans notre exemple)
Plus tard ce serveur fera aussi TFTP et éventuellement DHCP.

Si vous essayez de monter un export qui n'existe pas ou qui ne correspond pas votre ip vous obtiendrez ce message d'erreur:
mount.nfs: access denied by server while mounting 192.168.0.100:/var/nfs/node11

Notez que, pendant le temps du montage, le propriétaire des répertoires utilisé pour monter les exports est nobody.nogroup

ls -l /mnt
drwxrwxr-x 2 nobody nogroup     nfs_common
drwxrwxr-x 2 nobody nogroup     nfs_home


A moins que vos programmes s’exécutent en tant que root ou nobody, il faudra certainement faire un chmod o+w  pour écrire dans ces répertoires.

3 Debug NFS

Par défaut NFS n'est pas trés bavard dans les log. Pour avoir plus d'info il faut les demander avec rpcdebug.

  rpcdebug -m nfsd -s all       <-- debuger le serveur
  rpcdebug -m nfs  -s all       <-- debuger le client
  rpcdebug -m rpc  -c all       <-- debug utilisable des deux cotés

  nfsstat --all --list  <-- statistiques du serveur nfs