Testez la logique de cache de votre Varnish avec varnishtest
J’ai récemment eu à tester de manière exhaustive une toute nouvelle configuration de varnish. Le but étant de faire une infrastructure de cache complètement pilotable via des Headers HTTP en reprennant le principe de ce que Yakaz avait présenté au Varnish User Group.
Varnishtest : qu’est-ce que c’est ?
Varnishtest est un (outils / framework de test) utilisé notamment par les dévelopeurs de varnish pour tester la non régression de leur reverse-proxy cache. Cet outils est vraiment puissant et permet de créer pleins de scénarios pour tester le comportement de varnish en fonction d’un code VCL. Vous pouvez trouver l’ensemble des tests de varnish dans leur repo git:
$ git clone https://github.com/varnish/Varnish-Cache.git $ cd Varnish-Cache/bin/varnishtest/tests/
Tous ces exemples vont vous permettre de comprendre le fonctionnement de varnishtest car malheureusement la documentation est très limitée pour le moment. Vous pouvez aussi vous reporter à cet article de blog qui est une bonne introduction.
Que peut-on faire avec varnishtest
Avec varnishtest on peut (sans être exhaustif) :
- Mocker des backends et définir leurs comportements
- Lancer des serveurs varnish avec des vrais morceaux de vcl dedans pour les configurer
- Utiliser des clients HTTP et leur définir les réponses attendues
- Faire des tests sur les statistiques des serveurs varnish lancés
Comment fait-on tout ça ?
Déclaration d’un backend :
server s1 { rxreq txresp -body "réponse 1" rxreq txresp -body "réponse 2" rxreq txresp -body "réponse 3" } -start
Voila, c’est tout, vous avez mocké un backend qui peut répondre à 3 requêtes et pas une de plus. La configuration de ces servers peut être plus complète avec la directive expect. Voici un exemple contenu dans les test « a00001.vtc » de Varnish-Cache:
server s1 { rxreq expect req.method == GET expect req.proto == HTTP/1.1 expect req.url == "/" txresp }
La définition de ce serveur va donner l’accès à des variables telles-que ${s1_addr} et ${s1_addr} que l’on pourra utiliser par la suite.
Il est évidemment possible de mocker plusieurs serveurs.
Déclaration d’un serveur varnish :
De la même manière, il est possible de déclarer des serveurs varnish :
varnish v1 -vcl { backend b1 { .host = "${s1_addr}"; .port = = "${s1_port}"; } sub vcl_fetch { .... } }
Cet exemple permet donc d’instancier un objet v1 qui sera un varnish et de lui spécifier un comportement en lui donnant directement un morceau de VCL.
Il est possible de forcer Varnish à se binder sur un port spécifique en le déclarant comme ca :
varnish v1 -arg "-a 127.0.0.1:8080" -vcl { .... }
Etrangement Varnish n’a pas l’air de vérifier l’état de santé des backends déclarés. Si vous avez besoin de tester la mort d’une backend vous pouvez le faire comme cela :
varnish v1 -cliok "backend.set_health b1 sick"
Utilisations des clients et des assertions:
La syntaxe pour déclarer un client est relativement proche :
client c1 { txreq -url "/object" -hdr "X-TTL:1s" rxresp expect resp.status == 200 expect resp.body == "réponse 1" } -run
Donc ce client va faire un GET sur le serveur Varnish v1. Il s’attend à recevoir un 200 et que le body de la réponse soit « réponse 1″.
On peut aussi faire des tests sur les statistiques internes de varnish :
varnish v1 -expect n_object == 1 varnish v1 -expect cache_hit == 0 varnish v1 -expect cache_miss == 1
Executer votre test varnish:
Pour lancer le test, rien de plus simple :
$ varnishtest affinity.vtc top TEST affinity.vtc passed (0.978)
En cas d’erreur vous aurrez un message tel que :
c1 0.9 EXPECT resp.body (server 1) == server 2 (server 2) failed
Industrialisation des tests
Le but n’étant pas de tester varnish en lui même mais le VCL déployé en production nous avons tout simplement utilisé la directive include dans la définition des varnish pour inclure le VCL de production.
Il existe plusieurs limitations à cette méthode :
- Il faut séparer la définition des backends de votre logique de cache dans votre VCL de production. En effet, nous avons besoin de ne sourcer que la logique et de surcharger les backends. Il est à noter qu’il est possible d’utiliser de vrais backends avec varnishtest.
- Les include ne semblent pas autoriser l’utilisation de chemins relatifs. Soit vous spécifiez un chemin absolu soit la racine de votre chemin relatif est « /etc/varnish » (sous debian).
Vous pouvez retrouver un exemple de test et mon script d’industrialisation des tests sur mon repo github.