Analyse de logs wordpress pour Matomo, le tout sous k8s

J’ai cherché un bon moment avant de trouver une solution propre pour alimenter Matomo avec les logs d’un wordpress hébergé sous kubernetes.

Matomo peut être alimenté soit en javascript, soit par analyse des logs. C’est cette seconde solution que j’ai choisie (malgré qu’elle soit bien plus compliquée à mettre en place que la première).

Solutions envisagées

Dans l’image docker wordpress officielle (en tous cas dans sa variante par défaut, basée sur Apache), /var/log/apache2/access.log est redirigé vers stdout. Ca parait logique dans un contexte docker: c’est docker (ou l’orchestrateur de conteneur) qui gère les logs.

La doc de Matomo propose d’utiliser leur script python pour le parsing des logs: https://github.com/matomo-org/matomo-log-analytics (il est aussi embarqué avec wordpress, dans le répertoire misc). Mais comment fournir les logs à ce script? J’ai eu plusieurs idées:

  • y accéder depuis kubectl logs: il est possible que ça fonctionne, mais les logs repartent de zéro à chaque redémarrage du pod, donc on risque d’en perdre
  • un CustomLog qui envoie au fil de l’eau à Matomo, cf https://github.com/matomo-org/matomo-log-analytics#setup-apache-customlog-that-directly-imports-in-matomo. Ca marcherait probablement mais nécessite python, qui n’est pas dans l’image wordpress. Il serait dommage de devoir créer et maintenir notre propre image Docker pour ça
  • un Cronjob k8s (basé sur https://hub.docker.com/_/python avec le script python injecté dedans), qui lirait des logs écrites par WordPress dans un PV dédié (dans le même namespace), et qui les enverrait à Matomo
  • la même chose, mais dans un side-car container (qui aurait directement accès aux fichiers de log: pas besoin de les écrire dans un PV), avec un cronjob à l’intérieur. Je trouve moins facilement administrable qu’un CronJob k8s (qu’on peut lancer manuellement, notamment). Et, si les logs ne sont pas dans un PV, elles sont perdues en cas de redémarrage du pod

C’est la 3ème solution que j’ai choisie (CronJob k8s).

Rotation/purge des logs

Mais on a aussi un problème de rotation/purge des logs: Matomo en a besoin, mais l’image docker de wordpress n’embarque pas l’outil logrotate (car ce serait un processus distinct). Elle embarque par contre l’outil rotatelogs d’Apache. On peut l’utiliser pour qu’il fasse la rotation, mais il ne sait pas faire la purge.

        # We don't want to log the k8s probes
        SetEnvIf User-Agent "^kube-probe" dontlog

        # Config to write logs in a PV used to feed Matomo (with log rotation every day)
        CustomLog "|/usr/bin/rotatelogs -l /var/log/apache2_pv/access.log 86400" combined env=!dontlog

Il faut exclure le user-agent kube-probe (pour qu’il ne pollue pas les statistiques de Matomo): je l’ai filtré dans la conf d’Apache ci-dessus.

J’ai aussi ajouté un Cronjob de compression/purge de ces fichiers access.log.*.

Pour faire encore mieux (en termes de sécurité), j’ai configuré un autre user-agent pour les probes k8s. Oui, parce qu’un pirate malin pourrait utiliser le user-agent « kube-probe » pour passer « sous les radars ». C’est faisable facilement, en configurant les headers des probes. Exemple:

        livenessProbe:
          httpGet:
            # This path avoids the pod to be restarted when in maintenance mode
            # See https://github.com/bitnami/charts/issues/3019
            path: /wp-admin/install.php
            port: 8080
            httpHeaders:
              - name: Host
                value: blog.mossroy.fr
              - name: X-Forwarded-Host
                value: blog.mossroy.fr
              - name: X-Forwarded-Proto
                value: https
              - name: User-Agent
                value: my-kube-probe

(et bien sûr adapter le filtre dans la conf d’Apache)

Configuration du CronJob d’analyse

Il faut que le CronJob tourne chaque nuit juste avant la rotation, en prenant le fichier le plus récemment modifié. J’injecte donc le script ci-dessous en ConfigMap, et configuré en entrypoint (« command » sous k8s). J’y injecte aussi le script import_logs.py de Matomo.

    #!/bin/bash

    # Find the latest log file
    unset -v LATEST_FILE
    for file in /var/log/apache2/*access*; do
      [[ $file -nt $LATEST_FILE ]] && LATEST_FILE=$file
    done
    echo "Latest file is $LATEST_FILE: let's import it in Matomo"

    # Push the logs to Matomo
    python3 /import_logs.py --url=matomo.matomo.svc.cluster.local --idsite=1 --token-auth $MATOMO_TOKEN_AUTH --enable-reverse-dns $LATEST_FILE

Il faut lui passer un MATOMO_TOKEN_AUTH en variable d’environnement, et monter /var/log/apache2 avec le même PV où wordpress écrit ses logs.

NB: l’image docker wordpress embarque bien le nécessaire (module mod_remote_ip) pour que ce soit l’IP affichée dans les logs soit bien celle de l’utilisateur (et non un reverse-proxy intermédiaire). Cf https://github.com/docker-library/wordpress/issues/383.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *