CloudInit, kesako ?

Si comme moi la montée de l’IaaS  (Infrastructure as a Service) vous fascine par le biais des différents acteurs du marché (Amazon, Azure, OpenStack, … ) et que vous vous y intéressez sans forcément être expert, cet article est donc pour vous.

Dans le monde de l’IaaS, chaque instance a ses propres spécificités techniques, par exemple : les paquets installés et les services configurés (Apache, MySQL, …). Ces instances sont à l’origine des images de VMs (AMI “Amazon Machine Images” dans le monde EC2 d’Amazon) qui ont été installées puis customisées.

Dans ce contexte, Canonical l’éditeur d’Ubuntu propose sa solution pour automatiser la customisation des instances lors de leur premier démarrage : CloudInit.

 

CloudInit en deux mots :

CloudInit est un package Ubuntu. Pour être plus précis, il s’agit d’un framework permettant d’exécuter un script fourni lors de l’instanciation de la VM.

CloudInit est écrit en Python. Le code est disponible sur un dépôt Launchpad.

La mécanique qui permet d’injecter un script à l’environnement CloudInit doit être supportée par l’API de la solution IaaS. Aujourd’hui, les APIs EC2 et OpenStack gèrent CloudInit.

Ainsi, lorsque vous lancez une VM Ubuntu sur EC2 avec la commande suivante :

ec2-run-instances --group default --key $EC2_KEYPAIR_NAME --user-data-file user-script.txt ami-MyAMI-ID

vous faites appel sans le savoir à CloudInit qui va récupérer le script user-script.txt, l’interpréter puis éventuellement le jouer.

 

CloudInit et les metadatas :

Pour aller un peu plus loin, la récupération du script passe par un service de Metadata. Dans une solution IaaS, un service de metadata permet de :

  • Collecter des paramètres fournis par un utilisateur lors du lancement d’une VM.
    Par exemple : le profil matériel (small, large, …), le groupe de sécurité ou l’image à utiliser.

  • Exposer les paramètres de lancement, ainsi que d’autres données attribuées dynamiquement : identifiant de la VM, nom d’hôte publique, …

 

Une VM peut alors appeler le service de métadata de la solution IaaS pour récupérer ces informations qui lui sont associées. Chaque VM EC2 et OpenStack accède en local au service métadata par l’ip : 169.254.169.254. Cette IP en lien avec le mécanisme APIPA (Automatic IP Private Addressing) est statique et privée (accessible depuis l’instance).

Pour en revenir à CloudInit, celui-ci utilise l’entrée “user-data” du service metadata pour retrouver d’éventuelles données sous forme d’un script.

Ainsi, notre VM EC2 lancée avec la commande :

ec2-run-instances --group default --key $EC2_KEYPAIR_NAME --user-data-file user-script.txt ami-MyAMI-ID

pourra récupérer le contenu du script “user-script.txt”, via : http://169.254.169.254/latest/user-data

 

Les possibilités de CloudInit :

Plusieurs cas d’utilisations sont possibles avec CloudInit, à commencer par l’installation/mise à jour des paquets, l’import des clés ssh, le paramétrage des variables d’environnement ou l’exécution de simples commandes.

Des exemples de script sont aussi fournis sur le site officiel de CloudInit.

 

Syntaxe et exemple :

Le contenu du champ user-data peut se décliner sous différentes syntaxes. Comme pour tout script linux, ces syntaxes sont indiquées par la première ligne du fichier. Les plus importantes sont:

 

  • #cloud-config :
  • A noter que Les syntaxes cloud-config se font en YAML. Les entrées YAML sont associées à du code python spécifique embarqué dans le paquet CloudInit.

 

  • #include :

 

  • #! :

 

Pour aller plus loin, l’exemple détaillé ci-dessous montre un script de type cloud-config pour installer chef et jouer une liste de recettes :

