Plongée approfondie dans notre infrastructure d’hébergement Kitsu

Plongée approfondie dans notre infrastructure d’hébergement Kitsu

Déployer un serveur web peut être fait assez facilement. Surtout, des applications web comme Kitsu, où tout est documenté en ligne. Un service informatique prêt à y consacrer plusieurs jours y parviendra sûrement. Mais le problème, c’est qu’exécuter une application cloud ne consiste pas à configurer le service web : il s’agit de gérer l’imprévu.

Je peux l’affirmer avec certitude, car lorsque j’ai construit mon premier startup (Cozy Cloud), au début, je gérais nos serveurs.  J’ai mis en place des dizaines de machines virtuelles, configuré le DNS, et j’étais en mesure de fournir notre produit à nos utilisateurs abonnés. Tout semblait aller pour le mieux jusqu’à ce que les utilisateurs utilisent vraiment notre produit.

Une fois mon infrastructure, si belle, en place, j’ai dû faire face à des tonnes de situations pénibles : panne logicielle, indisponibilité du prestataire d’hébergement, lenteurs, stratégie de sauvegarde, restauration... Cela arrivait à n’importe quel moment du jour ou de la nuit. J’étais cofondateur et CTO, donc j’avais encore énormément d’autres responsabilités à gérer. J’ai appris beaucoup de choses, mais soyons honnêtes : ce n’était pas suffisant pour absorber la charge. Heureusement, nous avons levé des fonds et j’ai pu embaucher quelqu’un d’expérimenté pour nous aider à le gérer. J’aurais pu trouver bien d’autres solutions. Mais, au final, reconnaître que c’était un travail à temps plein a été ma meilleure décision pour gérer cette situation.

C’est pourquoi, avec CGWire, nous voulons éviter tous ces moments douloureux pour les studios. Nous savons que notre logiciel est gratuit, mais il ne serait pas judicieux de développer Kitsu sans vous proposer un service d’hébergement en complément. Votre travail principal est de faire des films, et vos équipes IT sont dédiées à vos artistes. Elles n’ont pas besoin de gérer la complexité de l’hébergement web et son comportement potentiellement dangereux, en plus du matériel et du service qu’elles assurent pour vos studios.

Kitsu est un élément clé de votre pipeline. Une panne de sa part peut mettre votre production en danger. C’est un stress supplémentaire que vous ne voulez ni pour vous, ni pour vos équipes.

Beaucoup de gens sont conscients de ce problème. C’est pourquoi proposer une solution cloud du logiciel est un modèle économique classique pour les projets gratuits et open source : ce n’est pas spécifique à nous.

Pour illustrer le travail nécessaire pour héberger correctement un tel logiciel, nous voulions vous montrer tout ce que nous avons mis en place sur notre infrastructure afin de vous servir Kitsu comme il se doit. Aujourd’hui, nous gérons l’installation de Kitsu pour 60 clients, soit environ 3 000 utilisateurs au total.

Dans cet article de blog, nous allons vous montrer tout ce que notre équipe ops a mis en place pour vous garantir le meilleur service possible pour votre utilisation de Kitsu.

Contexte

La stack de base

Pour rappel, Kitsu est une application web composée de :

  • Deux services Python Flask (REST API et un système pub/sub WebSocket)
  • Un daemon RQ
  • Une instance Redis
  • Une base de données Postgres.
  • Les fichiers sont stockés sur le disque ou dans une instance de stockage d’objets.
  • Un front-end constitué de fichiers Javascript statiques construits par les outils du framework Vue.js (basés sur Webpack).
  • Une instance Nginx pour servir les fichiers statiques et comme reverse proxy afin d’accéder à l’API et au front-end depuis un seul nom de domaine.

En résumé, il s’agit de sept services qui doivent toujours être opérationnels. Si l’un d’eux est en panne, l’application ne peut pas fonctionner correctement.

L’offre

Nous proposons deux offres à nos clients :

  • Hébergement cloud, où nous mettons à disposition une VM dédiée. Tous les services tournent dans notre cloud.
  • Installations on-premise : nos clients fournissent le matériel. Nous réalisons la mise en place, la maintenance et les mises à jour. Nous gérons l’intégration LDAP sur demande.
    Pour les clients plus importants, nous proposons un outil leur permettant de démarrer et d’arrêter des instances de Kitsu localement.

