Tests de chef chez PagerDuty
Chez PagerDuty, toute notre infrastructure informatique est automatisée à l'aide de Chef. Nous publions très fréquemment des fonctionnalités et des modifications dans notre base de code Chef – souvent plusieurs fois par jour – et il est donc crucial que nous testions notre code Chef avant de le déployer dans notre environnement de production. Comme nous l'avons appris, les échecs peuvent survenir à cause de dépendances non gelées, de valeurs incorrectes dans le fichier de configuration, d'erreurs logiques, de bogues dans les bibliothèques sous-jacentes, etc.
Dans cet article, nous passerons en revue les 5 outils/stratégies de tests séquentiels que nous utilisons pour créer une infrastructure prévisible et stable.
- Tests sémantiques – Dans notre pipeline d’intégration continue (CI), la première étape consiste à exécuter un outil de vérification appelé Foodcritic qui vérifie les erreurs sémantiques dans notre code Chef. Il est rapide et facilite un contrôle qualité uniforme. Nous nous arrêtons immédiatement en cas d’échec. Nous exécutons actuellement Foodcritic uniquement sur nos livres de recettes (notre répertoire de fournisseurs Berkshelf est exclu).
- Tests unitaires – La deuxième étape consiste à exécuter des tests unitaires via ChefSpec. Nous avons une couverture complète (c'est-à-dire vérifier au moins si le nœud converge) de toutes les recettes, et une couverture étendue sur celles spécifiques à PagerDuty. Nous avons récemment migré vers ChefSpec 3 (crier à Seth Vargo pour la réécriture), qui propose des assertions chaînables, des comparateurs personnalisés et de nombreuses autres améliorations. Pour certains des livres de recettes principaux (c'est-à-dire iptables), nous avons des comparateurs personnalisés pour les LWRP du même livre de recettes. En général, nous gardons nos recettes spécifiques à PagerDuty minces, celles de LWRP minces et une bibliothèque qui incarne l'essentiel de la logique. Les bibliothèques sont testées à l’aide de RSpec brut. En général, nous affirmons des dépendances supposées (c'est-à-dire que la spécification de pd-apache s'affirmera contre « service['apache'] ») à partir des livres de recettes de la communauté. En raison des offres « élaborées » de Chef sur la priorité des attributs, il peut être très difficile de prédire quel attribut finira par être utilisé et ChefSpec fournit un filet de sécurité pour cela. Les tests unitaires nous permettent également d'implémenter en toute sécurité les modes d'exécution du pourquoi dans nos LWRP personnalisés. Cela a été incroyablement utile lors de la refactorisation de composants critiques. Nous avons également désormais une meilleure compréhension des dépendances réseau que nous introduisons avec les appels de recherche individuels.
- Test fonctionel – Nous disposons d'une suite de tests fonctionnels très petite, mais naissante, qui couvre actuellement environ 80 % de notre infrastructure. Pour chacun de ces tests, nous appliquons les éléments de la liste d'exécution de niveau supérieur (c'est-à-dire les rôles directement attribués aux nœuds) à un conteneur Linux de la même plateforme et de la même version (nous utilisons Ubuntu). suite de tests fonctionnels crée un en mémoire du serveur Chef (crier à John Keiser ), télécharge toutes les données via notre script de restauration , génère le conteneur, puis effectue un bootstrap basé sur un couteau à l'aide de notre modèle. Avec cela, tous nos livres de recettes, rôles et environnements sont exécutés. Nous utilisons un gestionnaire personnalisé qui stocke les numéros de ressources et d'autres statistiques sous forme d'attributs de nœud. Nous invoquons Chef deux fois et utilisons ces attributs de métrique pour vérifier le nombre de ressources non idempotentes dont nous disposons. Nous avons une poignée de ressources non idempotentes, et notre objectif est de ramener ce chiffre à zéro. Certains des tests fonctionnels impliquent également la restauration des données de l'environnement de préparation et la convergence des conteneurs par rapport à celles-ci. Cela nous aide à simuler une véritable convergence de production ou de préparation et à affirmer des configurations impliquant des recherches approfondies. Toutes nos intégrations tierces (c'est-à-dire Chien de données et Sumologic ) sont testés dans le cadre de cette étape. Cela nous donne également un retour plus fréquent sur les performances des API externes, car nos serveurs de production consomment également ces API. Après les assertions, le conteneur passe par un démontage, où nous pouvons tester toutes nos étapes de démontage externe basées sur le couteau et de démontage interne basées sur la recette du chef (c'est-à-dire la désinscription des services externes ou la suppression du DNS). Nous utilisons la vanille rubis-lxc des liaisons avec RSpec pour tester tout cela. Bien que les tests fonctionnels soient toujours exécutés localement, notre objectif final est de les intégrer dans Jenkins.
- Tests d'intégration – Nous disposons de deux environnements principaux dans lesquels tout notre code Chef est testé en même temps que tout le code de l'application. Nous disposons d'un environnement de test générique dans lequel les fonctionnalités sont déployées et testées en permanence. Le deuxième environnement est celui dans lequel ces fonctionnalités sont testées en charge. Ces deux environnements sont logiquement indépendants, mais partagent certains services communs (par exemple, un compte AWS ou Chef Server).
- Vendredi d'échec – En plus de tous ces tests logiciels, nous injectons également de manière proactive des échecs dans notre pile Chef lors de nos Failure Fridays. Dans ce cadre, nous avons récemment testé : les dépassements de délai du serveur Chef, la perte d'un serveur Chef et la restauration à partir d'une sauvegarde, et ce qui arrive aux clients lorsque le serveur Chef présente des latences élevées et des pertes de paquets (alerte spoiler : tout ralentit). Pour plus d'informations sur les Failure Fridays, restez à l'écoute de la publication/présentation de Doug lors de DevOpsDays London.
Nous avons extrait quelques éléments clés de nos spécifications et les avons rendus disponibles ici :
Ces solutions sont basées sur les limitations actuelles des outils et technologies disponibles que nous pouvons adopter et intégrer. Beaucoup de ces outils méritent d'être intégrés dans leurs propres bases de code ou d'avoir leurs propres bibliothèques dédiées, ou d'être fusionnés avec leurs alternatives principales correspondantes une fois la pile sous-jacente stabilisée. Mais ceux-ci devraient fournir des exemples concrets sur lesquels nous pouvons discuter, imaginer et améliorer. Tout commentaire à ce sujet est le bienvenu.
C hef a joué un rôle déterminant dans notre infrastructure informatique. Grâce aux tests automatisés, nous pouvons fournir du code en continu. En réduisant nos délais de mise sur le marché et en augmentant la qualité de nos versions, les clients de PagerDuty peuvent compter sur notre infrastructure résiliente et haute disponibilité.