Project

General

Profile

Singularity

Description

Un conteneur Linux est une image qui contient votre propre environnement logiciel et qui partage le noyau Linux avec l'hôte.

Singularity est une solution de conteneur conçue pour le HPC qui permet la portabilité entre environnements Linux, la reproductibilité des résultats et la mobilité entre clusters.

Les utilisateurs font alors tourner un autre système d'exploitation dont ils peuvent contrôler la pile logiciels sans avoir besoin des privilèges root sur la machine hôte.

Singularity est installé sur Curta, ce qui permet de lancer à l'intérieur d'un job, un conteneur à l'environnement logiciel contrôlé.

Faire tourner des conteneurs sur des serveurs auxquels ont accès d'autres utilisateurs pose des problèmes de sécurité que les développeurs de Singularity ont pris soin de résoudre. Ainsi, il est interdit d'obtenir des privilèges administratifs dans un conteneur Singularity si on n'est pas root sur l'hôte. Ceci oblige l'utilisateur qui veut personnaliser son image de conteneur à le faire sur une machine Linux où il dispose de tels privilèges.

La procédure qui suit détaille les étapes pour configurer une image et utiliser des conteneurs dans vos jobs Curta.

Procédure

Documentation Singularity: https://www.sylabs.io/guides/3.0/user-guide/index.html

  • Pour créer un conteneur il faut une image (.sif) et un fichier de définition (.def) ainsi qu'un ordinateur où vous avez les droits root pour pouvoir exécuter la commande build. Une fois configurée, il faut la copier sur Curta pour l'utiliser dans un job.
  • Pour définir vos besoins dans le conteneur, il faut écrire un fichier de recette (container.def). Voici un exemple d'installation minimale d'un conteneur ubuntu:
    BootStrap: debootstrap
    OSVersion: trusty
    MirrorURL: http://us.archive.ubuntu.com/ubuntu/
    
    %runscript
        echo "This is what happens when you run the container..." 
    
    %post
        echo "Hello from inside the container" 
        sed -i 's/$/ universe/' /etc/apt/sources.list
        apt-get update
        apt-get -y install vim
        apt-get clean
        mkdir /scratch
    

    Ensuite, on crée l'image <container.sif> comme suit (cette opération peut prendre un certain temps):
    sudo singularity build <container.sif> <container.def>
    

    D'autres méthodes sont possibles pour construire son conteneur. Vous avez le détail ici: https://www.sylabs.io/guides/3.0/user-guide/build_a_container.html
  • Transférez votre image dans /scratch/<username> sur Curta. Attention cet espace est nettoyé au bout de 90 jours donc il faut garder une copie de votre image ailleurs.
  • Maintenant l'utilisation du conteneur dans un job est possible.
    Pour exécuter vos scripts dans le conteneur, il faudra utiliser la commande exec:
    singularity exec <container.sif> <CMD> (args)
    

    Si vous avez lancé un job interactif, vous avez la possibilité d'ouvrir un shell dans le conteneur:
    singularity shell <container.sif>
    
  • S'il vous manque un paquet dans votre conteneur, il faudra modifier votre conteneur sur votre ordinateur où vous avez les droits root, modifier le conteneur comme suit et retransférer l'image sur le scratch de Curta:
    sudo singularity shell -w <container.sif>
    Singularity centos7.sif:~> yum install <package>
    

Exemples d'utilisation

OpenMPI

