Le blog tech de Nicolas Steinmetz (Time Series, IoT, Web, Ops, Data)
Pour pouvoir tester différentes solutions, il peut être utile de pouvoir créer rapidement une infrastructure chez un fournisseur tiers. Pour cela nous allons nous appuyer sur la solution Terraform, dont l’objectif est de pouvoir gérer une insfrastructure via du code qui permet de décrire cette infrastructure et les règles associées (dans la tendance Infrastructure as Code).
Cela se fera chez Scaleway mais cela peut se faire chez d’autres fournisseurs tant qu’un provider Terraform existe.
Nous allons nous appuyer sur l’intégration Terraform/Scaleway pour créer un cluster de 3 machines.
Créer un ficheir cluster-3.tf
dans un dossier vide. Il est important qu’il soit vide car Terraform prend en compte tous les fichiers .tf
qu’il rencontre dans le répertoire courant.
Il faut commencer par déclarer notre provider
; je fournis les infos de key & token, ainsi que le datacenter où je souhaite lancer mon cluster :
provider "scaleway" {
organization = "<access key>"
token = "<token>"
region = "par1"
}
Je déclare ensuite des data
, que l’on peut assimiler à des variables à ce stade :
data "scaleway_bootscript" "latest" {
architecture = "x86_64"
name_filter = "stable"
}
data "scaleway_image" "ubuntu" {
architecture = "x86_64"
name = "Ubuntu Xenial"
}
Ensuite, je définis une politique de sécurité en 2 étapes :
resource "scaleway_security_group" "cluster_default" {
name = "cluster_default"
description = "Allow SSH, HTTP, HTTPS traffic"
}
resource "scaleway_security_group_rule" "ssh_accept" {
security_group = "${scaleway_security_group.cluster_default.id}"
action = "accept"
direction = "inbound"
ip_range = "0.0.0.0/0"
protocol = "TCP"
port = 22
}
resource "scaleway_security_group_rule" "http_accept" {
security_group = "${scaleway_security_group.cluster_default.id}"
action = "accept"
direction = "inbound"
ip_range = "0.0.0.0/0"
protocol = "TCP"
port = 80
}
resource "scaleway_security_group_rule" "https_accept" {
security_group = "${scaleway_security_group.cluster_default.id}"
action = "accept"
direction = "inbound"
ip_range = "0.0.0.0/0"
protocol = "TCP"
port = 443
}
Je pourrais donc me connecter en ssh, http et https sur l’ensemble de mon cluster une fois qu’il sera initialisé.
Je déclare ensuite une IP et je l’associe au serveur qui l’utilisera :
resource "scaleway_ip" "cluster-master_ip" {
server = "${scaleway_server.cluster-master.id}"
}
Enfin, je déclare mon serveur qui va reprendre l’ensemble des informations précédentes, ainsi que quelques informations spécifique comme le type d’instance (type
) ou encore le volume additionnel (volume
) attaché au serveur. Il y a des directives scaleway_volume
ou scaleway_volume_attachment
mais l’API Scaleway ne permet pas de les utiliser pour ce type de serveur.
resource "scaleway_server" "cluster-master" {
name = "cluster-master"
image = "${data.scaleway_image.ubuntu.id}"
type = "VC1M"
bootscript = "${data.scaleway_bootscript.latest.id}"
security_group = "${scaleway_security_group.cluster_default.id}"
volume {
size_in_gb = 50
type = "l_ssd"
}
}
Sur le même modèle, nous allons instancier les 2 autres noeuds de notre cluster :
resource "scaleway_ip" "cluster-node1_ip" {
server = "${scaleway_server.cluster-node1.id}"
}
resource "scaleway_server" "cluster-node1" {
name = "cluster-node1"
image = "${data.scaleway_image.ubuntu.id}"
type = "VC1M"
bootscript = "${data.scaleway_bootscript.latest.id}"
security_group = "${scaleway_security_group.cluster_default.id}"
volume {
size_in_gb = 50
type = "l_ssd"
}
}
resource "scaleway_ip" "cluster-node2_ip" {
server = "${scaleway_server.cluster-node2.id}"
}
resource "scaleway_server" "cluster-node2" {
name = "cluster-node2"
image = "${data.scaleway_image.ubuntu.id}"
type = "VC1M"
bootscript = "${data.scaleway_bootscript.latest.id}"
security_group = "${scaleway_security_group.cluster_default.id}"
volume {
size_in_gb = 50
type = "l_ssd"
}
}
Vous pouvez déjà valider qu’il n’y a pas d’erreur de syntaxe avec
↪ terraform fmt
cluster-3.tf
Si pas d’erreur, alors il ne retourne que le nom du fichier ou rien si commande déjà exécutée.
Ensuite vous pouvez regarder ce qu’il va se passer avec terraform plan
. Cela vous sort un diff
de ce qui va être réalisé (ou changé s’il y a mise à jour du plan)
Dans notre cas :
↪ terraform plan
[...]
+ scaleway_ip.cluster-master_ip
ip: "<computed>"
server: "${scaleway_server.cluster-master.id}"
+ scaleway_ip.cluster-node1_ip
ip: "<computed>"
server: "${scaleway_server.cluster-node1.id}"
+ scaleway_ip.cluster-node2_ip
ip: "<computed>"
server: "${scaleway_server.cluster-node2.id}"
+ scaleway_security_group.cluster_default
description: "Allow SSH, HTTP, HTTPS traffic"
name: "cluster_default"
+ scaleway_security_group_rule.http_accept
action: "accept"
direction: "inbound"
ip_range: "0.0.0.0/0"
port: "80"
protocol: "TCP"
security_group: "${scaleway_security_group.cluster_default.id}"
+ scaleway_security_group_rule.https_accept
action: "accept"
direction: "inbound"
ip_range: "0.0.0.0/0"
port: "443"
protocol: "TCP"
security_group: "${scaleway_security_group.cluster_default.id}"
+ scaleway_security_group_rule.ssh_accept
action: "accept"
direction: "inbound"
ip_range: "0.0.0.0/0"
port: "22"
protocol: "TCP"
security_group: "${scaleway_security_group.cluster_default.id}"
+ scaleway_server.cluster-master
bootscript: "8fd15f37-c176-49a4-9e1d-10eb912942ea"
enable_ipv6: "false"
image: "89457135-d446-41ba-a8df-d53e5bb54710"
name: "cluster"
private_ip: "<computed>"
public_ip: "<computed>"
public_ipv6: "<computed>"
security_group: "${scaleway_security_group.cluster_default.id}"
state: "<computed>"
state_detail: "<computed>"
type: "VC1M"
volume.#: "1"
volume.0.size_in_gb: "50"
volume.0.type: "l_ssd"
volume.0.volume_id: "<computed>"
+ scaleway_server.cluster-node1
bootscript: "8fd15f37-c176-49a4-9e1d-10eb912942ea"
enable_ipv6: "false"
image: "89457135-d446-41ba-a8df-d53e5bb54710"
name: "cluster-node1"
private_ip: "<computed>"
public_ip: "<computed>"
public_ipv6: "<computed>"
security_group: "${scaleway_security_group.cluster_default.id}"
state: "<computed>"
state_detail: "<computed>"
type: "VC1M"
volume.#: "1"
volume.0.size_in_gb: "50"
volume.0.type: "l_ssd"
volume.0.volume_id: "<computed>"
+ scaleway_server.cluster-node2
bootscript: "8fd15f37-c176-49a4-9e1d-10eb912942ea"
enable_ipv6: "false"
image: "89457135-d446-41ba-a8df-d53e5bb54710"
name: "cluster-node2"
private_ip: "<computed>"
public_ip: "<computed>"
public_ipv6: "<computed>"
security_group: "${scaleway_security_group.cluster_default.id}"
state: "<computed>"
state_detail: "<computed>"
type: "VC1M"
volume.#: "1"
volume.0.size_in_gb: "50"
volume.0.type: "l_ssd"
volume.0.volume_id: "<computed>"
Plan: 10 to add, 0 to change, 0 to destroy.
Pour provisionner l’infrastructure, il ne vous reste plus qu’à faire terraform apply
.
↪ terraform apply
data.scaleway_bootscript.latest: Refreshing state...
data.scaleway_image.ubuntu: Refreshing state...
scaleway_security_group.cluster_default: Creating...
description: "" => "Allow SSH, HTTP, HTTPS traffic"
name: "" => "cluster_default"
scaleway_security_group.cluster_default: Creation complete (ID: 06b93dc3-...2beffd62)
scaleway_security_group_rule.ssh_accept: Creating...
action: "" => "accept"
direction: "" => "inbound"
ip_range: "" => "0.0.0.0/0"
port: "" => "22"
protocol: "" => "TCP"
security_group: "" => "06b93dc3-9a8b-4022-80bf-e9172beffd62"
scaleway_server.cluster-master: Creating...
[...]
Apply complete! Resources: 10 added, 0 changed, 0 destroyed.
Vous pouvez consulter l’ensemble des informations de votre infrastructure avec la commande terraform show
.
Il ne vous reste plus qu’à vous connecter sur vos serveurs, faire les actions dont vous avez besoin.
Supposons que nous ayons besoin d’un 4ème noeud, il suffirait de rajouter dans le fichier cluster-3.tf
:
resource "scaleway_ip" "cluster-node3_ip" {
server = "${scaleway_server.cluster-node3.id}"
}
resource "scaleway_server" "cluster-node3" {
name = "cluster-node3"
image = "${data.scaleway_image.ubuntu.id}"
type = "VC1M"
bootscript = "${data.scaleway_bootscript.latest.id}"
security_group = "${scaleway_security_group.cluster_default.id}"
volume {
size_in_gb = 50
type = "l_ssd"
}
}
On peut valider notre changement avec terraform plan
:
↪ terraform plan
[...]
+ scaleway_ip.cluster-node3_ip
ip: "<computed>"
server: "${scaleway_server.cluster-node3.id}"
+ scaleway_server.cluster-node3
bootscript: "8fd15f37-c176-49a4-9e1d-10eb912942ea"
enable_ipv6: "false"
image: "89457135-d446-41ba-a8df-d53e5bb54710"
name: "cluster-node3"
private_ip: "<computed>"
public_ip: "<computed>"
public_ipv6: "<computed>"
security_group: "06b93dc3-9a8b-4022-80bf-e9172beffd62"
state: "<computed>"
state_detail: "<computed>"
type: "VC1M"
volume.#: "1"
volume.0.size_in_gb: "50"
volume.0.type: "l_ssd"
volume.0.volume_id: "<computed>"
Plan: 2 to add, 0 to change, 0 to destroy.
Puis de mettre à jour le cluster avec terraform apply
↪ terraform apply
[...]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Enfin, comme toutes les choses ont une fin, vous pouvez détruire l’ensemble de l’infrastructure créé via terraform destroy
.
↪ terraform destroy
[...]
Destroy complete! Resources: 14 destroyed.
J’espère que cette introduction à Terraform vous donnera des idées ; les éditeurs de code modernes fournissent souvent des plugins pour la syntaxe et les snippets terraform. Scaleway reste assez limité en tant que provider terraform. Si vous regardez le provider AWS, vous pouvez interagir avec énormément de services AWS (pour ne pas dire tous) : VPC, EC2, ELB, RDS, etc.
zsh
via “Oh My ZSH” mais je n’étais pas allé bien loin, revenant au final au bon vieux bash
. L’article m’a donné envie d’essayer fish et pour le moment, je trouve ça plutôt pas mal. Ne pas se fier à la première impression du site :)JSON
et surtout qu’il n’y a pas de rotation des journaux par défaut :’( ; l’article montre ensuite les intérêts du format GELF (avoir un message sous la forme d’un dictionnaire/tableau au format clé/valeur) et les limites (connextion UDP) avec les solutions de contournement actuelles et les solutions à venir prochainement.Un de nos clients souhaite pouvoir envoyer des newsletters à ses membres et utiliser des listes de diffusion pour la communication entre les membres.
Ayant de précédentes expériences avec mailman, je me suis naturellement tourné vers celui-ci. Pour l’occasion, j’ai installé une première instance de mailman3 via mailman-bundler. Si l’installation se fait sans trop de soucis, les versions packagées avec mailman-bundler ne sont pas les plus récentes et contiennent des bugs (parfois déjà corrigés dans les versions supérieures) rendant quelques fonctionnalités inopérantes (comme la modération des messages) ou provoquant des comportements étranges (certaines modifications d’options de liste ne sont parfois pas pris en compte). Même si le service fonctionnait à peu près correctement, nous décidions de revenir en mailman dans sa version 2. Même si cela résolvait les problèmes de stabilité et les bugs, il nous manquait une fonctionnalité : l’abonnement à une liste sans confirmation (la confirmation par réponse à un email étant jugé trop complexe).
Pour revenir à Mailman 3, la documentation et les développeurs considèrent qu’il n’est pas encore tout à fait prêt. A l’instar de la suite KDE, il faudra attendre une version 3.2 ou plus pour pouvoir l’utiliser sereinement. En tous cas, la nouvelle interface est prometteuse !
Notre client souhaitant pouvoir envoyer des listes avec son nom de domaine et celui-ci n’étant pas forcément prêt à payer pour cette fonctionnalité, cela disqualifiait plusieurs solutions hébergées (SaaS).
Je me suis donc rabattu sur Sympa.
Initialement, je voulais utiliser Postgres comme base de données, il s’est avéré que l’installateur debian ou sympa échoue. De guerre lasse, je me suis rabattu sur MySQL qui de toutes façons est considéré comme une dépendance de Sympa et je suis passé par la configuration via db-config
. Pour le serveur web, ayant déjà un apache2 sur ce serveur pour mailman, je suis resté sur cette configuration.
Avant toute chose, s’assurer que /etc/mailname
correspond bien à votre DNS utilisé pour le mail. Sympa semble prendre cette valeur par défaut et semble ignorer une mise à jour de ce fichier postérieurement à son installation.
apt update
apt install sympa
A ce stade vous avez une première configuration de sympa avec MySQL initialisée pour vos données.
Ensuite, vérifier que les dépendances de Sympa sont bien à jour et complètes ; Installer les librairies dont vous avez besoin pour votre scénario.
sympa_wizard --check
Ensuite, vous pouvez soit éditer les fichiers de configuration /etc/sympa/sympa.conf
et /etc/sympa/wwsympa.conf
ou bien utiliser le script prévu à cet effet : sympa_wizard
. Cela revient au même, le script prend en compte les valeurs du fichiers et complète le cas échéant avec vos nouvelles réponses. Ce sont surtout les premières questions qui sont importantes avec la définition des hôtes, url et surtout la définition des listmaster
. Les emails définis comme listmaster pourront en effet administrer Sympa. Pensez également a bien activer le support de fastcgi pour éviter une erreur 500.
Ensuite, en m’inspirant des fichiers /etc/apache2/conf-available/sympa.conf
/etc/apache2/conf-available/sympa.conf
et /etc/apache2/conf-available/sympa-soap.conf
fournis par Sympa, j’ai créé le fichier (simplifié) suivant dans /etc/apache2/sites-available/sympa.conf
:
#
# Apache >> 2.4 configuration for Sympa
#
<IfModule mod_fcgid.c>
Alias /static-sympa /var/lib/sympa/static_content
<Directory /var/lib/sympa/static_content>
Require all granted
</Directory>
ScriptAlias /wws /usr/lib/cgi-bin/sympa/wwsympa-wrapper.fcgi
<Directory /usr/lib/cgi-bin/sympa>
Require all granted
</Directory>
</IfModule>
#
# Apache >> 2.4 configuration for Sympa (soap webservice)
#
<IfModule mod_fcgid.c>
ScriptAlias /sympasoap /usr/lib/cgi-bin/sympa/sympa_soap_server-wrapper.fcgi
<Directory /usr/lib/cgi-bin/sympa>
Require all granted
</Directory>
</IfModule>
<VirtualHost *>
ServerName listes.domaine.fr
ServerAdmin contact@cerenit.fr
RewriteEngine On
RewriteRule ^/$ /wws/lists [R=301,L]
</VirtualHost>
Puis, activation du site via :
a2ensite sympa
systemctl restart apache2
Dans /etc/postfix/master.cf
, ajouter :
# Services Pour sympa
sympa unix - n n - - pipe
flags=R user=sympa argv=/usr/lib/sympa/bin/queue ${recipient}
sympabounce unix - n n - - pipe
flags=R user=sympa argv=/usr/lib/sympa/bin/bouncequeue ${recipient}
Dans /etc/postfix/main.cf
, ajouter :
#
## SYMPA
#
# Tranport vers les services sympa*
transport_maps = regexp:/etc/postfix/sympa_transport.cf
local_recipient_maps = regexp:/etc/postfix/sympa_transport.cf
# Un seul envoi/destinataire envoyé aux services sympa* à la fois
sympa_destination_recipient_limit = 1
sympabounce_destination_recipient_limit = 1
Et dans /etc/postfix/sympa_transport.cf
:
/^.*-owner\@listes\.domaine\.fr$/ sympabounce:
/^.*\@listes\.domaine\.fr$/ sympa:
Il ne nous reste plus qu’à redémarrer Postfix et Sympa pour s’assurer que nos modifications ont bien été prises en compte :
systemctl restart postfix sympa
Il ne vous reste plus qu’à aller sur http://listes.domaine.fr/wws/ et vous devriez avoir l’interface de Sympa.
Cliquer alors sur “1ère connection”, rentrer un des emails de listmaster pour obtenir votre mot de passe et pouvoir administrer Sympa en fonction de vos besoins.
htop
expliqué. Si vous avez d’autres questions sur les commandes shell : Explain Shell