This is an old revision of the document!


Moodle Mooc

Introduction

Telecom SudParis à mis en place en decembre 2013 un MOOC intitulé “Comprendre les concepts des Télécommunication”: http://mooc.telecom-sudparis.eu.

Cette page presente les aspects techniques systemes mis en oeuvre afin d'assurer la diffusion de ce MOOC.

Fort de notre experience sur la plateforme Moodle pour les cours en ligne des formations initiales et continus, et considerant les delais impartis, nous avons jugés opportun de poursuivre sur le LMS Moodle pour la diffusion de ce MOOC.

Cette article aborde les aspects tehniques :

  • applicatifs (moodle, gestionnaire git) et backends (apache, mysql),
  • des tests de montés en charge (tsung),
  • reporting, statistiques d'usages

References

statitics

pour commencer l'article sur un apect visuel, voici ci-dessous quelques graphs de statistics en terme d'usage appplicatifs (cours moodle), systeme (serveur load et apache hits) , logiciel d'analyse de log apache ⇒ awstats

moodle

tous les acces

toutes les activités

system

apache hits

system load

mysql requetes (1ere semaine)

Awstats

le résumé awstats d'apache pour le mois de Décembre 2013

Moodle Mooc

reference sur l'installation de moodle 2.x

database

création d'une base de donnée sur un serveur mysql

mysql>  CREATE DATABASE moodle_mooc;
Query OK, 1 row affected (0.00 sec)

mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP,INDEX,ALTER ON moodle_mooctsp.* to mooc-user@'mooctsp.int-evry.fr' IDENTIFIED by 'secret';
Query OK, 0 rows affected (0.00 sec)

statistiques

l'usage des statistiques dans moodle implique la possibilité à l'utilisateur propiétaire de la base de donnée de creer des tables temporaires, il faut donc ajouter cette aptitude à notre utilisateur

[root@mysql /]# mysql -u root -p
mysql> use mysql
mysql> select * from db where User='mooc-user';

mysql> update db set Create_tmp_table_priv='Y' where User='mooc-user';
mysql> flush privileges;

sans cette aptitude, la generation des statistiques moodle (reports) échoue.

il est alors possible de lancer “manuellement” la generation des statistics en appelant le script cron_stats.php

Server Time: Wed, 18 Dec 2013 15:37:02 +0100

Running daily statistics gathering, starting at 1383778800:
... started 15:37:03. Current memory use 26Mo.
Temporary tables created
Enrolments calculated
0:0 1:0 2:0 3:0 4:0 5:0 6:0 7:0 8:0 9:0 10:0 11:0 12:0 13:0 14:0 15:0 16:0 out:0   finished until 1383865200: vendredi 8 novembre 2013, 00:00 (in 0 s)
...
..stopping early, reached maximum number of 31 days (5 s) - will continue next time.

GIT moodle

Utilisation de GIT pour gerer plus finement notre instance moodle (mises à jours, versionning des modifications, plugins, logs etc ..)

variables d'environement GIT

[root@mooc ~]# mkdir git-moodle-mooc
[root@mooc ~]# cd git-moodle-mooc/
[root@mooc git-moodle-mooc]# git config --global user.name "disi-sudparis"
[root@mooc git-moodle-mooc]# git config --global user.email "admins@int-evry.fr"

repertoire de travail

[root@mooc git-moodle-mooc]# mkdir mooctsp
[root@mooc git-moodle-mooc]# cd mooctsp/

initialisation

initialisation du repertoire local et récuperation du code depuis la version de base MOODLE_25_STABLE sur le serveur git de moodle

[root@mooc mooctsp]#  git init
Initialized empty Git repository in /root/git-moodle-mooc/mooctsp/.git/
[root@mooc mooctsp]# git remote add moodle git://git.moodle.org/moodle.git