#cloud-config
# The default is to install from packages.
# Key from http://apt.opscode.com/packages@opscode.com.gpg.key
apt_sources:
 - source: "deb http://apt.opscode.com/ $RELEASE-0.10 main"
   key: |
     -----BEGIN PGP PUBLIC KEY BLOCK-----
     Version: GnuPG v1.4.9 (GNU/Linux)

     mQGiBEppC7QRBADfsOkZU6KZK+YmKw4wev5mjKJEkVGlus+NxW8wItX5sGa6kdUu
     3ZRAq/HMGioJEtMFrvsZjGXuzef7f0ytfR1zYeLVWnL9Bd32CueBlI7dhYwkFe+V
     Ep5jWOCj02C1wHcwt+uIRDJV6TdtbIiBYAdOMPk15+VBdweBXwMuYXr76+A7VeDL
     zIhi7tKFo6WiwjKZq0dzctsJJjtIfr4K4vbiD9Ojg1iISQQYEQIACQUCSmkLtAIb
     DAAKCRApQKupg++CauISAJ9CxYPOKhOxalBnVTLeNUkAHGg2gACeIsbobtaD4ZHG
     0GLl8EkfA8uhluM=
     -----END PGP PUBLIC KEY BLOCK-----

chef:

 # Valid values are 'gems' and 'packages' and 'omnibus'
 install_type: "packages"

 # Boolean: run 'install_type' code even if chef-client
 #          appears already installed.
 force_install: false

 # Chef settings
 server_url: "https://chef.yourorg.com:4000"

 # Node Name
 # Defaults to the instance-id if not present
 node_name: "your-node-name"

 # Environment
 # Defaults to '_default' if not present
 environment: "production"

 # Default validation name is chef-validator
 validation_name: "yourorg-validator"
 validation_key: |
     -----BEGIN RSA PRIVATE KEY-----
     YOUR-ORGS-VALIDATION-KEY-HERE
     -----END RSA PRIVATE KEY-----

 # A run list for a first boot json
 run_list:
  - "recipe[apache2]"
  - "role[db]"

 # Specify a list of initial attributes used by the cookbooks
 initial_attributes:
    apache:
      prefork:
        maxclients: 100
      keepalive: "off"

 # if install_type is 'omnibus', change the url to download
 omnibus_url: "https://www.opscode.com/chef/install.sh"

# Capture all subprocess output into a logfile
# Useful for troubleshooting cloud-init issues
output: {all: '| tee -a /var/log/cloud-init-output.log'}

 

Les limites de CloudInit :

CloudInit connaît plusieurs limites :

– La documentation : la syntaxe cloud-config parait très puissante au premier abord. Cependant, aucun détail n’est apporté sur les différents noeuds YAML possibles. La seule solution est de cloner le dépot Bazaar CloudInit pour regarder en détail les exemples, voir le code python dans certains cas.

– La transparence : les logs générés à l’issue de l’exécution du script sont peu verbeux et incomplets.

– La compatibilité :

  • Amazon EC2 et OpenStack permettent d’injecter des scripts CloudInit depuis leurs interface. Cette fonctionnalité demeure absente sur Azure par exemple. Pour palier à ce manque, l’utilisateur de CloudInit doit rajouter le script en dur dans l’image ISO du système d’exploitation.

  • Le projet est dédié à Ubuntu et a été porté en version bêta sur Debian à partir de la v8.04 et sur Fedora à partir de la version 16. En revanche CloudInit n’est pas intégré par défaut dans ces distributions (y compris Ubuntu) et donc seules des versions pré-packagés peuvent être utilisées.

  • Cette solution demeure non-standard pour les autres distributions Linux. Sans parler de Windows Server.

 

Quelle utilisation de CloudInit ?

Le périmètre d’utilisation de ce framework non standardisé est très large et rentre en partie en concurrence avec les outils plus adoptés de gestion des configurations type Puppet, Cfengine ou Chef.

L’avantage de CloudInit par apport à ces outils est le fait d’être supporté nativement par certaines versions d’Ubuntu et maniable en utilisant les APIs EC2 sans avoir à intervenir directement sur l’instance, au contraire de Chef qui nécessite une intervention sur chaque instance pour l’installer et surtout pour indiquer les recettes à jouer.

Le scénario idéal qui se dégage est l’utilisation de CloudInit lors du premier démarrage afin d’installer et de paramétrer Chef en mode client ou solo, puis de reposer sur ce dernier pour la suite de l’installation et de la configuration.