Author Archives: Fitzdsl

Faites tourner vos foreman-proxy avec passenger

J’ai récemment décidé de remplacer le démon Webrick utilisé habituellement par Foreman-Proxy
par Apache 2.4 et Passenger pour des question principalement d’industrialisation.
Comme nous allons le voir le setup est assez simple.
Je pars du principe que vous avez déjà installé apache et passenger (pour Foreman, Puppetmasterd, etc ..).

Mon installation de smart-proxy étant par Git, celui-ci est localisé dans /opt, je vous laisse adapter vos chemins !
La configuration d’apache est la suivante :

Listen 8444
<VirtualHost *:8444>
  ServerName foreman-proxy.example.com
  ServerAlias proxy1.example.com

  DocumentRoot /opt/smart-proxy/public

  RailsAutoDetect On
  PassengerTempDir /opt/smart-proxy/tmp
  AddDefaultCharset UTF-8
  HostnameLookups On

  SSLEngine on
  SSLCertificateKeyFile /var/lib/puppet/ssl/private_keys/proxy1.example.com.pem
  SSLCertificateFile /var/lib/puppet/ssl/certs/proxy1.example.com.pem
  SSLCACertificateFile /var/lib/puppet/ssl/certs/ca.pem

  <Directory /opt/smart-proxy/public>
     Require local
     Require ip 192.168.0.0/16 10.0.0.0/8
  </Directory>

  CustomLog ${APACHE_LOG_DIR}/foreman-proxy.example.com/access.log combined
  ErrorLog ${APACHE_LOG_DIR}/foreman-proxy.example.com/error.log
</VirtualHost>

J’ai choisi de ne pas faire écouter passenger sur le même port que le démon webrick, mais vous pouvez très bien utiliser le 8443.
On remarque que la configuration SSL ne se fait plus au niveau de la configuration du proxy mais directement dans apache.

Au niveau du proxy, il est important de savoir que pour le moment, la directive « :trusted_hosts » provoque une erreur 500.
Le bug à été remonté ici : http://projects.theforeman.org/issues/2259

Voila, il vous reste à arrêter votre daemon smart-proxy et relancer apache et c’est tout bon !
Attention, si vous avez changé de port d’écoute, penser à mettre à jour votre configuration au niveau de Foreman.

Share

Générer avec Puppet des certificat SSL avec des « Alternative Name »

J’avais besoins de cette fonctionnalité pour mettre en place la communication SSL entre mes deux serveurs Foreman et ses proxies.
Mon problème étant que mes serveurs Foreman sont utilisé en faillover (avec une VIP) avec un DNS généric et non pas en utilisant leur FQDN.
Ceci provoquait un problème avec le certificat puppet utilisé car l’adresse ne correspondait pas au CN exposé.
J’ai donc mis en place un certificat puppet dont le CN est le FQDN (ex:foreman1.example.com) de la machine et qui comprend en plus comme
‘Subject Alternative Name’ le nom du faillover utilisé (ex:foreman.example.com).

C’est très simple à réaliser mais l’info est pas très documentée sur le net.
Il faut commencer par révoquer et supprimer tous les certificats existants pour cette machine :
Sur le client (sur Debian) :

# rm -rf /var/lib/puppet/ssl

Sur le puppet master :

# puppet cert clean foreman1.example.com

Modifier le puppet.conf du client et lui ajouter la directive :

dns_alt_names = foreman.example.com

Puis lancer puppet sur le client pour forcer la création du nouveau certificat et envoyer la demande de signature au master :

# puppet agent -t --report --pluginsync

Sur le master vous pouvez voir une nouvelle demande de certificat et vous pouvez le signer :

# puppet cert list
  "foreman1.example.com" (SHA256) 2C:76:5B:85:67:28:1C:92:48:AA:10:22:44:C7:9B:A7:0D:9B:E2:A5:5F:10:71:87:B9:3F:46:E4:70:4B:43:6C (alt names: "DNS:foreman.example.com", "DNS:foreman1.example.com")