[root@mooc mooctsp]# git fetch moodle
remote: Counting objects: 703676, done.
remote: Compressing objects: 100% (164991/164991), done.
remote: Total 703676 (delta 522649), reused 703676 (delta 522649)
Receiving objects: 100% (703676/703676), 262.39 MiB | 9.71 MiB/s, done.
Resolving deltas: 100% (522649/522649), done.
From git://git.moodle.org/moodle
 * [new branch]      MOODLE_13_STABLE -> moodle/MOODLE_13_STABLE
...
 * [new branch]      master     -> moodle/master
...
From git://git.moodle.org/moodle
 * [new tag]         v1.0.0     -> v1.0.0
...
 * [new tag]         v2.5.2     -> v2.5.2
 * [new tag]         v2.6.0-beta -> v2.6.0-beta

Déclaration de suivi de la branche MOODLE_25_STABLE

# git branch --track MOODLE_25_STABLE moodle/MOODLE_25_STABLE
# git checkout MOODLE_25_STABLE

Repository mooc disi

Depuis la version moodle_stable2.5 on fork notre “version” maison (disi) du projet.

[root@mooc mooctsp]# git checkout -b mooc_disi
Switched to a new branch 'mooc_disi'

A partir de là, nous allons gerer sur notyre propre serveur GIT, une version “remote” afin de disposer d'un serveur de distribution GIT de notre propre branche (pour d'eventuels clones et autres serveurs de failover …)

⇒ declaration du remote disi

# ssh-keygen
# ssh-copy-id gituser@git.tem-tsp.eu

# git remote add mooc ssh://gituser@git.tem-tsp.eu/~/moodle/mooc.git

puis push vers le remote serveur (git.tem-tsp.eu) de notre branche mooc_disi

# git push mooc mooc_disi:mooc_disi

[root@mooc mooctsp]# git branch 
  MOODLE_25_STABLE
* mooc_disi

recapitulatif

etat des lieux GIT à ce niveau, liste de toutes les branches:

[root@mooc mooctsp]# git branch -a
  MOODLE_25_STABLE
* mooc_disi
  remotes/mooc/mooc_disi
  
  remotes/moodle/MOODLE_13_STABLE
  remotes/moodle/MOODLE_14_STABLE
  remotes/moodle/MOODLE_15_STABLE
  remotes/moodle/MOODLE_16_STABLE
  remotes/moodle/MOODLE_17_STABLE
  remotes/moodle/MOODLE_18_STABLE
  remotes/moodle/MOODLE_19_STABLE
  remotes/moodle/MOODLE_20_STABLE
  remotes/moodle/MOODLE_21_STABLE
  remotes/moodle/MOODLE_22_STABLE
  remotes/moodle/MOODLE_23_STABLE
  remotes/moodle/MOODLE_24_STABLE
  remotes/moodle/MOODLE_25_STABLE
  remotes/moodle/master

D'apres http://www.techblogistech.com/2012/07/setting-a-default-upstream-branch-in-git/, nous devons indiquer a chaque commande git pull et git push depuis où retirer les modifications et vers où les envoyer. C'est fastidieux, nous allons donc fixer la branche remote par defaut.

[root@mooc mooctsp]# git branch --set-upstream remotes/mooc/mooc_disi
Branch remotes/mooc/mooc_disi set up to track local branch mooc_disi.

1er mise en ligne via rsync

Nous mettons en ligne (dans une arborescence visible du serveur apache) notre repository d'instance maison moodle (mooctsp)

[root@mooc mooctsp]# cd ..
[root@mooc git-moodle-mooc]# rsync -a --delete --exclude=.htaccess --exclude=.git/ mooctsp /var/www/

modification et ajout de fichiers

on veux gerer config.php via git donc on le retire de .gitignore

[root@mooc mooctsp]# grep config.php .gitignore 
##/config.php

ajout et commit

[root@mooc mooctsp]# cp config-dist.php config.php 
[root@mooc mooctsp]# vim config.php 

