SCRIPTS POUR SUIVRE L’ÉTAT DES RESSOURCES Télémétrer le CPU
Nous souhaitons avoir à intervalle de temps régulier le pourcentage de charge d’utilisation du CPU. L’intervalle de temps est fixé dans un fichier de configuration. Pour les conteneurs, les commandes Linux des CGroups nous permettent d’obtenir le temps total d’utilisation du CPU par un conteneur. Le détail de toutes les commandes possibles est disponible au chapitre 8.2.3 du guide Oracle Linux (Oracle). Pour avoir le pourcentage, nous relevons donc la charge d’utilisation du CPU à un instant t1 puis à un instant t2 et nous faisons la différence.
#!/bin/bash
# ${1} is the container's name # ${2} is the time for observation # ${3} is a computer constante # get the cpu usage a t=0
NSCPUNOW=`lxc-cgroup -n ${1} cpuacct.usage` # get the cpu usage a ${2} second later
sleep ${2}
NSCPUAFTER=`lxc-cgroup -n ${1} cpuacct.usage` # calculate the percentage of cpu usage
NSDIFFERENCE=`echo "$NSCPUAFTER $NSCPUNOW" | awk '{print $1-$2}'` TOTALTIME=$((${2}*1000000000))
RESULT=`echo "$NSDIFFERENCE $TOTALTIME" | awk '{print $1*100/$2}'` # save result in text file
HOUR=$(date +%H) MINUTE=$(date +%M) SECONDE=$(date +%S)
echo ""$HOUR:$MINUTE:$SECOND", $RESULT" >> ./result/containers-${1}-cpu.csv echo ""$HOUR:$MINUTE:$SECOND", $RESULT"
Pour l’hôte, Linux nous fournit une commande, mpstat, qui permet d’avoir pour chaque cœur de la machine physique son pourcentage d’utilisation. Il faut donc utiliser cette commande et récupérer la valeur correspondant à chaque cœur.
#!/bin/bash
# ${1} is the time for observation # ${2} is a computer constante
# get the number of computer processors
NBPROCESSOR=`cat /proc/cpuinfo | grep processor | wc -l` # to initialize the good line to get value
COUNTER=0
MAX=`echo "$NBPROCESSOR $COUNTER" | awk '{print $1+$2}'` # Initialization of arrays PREV_USER=() USER=() PREV_NICE=() NICE=() PREV_SYST=() SYST=() PREV_IDLE=() IDLE=() PREV_TOTAL=() TOTAL=()
while [ $COUNTER -lt $MAX ]; do
CPU=`cat /proc/stat | grep '^cpu'$COUNTER' '`
PREV_USER=("${PREV_USER[@]}" "`echo $CPU | awk '{print $2}'`") PREV_NICE=("${PREV_NICE[@]}" "`echo $CPU | awk '{print $3}'`") PREV_SYST=("${PREV_SYST[@]}" "`echo $CPU | awk '{print $4}'`") PREV_IDLE=("${PREV_SYST[@]}" "`echo $CPU | awk '{print $5}'`")
let SUM=${PREV_USER[$COUNTER]}+${PREV_NICE[$COUNTER]}+${PREV_SYST[$COUNTER]} PREV_TOTAL=("${PREV_TOTAL[@]}" "$SUM") let COUNTER=COUNTER+1 done sleep ${1} COUNTER=0
while [ $COUNTER -lt $MAX ]; do
CPU=`cat /proc/stat | grep '^cpu'$COUNTER' '` USER=("${USER[@]}" "`echo $CPU | awk '{print $2}'`") NICE=("${NICE[@]}" "`echo $CPU | awk '{print $3}'`") SYST=("${SYST[@]}" "`echo $CPU | awk '{print $4}'`") IDLE=("${SYST[@]}" "`echo $CPU | awk '{print $5}'`")
let SUM=${USER[$COUNTER]}+${NICE[$COUNTER]}+${SYST[$COUNTER]} TOTAL=("${TOTAL[@]}" "$SUM")
let COUNTER=COUNTER+1 done
COUNTER=0
while [ $COUNTER -lt $MAX ]; do
# Calculate the CPU usage between two checked. let SLEEPTIME=${2}*${1} let "DIFF_TOTAL=${TOTAL[$COUNTER]}-${PREV_TOTAL[$COUNTER]}" let "DIFF_USAGE_IDLE=100*DIFF_TOTAL/$SLEEPTIME" let "DIFF_USER=${USER[$COUNTER]}-${PREV_USER[$COUNTER]}" let "DIFF_USAGE_USER=100*$DIFF_USER/$SLEEPTIME" let "DIFF_SYST=${SYST[$COUNTER]}-${PREV_SYST[$COUNTER]}"
let "DIFF_USAGE_SYST=100*$DIFF_SYST/$SLEEPTIME" # incremente and number to save
let COUNTER=COUNTER+1 # Save result in text file
RESULT=`echo $RESULT$DIFF_USAGE_IDLE+` HOUR=$(date +%H)
MINUTE=$(date +%M) SECOND=$(date +%S)
echo ""$HOUR:$MINUTE:$SECOND", $DIFF_USAGE_USER" >> ./result/host-cpu-$COUNTER-usr.csv echo ""$HOUR:$MINUTE:$SECOND", $DIFF_USAGE_SYST" >> ./result/host-cpu-$COUNTER-sys.csv echo ""$HOUR:$MINUTE:$SECOND", $DIFF_USAGE_IDLE" >> ./result/host-cpu-$COUNTER.csv done
echo ""$HOUR:$MINUTE:$SECOND", $RESULT"
Télémétrer la mémoire
Nous souhaitons avoir à intervalle de temps régulier l’utilisation de la mémoire par les conteneurs. Nous retrouvons au chapitre 8.2.8 du guide Oracle Linux (Oracle) la commande à utiliser. Elle nous renvoie la mémoire, en octets, utilisée par un conteneur. Il nous suffira ensuite de récupérer la capacité totale en mémoire de la machine physique pour calculer le pourcentage d’utilisation de cette dernière par le conteneur étudié.
#!/bin/bash
# ${1} is the container's name # computer memory
TOTALCOMPUTER=`free -b | awk '$2 {print $2}' | awk 'NR==2'` # memory use by the container
USEDCONTAINER=`lxc-cgroup -n ${1} memory.usage_in_bytes` # percentage
RESULT=$USEDCONTAINER # save result in text file
HOUR=$(date +%H) MINUTE=$(date +%M) SECOND=$(date +%S)
echo ""$HOUR:$MINUTE:$SECOND", $RESULT" >> ./result/containers-${1}-memory.csv echo ""$HOUR:$MINUTE:$SECOND", $RESULT"
Télémétrer la bande passante
La dernière ressource de bas niveau que nous souhaitons télémétrer est le nombre d’octets lu et écrit sur le réseau par chaque conteneur et par l’hôte.
Dans les deux cas, la commande Linux ifconfig a été utilisée, car elle donne l’information souhaitée pour toutes les interfaces de la machine physique. Il a seulement fallu, avant
d’exécuter cette commande, récupérer le nom de l’interface pour chaque instance que nous souhaitons observer. Pour les conteneurs, une commande des CGroups, lxc-info, permet de récupérer de nombreuses informations sur un conteneur, dont le nom de son interface.
#!/bin/bash
# ${1} is the container's name # ${2} is the time for observation # save result in text file
HOUR=$(date +%H) MINUTE=$(date +%M) SECOND=$(date +%S) # get the interface network # monitor at t = 0
RX0=`lxc-attach -n ${1} ifconfig eth0 | grep "RX bytes" | cut -d: -f2 | awk '{ print $1 }'` TX0=`lxc-attach -n ${1} ifconfig eth0 | grep "TX bytes" | cut -d: -f3 | awk '{ print $1 }'` # wait TIME_MONITORING seconds
SLEEP=`echo "${2}" | awk '{print $1/2}'` sleep $SLEEP
# monitor at t = t+TIME_MONITORING
RX1=`lxc-attach -n ${1} ifconfig eth0 | grep "RX bytes" | cut -d: -f2 | awk '{ print $1 }'` TX1=`lxc-attach -n ${1} ifconfig eth0 | grep "TX bytes" | cut -d: -f3 | awk '{ print $1 }'` RX=`echo "$RX1 $RX0 $SLEEP" | awk '{print ($1-$2)/$3}'`
TX=`echo "$TX1 $TX0 $SLEEP" | awk '{print ($1-$2)/$3}'`
echo ""$HOUR:$MINUTE:$SECOND", $RX" >> ./result/containers-${1}-Rx-network.csv echo ""$HOUR:$MINUTE:$SECOND", $TX" >> ./result/containers-${1}-Tx-network.csv echo ""$HOUR:$MINUTE:$SECOND", $RX+$TX"
Pour l’hôte, la première étape a été de lancer une commande permettant de trouver l’adresse IP de la machine. Ensuite, à partir de cette adresse, le nom de l’interface a pu être retrouvé. L’adresse IP a été trouvée grâce au code python suivant :
ipaddress = [(s.connect(('8.8.8.8', 80)), s.getsockname()[0], s.close()) for s in