====== Content Delivery Networks ======
===== Qu'est ce qu'un CDN ? =====
**CDN** signifie Content Delivery Network. C'est un réseau sur lequel on va pouvoir stocker des images, des vidéos ( en fait des contenus qui ne conviennent pas aux bases de données ou au NoSQL ).
La problématique d'utilisation d'un CDN ici est simple : on a plein de serveurs webs qui travaillent en parallèle, et on ne peut stocker d'informations sur ceux ci comme on pourrait le faire avec un serveur web classique. En effet, les autres serveurs webs ne pourraient y avoir accès. On doit donc stocker nos informations ailleurs. Pour ce qui est nombres et textes, des bases de données et du NoSQL seront utilisés.
Pour ce qui est des images / vidéos / autre uploadé par l'utilisateur il faut utiliser un espace de stockage centralisé. Utiliser directement un système d'espace de stockage centralisé ne suffit pas ( opérations concurrentes possibles, ce qui mènerait tel que je le vois à une coûteuse gestion gestion de verrou sur les serveurs webs ... ). C'est là que les CDNs font leur entrée en jeu. En gros on met des données dessus depuis les serveurs webs, et on les récupère sur le CDN quand on en a besoin.
On attend par ailleurs d'un CDN que les contenus soit répliqués dans plusieurs DataCenter ( pour des raisons de coûts / performances ).
La solution classique et que beaucoup choisissent c'est des CDNs payants ( c'est après tout moins cher que de déployer et entretenir le sien ... ) . Je peux citer ( merci wikipédia ) Amazon cloudfront, CDNetworks, CloudFlare ... Vous l'aurez compris ( et vous devez commencer à me connaître ... ), nous essayerons ici de trouver des pistes pour utiliser notre propre CDN ( et pas celui des voisins ... ).
===== Utiliser CEPH =====
CEPH est un système de fichier orienté Object Storage. Il est donc particulièrement adapté pour être utilisé en temps que CDN.
Vous trouverez sur cette page des détails sur [[wiki:divers:ha:glusterfs|CEPH]].
CEPH introduit une Object gateway, qui nous fournis une interface RESTFULL. On pourra donc, très simplement, depuis nos serveurs webs, via le protocole http ajouter / consulter / modifier / supprimer le contenu.
==== Instalation de CEPH Object Gateway ====
Nous allons installer CEPH Object Gateway sur un de nos moniteurs ( vous pouvez mettre sans problème deux CEPH Object gateway derrière un [[wiki:divers:ha:haproxy|HAproxy]]... ).
Nous allons utiliser apache2 ainsi que FastCGI. Pour les installer, rien de plus simple :
apt-get install apache2 libapache2-mod-fastcgi
On active ensuite les modules rewrite et fast-cgi :
a2enmod rewrite
a2enmod fastcgi
On crée les virtualHost rgw.conf : ''/etc/apache2''
FastCgiExternalServer /var/www/s3gw.fcgi -socket /tmp/radosgw.sock
ServerName benwa-ceph-master-1
ServerAdmin benwa@minet.net
DocumentRoot /var/www
Options +ExecCGI
AllowOverride All
SetHandler fastcgi-script
Order allow,deny
Allow from all
AuthBasicAuthoritative Off
AllowEncodedSlashes On
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
ServerSignature Off
Puis on l'active :
a2ensite rgw.conf
Et on désactive le virtual Host par défaut :
a2dissite default
Bon maintenant créons le fichier ''/var/www/s3gw.fcgi'' :
#!/bin/sh
exec /usr/bin/radosgw -c /etc/ceph/ceph.conf -n client.radosgw.gateway
Maintenant il ne reste plus qu'à installer rados ( qui gère les objets de la CEPH Object Gateway ) :
apt-get install radosgw
La configuration se fait ensuite dans ''/etc/ceph/conf'' :
[global]
fsid = 1af68adc-4fff-46a5-ba0b-d0f7e9f12cca
mon_initial_members = benwa-ceph-master-1, benwa-ceph-master-2
mon_host = 192.168.103.222,192.168.103.223
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
filestore_xattr_use_omap = true
[client.radosgw.gateway]
host = benwa-ceph-master-1
keyring = /etc/ceph/keyring.radosgw.gateway
rgw socket path = /tmp/radosgw.sock
log file = /var/log/ceph/radosgw.log
rgw enable ops log = false
Comme nous utilisons l'authentification via **cephx** il nous faut générer nos clés :
ceph-authtool --create-keyring /etc/ceph/keyring.radosgw.gateway
chmod +r /etc/ceph/keyring.radosgw.gateway
ceph-authtool /etc/ceph/keyring.radosgw.gateway -n client.radosgw.gateway --gen-key
ceph-authtool -n client.radosgw.gateway --cap osd 'allow rwx' --cap mon 'allow rw' /etc/ceph/keyring.radosgw.gateway
ceph -k /etc/ceph/ceph.client.admin.keyring auth add client.radosgw.gateway -i /etc/ceph/keyring.radosgw.gateway
Chez moi ça marche ;-)
==== Limites ====
Cette fonctionnalité de CEPH est très sympa et rempli simplement le contrat fournit initialement. Néanmoins je note un certain nombre de bémols :
* L'utilisation de CEPH Object Gateway n'est pas transparente à l'application web que nous déployons. Il faudra en tenir compte lors de la programmation.
* Moins grave, des clients pour l'API swift ne sont disponibles que pour les langages suivants : python ruby et Java. L'API compatible Amazon S3 élargie un peu la gamme de langages possibles ( mais y a pas de node.js ).
* Et pour finir, la répartition des données se fait via les CRUSH tables. Comme il s'agit d'une politique globale, cela veut dire qu'on ne peut pas avoir une politique orientée cas particulier.
Je m'explique : imaginez youtube. Ils ont envie d'avoir plusieurs copies de la vidéo de Cyprien sur tous leurs data-centers afin de pouvoir tenir la charge, minimiser leurs transits de donnée, et fournir une meilleure qualité de service à leurs clients. En revanche ils ne voudront garder que deux exemplaires de ma vidéo sur l'usage de l'emmental rapé en Ukraine car tout le monde s'en fout, ce n'est pas demandé, et ça leur coute de l'espace disque.
Ce genre de politique peut être obtenue via CEPH en jouant sur les pools sur lequel on écrira l'objet. Décision prise par les serveurs webs ( pas cool ). Et pire, le résultat obtenu sera "statique" : si ma vidéo fait le buzz parce que j'ai mis un chapeau péruvien ridicule et que je zozotait, il sera assez difficile de la changer de pool, et le tout de manière transparente.
* Dernier point, CEPH Object Gateway s'interface avec les serveurs webs. Si je regarde une vidéo, elle passera par les serveurs webs ( et surchargera donc mes liens en interne de manière somme toute assez inutile... Je pourrais vouloir que mon client la récupère directement ( sans passer par un serveur web... ).
Bien sur tout ceci est à nuancer, et CEPH Object Gateway est vraiment un outil super, mais il ne conviendra à mon sens pas à certaines situations particulières et exigeantes.
==== Liens ====
* La DOC de [[http://ceph.com/docs/master/radosgw/|CEPH Object Gateway]]
===== Un CDN personnalisé ? =====
Bon, supposons que j'apporte un attention très poussée à la gestion de la réplication des données sur mon CDN. Je veux aussi pas surcharger mes liens internes. Comment faire ?
Bah j'ai cherché longtemps, et je n'ai pas trouvé. On va dire que proposer une solution libre et simple serait un de mes projets.
==== Architecture de la solution ====
L'architecture s’appuierai sur quatre éléments :
* Des serveurs NGinx en front pour permettre aux clients de consulter les éléments du CDN.
* Un système de fichier distribué, sur lequel sont stockés les objets du CDN. Le mot "distribué" est important : il permet aux serveurs NGinx d'accéder tous au même contenus.
* Un ensemble de contrôleurs. Son but est de :
- Gérer l'ajout de fichier dans le CDN ( requête PUT depuis les serveurs webs )
- Gérer la suppression ( requête DELETE depuis un des serveurs webs )
- Gérer la réplication de l'objet vers les autres nœuds du CDN.
* Du NoSQL clé / valeur, pour stocker les infos sur un objet, ce dont ont besoin les contrôleurs. Je me serais orienté vers REDIS.
Un petit schéma vous permettra de mieux comprendre de quoi il en retourne...
{{:wiki:divers:ha:my_cdn.png?800|}}
Pour plus de souplesse, le système s'appuiera sur un ensemble de scores :
- Initial, envoyé lors du PUT ( permettra a la vidéo de Cyprien d'être directement dupliquée sur de nombreux data-centers...)
- En fonction du nombres de vues... L'objet serais copié en cas de nécessité vers les autres data-centers.
Clairement, compte tenu de ces choix il nous faut :
* Modifier NGINX afin que :
- Il redirige la requête client vers un datacenter possédant l'objet si lui ne le possède pas (lecture de la fiche REDIS sur cet objet)
- Il notifie ses vues et avertisse un de ces contrôleurs en cas de besoin de réplication. ( pour le dernier point on pourrait aussi opter pour une tache de fond sur les contrôleurs )
* Complètement écrire le code du contrôleur. Je le verrai bien en node.js...
==== Conclusion ====
Le projet est dans les cartons et attend un peu de temps libre pour avancer.
Note : j'entrevois une difficultée : c'est l'authentification lors de l'accès au contenu... Comme on ne passe plus par les serveurs webs, ça complique les choses... A moins de renoncer dans ce cas à servir directement le client...
--- //[[benwa@minet.net|Benoit Tellier]] 2014/02/18 21:26//