[root@mooc mooctsp]# git add config.php
[root@mooc mooctsp]# git commit -a -m "add config.php and configured to DB  mysql3"
[mooc_disi 792f740] add config.php and configured to DB  mysql3
 1 files changed, 651 insertions(+), 0 deletions(-)
 create mode 100644 config.php

push serveur git local

on push nos modifications sur notre serveur git local

[root@mooc mooctsp]# git push mooc mooc_disi:mooc_disi
Counting objects: 8, done.
Delta compression using up to 32 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 11.24 KiB, done.
Total 6 (delta 3), reused 0 (delta 0)
To ssh://gituser@git.tem-tsp.eu/~/moodle/mooc.git
   c9ee1a7..792f740  mooc_disi -> mooc_disi

publication web

depuis notre répertoire de travail git (dans le homedir de root) nous allons pousser notre instance moodle dans une arborescence de visibilité web d'apache ⇒ “DocumentRoot”

[root@mooc git-moodle-mooc]# rsync -av --delete --exclude=.htaccess --exclude=.git/ mooctsp /var/www/
sending incremental file list
mooctsp/
mooctsp/.gitignore
mooctsp/config.php

sent 354720 bytes  received 3558 bytes  238852.00 bytes/sec
total size is 116222732  speedup is 324.39

etat des lieux

[root@mooc mooctsp]# git remote -v 
mooc	ssh://gituser@git.tem-tsp.eu/~/moodle/mooc.git (fetch)
mooc	ssh://gituser@git.tem-tsp.eu/~/moodle/mooc.git (push)
moodle	git://git.moodle.org/moodle.git (fetch)
moodle	git://git.moodle.org/moodle.git (push)

[root@mooc mooctsp]# git remote show mooc
* remote mooc
  Fetch URL: ssh://gituser@git.tem-tsp.eu/~/moodle/mooc.git
  Push  URL: ssh://gituser@git.tem-tsp.eu/~/moodle/mooc.git
  HEAD branch: (unknown)
  Remote branches:
    mooc_disi       tracked
  Local refs configured for 'git push':
    mooc_disi       pushes to mooc_disi       (up to date)

Apache

Définition d'un Virtual Host Apache pour heberger cette instance moodle-mooc ⇒ création d'un fichier de configuration spécifique dans conf.d d'apache.

On notera l'usage d'une authentification SSO shibboleth pour la communauté education/recherche, qui ne sera pas detaillée ici, c'est un sujet à part entiere …

On gere aussi une instance en https avec les certificats qui vont bien.

[root@mooc ~]# cat /etc/httpd/conf.d/mooc.conf
#mooctsp
<VirtualHost 157.159.10.35:80>
        ServerName mooc.telecom-sudparis.eu
#        ServerAlias mooc.*
        DocumentRoot /var/www/mooctsp
        ErrorLog logs/mooctsp-error_log
        CustomLog logs/mooctsp-access_log combined
        # Moodle private data - must NOT be publically accessible
        <Directory /var/www/moodledata_mooctsp>
        Order deny,allow
        Deny from all
        </Directory>
        <Directory  /var/www/mooctsp/auth/shibboleth/index.php>
        AuthType shibboleth
        ShibRequireSession On
        require valid-user
        </Directory>
<Location />
ShibRequestSetting applicationId default
</Location>
</VirtualHost>

#mooc https
<VirtualHost 157.159.10.35:443>
        ServerName mooc.telecom-sudparis.eu
#        ServerAlias mooc.*
        DocumentRoot /var/www/mooctsp
        ErrorLog logs/ssl_mooctsp-error_log
        CustomLog logs/ssl_mooctsp-access_log combined
        LogLevel warn
        SSLEngine on
        SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
        SSLCertificateFile /etc/pki/tls/certs/cert-19020-mooc.telecom-sudparis.eu.pem
        SSLCertificateKeyFile /etc/pki/tls/private/mooc_telecom-sudparis_nop.key
        SSLCertificateChainFile /etc/pki/tls/certs/chain-19020-mooc.telecom-sudparis.eu.pem
        SSLCACertificateFile /etc/pki/tls/certs/add_trust_external_ca_root.pem
       <Directory /var/moodledata_mooctsp>
        Order deny,allow
        Deny from all
        </Directory>
        <Directory  /var/www/mooctsp/auth/shibboleth/index.php>
        AuthType shibboleth
        ShibRequireSession On
        require valid-user
        </Directory>