Orchestration

Nous utilisons OVH comme prestataire d’hébergement et OpenStack comme IaaS (Infrastructure as a Service). Notre infrastructure repose sur des machines virtuelles. Grâce à Terraform, nous décrivons nos besoins matériels. Cela nous permet de créer rapidement de nouvelles instances de Kitsu.

Voici un exemple de fichier Terraform utilisé pour lancer une nouvelle instance de Kitsu :

module "customer_cgwire" {
  source         = "./modules/customer"
  shortname      = "cgwire"
  fqdn           = "cgwire"
  customer_class = "bronze"
  flavor         = "${var.flavor_bronze}"
  net_public     = "${var.net_public}"
  net_priv       = "${var.net_priv}"
  region         = "${var.region}"
  image_name     = "${var.image_name}"
  key_pair       = "${openstack_compute_keypair_v2.keypair.name}"
}

Terraform fournit une commande simple (terraform apply) pour appliquer nos fichiers de configuration à une infrastructure en production.

Quand la VM Kitsu est en ligne, l’étape suivante consiste à configurer l’instance. Nous créons la base de données, configurons le système d’exploitation et initialisons les données. Pour cela, nous utilisons un système de gestion de configuration. Nous avons utilisé Ansible pendant un moment, mais récemment nous sommes passés à Saltstack. Il nous a semblé plus pratique pour exécuter de nombreuses mises à jour en parallèle.

Pour l’utiliser, nous décrivons des fichiers de configuration et tout ce qui doit être en place pour avoir une instance Kitsu correcte. Ensuite, nous lançons la commande salt state.highstate. Une fois terminé, l’instance Kitsu est prête à être utilisée !

Exemple de fichiers Saltstack (ici pour mettre en place un service Redis) :

====== redis.sls
redis_packages:
  pkg.latest:
    - pkgs:
      - redis-server

/etc/redis/redis.conf: file.managed: - user: redis - group: redis - mode: '0640' - template: jinja - source: salt:///files/redis.conf.j2 - context: bind_addrs: - require: - pkg: redis_packages

redis: service.running: - name: redis-server - enable: True - require: - pkg: redis_packages - watch: - file: /etc/redis/redis.conf

====== redis.j2 daemonize yes pidfile /var/run/redis/redis-server.pid port 6379 bind

Stockage

Kitsu stocke des tonnes de fichiers d’aperçu. Ce sont principalement des fichiers vidéo. À chaque fois qu’un utilisateur téléverse une vidéo, elle est normalisée et certaines miniatures sont extraites. Comme les studios veulent pouvoir accéder à une version haute définition des vidéos, les fichiers stockés sont assez volumineux.
Les images génèrent aussi des miniatures et d’autres types de fichiers sont stockés directement.

Alors, comment stockons-nous ces fichiers ? Cela dépend du contexte : nous avons deux cas :

  • Installations on-premise : nous stockons principalement les aperçus sur un simple système de fichiers (un dossier disponible sur l’hôte sur lequel nous hébergeons l’instance Kitsu). Kitsu organise les dossiers à partir des UUID des fichiers d’aperçu (générés par Postgres) afin d’éviter d’avoir trop de fichiers dans le même dépôt et de garantir l’absence de collision. En alternative, nous proposons aussi du stockage d’objets local pour les clients entreprise.
  • Hébergement cloud : nous utilisons OpenStack Swift de OVH comme stockage d’objets. Dans une infrastructure cloud, vous pouvez perdre facilement une machine virtuelle. Cela conduit à perdre toutes les données de vos fichiers. Utiliser un stockage dédié, découplé de la VM, rend les choses plus simples pour les sauvegardes (nous répliquons chaque fichier 3 fois dans 2 emplacements différents). Cela nous permet de détruire et de restaurer facilement des VM Kitsu.

Calcul

Un autre point à gérer est le traitement vidéo. Il est important de normaliser chaque vidéo téléversée pour garantir une expérience fluide pendant la lecture. Pour y parvenir, nous utilisons FFmpeg. Il gère tous les codecs et conteneurs possibles en entrée. De l’autre côté, en sortie, il fournit des vidéos standardisées et optimisées pour notre système.