# puppet cert sign devshinken4.yzserv.com --allow-dns-alt-names

Vous avez donc maintenant un certificat signé par votre Puppet CA qui comprend un DNS Alt Name.

Share

Migrez vos Foreman et dormez sur vos deux oreilles.

Je viens de migrer Foreman pour mettre la version 1.1 en production (je reviendrais sur les nouvelles fonctionnalités de la version 1.1).

Un des points les plus important que je teste quand je mets Foreman à jour, c’est la non regression de l’output de l’ENC. C’est à dire, je vérifie que la nouvelle version de Foreman envoie le même YAML au Puppet Master pendant ENC lookup. Pour me faciliter la vie, j’ai écris un petit script ruby (en partant du script d’external node controler de Foreman) qui va comparer les réponses en YAML entre deux instances de Foreman (ex: une instance de production et une instance de QA).

Afin de supporter les classes paramétrées, Foreman à changé un peu la structure du YAML mais le script supporte ce changement.
Vous pouvez le retrouver sur mon Github. Vous avez juste à modifier les deux URLs de vos Foreman de Production et de DEV ainsi que vos identifiants et mot de passe.

Le script s’arrête automatiquement si il trouve une définition de node différente entre le Foreman de dev et celui de production. Cet outils me permet donc d’être plus tranquile quand je fais une mise à jour majeure de mes Foreman !

Share

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.

Share

Installation d’un conteneur LXC sur Dedibox

Je viens de migrer mon blog sur un nouveau serveur Dedibox Classic +.
Celui offrant plus de puissance que mon ancienne Kimsufi mKS 2G, j’ai décidé d’expérimenter l’utilisation de conteneur LXC pour isoler un certain nombre de services. Le choix de LXC comme méthode de virtualisation réside principalement dans une volonté d’expérimentation : j’ai en effet l’habitude de travailler avec KVM au travail.

La première chose à faire est de commander une IP de Failover chez Online. Avec mon serveur j’ai accès à 5 IP de failover soit 5 conteneurs LXC potentiels en plus de ma machine hôte.
Une fois l’IP de failover achetée et assignée à votre machine hôte, il faut aller demander la déclaration d’une nouvelle adresse MAC pour votre serveur.
Ceci est à faire dans l’onglet ‘Etat’ de la console d’administration de votre dédibox. J’ai personnellement choisi une MAC de type KVM.

ATTENTION : si vous ne déclarez pas votre adresse MAC, votre port de switch sera automatiquement coupé chez Online lors du boot de votre conteneur.

Installation de LXC

Sous Ubuntu 12.10, la mise en place d’un conteneur LXC est relativement triviale :

# apt-get install lxc bridge-utils

Configuration du bridge sur votre machine hôte

Pour configurer le bridge de votre machine hôte :

# cat /etc/network/interfaces
# The loopback network interface
auto lo
   iface lo inet loopback
# The primary network interface
auto eth0
   iface eth0 inet manual

auto br0
   iface br0 inet static
   bridge_ports eth0
   bridge_stp off
   bridge_maxwait 0
   bridge_fd 0
   address IP
   netmask 255.255.255.0
   network RESEAU
   broadcast IP_DE_BROADCAST
   gateway IP_GW

Il faut ensuite appliquer la nouvelle configuration de votre réseau :

# service networking restart

Si pour une raison ou une autre quelquechose se passe mal et vous perdez la main sur votre serveur,
vous avez toujours la possibilité d’utiliser le KVM mis à votre disposition par Online

Si tout se passe bien vous devrier avoir quelquechose comme ca :

# ifconfig 
br0   Link encap:Ethernet HWaddr bc:30:5b:cf:38:8f
      inet adr:88.190.18.38 Bcast:88.190.18.255 Masque:255.255.255.0
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
      Packets reçus:2402562 erreurs:0 :73 overruns:0 frame:0
      TX packets:720626 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 lg file transmission:0
      Octets reçus:115870995 (115.8 MB) Octets transmis:6334732297 (6.3 GB)