<Location />
ShibRequestSetting applicationId default
</Location>
</VirtualHost>
#ipv6 mooc
#<VirtualHost [2001:660:3203:100:1:0:80:35]:80>
....
# desctivation de cette version IPv6 pour l'instant ...

moodledata

l'espace de stockage de data de moodle

[root@mooc mooctsp]# mkdir /var/www/moodledata_mooctsp/
[root@mooc mooctsp]# chown -R apache /var/www/moodledata_mooctsp

installation web

Une fois le serveur apache parametré, on peux lancer l'installation interractive de moodle depuis l'interface web

http://mooc.telecom-sudpris.eu/admin/index.php

Plateforme de stress applicatif Tsung

Quand on met en ligne une application il est toujours intéréssant de pouvoir tester sa montée en charge. Une application fonctionnant très bien sous une faible charge peut s'avérer défaillante lors de la montée en charge. Pour cela nous allons utiliser tsung.

installation

au plus simple, tsung etant packagé !

yum install tsung

il s'installe avec toute une série de dépendance de packages “erlang-*” .

plateforme distribuée

Nous utiliserons plusieurs agents tsung, afin d'effectuer acces distribué sur 3 clients, le host principal (ici flow) et deux “slave” (wik.tem-tsp.eu et aude.tem-tsp.eu)

astuce de parametrage

pour que le coté distribué fonctione il faut plusieurs conditions, un bon fichier /etc/hosts, un bon partage de clés ssh, un bon hostname etc … cf

il faut aussi que le “master” tsung accept les packets des ces slave dans le firewall

[root@flow .tsung]# grep /32 /etc/sysconfig/iptables
-A RH-Firewall-1-INPUT -s 157.159.11.129/32 -m state --state NEW -m tcp -p tcp -j ACCEPT
-A RH-Firewall-1-INPUT -s 157.159.211.18/32 -m state --state NEW -m tcp -p tcp -j ACCEPT

test erl de base depuis le master flow vers le slave aude.tem-tsp.eu :

[root@flow .tsung]# erl -rsh ssh -sname foo -setcookie mycookie
Erlang R14B04 (erts-5.8.5) [source] [smp:32:24] [rq:32] [async-threads:0] [kernel-poll:false]

Eshell V5.8.5  (abort with ^G)
(foo@flow)1> slave:start(aude,bar,"-setcookie mycookie"). 
{ok,bar@aude}

senario moocZ

nous utilisons un clone de notre serveur mooc (moocZ) pour effectuer cette montée en charge