Le revers, c’est que cela entraîne une consommation de ressources très intensive. Pour éviter de surcharger nos VM, nous mettons en place un cluster Nomad de la société Hashicorp. Nous lui envoyons toutes les tâches async lourdes en calcul depuis les instances Kitsu. Kitsu crée un job Nomad, qui démarre un conteneur Docker, récupère la vidéo, la traite, puis téléverse tous les fichiers sur le stockage d’objets. Ensuite, il supprime tout localement pour pouvoir gérer les vidéos suivantes.

Nomad peut gérer un cluster de VM et fournit un point d’entrée unique pour tout ce qui doit utiliser le cluster. Cela rend notre normalisation vidéo beaucoup plus efficace. Nous l’utilisons aussi pour la construction des playlists : nos utilisateurs concatènent plusieurs versions de plans pour construire un seul film. Cette action est de loin la plus gourmande en ressources.

Journaux

Dans toutes les instances, les journaux standards sont écrits sur chaque hôte. Il est compliqué d’y accéder tous pour trouver des bugs ou analyser des situations. C’est pourquoi nous utilisons Grafana Loki comme système d’agrégation de logs.

Il récupère toutes les informations de journal et nous permet de rechercher les occurrences d’erreurs à travers les instances. À partir de là, nous pouvons aussi surveiller les goulots d’étranglement de performance. Enfin, et ce n’est pas le moindre, cela donne une idée de l’origine des requêtes. Ce qui peut être utile en cas d’attaque informatique.

Supervision

Un point très important pour un administrateur système, c’est la supervision. Elle vous alerte lorsqu’un problème apparaît sur votre infrastructure. Cela compte énormément parce que :

  • Nous sommes au courant des problèmes avant que le client ne nous appelle en disant « c’est cassé ! »
  • Elle nous aide à trouver rapidement la cause racine d’un problème.

Pour le rendre plus concret, principalement nous collectons un ensemble de conditions de manière régulière :

  • Les services clés sont en ligne ou non.
  • L’instance Kitsu est joignable depuis Internet ou non.
  • La charge CPU dépasse un seuil.
  • La consommation mémoire dépasse un seuil.
  • L’espace disque libre est inférieur à un seuil.

Si l’une des conditions n’est pas remplie, une alerte est déclenchée. Si une alerte survient, nous savons que nous devons agir immédiatement pour corriger la situation.

Pour la stack cloud, nous configurons la supervision avec les produits Grafana : Prometheus et Alertmanager. Nous envoyons les messages d’alerte vers un canal Slack dédié et les plus importantes sont aussi envoyées par e-mail.

Le tableau de bord Alertmanager affiche toutes les alertes en cours en temps réel :

Nous collectons des métriques sur les hôtes système et nous pingons les ports HTTP pour avoir une vue d’ensemble complète des informations.

Pour nos installations on-premise, pour des raisons de compatibilité avec l’existant et de simplicité, nous utilisons l’ensemble Monit et M/Monit afin d’avoir une vue centralisée de l’état de nos installations.

Métrologie

C’est l’autre face de la supervision. Ici, nous analysons les données visuellement. Nous ne cherchons pas uniquement à savoir si l’instance est en ligne ou non. Nous cherchons plutôt des comportements étranges (des changements inattendus dans le temps), comme une utilisation prolongée du CPU (dans ce cas, le système est toujours en ligne, mais le service est dégradé).

Nous utilisons les mêmes outils pour collecter les métriques de métrologie. Le composant central est Prometheus pour stocker les données. Il est couplé à Grafana pour l’affichage. Il fournit un système puissant pour voir comment les métriques évoluent au fil du temps. Lorsque votre système de fichiers rencontre un problème, vous pouvez voir si cela s’est produit en une seconde, en une journée ou en une minute. Vous pouvez aussi identifier des schémas récurrents. C’est très utile pour trouver la cause racine de votre problème.

Voici quelques exemples :

Vérifier la « santé HTTP » d’une instance :

Voir comment évolue la consommation de ressources :

Sécurité