Pour que vos jobs s'exécutent correctement, il faut installer dans le conteneur une version de openmpi qui soit également installée en module sur Curta (et charger ce module-ci dans votre job).

  • Fichier de définition openmpi.def
    Bootstrap: yum
    OSVersion: 7
    MirrorURL: http://mirror.centos.org/centos-%{OSVERSION}/%{OSVERSION}/os/$basearch/
    Include: yum
    
    %post
        echo "Hello from inside the container" 
    
        echo "Installing Development Tools YUM group" 
        yum -y groupinstall "Development Tools" 
    
        yum -y install wget which less nano emacs
        mkdir /scratch
        mkdir /tmp/mpi
        cd /tmp/mpi
    
        echo "Installing OpenMPI into container..." 
        wget https://download.open-mpi.org/release/open-mpi/v3.1/openmpi-3.1.3.tar.gz
        tar xvzf openmpi-3.1.3.tar.gz
        cd openmpi-3.1.3
        ./configure --prefix=/usr/local
        make
        make install
        /usr/local/bin/mpicc examples/ring_c.c -o /usr/bin/mpi_ring
        cd /
        rm -rf /tmp/mpi
    
        exit 0
    
    
  • Job SLURM
    Pour un bon fonctionnement de openmpi:
    • Il faut charger la même version openmpi que celle installée dans le conteneur.
    • Une façon de procéder est de compiler le programme dans le conteneur avant de l'exécuter (mpirun/mpiexec).
      #!/bin/bash
      #
      #SBATCH -J singularity_openmpi
      #SBATCH -o /scratch/aldarrie/singularity/%x-%j.out
      #SBATCH -N 3
      #SBATCH --ntasks-per-node=4
      #SBATCH -t 10:00
      
      echo "#############################" 
      echo "User:" $USER
      echo "Date:" `date`
      echo "Host:" `hostname`
      echo "Directory:" `pwd`
      echo "SLURM_JOB_NAME:" $SLURM_JOB_NAME
      echo "SLURM_JOB_ID:" $SLURM_JOB_ID
      echo "SLURM_NODELIST: " $SLURM_NODELIST
      echo "SLURM_NTASKS: " $SLURM_NTASKS
      echo "#############################" 
      echo
      
      IMG=/scratch/aldarrie/singularity/openmpi.sif
      
      module load singularity/3.6.4
      module load mpi/openmpi/3.1.3
      
      echo "OpenMPI" 
      NP=$SLURM_NTASKS
      echo "Running on $NP processors" 
      
      mpiexec -pernode singularity exec $IMG mpicc mpitest.c -o mpitest
      
      mpirun -np $NP singularity exec $IMG ./mpitest
      
      echo "Job finished" 
      
      

R

  • Fichier de définition
    BootStrap: debootstrap
    OSVersion: trusty
    MirrorURL: http://us.archive.ubuntu.com/ubuntu/
    
    %runscript
        echo "This is what happens when you run the container..." 
    
    %post
        echo "Hello from inside the container" 
        sed -i 's/$/ universe/' /etc/apt/sources.list
        apt-get update
        apt-get -y install vim
        apt-get install -y r-base r-base-core r-base-dev wget vim git nano git cmake curl wget python autoconf bzip2 libtool python-pip python-dev glpk-utils libglpk-dev glpk-doc python-glpk
        apt-get clean
        mkdir /scratch
    
    %test
        #!/bin/sh
        exec R --slave -e 'print("Hello Worl!")'
    
    %runscript
        glpsol -m sudoku.mod
    
    
  • Job SLURM
    #!/bin/bash
    #
    #SBATCH -J singularity_R
    #SBATCH -o /scratch/aldarrie/singularity/%x-%j.out
    #SBATCH -N 1
    #SBATCH --ntasks-per-node=1
    #SBATCH -t 10:00
    
    echo "#############################" 
    echo "User:" $USER
    echo "Date:" `date`
    echo "Host:" `hostname`
    echo "Directory:" `pwd`
    echo "SLURM_JOB_NAME:" $SLURM_JOB_NAME
    echo "SLURM_JOB_ID:" $SLURM_JOB_ID
    echo "SLURM_NODELIST: " $SLURM_NODELIST
    echo "SLURM_NTASKS: " $SLURM_NTASKS
    echo "#############################" 
    echo
    
    IMG=/scratch/aldarrie/singularity/r.sif
    
    module load singularity/3.6.4
    module load R/3.5.0
    
    cp $IMG $TMPDIR
    cp sudoku.mod $TMPDIR
    
    echo "R sudoku program" 
    
    singularity test $TMPDIR/r.sif
    singularity run $TMPDIR/r.sif
    
    echo "Job finished"