À propos de ce Projet
L'histoire en arrière-plan
Donc, avant de finalement vendre mon âme à Kubernetes, j'ai décidé qu'un projet IaaS raisonnablement complet s'imposait. Je voulais faire bon usage de bases solides en Réseaux, Sécurité, Scripting, puis de Terraform, Ansible, Docker, Traefik et Wireguard (et de tous les concepts qu'ils représentent), pour un projet complet. Puisque Kubernetes était l'outil principal de ma liste des 'choses à apprendre' depuis un certain temps, je me suis dit, eh bien, pourquoi ne pas déployer tous les outils nécessaires dont j'aurais besoin pour ma transition vers son utilisation dans un projet précurseur ? Cela m'a semblé être une excellente idée !
Le petit rebondissement, c'est que j'ai eu cette idée pendant un moment, jusqu'à ce que j'aie une raison de mettre rapidement en place une infrastructure qui me permettrait d'héberger mon propre gestionnaire de mots de passe Vaultwarden, car mon abonnement Bitwarden de l'époque était sur le point d'expirer. Bitwarden en ligne n'est pas cher, mais je n'avais pas les 10 $ pour le renouveler à ce moment-là. Ce que j'avais, en revanche, c'était des crédits cloud sur DigitalOcean, un nom de domaine, Cloudflare gratuit, l'idée de ce projet et des compétences raisonnables en infrastructure informatique.
Il pourrait être intéressant pour vous de savoir que dans mon implémentation de ce projet, j'ai créé chaque fichier avec Neovim (LazyVIM), que j'ai commencé à apprendre fin août. Dans l'ensemble, je crois que cela a rendu tout le processus encore plus amusant et gratifiant.
Donc, pour ce projet, il y avait 5 objectifs primordiaux (et un 6ème) :-
- AUTOMATISATION COMPLÈTE (De bout en bout, du type on configure et on va dormir)
- VISIBILITÉ COMPLÈTE (Rien ne bouge d'un centimètre dans l'environnement sans être repéré et consigné)
- REPRODUCTIBILITÉ COMPLÈTE (Toutes les données importantes entièrement sauvegardées. Accompagné d'une politique de restauration à une date donnée du type on configure et on s'en va)
- BONNE SÉCURITÉ (VPN privé et clés SSH uniquement accessibles. Verrouillage complet du pare-feu, communication Docker vers hôte sécurisée)
- Le faire de la manière la plus PEU COÛTEUSE, AUTO-HÉBERGÉE, OPEN-SOURCE possible (Sur un seul VPS qui correspond à mon budget)
- Le faire À PARTIR DE ZÉRO
Avant que vous ne lisiez plus loin, je dois préciser que ce projet N'EST PAS adapté aux environnements à haute disponibilité. Malgré la nature hautement reproductible de ses environnements, être sur un seul serveur implique un certain temps d'arrêt opérationnel (mais pas de la charge de travail) pour les opérations de restauration. Cela dit, les organisations petites, naissantes, à budget restreint et ayant besoin d'initialiser une infrastructure à la vitesse de l'éclair pourraient s'en sortir à merveille avec cela.
Dans ce projet, j'ai déployé les 5 services les plus courants dont on aurait typiquement besoin pour piloter un environnement k8s (et quelques petites choses personnelles supplémentaires, y compris un frontend LLM que j'appelle Jarvis 😉).
- Un service d'hébergement Git privé (Gitea)
- Un outil CI/CD (Jenkins)
- Un outil de gestion des secrets (Harshicorp Vault)
- Un Artifactory privé (JFrog Container Registry)
- Un outil de scan des vulnérabilités (SonarQube)
Avec ceux-ci, vous pourriez héberger du code privé sur Gitea, builder avec Jenkins, scanner (scans de code et d'images) avec SonarQube et Trivy, publier (release) sur l'Artifactory auto-hébergé, et déployer sur Kubernetes ou tout autre environnement. Tout cela, en sécurisant vos secrets à la fois au sein de vos Pipelines et de votre/vos environnement(s) Kubernetes via une instance Vault centrale.
Pour atteindre le deuxième objectif, j'ai déployé une Stack de Monitoring et d'Observabilité qui offre un aperçu complet à la fois du serveur Hôte et de tous les environnements de Contenedurs.
- Prometheus et cAdvisor pour la collecte de Métriques
- Loki et Promtail pour l'agrégation de Logs
- Grafana pour la Visualisation des Métriques et des Logs
Concernant la Sécurité, puisque cette Infrastructure est censée être la colonne vertébrale des opérations DevOps d'une organisation et est donc Interne, son environnement est complètement isolé de l'Internet public, et accessible uniquement via un VPN. Le projet instrumente également un port SSH personnalisé, protégeant efficacement l'environnement de la plupart des attaques Internet automatisées et aléatoires. De plus, une communication sécurisée de Docker à l'Hôte via des règles IPTables appropriées est implémentée, garantissant qu'une isolation adéquate est maintenue entre les environnements des Conteneurs et de l'Hôte.
Où est le code source ?
Je suis très disponible (extrêmement désireux) pour aider votre Organisation à mettre en service cette Infrastructure ou une qui s'en rapproche. Je porterai cela dans n'importe quel environnement (cloud ou sur site), avec la garantie qu'aucune des fonctionnalités principales énumérées ci-dessus ne sera manquante ou incomplète. Amenez-les ces contrats :cool:
Et la suite pour moi ?
Maintenant, en vertu du pouvoir qui m'est conféré (par quelqu'un), je me déclare officiellement Kubestronaute. À partir de maintenant, je vis et je respire Kubernetes, lol. Alors pour la suite, je vais m'attaquer à quelques projets k8s bien croustillants que je prépare avec quelques amis. Nous allons porter une application de microservices assez compliquée sur k8s en partant de zéro (via DevSecOps). Créer des clusters k8s, les équiper avec ArgoCD et devenir fou avec GitOps, d'ici novembre.
Si vous avez aimé ce projet, n'oubliez pas de laisser un J'aime et de vous Abonner pour plus de "contenu" comme celui-ci. Dites-moi également dans les commentaires ce que vous pensez du projet et comment vous pensez que j'aurais pu l'améliorer.
SI vous souhaitez répéter ce projet
- Soyez prévenus, je n'ai pas écrit d'instructions sur comment faire quoi que ce soit.
- Tout ce que vous trouverez, ce sont des instructions sur quoi faire. J'ai noté ces étapes pendant que je travaillais sur ce projet avec des amis. Idéalement, ces instructions devraient vous aider à réaliser cela d'une manière sensée.
- Tout le plaisir réside dans la découverte du comment pour n'importe partie du projet avec laquelle vous n'êtes pas familier.
Prérequis du Projet
- Un nom de domaine
- Un accès à un hébergement Cloud
- Un magasin de clés (Key store) Cloud
- Un (ou plusieurs) bucket(s) de stockage Cloud
- Quelques connaissances en informatique
Remarques importantes sur la structure et l'organisation du Projet
Les Comptes Cloud de Contrôle et Cible
Ce projet suppose l'existence de deux comptes de plateformes Cloud différents. L'un pour les ressources cibles et l'autre pour l'accès administrateur ultime sur ces ressources déployées sur le compte cible.
Les parties les plus importantes de ce projet sont à savoir ;
- Le State Terraform (pour des raisons évidentes)
- Les Clés SSH du Serveur, dont Ansible ou une autre personne aurait besoin pour se connecter au Serveur.
- Les Archives de Sauvegarde (Backups)
- Les clés de déverrouillage automatique (Auto-Unseal) de Hashicorp Vault
Avec ces quatre éléments, et l'implémentation du code, le système entier pourrait être reproduit intégralement, à partir de zéro.
Par conséquent, au cours de ce projet, j'ai supposé qu'il y aurait un Individu (ou un ensemble d'Individus) avec un accès Super Admin sur l'ensemble de l'Infrastructure de base (opérationnelle) de l'entreprise. Ceux-ci seraient (idéalement) des parties prenantes clés telles que le PDG ou le Directeur de l'Ingénierie. Ce seraient les personnes détenant les clés (proverbiales) ultimes du royaume.
En pratique, les comptes "de contrôle" et "de ressources" peuvent prendre diverses formes et configurations, en fonction de votre configuration et de vos besoins spécifiques. Ces comptes pourraient représenter différentes entités sur de multiples aspects de votre infrastructure cloud. Voici quelques scénarios possibles :
1. Multi-cloud : Les comptes pourraient appartenir à des plateformes cloud complètement différentes. Par exemple, vous pourriez avoir votre compte de contrôle hébergé sur Azure, tandis que vos ressources sont déployées sur un fournisseur cloud distinct comme Digital Ocean. Cela vous permet de tirer parti des fonctionnalités et des services uniques offerts par chaque plateforme.
2. Même plateforme cloud, comptes différents : Les comptes pourraient être des comptes séparés au sein du même fournisseur cloud. Cette configuration est courante lorsque vous souhaitez maintenir une isolation entre différents environnements, comme la production et le développement, ou entre différents départements ou projets au sein de votre organisation.
3. Même plateforme cloud, différentes unités organisationnelles : Dans certaines plateformes cloud, comme Azure avec ses groupes de ressources ou Google Cloud avec ses projets, les comptes pourraient représenter différents regroupements logiques au sein du même compte cloud. Cela vous permet d'organiser et de gérer les ressources en fonction de critères spécifiques, tels que le projet, l'environnement ou l'application.
J'ai adopté l'approche Multi-cloud, mes ressources sont déployées chez Digital Ocean, tandis que mon Compte de Contrôle est sur Azure.
À Propos du Déploiement d'Autres (Extras) Services
Comme vous l'avez probablement remarqué, en plus des outils de base, j'ai déployé les applications VaultWarden Password Manager et AnythingLLM. Ces outils ont été déployés pour moi. Vous êtes libre de vous en débarrasser et de déployer n'importe quel autre outil de votre choix.
Aperçu Général
Dans l'esprit d'un aperçu général, voici les fonctions de chacun des trois composants de base de ce projet ;
Terraform pour déployer ;
- Ressources serveur (VPC, Firewall/SG)
- Serveur chez DO/AWS/etc, avec script Userdata
- Enregistrements DNS chez Cloudflare/etc
- Playbook Ansible
Playbook Ansible pour ;
- Configurer le serveur (Hostname, règles Réseau/Sécurité)
- Installer des utilitaires (s3cmd, prometheus-node-exporter)
- Installer & Configurer Docker
- Installer & Configurer le VPN WireGuard
- Déployer Docker compose (Stacks de Services et de Monitoring)
- Scripts et tâches (jobs) pour les sauvegardes des volumes Docker
- Scripts pour la restauration des volumes Docker
Docker Compose pour Déployer ;
- Gateway Traefik (HTTP, SSL, Redirections HTTP-HTTPS, Liste blanche IP)
- Gitea
- Jenkins
- Hashicorp Vault
- JFrog Container Registry
- SonarQube OSS
- Prometheus
- Loki & Promtail
- Grafana
- Vaultwarden
- AnythingLLM
Groupements de Tâches
Ces groupements de tâches ont été des contributeurs clés au fait que j'aie terminé ce projet. Je les traçais chaque jour où je travaillais sur le projet avec mes amis. Ils sont une des grandes raisons pour lesquelles je n'ai pas abandonné. Dans la plupart (sinon dans tous les cas), ils représentent des objectifs quotidiens. Faites-les dans l'ordre, et vous obtiendrez une Infrastructure entièrement fonctionnelle.
Tâche 1
Objectif : Initialiser (Bootstrap) l'Infrastructure via Terraform
- Serveur unique chez DO/AWS/etc via local state
- Pare-feu/Groupe de Sécurité (Security Group)
- Enregistrements DNS chez Cloudflare/Route53, etc pour les futurs services (jenkins, etc)
Tâche 2
Objectif : Configurer le remote state pour l'Infra. S'assurer qu'Ansible peut y accéder et se déployer sur la ressource serveur.
- Configurer le remote state pour Terraform
- Configurer Terraform pour déployer un playbook Ansible factice (dummy)
2.1 Créer un playbook Ansible factice
2.2 Créer une paire de clés ssh pour l'accès au serveur
2.2 Configurer le compte utilisateur Ansible sur le serveur via le script cloud-init userdata. Le script userdata crée un compte utilisateur 'ansible', et configure une clé d'hôte connu (known-host key) (avec la clé publique générée à l'étape 2.2).
2.3 Utiliser notre clé privée pour exécuter le playbook factice sur le serveur via un local-provisioner Terraform.
Tâche 3
Objectif : Apprendre à déployer Docker Compose via Ansible. Apprendre les bases de Traefik.
- Créer un fichier docker-compose qui déploie une instance Jenkins temporaire sur l'url
jenkins.votre-domaine.comen utilisant un conteneur reverse-proxy Traefik. Déployer uniquement sur http. Pas encore besoin de persistance via des volumes Docker. - Déployer le fichier docker-compose via un rôle Ansible. Le déploiement via un rôle est obligatoire. N'oubliez pas de vous débarrasser du précédent déploiement factice maintenant, il n'est plus nécessaire.
Tâche 4
Objectif : Implémenter la sécurité de base du système.
- Configurer notre serveur pour qu'il utilise un port SSH différent.
- Désactiver la connexion SSH par mot de passe pour tous les Utilisateurs
- Désactiver la connexion SSH Root
- Modifier nos règles de pare-feu pour fermer le port 22 et ouvrir le nouveau port SSH.
- Configurer Ansible pour se connecter via le nouveau port ssh.
- Ajouter le https à notre déploiement Docker compose.
Tâche 5
Objectif : Configurer le monitoring du serveur hôte. Mettre à niveau l'environnement de charge de travail de nos conteneurs.
- Installer un Node Exporter Prometheus sur le serveur hôte via Ansible.
- Installer Prometheus et Grafana dans nos charges de travail de conteneurs.
- Créer un nouveau réseau Docker avec le pilote (driver) bridge, attribuer n'importe quelle adresse /24 privée comme sous-réseau. Attribuer toutes les charges de travail de conteneurs à ce réseau.
(Si vous le souhaitez, créez différents fichiers compose pour la stack de monitoring, et la stack de services. C'est d'ailleurs conseillé, car tous ces services sur un seul fichier compose auront l'air peut-être un peu désordonnés à la fin). - Créer des volumes Docker appropriés pour chaque service compose, et attribuer ces volumes aux services.
- Ajouter notre machine hôte en tant que cible (target) de métriques dans le service Prometheus, via Ansible.
- Configurer Grafana pour obtenir nos Métriques Prometheus.
- Ajouter un tableau de bord Grafana pour surveiller notre serveur hôte. Ceci, pour le moment, est juste pour s'assurer que la configuration fonctionne. Ce sera temporaire.
Tâche 6
Objectif : Implémenter des sauvegardes (backups).
- Écrire un script pour sauvegarder tous les volumes docker et les uploader dans un bucket distant.
1.1 Le script doit monter chaque volume dans un conteneur temporaire
1.2 Compresser (Tar et Gzip) son contenu. En gardant intactes toutes les informations de propriété des fichiers et répertoires.
1.3 Enregistrer l'archive dans un dossier 'backups'. Utiliser une convention de nommage de fichier 'nom-du-volume-timestamp.tar.gz'.
1.4 Quand tous les volumes sont archivés. Uploader tout ce qui se trouve dans le dossier 'backups' vers le bucket de stockage cloud que vous avez désigné pour les sauvegardes. - Utiliser une tâche cron (cron-job) pour faire tourner ce script de sauvegarde deux fois par jour, à n'importe quelles deux heures de votre choix, via Ansible.
Tâche 7
Objectif : Créer une politique de rétention des sauvegardes.
- Écrire un script pour supprimer toutes les sauvegardes plus anciennes qu'un nombre spécifié de jours. Le nombre de jours doit être un paramètre passé au script au moment de l'appel.
1.1 Par exemple, si le script est appelé avec un paramètre '5', il devrait supprimer toutes les sauvegardes qui ne sont pas dans le laps de temps des 5 derniers jours. Il ne devrait conserver que les 5 jours de sauvegardes récentes.
Optionnellement, vous pourriez choisir de toujours conserver les sauvegardes les plus récentes de chaque volume. - Via Ansible, créer un cron-job pour exécuter ce script de 'nettoyage' (cleanup) une fois par jour. Conserver 7 jours de sauvegardes récentes.
Tâche 8
Objectif : Mettre en place une Infrastructure de Journalisation (Logging).
- Modifier vos scripts de sauvegarde et de nettoyage pour logger les actions pertinentes sur stdout.
- Modifier vos cron-jobs de sauvegarde et de nettoyage pour diriger (pipe) toutes les sorties et erreurs, avec des balises (tags) pertinentes, vers le syslog.
- Déployer Promtail et Grafana Loki via Docker compose. Monter le répertoire '/var/log' en lecture seule (read-only) dans le conteneur Promtail.
- En utilisant Ansible, écrire un fichier de configuration Promtail pour récupérer (scrape) les logs du répertoire /var/log, et les envoyer au service Loki.
- Installer le plugin docker Loki sur le serveur hôte en utilisant Ansible. Configurer le démon (daemon) Docker pour utiliser Loki comme pilote (driver) de logs par défaut en modifiant le fichier /etc/docker/daemon.json de manière appropriée. N'oubliez pas de redémarrer le service Docker et de recréer tous les conteneurs après cette étape.
- Ajouter Loki comme source de données (data-source) dans Grafana. Confirmez que vous pouvez visualiser les logs du répertoire /var/log et de tous les conteneurs docker en cours d'exécution sur l'hôte via l'onglet 'Explore' de Grafana.
Tâche 9
Objectif : Achever le Déploiement des Services.
- Déployer Gitea via docker-compose
- Déployer Hashicorp Vault via docker-compose
- Déployer JFrog Container Registry OSS via docker-compose
- Déployer SonarQube via docker-compose
- Déployer cAdvisor pour surveiller l'utilisation des ressources de l'hôte par service de conteneur
- Exposer les métriques Prometheus à partir du service Traefik
- Créer des tableaux de bord Grafana pour Traefik, et cAdvisor
- Déployer tout autre service de votre choix !
Tâche 10
Objectif : Implémenter une politique de restauration des sauvegardes.
- Créer un script de restauration de sauvegardes qui s'exécute uniquement lorsque la valeur d'une variable 'restore' est égale à 'true'. Le script doit prendre le nom du bucket, la date de la sauvegarde spécifique à restaurer, et une valeur '1' ou '2' indiquant si c'est la première ou la deuxième sauvegarde de la journée qui doit être restaurée.
Tâche 11
Objectif : Privatiser l'accès à l'Infrastructure via le VPN WireGuard.
- Installer Wireguard sur le serveur Hôte via Ansible.
- Grâce à une combinaison d'étapes Ansible et Terraform, mettre en place et configurer une Interface Wireguard sur le serveur, générer un fichier de configuration approprié pour cette Interface, configurer l'Interface avec le fichier de configuration, puis générer des fichiers de configuration client appropriés pour une utilisation en se connectant à cette Interface.
- Configurer Traefik, via une liste blanche d'adresses IP (IP-Whitelist), pour autoriser le trafic vers tous les services uniquement sur les connexions initiées via le sous-réseau VPN de Wireguard.
Tâche 12
Objectif : Déployer et Configurer un VPS Agent Jenkins via Terraform et Ansible.
- En utilisant Terraform, déployer un serveur VPS supplémentaire de la taille de votre choix pour agir comme agent de build pour votre instance Jenkins.
- Configurer votre agent avec Ansible, en installant tout outil dont Jenkins aurait besoin, comme un package JDK, et Trivy pour le Scan d'Images de Conteneurs.
- En utilisant Ansible, installer Wireguard sur votre agent et le configurer comme un Peer (pair) dans votre VPN privé.
- (Optionnel) Si vous souhaitez pouvoir accéder à vos services dans Traefik en utilisant leurs FQDN (noms de domaine complets) depuis l'Agent, configurez des enregistrements DNS appropriés en utilisant Ansible sur l'Agent.
Conclusion
Et voilà ! Si vos compétences vous ont mené jusqu'ici 😉 Alors vous avez désormais une copie fonctionnelle de cette Infrastructure. Si vous avez aimé ce projet, n'oubliez pas de laisser un J'aime. Dites-moi également dans les commentaires ce que vous pensez du projet et comment vous pensez que j'aurais pu l'améliorer.
Lire la suite
Mise en œuvre du flux de travail central de Terraform en collaboration, via Github Pull Requests, Actions, Bot, Environments et un Backend Distant.
Mettez en œuvre un flux de travail Terraform collaboratif à l'aide de GitHub Actions, de pull requests et d'un backend distant pour les équipes de production.
Déployer un serveur sur Digital Ocean via Terraform (Tutoriel)
Un guide étape par étape pour approvisionner un droplet DigitalOcean à l'aide de Terraform et des pratiques de base de l'Infrastructure as Code.
Déploiement automatique de Jenkins sur un serveur distant (avec SSL gratuit) via Ansible (Tutoriel)
Apprenez à déployer automatiquement un serveur Jenkins auto-hébergé avec des certificats SSL gratuits à renouvellement automatique à l'aide d'Ansible.