[root@flowmon .tsung]# cat tsung-moocZ-scenario5.xml
<?xml version="1.0"?>
<!DOCTYPE tsung SYSTEM "/usr/share/tsung/tsung-1.0.dtd">
<tsung loglevel="notice" version="1.0">
 
    <!-- Configuration du client -->
  <!--  <clients> -->
      <!--  <client host="localhost" use_controller_vm="true"/> -->
        <!--<client host="ursinum.int-evry.fr" use_controller_vm="true"/> -->
        <!--	<ip value="157.159.22.73"></ip> 
        	<ip value="157.159.22.85"></ip>
        </client> -->
  <!--  </clients> -->
    <!-- Configuration du client -->
    <clients>
            <client host="flowmon" use_controller_vm="false"/>
            <client host="wikis" weight="1" maxusers="600" cpu="1"> 
        	<ip value="157.159.11.129"></ip>
            </client>
            <client host="auth" weight="2" maxusers="600" cpu="1"> 
        	<ip value="157.159.211.18"></ip>
            </client>
    </clients>

 
    <!-- Configuration du serveur -->
    <servers>
        <server host="moocZ.telecom-sudparis.eu" port="80" type="tcp"></server>
    </servers>
 
    <!-- phases d'arrivée, 3 paliers de 10 minutes où l'on augmente la fréquence d'arrivée de 1 puis 5 puis 10 visiteurs par seconde -->
    <load>
        <arrivalphase phase="1" duration="1" unit="minute">
            <users arrivalrate="1" unit="second"></users>
        </arrivalphase>
        <arrivalphase phase="2" duration="5" unit="minute">
            <users arrivalrate="5" unit="second"></users>
        </arrivalphase>
        <arrivalphase phase="3" duration="10" unit="minute">
            <users arrivalrate="10" unit="second"></users>
        </arrivalphase>
    </load>
 
    <!-- Les scénarios -->
    <sessions>
        <!-- Scénarios 1 avec 70% de probabilité, l'internaute charge successivement 3 pages -->
        <session name="scenario1" probability="70" type="ts_http">
		<request><http url='/index.php' version='1.1' method='GET'></http></request>
		<request><http url='/login/signup.php' version='1.1' method='GET'></http></request>
		<request><http url='/mod/page/view.php?id=110' version='1.1' method='GET'></http></request>
        </session>
        <!-- Scénarios 2 avec 30% de probabilité, l'internaute charge 10 fois la page 1 -->
        <session name="scenario2" probability="30" type="ts_http">
            <for from="1" to="10" var="i">
                <request><http url='/login/forgot_password.php' version='1.1' method='GET'></http></request>
            </for>
        </session>
    </sessions>
</tsung>

Rapport tsung

on peux lancer un rapport sur la campagne de test tsung réalisée en lançant dans le repertoire de log correpondant la commande “/usr/lib/tsung/bin/tsung_stats.pl”

[root@flow log]# cd 20140103-1439
[root@flow 20140103-1439]# /usr/lib/tsung/bin/tsung_stats.pl
creating subdirectory data 
creating subdirectory gnuplot_scripts 
creating subdirectory images 
warn, last interval (7) not equal to the first, use the first one (10)
No data for Bosh
No data for Match
No data for Async
No data for Errors

Cela génere des graphs gnuplot et une page report.html qui resume l'ensemble, en voici un apperçu:

Tunning openvz

La machine étant sous forme de VM / container openvz, des ajustements ont du etre mis en place pour repondre à la monté en charge

une reference en français sur le sujet:

# vzctl set 10035 --numproc=800 --save
# vzctl set 10035 --tcpsndbuf=5500000 --save
# vzctl set 10035 --diskinodes 400000:500000 --save
Running: /usr/sbin/vzquota stat 10035 -f
Running: /usr/sbin/vzquota setlimit 10035 -i 400000 -I 500000
CT configuration saved to /etc/vz/conf/10035.conf 
UB limits were set successfully
CT configuration saved to /etc/vz/conf/10035.conf


# vzlist -o ctid,hostname,laverage,privvmpages,numproc,numtcpsock,tcpsndbuf,kmemsize,kmemsize.l -s laverage
      CTID HOSTNAME                               LAVERAGE    PRIVVMP      NPROC   NTCPSOCK    TCPSNDB   KMEMSIZE KMEMSIZE.L
     100041 muxt.tem-tsp.eu                  0.00/0.00/0.00     215695         86          8     139520  752963645 9223372036854775807
     100035 mooc.telecom-sudparis.eu         0.15/0.21/0.18     389644        105         12     404216 1171646505 9223372036854775807