eth0  Link encap:Ethernet HWaddr bc:30:5b:cf:38:8f
      UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
      Packets reçus:65300606 erreurs:0 :147 overruns:0 frame:0
      TX packets:96867267 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 lg file transmission:1000
      Octets reçus:36490517096 (36.4 GB) Octets transmis:131124295065 (131.1 GB)

lo    Link encap:Boucle locale
      inet adr:127.0.0.1 Masque:255.0.0.0
      adr inet6: ::1/128 Scope:Hôte
      UP LOOPBACK RUNNING MTU:16436 Metric:1
      Packets reçus:242326 erreurs:0 :0 overruns:0 frame:0
      TX packets:242326 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 lg file transmission:0
      Octets reçus:68993249 (68.9 MB) Octets transmis:68993249 (68.9 MB)

C’est normal que votre interface eth0 n’ai pas d’IP puisque c’est votre bridge qui la possède.

Configuration de LXC

Vous devez maintenant configurer LXC au niveau réseau :

# vim /etc/lxc/lxc.conf
lxc.network.type=veth
lxc.network.link=br0
lxc.network.hwaddr=MAC_ADRESSE
lxc.network.ipv4=FAILOVER_IP/32
lxc.network.flags=up

Attention à bien utiliser l’adresse MAC que online vous à affecté et de spécifier un netmask en /32 pour votre IPv4.

Vous pouvez maintenant créer un nouveau conteneur :

# lxc-create -n conteneur_name -t ubuntu fssize=10G
# lxc-start --name conteneur_name

Cela va créer votre conteneur et le lancer. Votre terminal va afficher une console. Pour lancer votre conteneur en daemon, il faut utiliser ‘-d’, mais nous avons besoin dans un premier temps de configurer le réseau du conteneur.

Pour vous logger, il faut utiliser le user ubuntu avec le mdp ubuntu par défaut.

Configuration du réseau du conteneur

Au startup votre conteneur à bien son IP assignée par LXC mais n’a aucune route pour sortir.
Il faut donc lui en indiquer une. J’ai choisi de rester en DHCP pour son IP et de faire cette configuration :

# cat /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
	up route add 88.190.18.1/32 dev eth0
	up route add default gw 88.190.18.1

Avec 88.190.18.1 qui est la GW de ma machine hôte.

Au niveau de votre machine hôte vous devrier voir votre bridge avec une configuration comme celle-ci :

                                     
bridge name	bridge id		STP enabled	interfaces
br0		8000.bc305bcf388f	no		eth0
							vethFKSYFV

Avec cette configuration vous devriez avoir un conteneur valide qui à un accès direct à internet.

Share

Migration de rtorrent et rtgui à transmission

Je gère un serveur dédié qui partage un client torrent avec une interface web pour quelques personnes.
J’utilisais jusqu’à présent un client rtorrent avec rtgui comme frontend web. Cela remplissait globalement
les objectifs, cependant :

  • rtgui est pas très pratique à utiliser. On doit envoyer manuellement chaque torrent via l’interface Web
  • rtorrent crashait de manière aléatoire pour des raisons que je n’ai jamais réussi à vraiment identifier
  • Gérer rtorrent comme un service n’est pas forcément aisé
  • Pas de client lourd utilisable.

C’est pour ces raisons que j’ai décidé de passer à transmission en migrant ce blog de serveur.

Installation et configuration de transmission

L’installation de transmission est relativement simple :

 # apt-get install transmission-daemon

Dans les paramètres de transmission, j’ai changé quelques directives :
J’ai activé incomplete-dir pour n’avoir que les fichiers terminés dans mon répertoire final.
Je trouve ca plus pratique à utiliser comme ca.

"incomplete-dir": "/var/lib/transmission-daemon/downloads",
"incomplete-dir-enabled": true,

J’ai mis en place apache2 comme reverse-proxy. Pour cela, j’ai activé RPC, en localhost seulement, sans authentication car j’utilise l’authentication apache.

