B
baltho

  • 11 sept. 2017
  • Inscrit 1 août 2017
  • Désolé de répondre si tard, mais il est partit avant la demande d'hydrog3n 😉

  • Bonsoir,

    N'ayant plus l'utilité de mon KS-1, je le résilie à la fin du mois.
    Sachant combien il peut être compliqué de s'en procurer, je propose ici de le céder à qui veut s'il y a un preneur. Si non, il disparaîtra dans les limbes d'OVH début Septembre 🙂

    Baltho.

    • Effectivement, elle est un peu indispensable cette variable !

    • J'y ai pensé, mais à part vérifier le statut du container; il n'y a pas d'autre moyen... vu qu'il n'expose rien !

    • Si tu utilises slack, je veux bien.

      Il faudrait trouver la syntaxe à utiliser pour la variable "content"
      En gros, il faudrait envoyer un message équivalent à celui de telegram (icone KO/texte/fichier de logs attaché).

      Voici le content actuel (directement repris de ton lien) :
      content="\"attachments\": [ { \"mrkdwn_in\": [\"text\", \"fallback\"], \"fallback\": \"SSH login: $PAM_USER connected to `$HOSTNAME`\", \"text\": \"SSH login to `$HOSTNAME`\", \"fields\": [ { \"title\": \"User\", \"value\": \"$PAM_USER\", \"short\": true }, { \"title\": \"IP Address\", \"value\": \"$PAM_RHOST\", \"short\": true } ], \"color\": \"#F35A00\" } ]"`

      Rien que ça me soulagerai bien 🙂

    • J'ai commencé à travailler dans ce sens sur la branche dev, mais il y a encore du boulot 🙂

    • Je viens de jeter un oeil sur le tuto pour slack, et ça semble assez simple à mettre en oeuvre j'avoue.

      Je me demande à quel point il ne serait pas intéressant d'inclure directement ces scripts (telegram/sclack) dans mon github pour faire un outil plus complet.

    • BXT Actuellement dans mon script, il ne fait qu'un restart en effet.
      Par contre, pour rajouter un label, il faut faire un up -d, et ça, ça détruit le container et le recréé avec les nouveaux paramètres.

    • BXT C'est une bonne et une mauvaise nouvelle. ça veut dire qu'il va encore falloir que je triffouille mon iptables ! Groumph...

    • ça ne fait pas que le redémarrer, ça le recréé entièrement !

      Bon, j'ai créé un compte github, reste à voir comment ça fonctionne 😃
      https://github.com/Balth0/check_websites

      Pour ta requête de passer le redémarrage en paramètre, ça peut ce faire sans soucis. Si c'est utile à certains, autant le faire.

      Concernant slack, n'étant pas utilisateur (je lui préfère Mattermost 😉 ) je n'ai pas la possibilité de faire des tests (et n'aurais pas le temps de rajouter des fonctions "complexes" avant fin Aout. Je vais avancer le script au max d'ici la fin de semaine en l'état, je le reprendrai au retour des vacances pour rajouter des fonctionnalités.).

    • Bon, mes premiers tests ne sont pas concluants... ça répond chez toi quand tu curl ip:port ?

      curl -s -o /dev/null -w "%{http_code}" -L ip:port

      Aucune réponse chez moi, mais avant de casser mon iptables, je veux savoir ce qu'il en est sur une config "standard".
      (J'ai complètement bidouiller mon iptables pour museler un peu docker. il y a des chances que ça vienne de là... mais comme je ne vois pas de blocage dans les logs, je préfère confirmer avant de trifouiller là dedans )

    • OK.

      Personnellement, j'utilise le label uniquement sur les containers où il faut check une URL différente de la racine. Pour le moment, seul elFinder le nécessite parmi les applications que j'utilise.

    • J'avais trouvé ça moi :
      docker inspect -f '{{ .NetworkSettings.Networks.$DOCKER_FRONTEND_NETWORK.IPAddress }}' $i
      😉

      1 seule commande !
      Plus simple que jq (que je ne connaissais pas au passage) : ça n'impose pas d'installer un outil supplémentaire. De plus, comment réagi jq si le container a plusieurs adresses (cas d'une app avec plusieurs containers font-end/back-end par exemple) ?
      Avec la mienne, pas de doute !

      Par contre, il y a une limitation qui ne fonctionne pas avec le nom que j'utilise pour mon réseau frontend : iil ne supporte pas le "-" dans le nom et je ne trouve pas comment l'échapper. Il va falloir que je le note et que je le change chez moi

      Je vais développer tout ça aujourd'hui et faire des tests.

      Pour github, j'y ai pensé oui. Il va falloir que je regarde ça.

      PS : Qu'est-ce qui te dérange dans le fait de re-créer tes containers pour rajouter un label ?
      Merci pour les pistes !

    • MéCéBienSur... Pourquoi n'y ai-je pensé plus tôt !
      ça peut même simplifier le reste.

      Le port est facilement récupérable en label pour traefik ou en variable pour nginx, ce n'est donc pas un soucis.

      Je vais retravailler ça, Merci 🙂

    • J'avoue, je n'ai rien qui tourne avec une auth basique (j'utilise le rtorrent de @Wondefall avec Flood). J eme pencherai sur ce cas, mais c'est vrai qu'à froid, je ne vois pas trop comment contourner le problème. Sauf à rajouter 403 dans les codes acceptables, mais ce serait biaisé.. Et faux !
      Après, c'est aussi l'intérêt du label que j'ai rajouté, c'est que tu peux lui faire tester une autre URL que le VIRTUAL_HOST.

      Quand au -L dont tu parles, il y est bien, regardes 😉 (et non, je n'ai pas édité entre temps )

      Il ya a toujours du travail, c'est aussi pour ça que je le partage : avoir des remarques/idées de progression. En 3 jours, j'ai déjà fais 3 révisions !

      Merci à tous ceux qui me font des retours 🙂

    • Hop, c'est fait 🙂
      MAJ en v1.1.1 :
      - Optimisation de la méthode de recherche de l'URL. Plus besoin de spécifier le type de proxy utilisé, le script va directement aller chercher le bon label. Il va d'abord chercher si un label personnalisé est défini, puis cherchera une URL aussi bien pour traefik que nginx.

      • Optimisation des logs (encore 😃). Je trouve ça plus clair.
    • Il fonctionne avec :
      - Traefik
      - nginx+letsencrypt (testé avec le build de jwilder)
      - et en mode personalisé si tu rajoutes le label cw.check.url suivi de l'url à tester sur les containers à tester.

      ça me fait penser que je peux améliorer ma boucle de détection.
      En gros, il cherche d'abord le label custom, et s'il ne le trouve pas, il va chercher l'url en fonction de traefik ou de nginx.

      • BXT a répondu à ça.
      • BXT aime ça.
      • Bonjour,

        Pour mes besoins personnels et parce que c'est calme au bureau, j'ai écris le script suivant.

        1. But :
          Le but premier est de surveiller mes différents services web qui tournent sous docker et automatiser une première étape de troubleshooting (= redémarrer un container). Le tout en envoyant des notifications via telegram afin d'alerter l'admin du serveur.

        2. Principe de fonctionnement :
          1/ Le script scanne les containers exposés en front-end à la recherche de leur url (compatible avec traefik et nginx pour ceux qui utilisent le combo nginx/letsencrypt de jwilder).
          2/ Ensuite, il teste l'url à la recherche d'un code 200 (= site OK). Si KO, il redémarre le container et teste à nouveau.
          3/ Si le site est remonté, il envoi une notification pour signaler l'opération.
          4/ Si le site est toujours KO, il envoi une notification avec les logs du container en défaut.

        3. Comment l'utiliser ?
          La réponse facile : Tout est écrit dans le header du script, RTFM !
          Bon OK, vu que j'ai tout écris en anglais, je vous la refait version :emoji_flag_fr:

        Pré-requis :
        1 - Récupérer le script telegram-notify.sh et son fichier de conf telegram-notify.conf de Nicolas Bernaerts :

        wget https://raw.githubusercontent.com/NicolasBernaerts/debian-scripts/master/telegram/telegram-notify
        wget https://raw.githubusercontent.com/NicolasBernaerts/debian-scripts/master/telegram/telegram-notify.conf

        2 -Créer un bot telegram :
        Suivre les étapes 1 à 13 ici : https://github.com/topkecleon/telegram-bot-bash
        /!\ Noter la clé API donnée par @BotFather

        3 - Récupérer l'ID utilisateur du bot :
        + Envoyer un message à votre bot depuis l'application telegram.
        + A l'aide de votre navigateur, aller sur l'adresse suivante en ayant remplacé XXXXX par la clé API récupérée à l'étape précédente : https://api.telegram.org/botXXXXX/getUpdates
        + Sur la page affichée, cherchez "from":"id":YYYYY, ". et notez YYYYY. C'est votre ID utilisateur.

        4 - Mettez à jour le fichier telegram-notify.conf avec votre clé API et cotre ID utilisateur.

        Installer le script :
        1 - Copier le code tout en bas et collez le dans un fichier check_websites.sh.
        Note : si vous avez un serveur tout neuf avec Debian 9 et que vous utilisez vi, pensez à faire un ":set paste" avant de coller le contenu pour conserver l'indentation.

        2 - Rendez le fichier exécutable :
        chmod +x check_website.sh

        3 - Vérifiez et mettez à jour les variables en début de script. En particulier celle contenant le nom du réseau front-end de docker. La bien-nommée : DOCKER_FRONTEND_NETWORK

        4 - Exécutez le script à la main ou via crontab (perso, je l'éxécute toutes les 5mn) :
        /5 * /data/scripts/check_websites.sh

        5 - Vous avez maintenant un nouvel ami sur telegram qui vous veut du bien 😊

        Notes :
        - Si vous avez besoin de tester une adresse différente de celle de base, vous pouvez rajouter le label suivant dans le docker-compose du container à customiser :
        cw.check.url=sdom.domain.tld/elFinder/elfinder.html

        #!/bin/bash
        #
        # -- check_websites.sh --
        # 
        # Description :
        # -------------
        # This script scan all containers exposed to the front-end looking for the url associated.
        # Then, it check the service behind for a 200 http code.
        # If not found, it restart the container and check again.
        # if still KO, send a telegram notification with docker logs of the container.
        #
        # Works with :
        # ------------
        #  - Traefik
        #  - nginx from jwilder
        #  - custom label cw.check.url
        #
        # Prerequisites :
        #   - Get telegram-notify.sh & telegram-notify.conf from Nicolas Bernaerts :
        #      wget https://raw.githubusercontent.com/NicolasBernaerts/debian-scripts/master/telegram/telegram-notify-install.sh
        #      wget https://raw.githubusercontent.com/NicolasBernaerts/debian-scripts/master/telegram/telegram-notify.conf
        #   - Create a telegram bot :
        #      Follow steps 1 to 13 here : https://github.com/topkecleon/telegram-bot-bash
        #      /!\ Note down the API key given by @BotFather
        #   - Get user ID :
        #      + Send a message to your Bot from your Telegram client
        #      + Call the following URL from any web browser. XXXXX = your API key.
        #          https://api.telegram.org/botXXXXX/getUpdates
        #          In the page displayed, you'll get some information. search for "from":"id":YYYYY, ". YYYYY is your user ID.
        #   - Update telegram-notify.conf with your telegram API key and user ID.
        # 
        # Author :
        #   Baltho ( cg.cpam@gmail.com )
        #
        # Versions :
        #   - 2017-08-01: v1.1.1 :
        #         - Get URL optimizations : no need to specify proxy's name. The script is 
        #                             now looking first for custom label and next for traefik
        #                             and nginx ones.
        #         - Logs optimizations : Should be more efficient now.
        #   - 2017-07-31: v1.1   :
        #         - Custom URL test : If you have a url different from the base one to test,
        #                             you can set a new label to your container :
        #                             cw.check.url=sdom.domain.tld/location/file.ext
        #         - Better log management : Only 1 only used when all checks are OK. 
        #                             You cant see details of the last test on the .last file
        #                             stored on the same location thant the log file.
        #   - 2017-07-28: v1.0 - First release.
        
        # Set the name of the docker's front-end network :
        DOCKER_FRONTEND_NETWORK=traefik-proxy
        
        # Path of the telegram-notify.sh script.
        TELEGRAM_PATH=/data/scripts/telegram-notify.sh
        
        # LOGS_PATH = Path where logs will be stored
        LOGS_PATH=/var/log
        # LOG_FILE_NAME = Name of the log file
        LOG_FILE_NAME=cw
        
        # Temp file used to store current KO's containers name :
        NOTIFIED_LIST=/tmp/notified
        
        ############################################################################################
        # DOT NOT MODIFY ANYTHING BEHIND THIS LINE EXCEPT IF YOU KNOW EXACTLY WHAT YOU ARE DOING ! #
        ############################################################################################
        
        DATE=$(date)
        SCRIPT_LOG_FILE=$LOGS_PATH/$LOG_FILE_NAME.log
        LOG_TEMP=$LOGS_PATH/$LOG_FILE_NAME.last
        
        #--- Define text colors
        CSI="\033["
        CEND="${CSI}0m"
        CRED="${CSI}1;31m"
        CGREEN="${CSI}1;32m"
        CYELLOW="${CSI}1;33m"
        
        #--- Set log header
        echo " " > $LOG_TEMP
        echo "+----------------+---------------+--------------+" >> $LOG_TEMP
        echo "| $DATE" >> $LOG_TEMP
        echo "|" >> $LOG_TEMP
        
        # Check all running containers
        for i in $(docker network inspect $DOCKER_FRONTEND_NETWORK | grep Name | sed 1d | awk -F\" '{print $4}')
         do
           # Get url associated to the container from traefik label "traefik.frontend.rule" or from environnement variable "VIRTUAL_HOST" if using nginx
           URL=$(docker inspect $i | grep cw.check.url | awk -F"\"" '{print $4}')
           if [ -z "$URL" ]; then
             URL=$(docker inspect $i | grep traefik.frontend.rule | awk -F":" '{print $3}' | awk -F\" '{print $1}')
             if [ -z "$URL" ]; then
               URL=$(docker inspect $i | grep VIRTUAL_HOST | awk -F"=" '{print $2}' | awk -F\" '{print $1}')
             fi
           fi
           DOCKER_SCRIPT_LOG_FILE=$LOGS_PATH/cw_$i.log
           if [ ! -z "$URL" ]; then
             # If there is a URL on that container, get http code associated
             RESULT=$(curl -s -o /dev/null -w "%{http_code}" -L $URL)
             if [ "$RESULT" != "200" ]; then
        	   # If website is KO, restart the container
               echo -e "[ ${CRED}KO$CEND ] ${CYELLOW}https://$URL$CEND down with code $RESULT. Try restarting container $i..." >> $LOG_TEMP
               docker restart $i >/dev/null
               sleep 10
               RESULT2=$(curl -s -o /dev/null -w "%{http_code}" -L $URL)
        	   # If website is still KO after a container restart, notify through telegram with container's logs
               if [ "$RESULT2" != "200" ]; then
                 echo -e "[ ${CRED}ERR$CEND ] ${CYELLOW}https://$URL$CEND is still ${CRED}KO$CEND with http code : $RESULT2. Please check $i !" >> $LOG_TEMP
                 if [ ! -f $NOTIFIED_LIST ] || [[ ! " $(cat $NOTIFIED_LIST) " =~ " $i " ]]; then
        		   docker logs $i > $DOCKER_SCRIPT_LOG_FILE 2>/dev/null
                   $TELEGRAM_PATH --error --text "https://"$URL" is DOWN\nhttp code "$RESULT2"\nPlease check "$i" logs" --document $DOCKER_SCRIPT_LOG_FILE
                   echo $i >> $NOTIFIED_LIST
                 fi
        	   else
        	     # If website if OK after a container's restart, notify it through telegram
        	     $TELEGRAM_PATH --success --text "https://"$URL" was KO, but is OK after $i's restart"
               fi
             else
               echo -e "[ ${CGREEN}OK$CEND ] https://$URL is up." >> $LOG_TEMP
               while read line; do
                 if [ $line = "$i" ]; then
        		   # If a previously KO website is now OK, notify it through telegram
                   $TELEGRAM_PATH --success --text "https://"$URL" is back online"
                   sed -i /$i/d $NOTIFIED_LIST
                 fi
               done < $NOTIFIED_LIST
             fi
           fi
        done
        
        while read CHECK; do
          CHECK_KO=$(echo $CHECK | grep ERR)
          CHECK_STRING=${CHECK_KO/]/] $DATE : }
          if [ ! -z "$CHECK_KO" ]; then
            echo $CHECK_STRING >> $SCRIPT_LOG_FILE
            SITE_KO=1
          fi
        done < /var/log/cw.last
        if [ "$SITE_KO" != "1" ]; then
          echo -e "[ ${CGREEN}OK$CEND ] $DATE : All checks are OK" >> $SCRIPT_LOG_FILE
        fi
        
        if [ ! -s $NOTIFIED_LIST ]
        then
          # If previously notified list is empty, remove file
          rm -f $NOTIFIED_LIST
        fi
        

        Voici à quoi ressemblent les messages reçus :

        4 - Mises à jour :

        • Mise à jour en v1.1.1 :

        • Optimisation de la méthode de recherche de l'URL. Plus besoin de spécifier le type de proxy utilisé, le script va directement aller chercher le bon label. Il va d'abord chercher si un label personnalisé est défini, puis cherchera une URL aussi bien pour traefik que nginx.

        • Optimisation des logs (encore 😃). Je trouve ça plus clair.

        • Mise à jour en v1.1 :

        • Ajout de la possibilité de tester une URL différente de celle de base. J'ai eu le cas avec elFinder par exemple ou l'url de base ne répond pas. Il faut tester sdom.domain.tld/elFinder/elfinder.html dans ce cas précis.
          Pour ce faire, j'ai rajouté le support d'un label spécial : cw.check.url

        Toujours avec mon exemple, il suffit de rajouter le label suivant dans le docker-compose de elFinder :
        - cw.check.url=sdom.domain.tld/elFinder/elfinder.html

        Ensuite, recréer le container avec
        docker-compose up -d

        Le script détectera ce label et utilisera cette URL pour son test.

        • Simplification des logs : Le fichier de logs prenant rapidement du poids, j'ai simplifié sa génération. Dorénavant, si tous les tests sont OK, 1 seule ligne sera ajoutée au fichier de log.
          J'ai laissé la possibilité de regarder le résultat du dernier test an créant un fichier identique au fichier de log avec l'extension .last. Celui-ci est écrasé à chaque test.