La sécurité est la partie la plus importante de la configuration. Pour renforcer nos machines, nous avons appliqué des principes fondamentaux :

  • La seule façon de se connecter à un hôte est SSH via une clé SSH protégée par une phrase secrète. Cela réduit le risque de connexion inutile par attaques par force brute sur le mot de passe.
  • Certaines machines virtuelles n’ont pas besoin d’être accessibles depuis Internet. Nous utilisons donc des relais SSH pour les gérer. Cela réduit la surface d’attaque.
  • Nous autorisons uniquement des adresses IP pour accéder à nos machines critiques qui doivent encore être joignables depuis Internet.
  • En on-premise, nous utilisons des VPN pour nous connecter avec les studios qui ont des mesures de sécurité importantes.
  • Nous disposons de groupes de sécurité qui n’autorisent que les ports TCP utilisés par nos clients.
  • Nous mettons en place des pare-feu et des mécanismes de blocage d’IP sur toutes les machines.
  • Toutes les instances Kitsu utilisent une configuration SSL robuste pour gérer les connexions des utilisateurs.
  • Le système d’exploitation de notre instance est toujours à jour.
  • Nos journaux sont collectés et analysés via une protection SIEM.

La prochaine étape pour nous sera de chiffrer les fichiers dans le stockage d’objets afin de limiter les problèmes si le stockage d’objets est compromis.

Restauration

Un autre point très important est la sauvegarde et la restauration. Avec des aperçus dans le stockage d’objets, une base de données Postgres dupliquée et une sauvegarde de base de données dans le stockage d’objets, nous avons tout ce qu’il faut pour recréer rapidement une instance Kitsu.

Si une instance client « brûle », nous la recréons avec Terraform, puis nous la configurons avec Saltstack. Et voilà, c’est en ligne ! L’instance peut encore accéder au stockage d’objets, remettre en place la base de données, et servir les fichiers comme d’habitude.

Si le stockage d’objets tombe en panne, nous pouvons nous connecter au stockage d’objets répliqué et reprendre l’utilisation de notre logiciel comme avant. Il suffit de mettre à jour nos fichiers de configuration via Saltstack.

Divers

Nous envoyons des e-mails à nos utilisateurs depuis notre propre domaine. Pour améliorer la délivrabilité, nous avons configuré tous nos systèmes avec SPF et DKIM. Ces protocoles permettent de tracer tous les e-mails envoyés avec cg-wire.com comme nom de domaine.

Pour surveiller cela, nous configurons le protocole DMARC. Ainsi, chaque serveur qui relaie un e-mail @cg-wire.com envoie un rapport quotidien qui aide à identifier les sources d’e-mails. Nous savons aussi s’ils utilisent correctement SPF et DKIM, et quand nos e-mails sont considérés comme du spam. Cela nous permet aussi de construire des tableaux de bord pour suivre des analyses sur nos e-mails et comprendre pourquoi ils ont été mal étiquetés. Au final, nous conservons une bonne réputation pour notre domaine d’e-mails.

Derniers mots

Voilà pour la visite ! Nous ne vous avons montré que la partie émergée de l’iceberg. Il existe de nombreuses subtilités et détails que nous ne pouvons pas aborder ici (cela demanderait d’écrire un livre). Néanmoins, cela vous donne un aperçu du travail nécessaire pour faire tourner n’importe quelle application web comme Kitsu. Ce que nous concevons chez CGWire, ce n’est pas seulement un logiciel beau et efficace. Nous apportons la même attention à votre installation et à vos données. Nous travaillons toujours dessus comme sur quelque chose dont nous voulons pouvoir être fiers de faire la démonstration : et qui fonctionne parfaitement avec vous.

La collaboration avec les studios nécessite un logiciel qui fonctionne correctement, qui est sûr et capable d’absorber des charges importantes. Les gens doivent pouvoir avoir confiance dans un outil pour l’utiliser. C’est notre rôle de le rendre solide, efficace et sécurisé.

Notre prochain défi sera la gestion de la région pour notre infrastructure cloud. Nous avons de plus en plus de clients loin de la France. Nous voulons offrir les meilleures performances possibles en proposant des instances de Kitsu proches de leur studio. Une fois que nous aurons résolu ce problème, nous partagerons notre recette. Alors, restez connectés pour savoir comment nous l’avons fait !

Nous avons dédié ce blog à l’Animation Production Management, à l’Animation Pipeline et à nos produits. Mais vous pouvez nous suivre sur LinkedIn pour voir nos actualités. Nous partageons aussi des nouvelles de l’industrie de l’animation. Venez jeter un coup d’œil et nous rejoindre !

Vous appréciez cet article ?

Abonnez-vous à notre newsletter pour plus d'analyses, de tutoriels et d'actualités du secteur.