JDB - Migration hébergement 2021 : Différence entre versions
(→Etapes de migration pour la prod) |
(→Code Ansible) |
||
Ligne 349 : | Ligne 349 : | ||
'''NB:''' ceci évite d'avoir à passer des commandes en local sur le serveur distant. | '''NB:''' ceci évite d'avoir à passer des commandes en local sur le serveur distant. | ||
+ | |||
+ | === Debug des problèmes liés à la mise à jour du cache Aptitude === | ||
+ | |||
+ | Lors des installations de packages, on peut demander à Ansible de mettre à jour le cache Aptitude avant d'installer (update_cache): | ||
+ | |||
+ | <u>Exemple de task:</u> | ||
+ | |||
+ | <pre> | ||
+ | - name: Install Lets Encrypt | ||
+ | apt: | ||
+ | name: letsencrypt | ||
+ | update_cache: yes | ||
+ | state: latest | ||
+ | </pre> | ||
+ | |||
+ | Lors des premiers runs de playbook sur le serveur de tests, on tombe sur des erreurs indiquant un besoin de validation de modification de configuration de repository pour Aptitude sur le remote node. Ce message correspond aux erreurs suivantes lorsqu'on lance une mise à jour manuelle du cache sur le remote node: | ||
+ | |||
+ | <pre> | ||
+ | root@tf-test-srv:~# apt-get update | ||
+ | Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB] | ||
+ | Get:2 http://deb.debian.org/debian buster InRelease [122 kB] | ||
+ | Get:3 http://deb.debian.org/debian buster-updates InRelease [51.9 kB] | ||
+ | Get:4 http://deb.debian.org/debian buster-backports InRelease [46.7 kB] | ||
+ | Hit:5 http://ppa.launchpad.net/scaleway/stable/ubuntu focal InRelease | ||
+ | Reading package lists... Done | ||
+ | E: Repository 'http://security.debian.org/debian-security buster/updates InRelease' changed its 'Suite' value from 'stable' to 'oldstable' | ||
+ | N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details. | ||
+ | N: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Version' value from '10.9' to '10.10' | ||
+ | E: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Suite' value from 'stable' to 'oldstable' | ||
+ | N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details. | ||
+ | E: Repository 'http://deb.debian.org/debian buster-updates InRelease' changed its 'Suite' value from 'stable-updates' to 'oldstable-updates' | ||
+ | N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details. | ||
+ | </pre> | ||
+ | |||
+ | ==== Solution "sale" ==== | ||
+ | |||
+ | Après quelques recherches Google, on identifie [https://superuser.com/questions/1456989/how-to-configure-apt-in-debian-buster-after-release une méthode] permettant de supprimer ces erreurs (méthode confirmée sur d'autres sources, à éclairer par lecture du man apt-get). | ||
+ | |||
+ | <pre> | ||
+ | root@tf-test-srv:~# apt-get update --allow-releaseinfo-change | ||
+ | Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB] | ||
+ | Get:2 http://deb.debian.org/debian buster InRelease [122 kB] | ||
+ | Get:3 http://deb.debian.org/debian buster-updates InRelease [51.9 kB] | ||
+ | Hit:4 http://deb.debian.org/debian buster-backports InRelease | ||
+ | Hit:5 http://ppa.launchpad.net/scaleway/stable/ubuntu focal InRelease | ||
+ | Get:6 http://security.debian.org/debian-security buster/updates/main Sources [199 kB] | ||
+ | Get:7 http://security.debian.org/debian-security buster/updates/main amd64 Packages [302 kB] | ||
+ | Get:8 http://security.debian.org/debian-security buster/updates/main Translation-en [158 kB] | ||
+ | Get:9 http://deb.debian.org/debian buster/main Sources [7836 kB] | ||
+ | Get:10 http://deb.debian.org/debian buster/main amd64 Packages [7907 kB] | ||
+ | Get:11 http://deb.debian.org/debian buster/main Translation-en [5968 kB] | ||
+ | Get:12 http://deb.debian.org/debian buster-updates/main Sources.diff/Index [7624 B] | ||
+ | Get:13 http://deb.debian.org/debian buster-updates/main amd64 Packages.diff/Index [7624 B] | ||
+ | Get:14 http://deb.debian.org/debian buster-updates/main Translation-en.diff/Index [5164 B] | ||
+ | Get:15 http://deb.debian.org/debian buster-updates/main Sources 2021-06-21-1401.46.pdiff [923 B] | ||
+ | Get:16 http://deb.debian.org/debian buster-updates/main Sources 2021-06-23-1401.37.pdiff [15.6 kB] | ||
+ | Get:17 http://deb.debian.org/debian buster-updates/main amd64 Packages 2021-06-21-1401.46.pdiff [656 B] | ||
+ | Get:18 http://deb.debian.org/debian buster-updates/main amd64 Packages 2021-06-23-1401.37.pdiff [4999 B] | ||
+ | Get:16 http://deb.debian.org/debian buster-updates/main Sources 2021-06-23-1401.37.pdiff [15.6 kB] | ||
+ | Get:19 http://deb.debian.org/debian buster-updates/main Translation-en 2021-06-21-1401.46.pdiff [719 B] | ||
+ | Get:18 http://deb.debian.org/debian buster-updates/main amd64 Packages 2021-06-23-1401.37.pdiff [4999 B] | ||
+ | Get:20 http://deb.debian.org/debian buster-updates/main Translation-en 2021-06-23-1401.37.pdiff [6585 B] | ||
+ | Get:20 http://deb.debian.org/debian buster-updates/main Translation-en 2021-06-23-1401.37.pdiff [6585 B] | ||
+ | Fetched 22.4 MB in 7s (3169 kB/s) | ||
+ | Reading package lists... Done | ||
+ | N: Repository 'http://security.debian.org/debian-security buster/updates InRelease' changed its 'Suite' value from 'stable' to 'oldstable' | ||
+ | N: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Version' value from '10.9' to '10.10' | ||
+ | N: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Suite' value from 'stable' to 'oldstable' | ||
+ | N: Repository 'http://deb.debian.org/debian buster-updates InRelease' changed its 'Suite' value from 'stable-updates' to 'oldstable-updates' | ||
+ | </pre> | ||
+ | |||
+ | '''=> les erreurs lors de l'update manuel disparaissent.''' | ||
+ | '''=> à partir de là, les erreurs lors d'une tâche d'installation de package avec mise à jour préalable du cache aptitude disparaissent également.''' | ||
+ | |||
+ | ==== Solution "propre" ==== | ||
+ | |||
+ | Toujours dans l'idée d'éviter de se connecter au serveur distant pour y passer des commandes en local, on peut (comme précisé sur [https://askcodez.com/ansible-playbook-pour-executer-les-commandes-shell.html ce forum]) passer la commande à distance: | ||
+ | |||
+ | <pre> | ||
+ | ansible <alias> -m command -a '<commande shell>' | ||
+ | </pre> | ||
+ | |||
+ | <u>Ex:</u> | ||
+ | |||
+ | <pre> | ||
+ | ansible jules -m command -a 'sudo apt-get update --allow-releaseinfo-change' | ||
+ | </pre> | ||
+ | |||
+ | '''NB:''' le passage de cette commande ansible produit des warning sur l'utilisation de sudo au lieu de become, on les laisse de côté étant donné qu'on est sur de la commande one shot. | ||
+ | |||
=== Control node à proximité du remote node === | === Control node à proximité du remote node === | ||
Ligne 529 : | Ligne 619 : | ||
</pre> | </pre> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Application des configurations Terraform == | == Application des configurations Terraform == |
Version du 1 septembre 2021 à 12:09
Sommaire
- 1 Introduction
- 2 Versions
- 3 Liens utiles
- 4 Journal de bord de la migration
- 4.1 Préparation du poste
- 4.2 Configuration Scaleway
- 4.3 Code Terraform
- 4.4 Code Ansible
- 4.5 Application des configurations Terraform
- 4.6 Application des configurations Ansible
- 5 Etapes de migration pour la prod
- 6 Reste à faire
Introduction
Objectif de la migration:
- on reste sur le même provider Cloud.
- on monte 2 nouveaux serveurs en Debian 10.
- on contrôle les déploiements par Terraform.
- on contrôle la gestion fine des serveurs par Ansible.
Ce wiki décrit les installations et configurations faites sur une instance de test (jetable), permettant de valider aussi bien le code Terraform que le code Ansible.
NB: cette migration a été faite depuis un poste Windows, mais toutes les commandes dans WSL (git, terraform, ansible) sont également valables si on travaille depuis un poste ou un serveur Linux.
Versions
- OS: Debian 10.9
- Git: 2.20.1
- Terraform: v1.0.5
- Ansible: 2.7.7
- Python (poste de contrôle): 3.7.3
- Python (node distant): 3.7.3
Liens utiles
- Description des objets Scaleway.
- Pricing des objets Scaleway.
- Les versions de PHP par version d'OS Debian.
- Configuration Ansible.
- Best practices Terraform:
- Best practices Ansible:
Journal de bord de la migration
Préparation du poste
Installation WSL
La migration s'opère depuis un poste Windows 10.
On maximise l'utilisation de WSL pour plus de confort.
Cf la documentation officielle de Microsoft.
Les packages ou applications à installer:
- Windows Terminal.
- WSL Debian.
En complément, mais non essentiel pour le projet, activation de WSL2.
Installation VSCode
Pour plus de confort, on installe et on utilisera Visual Studio Code.
Installation Git
Installation
Dans la distribution WSL Debian:
sudo apt-get install git
Configuration
Initialisation de Git en suivant ce super tuto Renater:
cd /mnt/d/Jules/Tech/Git/ git config --global color.diff auto git config --global color.status auto git config --global color.branch auto git config --global user.email "jules@pedrono.fr" git config --global user.name "jules" cd scaleway git init
NB: je n'utilise pour l'instant que le repository local, on ne push pas vers un serveur Gitlab distant ou sur Github.
Exclusions de fichier par gitignore:
git config --global core.excludesfile ./.gitignore
=> à priori sans effet car valeur par défaut contrairement au wiki ci dessus.
vi .gitignore (ignorer /tmp) git status
Contenu du gitignore (.git/info/exclude):
# git ls-files --others --exclude-from=.git/info/exclude # Lines that start with '#' are comments. # For a project mostly in C, the following would be a good set of # exclude patterns (uncomment them if you want to use them): # *.[oa] # *~ /tmp /old
vi .git/info/exclude rm .gitignore git status
Fichiers ignorés
- /tmp: des fichiers temporaires.
- /old: des vieux exemples de code, utiles pour ce projet.
- *.retry: fichiers Ansible de retry limité en cas d'échec précédent.
- *.plan: les fichiers de planification Terraform
- scwcreds.sh: script de stockage des creds Scaleway.
NB: certains articles indique qu'il est bon de stocker sous git son fichier d'état Terraform (tfstate), d'autres indiquent que non... En fait tout dépend vers où on commit (son propre poste, ou un repo distant sur internet, éventuellement public comme Github), et du risque potentiel d'exposer des données critiques (creds, chaîne d'accès à une base de donnée, etc...).
Installation Terraform
Installation
Dans la distribution WSL Debian:
sudo apt-get update sudo apt-get install curl sudo apt-get install gnupg1 curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add - sudo apt-get install lsb-release
Cf cette doc pour le troubleshooting lors de l'ajout du repository.
sudo apt-get install software-properties-common sudo apt-add-repository "deb [arch=$(dpkg --print-architecture)] https://apt.releases.hashicorp.com $(lsb_release -cs) main" sudo apt install terraform
Cf ce tuto pour l'ajout du provider Scaleway.
Bloc à placer avant la déclaration du provider:
terraform { required_providers { scaleway = { source = "scaleway/scaleway" } } required_version = ">= 0.13" }
Configuration
jules@DESKTOP-QQG9015:/mnt/d/Jules/Tech/Git/scaleway/terraform$ terraform init Initializing the backend... Initializing provider plugins... - Finding latest version of scaleway/scaleway... - Installing scaleway/scaleway v2.1.0... - Installed scaleway/scaleway v2.1.0 (signed by a HashiCorp partner, key ID F5BF26CADF6F9614) Partner and community providers are signed by their developers. If you'd like to know more about provider signing, you can read about it here: https://www.terraform.io/docs/cli/plugins/signing.html Terraform has created a lock file .terraform.lock.hcl to record the provider selections it made above. Include this file in your version control repository so that Terraform can guarantee to make the same selections by default when you run "terraform init" in the future. Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.
Installation Ansible
Cf la documentation officielle Ansible.
sudo apt-get update sudo apt-cache search ansible sudo apt-get install ansible
Configuration Scaleway
- Suppression des clés RSA dans les "Identifiants" du compte Scaleway, et re création avec le contenu de ma clé publique utilisée par défaut.
NB: cette clé sera automatiquement placée par Scaleway dans le authorized_keys du user root au moment du déploiement de l'instance.
Vérification de la fingerprint de ma clé publique:
jules@DESKTOP-QQG9015:~$ ssh-keygen -l -E md5 -f ./id_rsa_jules.pub 2048 MD5:bc:c2:f5:6f:a9:03:97:fb:fc:65:3f:f0:de:d1:31:24 jules@DESKTOP-QQG9015 (RSA)
- Suppression des anciennes clés d'API et re création d'une paire clé/clé secrète.
Code Terraform
Documentations utiles
Choix de départ: on colle tout le code Terraform dans un seul main.tf.
- Cf cette documentation officielle Scaleway.
- Cf cette documentation officielle Terraform pour la création d'instances Server.
- Cf cette documentation officielle Terraform pour la création d'instances IP Publique.
- Cf cette documentation officielle Terraform pour la création d'instances Volume.
- Cf cette documentation officielle Terraform pour la création d'instances Security Group.
- Cf cette documentation officielle Terraform pour la migration de version du provider Scaleway.
- Cette documentation ne nous concerne pas vraiment puisque les serveurs concernés n'étaient pas gérés par terraform auparavant.
- En revanche elle donne quelques informations utiles, notamment pour permettre de corriger des références de la documentation Scaleway (1er lien ci-dessus).
Code du projet
Etapes:
- Câblage du provider Scaleway:
terraform { required_providers { scaleway = { source = "scaleway/scaleway" } } required_version = ">= 0.13" }
- Déclaration du provider:
provider "scaleway" { access_key = "<clé API Scaleway>" secret_key = "<clé secrète de la clé d'API>" project_id = "<utiliser l'ID de l'organisation Scaleway>" zone = "fr-par-1" region = "fr-par" }
- Réservation d'une IP publique:
resource "scaleway_instance_ip" "public_ip" {}
- Configuration du Security Group:
resource "scaleway_instance_security_group" "test-sg" { inbound_default_policy = "drop" outbound_default_policy = "accept" name = "tf-test-sg" inbound_rule { action = "accept" port = "22" ip = "<IP publique du poste ou serveur d'administration>" } inbound_rule { action = "accept" port = "80" } inbound_rule { action = "accept" port = "443" } }
- Déclaration de l'instance serveur:
resource "scaleway_instance_server" "test-srv" { type = "DEV1-S" image = "debian_buster" name = "tf-test-srv" state = "started" tags = [ "test", "web" ] ip_id = scaleway_instance_ip.public_ip.id security_group_id = scaleway_instance_security_group.test-sg.id }
NB:
- A confirmer, mais les types d'instance DEV n'ont pas l'air de supporter un disque additionnel, donc on retire ce bout de code de l'exemple fourni par Scaleway et on se contente du disque local de base (20Go pour DEV1-S).
- la proposition de la doc Scaleway d'utiliser une clé organization_id n'est plus valable dans cette version de Terraform, cf ce tuto Terraform. A partir de là, on remplace organization_id par project_id, et on fixe par défaut la valeur à l'ID de notre organisation Scaleway.
Code Ansible
Documentations utiles
Premiers pas:
Debug des appels distants à Python
Solution "sale"
NB: Dans notre cas, les appels ansible échouaient avec une erreur du type:
"/bin/sh: 1: /usr/bin/python: not found\r\n",
Sur le node contrôlé par Ansible, on constate en effet que ce fichier n'existe pas, on contourne brutalement la situation via la commande suivante:
ln -s /usr/bin/python3.7 /usr/bin/python
Solution "propre"
La documentation Ansible sur la gestion de l'inventaire précise que via l'inventaire, on peut préciser explicitement le binaire python à utiliser:
<alias> ansible_host=<ip_serveur> ansible_python_interpreter=/usr/bin/python3.7
NB: ceci évite d'avoir à passer des commandes en local sur le serveur distant.
Debug des problèmes liés à la mise à jour du cache Aptitude
Lors des installations de packages, on peut demander à Ansible de mettre à jour le cache Aptitude avant d'installer (update_cache):
Exemple de task:
- name: Install Lets Encrypt apt: name: letsencrypt update_cache: yes state: latest
Lors des premiers runs de playbook sur le serveur de tests, on tombe sur des erreurs indiquant un besoin de validation de modification de configuration de repository pour Aptitude sur le remote node. Ce message correspond aux erreurs suivantes lorsqu'on lance une mise à jour manuelle du cache sur le remote node:
root@tf-test-srv:~# apt-get update Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB] Get:2 http://deb.debian.org/debian buster InRelease [122 kB] Get:3 http://deb.debian.org/debian buster-updates InRelease [51.9 kB] Get:4 http://deb.debian.org/debian buster-backports InRelease [46.7 kB] Hit:5 http://ppa.launchpad.net/scaleway/stable/ubuntu focal InRelease Reading package lists... Done E: Repository 'http://security.debian.org/debian-security buster/updates InRelease' changed its 'Suite' value from 'stable' to 'oldstable' N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details. N: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Version' value from '10.9' to '10.10' E: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Suite' value from 'stable' to 'oldstable' N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details. E: Repository 'http://deb.debian.org/debian buster-updates InRelease' changed its 'Suite' value from 'stable-updates' to 'oldstable-updates' N: This must be accepted explicitly before updates for this repository can be applied. See apt-secure(8) manpage for details.
Solution "sale"
Après quelques recherches Google, on identifie une méthode permettant de supprimer ces erreurs (méthode confirmée sur d'autres sources, à éclairer par lecture du man apt-get).
root@tf-test-srv:~# apt-get update --allow-releaseinfo-change Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB] Get:2 http://deb.debian.org/debian buster InRelease [122 kB] Get:3 http://deb.debian.org/debian buster-updates InRelease [51.9 kB] Hit:4 http://deb.debian.org/debian buster-backports InRelease Hit:5 http://ppa.launchpad.net/scaleway/stable/ubuntu focal InRelease Get:6 http://security.debian.org/debian-security buster/updates/main Sources [199 kB] Get:7 http://security.debian.org/debian-security buster/updates/main amd64 Packages [302 kB] Get:8 http://security.debian.org/debian-security buster/updates/main Translation-en [158 kB] Get:9 http://deb.debian.org/debian buster/main Sources [7836 kB] Get:10 http://deb.debian.org/debian buster/main amd64 Packages [7907 kB] Get:11 http://deb.debian.org/debian buster/main Translation-en [5968 kB] Get:12 http://deb.debian.org/debian buster-updates/main Sources.diff/Index [7624 B] Get:13 http://deb.debian.org/debian buster-updates/main amd64 Packages.diff/Index [7624 B] Get:14 http://deb.debian.org/debian buster-updates/main Translation-en.diff/Index [5164 B] Get:15 http://deb.debian.org/debian buster-updates/main Sources 2021-06-21-1401.46.pdiff [923 B] Get:16 http://deb.debian.org/debian buster-updates/main Sources 2021-06-23-1401.37.pdiff [15.6 kB] Get:17 http://deb.debian.org/debian buster-updates/main amd64 Packages 2021-06-21-1401.46.pdiff [656 B] Get:18 http://deb.debian.org/debian buster-updates/main amd64 Packages 2021-06-23-1401.37.pdiff [4999 B] Get:16 http://deb.debian.org/debian buster-updates/main Sources 2021-06-23-1401.37.pdiff [15.6 kB] Get:19 http://deb.debian.org/debian buster-updates/main Translation-en 2021-06-21-1401.46.pdiff [719 B] Get:18 http://deb.debian.org/debian buster-updates/main amd64 Packages 2021-06-23-1401.37.pdiff [4999 B] Get:20 http://deb.debian.org/debian buster-updates/main Translation-en 2021-06-23-1401.37.pdiff [6585 B] Get:20 http://deb.debian.org/debian buster-updates/main Translation-en 2021-06-23-1401.37.pdiff [6585 B] Fetched 22.4 MB in 7s (3169 kB/s) Reading package lists... Done N: Repository 'http://security.debian.org/debian-security buster/updates InRelease' changed its 'Suite' value from 'stable' to 'oldstable' N: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Version' value from '10.9' to '10.10' N: Repository 'http://deb.debian.org/debian buster InRelease' changed its 'Suite' value from 'stable' to 'oldstable' N: Repository 'http://deb.debian.org/debian buster-updates InRelease' changed its 'Suite' value from 'stable-updates' to 'oldstable-updates'
=> les erreurs lors de l'update manuel disparaissent. => à partir de là, les erreurs lors d'une tâche d'installation de package avec mise à jour préalable du cache aptitude disparaissent également.
Solution "propre"
Toujours dans l'idée d'éviter de se connecter au serveur distant pour y passer des commandes en local, on peut (comme précisé sur ce forum) passer la commande à distance:
ansible <alias> -m command -a '<commande shell>'
Ex:
ansible jules -m command -a 'sudo apt-get update --allow-releaseinfo-change'
NB: le passage de cette commande ansible produit des warning sur l'utilisation de sudo au lieu de become, on les laisse de côté étant donné qu'on est sur de la commande one shot.
Control node à proximité du remote node
Cette bonne pratique Ansible n'est pas respectée dans le cadre du projet dans un premier temps.
Pour la mettre en oeuvre il faudrait:
- envisager l'utilisation d'une instance bastion (à accès très limités) chez Scaleway, cette instance porterait l'application Ansible et les playbooks.
- envisager de pousser les playbooks sur un repository type Gitlab ou Github afin de pouvoir cloner les projets une fois les modifications poussées sur le repository.
Constitution de la liste d'hôtes / l'inventaire
Cf la documentation officielle Ansible sur la gestion de l'inventaire de parc.
Il y a de nombreuses façons de désigner les machines de l'inventaire:
- via une option de la ligne de commande ansible-playbook.
- via un fichier d'inventaire local au projet.
- via un fichier d'inventaire global dans /etc/ansible/hosts.
Dans un premier temps on applique une configuration simpliste dans le fichier global, on fera mieux ensuite:
sudo vi /etc/ansible/hosts ... [testservers] <ip_publique_serveur>
Gestion des utilisateurs
Cf La documentation Ansible du module User ainsi que cette documentation Ansible sur la gestion du module Authorized_keys.
Bonne pratique:
- Il est recommandé d'utiliser un autre utilisateur que root pour effectuer l'établissement de la session SSH par Ansible.
- Il faut privilégier l'usage d'un compte de déploiement ayant les droits suffisants pour passer toutes les commandes nécessaires en sudo.
- Il faut ensuite utiliser la directive become permettant de gérer les élévations de privilèges pour les tâches qui le nécessitent.
Le choix fait dans le cadre de cette migration est de:
- créer un playbook à exécuter à la création d'un serveur, ou à chaque ajout/suppression d'utilisateur de déploiement.
- ce playbook sera à exécuter en tant que root (puisque Scaleway livre ses serveurs avec un accès root autorisé et la ou les clés RSA d'administration autorisées à se connecter).
- tous les autres playbook seront joués avec l'utilisateur local de ma session WSL (l'utilisateur de déploiement aura le même login que mon compte WSL).
Playbook:
--- - name: Playbook de creation des users sudoers hosts: all vars: sudoers: - jules tasks: - name: Make sure we have a 'wheel' group group: name: wheel state: present - name: Allow 'wheel' group to have passwordless sudo lineinfile: dest: /etc/sudoers state: present regexp: '^%wheel' line: '%wheel ALL=(ALL) NOPASSWD: ALL' validate: visudo -cf %s - name: Add sudoers users to wheel group user: name: "{{ item }}" shell: /bin/bash groups: wheel append: yes with_items: "{{ sudoers }}" - name: Add jules public key authorized_key: user: "{{ item }}" state: present key: "{{ lookup('file', '<chemin_local_de_la_cle_publique_rsa>') }}" with_items: "{{ sudoers }}" ...
Dans les fils de discussions, on trouve des remarques pertinentes sur l'utilisation de sudoers.d à la place du fichier global sudoers, à tester dans un second temps si possible.
NB: ceci n'est évidemment pas une vraie gestion d'utilisateurs en bonne et dûe forme, et correspond plutôt aux besoins très simples du projet (1 seul ops utilisant toujours la même clé RSA pour l'authentification par exemple).
Déploiement des packages
Cf cette vieille doc Scaleway sur l'installation d'Apache par Ansible.
On peut installer un package, explicitement via Aptitude, grâce à une tâche du type:
tasks: - name: Install Apache2 => nom de la tâche, le nommage des tâches est une bonne pratique. apt: => désignation explicite du gestionnaire de package, puisqu'on ne gère pas un parc hétérogène. name: apache2 => nom du package tel que fournit par une recherche Aptitude. update_cache: yes => mise à jour du cache Aptitude avant l'installation. state: latest => version souhaitée du package.
Playbook:
--- - name: Playbook d'installation des packages debian hosts: all become: yes tasks: - name: Install Apache2 apt: name: apache2 update_cache: yes state: latest - name: Install php apt: name: php update_cache: yes state: latest - name: Install lib curl apt: name: php-curl update_cache: yes state: latest - name: Install lib mbstring apt: name: php-mbstring update_cache: yes state: latest - name: Install lib zip apt: name: php-zip update_cache: yes state: latest - name: Install lib imagick apt: name: php-imagick update_cache: yes state: latest - name: Install Lets Encrypt apt: name: letsencrypt update_cache: yes state: latest ...
NB:
- le code peut être largement factorisé en bouclant sur la liste de packages requis.
- la mise à jour systématique du cache Aptitude est discutable car elle pénalise la durée d'exécution de chaque tâche.
--- - name: Playbook packages factorise hosts: all become: yes vars: pkgs: - apache2 - php - php-curl ... - letsencrypt tasks: - name: Install packages apt: name: "{{ item }}" update_cache: yes state: latest with_items: "{{ pkgs }}"
Application des configurations Terraform
Planifier les modifications:
terraform plan
Planifier les modifications ET produire un fichier de planification:
terraform plan -out <fichier_de_planif>
Appliquer les modifications:
terraform apply
Application des modifications telles que planifiées:
terraform apply "<fichier_de_planif>"
Cf cette documentation Terraform sur le CLI et les états: Si un objet a été modifié "dans la vraie vie" et que son état n'est plus cohérent avec les états connus de terraform, il est possible d'importer l'état "de la vraie vie" pour rendre cohérents les états terraform. Cela permet de rattraper les écarts, par exemple, quand on n'a pas été rigoureux et qu'on a géré les objets par d'autres biais que terraform (ex: console Scaleway):
terraform import <nom_ressource_terraform> <region>/<id_de_l_objet_instancié>
Vous pouvez lister les objets connus de terraform:
terraform state list
Ex:
jules@DESKTOP-QQG9015:/mnt/d/Jules/Tech/Git/scaleway/terraform$ terraform state list scaleway_instance_ip.public_ip scaleway_instance_security_group.test-sg scaleway_instance_server.test-srv
Vous pouvez également lister l'état connu d'un objet par terraform:
terraform state show <nom_ressource_terraform>
Ex:
jules@DESKTOP-QQG9015:/mnt/d/Jules/Tech/Git/scaleway/terraform$ terraform state show scaleway_instance_server.test-srv # scaleway_instance_server.test-srv: resource "scaleway_instance_server" "test-srv" { additional_volume_ids = [] boot_type = "local" bootscript_id = "<id_bootscript>" enable_dynamic_ip = false enable_ipv6 = false id = "fr-par-1/<id_instance>" image = "debian_buster" ip_id = "fr-par-1/<id_ip>" ipv6_prefix_length = 0 name = "tf-test-srv" organization_id = "<id_organization>" private_ip = "<ip_privee>" project_id = "<id_projet>" public_ip = "<ip_publique>" security_group_id = "fr-par-1/<id_sg>" state = "started" tags = [ "test", "web", ] type = "DEV1-S" zone = "fr-par-1" root_volume { delete_on_termination = true size_in_gb = 20 volume_id = "fr-par-1/<id_volume>" } }
Application des configurations Ansible
Jouer un playbook:
ansible-playbook <nom_du_playbook>.yml
Possibilités de surcharges:
- -vvv: augmenter le niveau de verbosité (débug).
- -u: forcer l'usage d'un utilisateur spécifique (autre que celui de la session linux en cours).
- --private-key <path_to_priv_key>: forcer l'usage d'une paire de clé RSA spécifique.
Etapes de migration pour la prod
- Rédaction (duplication) du code Terraform pour les 2 serveurs de prod.
- Planification dans un fichier de plan, et application Terraform.
- Récupération via
terraform state show <id_objet_terraform_serveur>
des IPs publiques des 2 nouveaux serveurs. - Mise à jour de l'inventaire Ansible global.
- Ajout des groupes, des alias, et des options d'inventaire concernant la version du binaire Python.
- Test de ping d'un des 2 serveurs.
jules@DESKTOP-QQG9015:/mnt/d/Jules/Tech/Git/scaleway/ansible/init$ ansible jules -m ping -u root jules | SUCCESS => { "changed": false, "ping": "pong" }
- Tests pour l'application d'un playbook par host ou groupe => ECHEC, à reprendre plus tard.
- Application en root du playbook de création du user de déploiement.
- Correction de la désignation du chemin de la clé publique suite à la création des répertoires.
- Arrêt par Terraform du serveur de test.
- Mise en commentaire du serveur de test dans l'inventaire Ansible (pour éviter les échecs lors d'un hôte injoignable).
- Factorisation de la tâche d'installation des packages, à exécuter sur une liste de packages.
vars: pkgs: - apache2 - php - php-curl - php-mbstring - php-zip - php-imagick - letsencrypt - mariadb-server tasks: - name: Install all web packages apt: name: "{{ pkgs }}" update_cache: yes state: latest
- Ajout de mariadb à la liste des packages et début de recherche de documentation sur la gestion du service, des users et des bases.
- 1 commit git du projet.
- Stockage des crédentiels Scaleway en variable d'environnement, exclusion de ce script de git et suppression des creds en dur dans le main.tf.
- Test des accès Terraform avec cette nouvelle gestion de creds: OK.
- 1 commit git du projet.
- Ajout IP Denz dans les ACL SSH Terraform.
- Ajout clé RSA Denz dans les authorized_keys des users à privilèges.
- Création des databases:
- via depapt.yml installation complémentaire: python3-pymysql.
- identification du problème d'accès aux DB: par défaut, authentification MariaDB via le socket unix (fichier) => désignation de localhost à remplacer dans les tâches Ansible mysql.
- 1 playbook common.yml pour la sécurisation (accès root avec mdp entre autre).
- 1 playbook pour les bases de Jules.
- 1 playbook pour les bases de Denz.
- Rapatriement de l'inventaire Ansible dans le projet:
- 1 dossier inventory
jules@DESKTOP-QQG9015:/mnt/d/Jules/Tech/Git/scaleway/ansible$ tree inventory/ inventory/ Dossier d'inventaire ├── group_vars Dossier pour les variables de groupes │ └── prodservers.yml ├── hosts Fichier d'inventaire └── host_vars Dossier pour les variables d'hôtes ├── denz.yml └── jules.yml
- création d'un fichier de configuration Ansible (ansible.cfg) dans le dossier ansible et export d'une variable d'environnement pour contourner le pb de droits trop larges sur le fichier (liés à l'utilisation d'une arbo Windows dans WSL).
- Confs apache:
- récupération via scp des confs Apache2 actives en prod dans apache/files/.
- copie de ces fichiers sur les serveurs via tâche ansible.
- pour distinguer les vhosts par machine:
- 1 playbook Jules.
- 1 playbook Denz.
- Test de 2 méthodes pour la prise en compte des confs Apache:
- utilisation d'un handler.
- OU utilisation du module command pour appeler
apache2ctl restart/graceful
.
- dans le playbook de déploiement des packages (depapt.yml) ajout de tâches apache2_module pour l'activation des modules Apache2 (reprise des modules installés sur les prods d'origine).
- Début des tests:
- dump des bases sur les prods d'origine, et dépôts sur les nouvelles prods en deb10.
- récupération des DocRoot sur les prods d'origine, et dépôts sur les nouvelles prod en deb10.
Reste à faire
- Améliorer la lisibilité des hosts dans l'inventaire Ansible.
- Stocker l'inventaire localement au projet.
- Ajouter des tags aux items de l'inventaire pour cibler les déploiements dans les playbooks si besoin.
- Trouver le moyen d'appliquer un playbook par host plutôt qu'en hosts: all, plutôt que de faire des playbooks par machine ou par groupe.
- OK BOUCLE NATIVE DANS LE MODULE APT Playbook packages => faire 1 boucle sur les briques de PHP pour installer tout PHP en 1 seule tâche.
- Tester l'ajout d'un fichier d'inclus dans /etc/sudoers.d/ plutôt qu'un ajout de ligne dans /etc/sudoers pour les users privilégiés
- INUTILE, FAIT VIA INVENTAIRE Voir si la mise en place du lien symbolique pour python peut se faire via Cloud Init (cf documentation terraform).
- Stockage des états terraform pour permettre le partage avec un autre admin (ex: bucket S3).
- OK VARIABLE D'ENV Crédentiels Terraform à passer en variable d'environnement pour ne plus les écrire explicitement dans le code Terraform.
- Evaluer l'utilité des datas sources ssh key.
- Variabiliser les environnements (Jules, Denz, Test) pour ne pas dupliquer le code Terraform à chaque nouvelle machine?
- Ajouter des règles Terraform Security Group en sortie pour permettre l'envoi de mails via Gmail.