"rpc-authentication-required": false,
"rpc-bind-address": "127.0.0.1",

Attention à ne modifier le fichier de configuration de transmission-daemon seulement lorsque celui-ci est arrété, sinon il effacera votre configuration.

Pour toute autre question, la documentation se trouve içi.

Configuration Apache comme reverse proxy :

Je voulais accéder à transmission en passant seulement comme apache. J’ai donc utilisé le mod_proxy.

 # a2enmod proxy proxy_http

Dans la configuration de mon vhost :

ProxyPass /transmission http://localhost:9091/transmission
ProxyPassReverse /transmission http://localhost:9091/transmission
RewriteEngine On
RewriteRule ^/$ /transmission [R]

Pour conclure, cette nouvelle installation est nettement mieux pour moi :

  • Je peux utilise transmission-remote depuis tous mes desktops (Linux et Windows) : je gère mes torrents exactement comme si j’avais un client lourd local alors que ceux-ci sont directement téléchargés sur mon serveur.
  • Personnelement je trouve l’interface Web plus simplas à utiliser
  • Je peux manager mes torrents depuis mon téléphone android avec Transmission Remote sur le Play store

Quelques images de l’interface Web sur le site officiel de transmission :

GTK-Large Clutch-Large

Share

Déploiement automatisé et sans effort d’un webserver avec Foreman

L’objectif de ce post est de montrer le niveau d’industrialisation pour le déploiement d’application sur des machines virtuelles que nous apporte Foreman à Yakaz.

Cette vidéo montre comment très facilement nous pouvons créer une nouvelle machine virtuelle et comment puppet configure de manière automatisé le serveur pour faire tourner notre application. Nous utilisons la notion de Compute Resource qui arrive avec Foreman 1.0.

Comparés à l’ancien support de la virtualisation (les hypervisors cf précédent article), les Computes Resources permettent de :

  • Déployer des VM avec plusieurs disque et interfaces réseaux
  • Avoir une console VNC directement depuis l’interface de Foreman 
  • De contrôler qui peut utiliser quelle compute resource : ceci permet d’avoir un cluster de virtualisation pour l’environnement de dévelopement où n’importe qui peut déployer des VM et un cluster de production isolé.
  • Support de la gestion de l’alimentation de la VM directement dans Foreman 
  • Suppression de l’host dans Foreman supprime maintenant aussi la VM sur l’hyperviseur
Les computes resources supportées pour l’instant par Foreman sont : 
  • oVirt / RHEV-M
  • libvirt
  • Amazon EC2
  • support partiel de VMware
Pour rappel, lors d’un déploiement en ‘Unattended Installation’, Foreman s’occupe de :
  • Créer les enregistrements A et PTR pour le domaine
  • Créer la lease DHCP pour la machine
  • Configurer puppet pour la machine via les ENC
  • Signer le certificat client puppet de votre nouvelle VM dans la PuppetCA de votre puppetmaster
Voir ces billets part1 part2 part3 pour le déploiement de Foreman.
Une fois la VM créée et buildée puppet va configurer la machine afin qu’elle soit conforme à l’environnement d’exécution de l’application sélectioné (en l’occurence nos serveurs Web avec notre site)

Cette vidéo vous montre que notre temps humain nécessaire au déploiement d’un nouveau serveur à été drastiquement réduit en misant sur l’intégration de Foreman dans notre architecture. Cette approche nous apporte une forte fléxibilité et élasticité dans la gestion de notre production.

 

Share

Auto validation et supervision de la configuration de Nagios par lui même

Attention c’est un nom bien compliqué pour les trois lignes de bash qui vont suivre.

Ma problématique était la suivante : j’utilise Puppet et son module Naginator pour écrire l’ensemble de ma configuration Nagios. En cas de création d’un nouveau serveur avec Foreman, Puppet vient m’écrire dynamiquement la conf de Nagios avec tous les checks nécessaires en fonctions des classes puppet associées à ce serveur (supervision système, applicative, etc…). Quand puppet écris des changements dans la configuration de nagios,  il notifie automatiquement nagios du changement dans sa conf pour que celui-ci fasse un reload.