[root@mooc ~]# cat /proc/user_beancounters
Version: 2.5
       uid  resource                     held              maxheld              barrier                limit              failcnt
    10035:  kmemsize               1179549397           1182105600  9223372036854775807  9223372036854775807                    0
            lockedpages                     0                    0                 4096                 4096                    0
            privvmpages                420415              1351322              1024000              2048000                    0
            shmpages                      270                 1566               131072               131072                    0
            dummy                           0                    0  9223372036854775807  9223372036854775807                    0
            numproc                       133                  363                  800                  800                    0
            physpages                  666304               956320                    0  9223372036854775807                    0
            vmguarpages                     0                    0              2048000  9223372036854775807                    0
            oomguarpages               213170               473926              2048000  9223372036854775807                    0
            numtcpsock                      8                  205                  500                  500                    0
            numflock                        4                   34                  200                  220                    0
            numpty                          1                    2                   64                   64                    0
            numsiginfo                      0                   78                  512                  512                    0
            tcpsndbuf                  139520              5486448              5365760             10485760            417584502
            tcprcvbuf                  131072              1323600              5365760             10485760                    0
            othersockbuf               197280               423808              1503232              4063232                    0
            dgramrcvbuf                     0                13080               262144               262144                    0
            numothersock                  243                  337                  500                  500                    0
            dcachesize             1164468912           1164674029  9223372036854775807  9223372036854775807                    0
            numfile                      1655                 2445                 8192                 8192                    0
            dummy                           0                    0  9223372036854775807  9223372036854775807                    0
            dummy                           0                    0  9223372036854775807  9223372036854775807                    0
            dummy                           0                    0  9223372036854775807  9223372036854775807                    0
            numiptent                      53                   53                  128                  128                    0 

Process Apache

configuration standard du package apache pour RedHat/centos, mode Prefork conservé par defaut,

MPM Prefork vs Worker

A propos de MPM prefork vs worker il y a bien des soucis avec php qui serait parfois “non thread-safe”, donc problématique sur le model worker (threaded) d'apache from: http://stackoverflow.com/questions/1623914/what-is-thread-safe-or-non-thread-safe-in-php

“Since with mod_php, PHP gets loaded right into Apache, if Apache is going to handle concurrency using its Worker MPM (that is, using Threads) then PHP must be able to operate within this same multi-threaded environment – meaning, PHP has to be thread-safe to be able to play ball correctly with Apache!

At this point, you should be thinking “Ok, so if I'm using a multi-threaded web server and I'm going to embed PHP right into it, then I must use the thread-safe version of PHP”. And this would be correct thinking. However, as it happens, PHP's thread-safety is highly disputed. It's a use-if-you-really-really-know-what-you-are-doing ground.”

liste des extensions apache non thread-safe

explications détaillées

on a les librairies GD et ldap sur moodle qui sont peut-etre douteuses sur le sujet!?

Parametres prefork positionnés

<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
ServerLimit      256
MaxClients       256
MaxRequestsPerChild  4000
</IfModule>
[root@mooc ~]# apachectl -V
Server version: Apache/2.2.15 (Unix)
Server built:   Aug 13 2013 17:27:11
Server's Module Magic Number: 20051115:25
Server loaded:  APR 1.3.9, APR-Util 1.3.9
Compiled using: APR 1.3.9, APR-Util 1.3.9
Architecture:   32-bit
Server MPM:     Prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT="/etc/httpd"
 -D SUEXEC_BIN="/usr/sbin/suexec"
 -D DEFAULT_PIDLOG="run/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="logs/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"

Process apache par defaut

 [root@mooc ~]# ps -elf | grep http | wc -l
22

stats

$ curl -s 'http://mooc.telecom-sudparis.eu/server-status?auto' 
Total Accesses: 119166
Total kBytes: 2134616
CPULoad: 4.27854
Uptime: 312481
ReqPerSec: .381354
BytesPerSec: 6995.14
BytesPerReq: 18342.9
BusyWorkers: 11
IdleWorkers: 9
Scoreboard: R_R_.__RR_WW_W._._R_....RRR.....................................................................................................................................................................................................................................