Il existe de nombreuses façons d'automatiser le processus d'installation et de configuration d'une boîte. Pour quelque raison que ce soit, si l'ensemble de notre système à ce stade ne comprend qu'un seul boîtier, la mise en place d'une infrastructure SCM (Software Configuration Management) complète est exagérée. Les scripts shell sont une option, mais nous pourrions également utiliser une version allégée de SCM qui est disponible dans quelques-uns des outils disponibles. Chef est l'une des options les plus populaires et "chef-solo" est le mode de configuration autonome de Chef où nous n'avons pas besoin d'un nœud supplémentaire pour agir en tant que "chef-serveur". Tout ce dont il a besoin est une URL ou un chemin vers un package tarball qui contient des livres de cuisine de chef. Comparé aux scripts shell, ce type d'approche est plus déclaratif et plus efficace et est également une bonne introduction pour commencer avec les processus SCM ou IaC (Infrastructure as Code).
Quelques autres avantages à utiliser chef-solo:
- Composabilité: Utilisez les livres de cuisine communautaires du supermarché du chef ou d'autres endroits.
- Libre et open source; sous licence permissive Apache 2.0 License.
- Accès au reste de l'écosystème du chef (InSpec, ChefSpec, Cookstyle, Foodcritic, chef-shell, etc.)
- Les livres de recettes et les recettes peuvent ensuite être adaptés à un mode client / serveur.
Et quelques inconvénients:
- Certains livres de cuisine communautaires du supermarché Chef sont obsolètes, cassés et non entretenus.
- chef-solo ne peut pas résoudre seul les dépendances.
Les «recettes» à l'intérieur d'un «livre de cuisine» de chef ont une DSL à base de rubis qui décrit les «ressources» pour être dans un état particulier sur un nœud. Commençons par une procédure pas à pas pour se familiariser avec quelques concepts de chef qui sont également applicables au chef solo. Notre objectif est de mettre en place un nœud Ubuntu exécutant une application web Python / Django en utilisant Gunicorn et NGINX.
Remarque: Nous n'exigeons pas nécessairement que ChefDK soit installé sur notre "poste de travail Chef" (notre machine), bien qu'avec cela, nous pouvons utiliser les commandes "chef générer" pour démarrer avec une structure de répertoire pour créer des livres de cuisine, des recettes et plus encore. Dans cet article, nous supposerons que ChefDK est installé sur notre poste de travail. Les commandes ont été exécutées à l'aide de la version 4.7.26-1 de ChefDK.
(À partir de ce moment, tout, sauf indication contraire, doit être exécuté sur notre machine, également appelée «poste de travail du chef»)
Création du livre de cuisine
Les livres de cuisine dans le chef sont des unités réutilisables qui contiennent tout le nécessaire pour prendre en charge un scénario de configuration. Les livres de cuisine peuvent contenir plusieurs «recettes» et «recettes» se composent principalement de modèles de ressources. default.rb
est la recette par défaut qui sera exécutée lorsque le livre de recettes sera référencé dans une liste d'exécution . Différentes recettes permettent de séparer les préoccupations. Pour ce didacticiel, cependant, nous allons ajouter toutes les déclarations de ressources dans un fichier de recette principal, qui est le default.rb
.
Créez un dossier nommé "my-chef-project" et créez à l'intérieur un dossier appelé "cookbooks". De ./my-chef-project/cookbooks/
, exécutez:
$ chef generate cookbook my-cookbook
Notre structure de répertoires ressemblera maintenant à ceci:
.
└── my-chef-project
└── cookbooks
└── my-cookbook
├── CHANGELOG.md
├── LICENSE
├── Policyfile.rb
├── README.md
├── chefignore
├── kitchen.yml
├── metadata.rb
├── recipes
│ └── default.rb
├── spec
│ ├── spec_helper.rb
│ └── unit
│ └── recipes
│ └── default_spec.rb
└── test
└── integration
└── default
└── default_test.rb
Ajout de packages
La première étape de la configuration de notre nœud consiste à identifier les packages requis par notre application. Notre nœud est sélectionné pour être Ubuntu, nous pouvons donc compter sur le gestionnaire de packages APT pour rassembler les dépendances. Installer les packages fournis par la distribution OS est alors un jeu d'enfant:
apt_update
package 'python3'
package 'python3-pip'
package 'nginx'
package 'pkg-config'
package 'libcairo2-dev'
package 'libjpeg-dev'
package 'libgif-dev'
package 'libgirepository1.0-dev'
Ce sont assez explicites. La première ligne mettra à jour le référentiel apt et les lignes suivantes installeront ces packages.
Remarque: Les packages suivant 'nginx' sont nécessaires pour compiler certaines des dépendances python via pip. Ceux-ci peuvent différer en fonction de vos dépendances de projet python / django spécifiées dans requirements.txt
. Vous pouvez utiliser une méthode d'essai et d'erreur pour déterminer ces packages que vous devez inclure dans votre livre de recettes. Pour ce faire, effectuez un manuel sudo pip install -r requirements.txt
(Remarque: cela installe les packages à l'échelle du système!) Sur une machine Ubuntu fraîchement instanciée pour voir si elle fonctionne correctement. Sinon, le stderr devrait vous donner des conseils sur les paquets manquants.
Création d'utilisateurs Linux
Une fois que nous avons terminé d'ajouter les packages requis, nous devons créer un utilisateur Linux non privilégié qui sera propriétaire du code source de l'application.
user 'bob' do
uid 1212
gid 'users'
home '/home/bob'
shell '/bin/bash'
password '$1$alilbito$C83FsODuq0A1pUMeFPeR10'
end
Notez que le mot de passe est un format de hachage fantôme utilisé sous Linux. Il peut être dérivé à l'aide d'OpenSSL:
$ openssl passwd -1 -salt alilbitof mypassword
Y compris la source de l'application
Maintenant, incluons le code source de l'application Django dans notre livre de recettes. Placez le code source dans ./my-chef-project/cookbooks/my-cookbook/files/default/myapp/
Créer le ./my-chef-project/cookbooks/my-cookbook/files/default
répertoire s'il n'existe pas.
Les instructions pour copier ces fichiers vers un emplacement distant sur notre nœud sont décrites à l'aide de la ressource remote_directory :
remote_directory '/home/bob/myapp' do
source 'myapp' # This is the name of the folder containing our source code that we kept in ./my-cookbook/files/default/
owner 'bob'
group 'users'
mode '0755'
action :create
end
Extraire les dépendances python
Pour installer les paquets de python dans requirements.txt
, nous pouvons utiliser l' exécuter ressources pour exécuter une commande arbitraire. Dans ce cas, nous devons exécuter la commande pip install dessus:
execute 'install python dependencies' do
command 'pip3 install -r requirements.txt'
cwd '/home/bob/myapp'
end
Remarque: Gardez à l'esprit que cela va s'exécuter en tant qu'utilisateur root et que les bibliothèques python seront installées à l'échelle du système. Si notre nœud est conçu pour exécuter exclusivement cette seule application python, ce n'est pas vraiment un problème. Malgré cela, une meilleure option pour garder les choses propres et saines est de trouver et d'utiliser un livre de cuisine communautaire qui gère les installations python ou «virtualenvs». (ou à tout le moins, écrivez une série de blocs d' exécution pour répliquer cela). L'utilisation de virtualenvs dans python garantit qu'aucun outil système basé sur python ou autre projet python ne sera affecté.
Configuration de Gunicorn et NGINX
Il est maintenant temps de préparer le serveur HTTP Gunicorn WSGI avec NGINX comme proxy inverse. Nginx est également utilisé pour gérer tous les actifs statiques de Django.
Pour attacher Gunicorn en tant que service sur Ubuntu, Systemd peut être utilisé. La ressource systemd_unit est incluse dans Chef depuis la version 12.11.
systemd_unit 'gunicorn.service' do
content({
Unit: {
Description: 'Django on Gunicorn',
After: 'network.target',
},
Service: {
ExecStart: '/usr/local/bin/gunicorn --workers 3 --bind localhost:8080 myapp.wsgi:application',
User: 'bob',
Group: 'www-data',
WorkingDirectory: '/home/bob/myapp'
Restart: 'always',
},
Install: {
WantedBy: 'multi-user.target',
}
})
action [:create, :enable, :start]
end
Nous devons maintenant inclure une configuration de proxy NGINX standard sur ce serveur Gunicorn, comme indiqué ci-dessous. Cet extrait peut entrer ./my-cookbook/templates/nginx.conf.erb
. Créez le répertoire des modèles s'il n'existe pas.
Remarque: les modèles de Chef prennent en charge les fichiers Ruby intégrés qui peuvent contenir des variables, des expressions Ruby et des instructions. Bien que ce fichier ait l'extension «erb», nous n'avons utilisé aucune des instructions ou expressions ruby. Aussi, pour des raisons de simplicité, nous n'avons ici qu'une configuration nginx non HTTPS (rappel doux; veuillez ne pas le faire en production!)
server {
listen 80;
server_name http://example.com/;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/bob/myapp/myapp/static;
}
location / {
include proxy_params;
proxy_pass http://localhost:8080/;
}
}
Remarque: Il existe également une alternative et une meilleure configuration, où, par exemple, le serveur Gunicorn est lié à un socket de domaine Unix au lieu d'une connexion de bouclage TCP. Cela vaut la peine d'explorer cela pour des raisons de performances.
Pour copier cette configuration dans un dossier compatible avec les sites sur le nœud, utilisez la ressource de modèle de Chef.
template '/etc/nginx/sites-available/example.com.conf' do
source 'nginx.conf.erb'
owner 'root'
group 'root'
mode '0744'
end
L'activation des configurations sur nginx se fait normalement en créant un lien symbolique pointant vers la configuration sites-available
dans le sites-enabled
dossier de nginx . Les liens symboliques peuvent être déclarés dans les livres de cuisine du chef avec la ressource de lien comme indiqué ci-dessous:
link '/etc/nginx/sites-enabled/example.com.conf' do
to '/etc/nginx/sites-available/example.com.conf'
end
et pour supprimer le lien symbolique de configuration par défaut:
link '/etc/nginx/sites-enabled/default' do
action :delete
end
Démarrage de NGINX
Et enfin, pour lancer le service nginx:
service 'nginx' do
action :enable
action :start
end
Listes d'exécution
Les listes d'exécution dans chef sont une liste ordonnée de rôles ou de recettes dans un livre de recettes qui seront exécutées en séquence sur le nœud. Nous avons un livre de recettes "mon-livre de recettes" et la recette "par défaut" que nous devons exécuter sur la boîte Ubuntu, donc le runlist.json dans notre répertoire de projet ( ./my-chef-project/runlist.json
) devrait ressembler à ceci:
{
"run_list": [
"recipe[my-cookbook::default]"
]
}
Étapes finales
Notre livre de cuisine pour Chef solo est prêt à être servi. Il est temps de provisionner une machine Ubuntu 18.04 et d'installer ChefDK dessus:
$ ssh [email protected] 'apt-get update && yes | apt-get install curl && curl https://packages.chef.io/files/current/chefdk/4.7.45/ubuntu/18.04/chefdk_4.7.45-1_amd64.deb -o chefdk.deb && yes | dpkg -i chefdk.deb && rm chefdk.deb'
Pour revenir à notre poste de travail Chef , tout ce que nous devons faire est de placer le dossier des livres de recettes dans une archive tar, de transférer cette archive avec le runlist.json
nœud distant que nous avons fourni ci-dessus et d'exécuter la commande chef-solo:
(La commande ci-dessous doit être exécutée à l'intérieur du nœud ou du «client chef» et non du poste de travail Chef)
$ chef-solo --recipe-url $(pwd)/chef-solo.tar.gz -j $(pwd)/runlist.json --chef-license=accept
Ou voici un one-liner (à exécuter à partir de ./my-chef-project/
CWD sur Chef Workstation):
tar zvcf chef-solo.tar.gz ./cookbooks &&\
scp chef-solo.tar.gz runlist.json [email protected]:~/ &&\
ssh [email protected] 'chef-solo --recipe-url $(pwd)/chef-solo.tar.gz -j $(pwd)/runlist.json --chef-license=accept'
C'est tout! Regardez la sortie standard se remplir d'activité de Chef essayant de faire converger votre nœud vers ce que vous avez spécifié dans les livres de recettes. Chef-solo installera toutes les gemmes requises pour tous les livres de cuisine. Si la commande chef-solo réussit, nous aurons une application Django fonctionnelle fonctionnant derrière nginx sur la boîte Ubuntu. Accédez au domaine / IP pour le tester.
Remarque: N'oubliez pas que dans django, vous devrez peut-être définir ce domaine / ip dans la ALLOWED_HOSTS
liste settings.py
.
Répondre aux changements
Chaque fois que nous modifions le contenu de notre répertoire de projet (recettes, modèles ou le code source de l'application, etc.), exécutez simplement le one-liner ci-dessus à partir du répertoire de projet.
Astuce: Si le livre de cuisine est contrôlé par la version avec git (comme il se doit), une bonne recommandation est de définir des crochets git pour exécuter ce one-liner.
Hébergement de l'archive tar (facultatif)
Si vous regardez attentivement la dernière commande chef-solo, notez que le --recipe-url
est destiné à prendre une URL. Cela signifie que vous pouvez avoir un flux de travail où un CI va construire votre tarball chef-solo, le télécharger quelque part et configurer votre nœud pour en tirer périodiquement.
Astuce: utilisez curl pour tirer périodiquement le tarball modifié comme cronjob. curl -z $file
honorera les en- If-Modified-Since
têtes et ne téléchargera la balle tar que si le fichier distant a été modifié depuis l'horodatage sur le local existant $file
.