Cependant mon module nagios de Puppet n’étant pas parfait, j’arrive en cas d’erreur humaine à créer une configuration Nagios qui n’est malheureusement pas valide (un host nagios est créé et affecté dans un hostgroup qui n’existe pas). Par bonheur lorsqu’une erreur se produit,  nagios vérifie toujours la validité de la configuration avant de faire son reload. Je ne perds donc pas ma supervision mais bien que puppet continue a m’écrire les changements de conf, Nagios ne se met plus à jour.

C’est pourquoi j’ai décidé d’écrire un check de trois lignes de bash qui va vérifier que la configuration de Nagios est bien valide. J’utilise pour cela le le binaire de nagios avec l’option ‘-v’. Vous pouvez retrouver ce script sur Github.

Comme cela, je suis assuré que Nagios a toujours une configuration valide et que ma supervision évolue bien au rythme de mon SI.

J’écrirais surement bientôt un petit article pour expliquer en détail comment j’utilise Foreman / Puppet et Nagios dans mon SI.

Share

Forcez le chargement de module directement au boot du kernel

J’avais un problème avec le chargement de modules pour une carte réseau Broadcom (BMC5788 sous Fedora) .
Le kernel ne chargeait pas automatiquement les modules broadcom et tg3 afin de pouvoir utiliser la carte réseaux.
Malheureusement je me sers de cette carte pour déployer à distance en PXE des machines via Foreman. Je ne pouvais donc pas configurer directement le chargement des modules de manière standard.

Pour forcer le kernel à charger des modules directement au boot (attention ces modules doivent être présent dans l’initrd que vous envoyez en PXE !),
il vous suffit de rajouter à en options à la ligne de boot du kernel :

rd.driver.post=broadcom rd.driver.post=tg3

Au boot de la machine, la carte réseau est directement accessible !

Vous pouvez retrouver la documentation complète ici.

 

Share

Vérifiez le run de vos Puppet avec Foreman et Nagios

J’avais besoin de m’assurer de la fiabilité des runs de Puppet sur l’ensemble de ma production. Pour cela il faut m’assurer de 2 choses :

- Premièrement que puppet s’exécute correctement toute les demi-heure (j’utilise un cron et non pas le daemon puppet) . Pour cela, c’est assez simple, j’utilise un check nagios de base « check_file_age » et je vérifie l’âge du fichier « state.yaml ». Voici donc à quoi ressemble ma commande sur un serveur Debian:

/usr/lib/nagios/plugins/check_file_age -w 3780 -c 43200 -f /var/lib/puppet/state/state.yaml

- La première commande me permet de savoir que Puppet tourne bien régulièrement. Cependant je suis incapable de dire si les runs s’effectuent correctement ou non. C’est pourquoi  j’ai décidé d’utiliser la fonction de Reports de Foreman (voir ces 3 billets 1 2 3 pour l’installation de Foreman).

Vous pouvez trouver mon script içi sur Github. Pour l’utiliser sur un serveur Debian, il faut installer les dépendances (dont une qui n’est pas packagée en deb) :

# apt-get install libhttp-server-simple-perl libjson-perl
# wget http://search.cpan.org/CPAN/authors/id/M/MC/MCRAWFOR/REST-Client-243.tar.gz
# tar xvf REST-Client-243.tar.gz
# cd REST-Client-243
# make
# make install

Ensuite pour l’utiliser c’est très simple :

$ /usr/lib/nagios/plugins/check_foreman_puppet_failure.pl -H webserver.example.com -F http://foreman.example.com -w 3 -c 5 -u username -p password

Cette commande va vérifier les derniers rapports d’exécution de Puppet. Si le nombre de run en erreur est supérieur à warning ou critical alors le check retournera une erreur.

Voila, vous pouvez superviser correctement vos runs de Puppet grâce à Foreman et Nagios

Share