Ce syllabus est l’unique support de ce cours. Il contient la théorie à connaître pour la partie théorique de l’examen. Il contient également des explications et commandes pour les exercices des séances pratiques. Il vous permettra donc de vous aider à résoudre les exercices proposés durant les séances théoriques et pratiques. L’objectif est donc principalement la compréhension.
Conventions du syllabus :
Vous disposez d’un bouton pour copier/coller les commandes. Ceci peut s’avérer extrêmement utile pour réaliser les exercices. En se connectant en SSH, vous profiterez de l’avantage de ce copier/coller.
Vous constituerez vos propres fiches/notes papiers tout au long du cours. Vous pourrez utiliser ces notes papiers durant la partie pratique de l’examen.
Les séances théoriques mixeront des présentations théoriques, des exercices papiers, des préparations/exercices pour les séances pratiques ainsi que des QCM Wooclap. Il y aura des (petits) chapitres à lire dans le syllabus pour cette partie.
Les séances pratiques consisteront en des exercices sur machine. Les exercices renverront également vers ce syllabus.
L’évaluation de cette UE est composée de :
L’examen est intégré (partie théorique et pratique) au travers d’un examen de 3h durant les sessions de janvier et septembre.
Cet examen comporte une partie théorique d’une durée maximum d’une 1h. Cette partie consistera en des questions de connaissance.
Les éléments en rouge dans ce syllabus, les questions Wooclap présentées durant le cours théorique ainsi que les exercices papiers constituent la matière pour cette partie d’examen.
Pour cette partie, l’objectif est de pouvoir expliquer un concept ou élément présent dans ce syllabus ainsi que son rôle. Les exercices papiers vous aideront à étayer vos explications.
Exemple de question :
Quel est le rôle et l’utilité d’ARP ?
Cet examen comporte également une partie pratique d’une durée maximum de 2h. Cette partie se déroulera sur machine et se composera d’exercices similaires à ceux vus durant les séances pratiques. Pour cette partie, vous pouvez disposer de vos propres notes/supports et également d’Internet.
L’infrastructure d’une entreprise nécessitera le déploiement d’un réseau afin de faire communiquer les ordinateurs de l’entreprise entre eux. Typiquement, les PC des employés devront communiquer avec différents serveurs (authentification, partage fichiers …) déployés par l’entreprise. Pour déployer un réseau d’entreprise, aussi appelé LAN, l’administrateur réseau devra implémenter les 3 premières couches du modèle OSI. Il devra également déployer des services réseaux tel que le DNS, le DHCP…
Voici un exemple de réseau d’entreprise (très fortement inspiré de l’IPL). Vous retrouverez dans ce schéma tous les composants nécessaires à un réseau d’entreprise aussi appelé LAN. Certains sont sans doute déjà connu pour vous (IP, DNS…), d’autres non (VLAN, STP…). Les 2 premiers chapitres de ce syllabus vont les détailler et surtout expliquer leur rôle dans ce schéma.
Voici également une capture réseau réalisé avec le logiciel open source Wireshark. Celui-ci vous permet de mieux comprendre ce qui se passe dans un réseau par exemple lorsque vous faites une requête HTTP. Attention les écoutes réseau sont encadrées par des textes de lois. Faire des écoutes réseau sans l’accord de l’entreprise ou les personnes concernées est un délit.
Cette capture réseau a été réalisée chez moi (petit réseau de particulier). J’ai simplement effectué une requête HTTP via un navigateur vers le site http://ochoquet.be/syllabusHTML. Le logiciel Wireshark propose 3 fenêtres. La première en haut avec toute la capture réseau, la deuxième en dessous où pour chaque ligne de la capture vous allez retrouver le détail par couche du modèle OSI et enfin les données brutes.
Que remarque-t-on dans cette capture ?
Je rappelle également le principe d’encapsulation des couches du modèle OSI. Ici la requête HTTP va être encapsulée dans de segments TCP, eux-mêmes encapsulés dans des paquets IP, eux-mêmes encapsulés dans des trames (couche 2).
Image issue de http://openclassroom.com
Au niveau de la couche matérielle, différentes solutions existent pour implémenter son réseau physique. Cependant, une implémentation s’impose : l’utilisation d’un réseau avec une topologie en étoile et des câbles Ethernet. Ce réseau peut être renforcé avec de la fibre optique pour les liaisons les plus sollicitées. Un réseau sans fil accompagne la plupart du temps également cette architecture.
La couche 2 est généralement implémentée dans une infrastructure par une série de switchs (commutateur en français) qui concentrent les câbles Ethernet. Ces switchs, aussi appelés concentrateur, disposent d’un grand nombre de ports (24,48…) afin d’y connecter plusieurs machines. Au niveau de la couche 2, on parle de frames (trame en français). Celles-ci permettent à des PC présents sur le même sous-réseau de dialoguer. L’identifiant d’une machine est la MAC address. Une trame sera donc composée d’une MAC address source, d’une MAC address destination et du message. Le composant principal de cette couche (switch) conserve une table des MAC address permettant d’associer chaque port du switch à une MAC address. Cette table se met à jour continuellement en fonction de l’activité réseau. Si une machine ne communique plus pendant un laps de temps, sa MAC address est retirée de la table. Cette table permet au switch d’aiguiller les trames directement vers la machine de destination. Si le switch n’a pas connaissance dans sa table de la MAC address de destination, la trame est envoyée sur tous les ports.
Les VLAN (Virtual Local Area Network) permettent de séparer certains ports d’un switch par rapport à d’autres. Chaque switch disposera alors d’une table des MAC address par VLAN. L’intérêt des VLAN est de pouvoir utiliser un switch pour connecter des machines appartenant à des réseaux différents toute en garantissant la sécurité. Les ports se verront attribués un numéro de VLAN et les ports ayant un même numéro de VLAN pourront uniquement communiquer entre eux.
Exemple : Imaginons une entreprise avec des employés et une direction. Nous décidons de créer un sous-réseau pour chacune des populations. Sans la technique des VLAN, je devrai utiliser 2 switchs (un switch pour les machines “direction” et un autre switch pour les machines “employés”) tandis qu’avec les VLAN je pourrai utiliser un seul switch.
L’intérêt des VLAN est multiple :
L’architecture en étoile a un point faible. Le switch, au cœur de cette étoile, peut tomber en panne et dès lors toutes les machines connectées à celui-ci deviennent inaccessibles. Mais il y a plus grave, imaginer que le switch “Stud” tombe en panne dans la figure STP. Les machines des salles 1 et 2 ne peuvent plus communiquer entre elles. Pour éviter cela, on ajoutera un câble (redondance) entre les switchs de la salle 1 et 2. Le problème est que vous allez créer une boucle dans le réseau et ceci n’est pas permis. C’est ici qu’intervient le protocole STP (Spanning Tree Protocol), il va autoriser à créer des boucles en désactivant logiquement certains liens et en les réactivant en cas de panne.
La couche réseau est implémentée dans une infrastructure par des routeurs. Ceux-ci feront transiter des paquets IP d’un réseau à un autre. L’identifiant d’une machine pour cette couche est une adresse IP. Une adresse IP est composée d’une adresse réseau et d’un masque. Le masque d’une adresse IP est noté soit sous le format A.B.C.D (Ex: 255.255.0.0) ou sous le format CIDR (Ex : /16). Actuellement l’adressage IP version 4 (IPv4) est encore largement utilisé même si l’adressage IPv6 commence à faire son apparition.
Une adresse IPv4 étant codée sur 32 bits, nous sommes limités à 4 milliards d’adresses IP pour la terre entière, ce qui est insuffisant pour couvrir tous les besoins actuels. Cette limitation impose l’utilisation d’astuces (IP privée/IP publique notamment) pour contenter tout le monde. Une adresse IPv6 est codée sur 128 bits ce qui permet d’avoir une réserve d’adresses IP suffisante. Exemple Adresse IPv6 : 8000:0000:0000:0000:0123:4567:89AB:CDEF ou 8000::123:4567:89AB:CDEF (suppression des 0 inutiles). Dans la suite de ce document, on s’intéressera à l’adresse IPv4 uniquement.
Certaines adresses IP sont particulières. Vous connaissez peut-être déjà l’adresse 127.0.0.1 qui souvent utilisé pour la boucle locale (localhost). Il existe en fait des plages d’adresse réservées pour certains usages.
Plage | Usage |
---|---|
127.0.0.0/8 | Boucle locale |
10.0.0.0/8 | Adresses privées |
172.16.0.0/12 | Adresses privées |
192.168.0.0/16 | Adresses privées |
224.0.0.0/4 | Multicast |
Tableau à connaître
La boucle locale permet de créer un mini-réseau sur la machine permettant à l’utilisateur de tester/utiliser un service réseau sans être connecté (à un véritable réseau). Ceci permet notamment à un développeur d’utiliser un serveur Web sur sa machine de développement en l’absence de connexion réseau. Les adresses privées sont réservées pour être utilisées dans les réseaux d’entreprises (LAN) et ne sont pas routables sur Internet (Voir NAT). Vous devez utiliser ces adresses lorsque vous créez votre réseau d’entreprise. Les adresses multicast sont utilisées pour l’envoi de paquet en multicast (voir mode d’envoi ci-dessous).
Linux | Windows | Explication |
---|---|---|
ifconfig OU ip addr | ipconfig | Configuration / Consultation des informations IP d’une machine |
route | route | Configuration / Consultation des informations de routage d’une machine |
ping | ping | Tester la connectivité IP d’une machine |
traceroute | tracert | Voir le chemin parcouru par un paquet IP |
Tableau à connaître
Lors de l’envoi d’un message, les couches du modèle OSI vont être traversées. Dès qu’un paquet IP est arrivé au sous-réseau de destination, la couche réseau(3) passe la main à la liaison des données(2). Celle-ci, pour envoyer la trame à la machine de destination, a besoin de connaître la MAC address de la machine de destination. Or elle ne connaît ici que l’adresse IP. Le protocole ARP (Address Resolution Protocol) a été mis en place pour résoudre ce problème. Il permet à une machine de demander l’adresse MAC d’une autre machine sur base de son adresse IP. Une machine peut dès lors envoyer une requête ARP sur son sous-réseau avec la question suivante: “Quelle est la MAC address de la machine dont l’IP est … ?“. La machine possédant l’IP en question répondra directement à la machine ayant posé la question. Une requête ARP sera envoyée via l’adresse broadcast et la réponse sera en unicast. À noter que chaque machine dispose d’un cache ARP. Il s’agit d’une mémoire de toutes les requêtes ARP ayant déjà été faites. Ces requêtes ne sont conservées dans le cache ARP que pendant un certain temps. L’utilité de ce cache est d’éviter d’effectuer trop de requêtes ARP (qui sont en broadcast).
D’un point de vue sécurité, le protocole ARP est sensible aux attaques de type ARP cache poisoning/spoofing. Il s’agit pour l’attaquant de répondre à toutes les requêtes ARP en vue de détourner le trafic du sous-réseau vers sa propre machine et d’effectuer des écoutes.
Vous devez être capable de découper un réseau en sous-réseaux. Ceci peut être demandé dans la partie pratique de l’examen. La tâche d’un administrateur système sera de découper de manière intelligente son réseau. Ce découpage permet d’isoler les réseaux pour des raisons de sécurité et d’efficacité. Il devra calculer une adresse réseau et un masque de sous-réseau. Celui-ci permettra de donner le nombre maximal de machines que le sous-réseau pourra accueillir.
Exemple : un réseau “employés” composé de 25 machines
1. 25 machines → recherche de la puissance de 2 supérieure à 25 → 2⁵ = 32
2. Choix d’une adresse réseau parmi les plages d’adresses privées : 192.168.5.0 par ex.
3. Calcul du masque : 32 bits – 5 bits (puissance de 2 calculée précédemment) = 27 bits → /27 (255.255.255.224)
4. Résultat : 192.168.5.0/27
Une plage d’adresses pour un réseau débutera par l’adresse du réseau et se terminera par l’adresse de diffusion (broadcast). Entre ces 2 adresses, les autres adresses peuvent être utilisées par des machines.
Exemple : un réseau employés composé de 25 machines
1. Adresse réseau : 192.168.5.0/27
2. Adresse machine 1 : 192.168.5.1/27
3. Adresse machine 2 : 192.168.5.2/27
4. Adresse machine … : …
5. Adresse broadcast : 192.168.5.31/27
L’adresse de diffusion (broadcast) est la dernière adresse de la plage calculée. Tous les bits machines de cette adresse sont donc à 1.
Dans notre exemple: adresse réseau = 192.168.5.0/27 → 192.168.5.00011111 → 192.168.5.31/27
Astuce : une adresse réseau est toujours paire et une adresse de diffusion (broadcast) toujours impaire !
Le composant principal de cette couche 3, le routeur, maintient une table de routage. Vous pouvez imaginer un routeur comme étant un carrefour routier et une table de routage comme étant les panneaux indicateurs présents au carrefour. Une table de routage est un tableau qui précise pour une destination d’un sous-réseau (adresse réseau + masque) une passerelle (adresse IP d’une machine/routeur).
Un exemple ci-dessous :
Pour chaque destination, la table de routage indique une passerelle et une métrique. À noter que les destinations sont indiquées par réseau (adresse IP + masque). Les entrées de cette table peuvent être ajoutées à la main ou de manière automatique. On parle dans le premier cas de routage statique et dans le second cas de routage dynamique. Quelques exemples de protocoles de routage dynamique : RIP, OSPF (utilisant l’algorithme de Dijkstra).
Vu qu’il est impossible pour chaque machine de constituer une table de routage avec tous les chemins possibles, chaque machine possédera une passerelle par défaut (0.0.0.0/.0.0.0.0). Celle-ci sera utilisée lorsqu’aucune règle plus précise ne pourra être utilisée dans la table de routage. Grâce à cette passerelle par défaut, il est également plus simple d’automatiser la connexion de machines clientes à son réseau. En effet, il suffira de fournir à chaque machine cliente une adresse IP, un masque et une passerelle par défaut et celle-ci pourra utiliser notre réseau. Cette automatisation pourra se faire via un serveur DHCP (Voir DHCP).
Une machine a toujours accès au(x) réseau(x) auquel(s) elle est connectée directement. En définissant une adresse IP sur une machine, vous connectez directement cette machine à un sous-réseau. Il n’y a pas besoin de règle de routage supplémentaire pour que cette machine communique avec toutes les autres machines du sous-réseau. Par contre, si la machine essaie de joindre une machine ne se trouvant pas dans le même sous-réseau, celle-ci devra contacter sa passerelle par défaut (souvent un routeur) qui contient une table de routage permettant de transférer les paquets jusqu’à destination.
Dans le cas ci-dessus, h1 et h2 pourront communiquer ensemble simplement en leur définissant une adresse IP.
Pour que h1 et h3 discutent, il faut au minimum :
1. une passerelle par défaut (r1) sur h1
2. une passerelle par défaut (r1) sur h3
Pour que h1 et h4 discutent, il faut au minimum :
1. une passerelle par défaut (r1) sur h1
2. une passerelle par défaut (r2) sur h4
3. une règle de routage sur r1 : pour atteindre le réseau C → passer par r2
4. une règle de routage sur r2 : pour atteindre le réseau A → passer par r1
La couche 4 (Transport) va permettre une communication entre applications. Les applications respecteront le modèle d’architecture client-serveur. Cette couche 4 utilise la notion de port. Une application sera donc identifiée via son port. Typiquement, une application de type serveur se mettra en écoute sur un port tandis qu’une application cliente se connectera à ce serveur en précisant son adresse IP et port. Des ports par défaut ont été définis pour les applications les plus courantes :
Application | Port réservé |
---|---|
Web (HTTP) | 80 |
SSH | 22 |
HTTPS | 443 |
DNS | 53 |
Tableau à connaître
Chaque machine dispose de 65536 ports. Pour ses besoins personnels, on utilisera les ports au-dessus de 1024 qui ne sont pas réservés. Une politique de sécurité de base pour les administrateurs système est donc de bloquer sur le serveur tous les ports hormis ceux des applications utilisées.
Deux protocoles existent au niveau de la couche 4 : TCP et UDP le premier est un transport jugé fiable car chaque envoi est acquitté (confirmation que l’envoi a été bien reçu). Par contre, UDP se veut plus simple et ne demande aucune confirmation que l’envoi a été correctement reçu.
Pour qu’un réseau d’entreprise fonctionne correctement, il est nécessaire d’avoir au minimum 3 services à savoir :
Un administrateur système doit donc veiller à ce que son réseau mette ces 3 services à disposition de ses client.
Pour rappel, le système DNS permet de traduire un nom de domaine en une adresse IP et inversement. Ce système a été longuement décrit dans le cours d’IPP, nous ne détaillerons donc pas son fonctionnement ici. Par contre, nous allons nous attarder à l’usage d’un serveur DNS dans un réseau d’entreprise.
Pour traduire les noms de domaine Internet, il n’est pas obligatoire d’avoir son propre serveur DNS. On peut très bien utiliser le serveur DNS de son ISP (Internet Service Provider) ou encore le très célèbre DNS de Google (8.8.8.8). Dès lors, pourquoi est-il nécessaire pour un administrateur système d’installer un serveur DNS ? La raison est la suivante : dans un réseau d’entreprise, les machines clientes porteront des noms et ces noms devront être traduits en une adresse IP.
Une autre raison d’avoir un serveur DNS est la gestion du nom de domaine de l’entreprise. Dans ce cas, l’installation d’un serveur DNS n’est pas obligatoire. On peut très bien utiliser un serveur DNS fourni par son fournisseur de nom de domaine. En tout cas, l’administrateur système de l’entreprise devra gérer les enregistrements DNS de l’entreprise notamment les enregistrements DNS pointant vers les serveurs de l’entreprise et qui devront être accessibles depuis l’extérieur.
Un administrateur système installera généralement 2 serveurs DNS. Cette redondance permettra de gérer plus facilement la défaillance d’un serveur.
Un serveur DNS gère les enregistrements pour un nom de domaine aussi appelé zone DNS. Une zone DNS contient différents types d’enregistrements :
Exemple d’une configuration d’un serveur DNS sous Linux :
$TTL 604800
@ IN SOA ns.monbeaurezo.be. emailadmin.monbeaurezo.be. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
@ IN NS ns.monbeaurezo.be.
@ IN A 127.0.0.1
@ IN AAAA ::1
ns IN A 192.168.1.1
h1 IN A 192.168.1.5
aliasH1 IN CNAME h1
Il est très important de ne pas oublier que toute résolution de noms sur une machine commence par l’inspection du fichier hosts. Ce fichier est présent sous Linux à cet endroit /etc/hosts et sous Windows à cet endroit c:\Windows\System32\Drivers\etc\hosts.
Exemple de fichier hosts sous Windows :
Les administrateurs système utilisent abondamment ce fichier pour tester des services car cela évite l’installation d’un serveur DNS. En production, un serveur DNS sera bien évidemment employé.
Sur une machine Linux, les serveurs DNS sont enregistrés dans le fichier /etc/resolv.conf. Sous Windows les serveurs DNS sont renseignés dans les propriétés des paramètres IP.
Sous Windows comme sous Linux, on peut tester les réponses des serveurs DNS avec la commande nslookup.
Pour qu’une machine cliente puisse se connecter à un réseau et surfer sur Internet, cette machine a besoin au minimum des informations suivantes :
Un serveur DHCP permettra de répondre à ces besoins de manière automatique. Le protocole DHCP fonctionne comme ceci :
Les informations reçues en provenance du serveur DHCP ne seront valables qu’un certain temps. On parle de bail. Le client pourra évidemment renouveler son bail.
La requête DHCP_DISCOVER se fait en broadcast. Les broadcast ne passent pas les routeurs. Donc un serveur DHCP devra être présent dans chaque sous-réseau ou celui-ci devra avoir une interface réseau dans chaque sous-réseau.
Un administrateur système installera plusieurs serveurs DHCP pour se prémunir de la panne d’un serveur. Deux serveurs DHCP ne pouvant pas distribuer les mêmes adresses IP, l’administrateur système devra répartir ces adresses de manière intelligente entre les 2 serveurs.
Il est également possible de configurer les serveurs DHCP en failover pour se prémunir des pannes. Dans ce cas, les 2 serveurs se partagent la même étendue et ils peuvent travailler en ACTIF/PASSIF ou en ACTIF/ACTIF. Le mode ACTIF/PASSIF indique simplement qu’un serveur DHCP est le maître et l’autre l’esclave. C’est donc le serveur maître qui répond à toutes les demandes. Si celui-ci tombe en panne, l’esclave prend le relais. Le mode ACTIF/ACTIF indique que les 2 serveurs travaillent sur un même pied d’égalité. Ils distribuent donc tous les 2 des adresses IP et ceci sur la même étendue. Cela permet donc un équilibrage de charge. À noter que ces modes ACTIF/PASSIF ou ACTIF/ACTIF, nécessite une communication entre les serveurs DHCP et ne fonctionne donc correctement qu’avec des serveurs DHCP similaires (non hétérogènes).
Exemple de configuration d’un serveur DHCP sous Linux :
# fichier /etc/dhcp3/dhcpd.conf
# distribution d'adresses IP 10.0.0.0/8
subnet 10.0.0.0 netmask 255.0.0.0 {
# restriction de la distribution au range défini
range 10.0.0.10 10.0.0.250 ;
# envoi de la passerelle par défaut (gateway)
option routers 10.0.0.1 ;
# envoi serveur DNS
option domain-name-servers 10.0.0.1 ;
}
Le NAT est utilisé abondamment par les réseaux d’entreprise pour traduire les adresses IP privées de clients en adresses publiques routables sur Internet. Pour rappel, les adresses IPv4 sont limitées à 4 milliards ce qui ne permet pas de couvrir la totalité du globe terrestre. Donc certaines plages d’adresses ont été réservées (adresses privées) pour pouvoir être attribuées dans les réseaux locaux des entreprises. Ceci est très bien, mais pour aller sur Internet, j’ai besoin d’une adresse publique, autrement dit d’une adresse routable sur Internet. C’est ici qu’intervient le NAT. Vous allez comprendre comment la terre entière peut surfer sur Internet avec seulement 4 milliards d’adresses disponibles.
Dans ce cas, l’adresse IP source du paquet IP est traduite, “natée”.
Chaque machine cliente sera connectée au réseau de l’entreprise via une adresse privée et recevra une passerelle par défaut qui sera généralement le routeur qui vous permettra d’aller sur Internet. Ce routeur disposera d’une adresse IP publique reçue par votre fournisseur d’accès à Internet et il disposera également d’une adresse privée dans le réseau de l’entreprise. Nous activerons le NAT sur le routeur ce qui aura pour effet de traduire l’adresse IP source de tout paquet IP sortant sur Internet par l’adresse IP publique du routeur.
Dans cet exemple, les machines H1 et H2 surferont sur Internet grâce à l’adresse IP publique du routeur BBOX. Il reste un petit point à éclaircir : une fois la réponse reçue à une requête envoyée sur Internet, comment le routeur va-t-il savoir que cette réponse est pour la machine H1, H2, … ?
Le routeur va en fait identifier les machines clientes via un port choisi aléatoirement.
Exemple (requête HTTP) :
Avant NAT | Après NAT |
---|---|
IP Source : 192.168.1.2 | IP Source : 87.87.87.1 (adresse du routeur) |
IP Destination : 89.89.89.1 | IP Destination : 89.89.89.1 |
Port Source : / | Port Source : 10527 (port aléatoire, le routeur note l’association de ce port à la machine natée à savoir 192.168.1.2) |
Port Destination : 80 | Port Destination : 80 |
Lors de la réception de la réponse, le routeur pourra alors savoir en regardant le port la machine à qui est destiné le paquet.
Le NAT introduit une isolation du réseau de l’entreprise. En effet, il est impossible d’atteindre une machine du réseau de l’entreprise depuis l’extérieur. La seule machine que l’on sait atteindre est le routeur. Ceci est intéressant en termes de sécurité, mais nous devons quelquefois avoir accès à un serveur présent dans le réseau de l’entreprise. Pour ce faire, nous pouvons configurer le NAT pour qu’il fasse du port forwarding.
Le principe est le suivant : pour accéder à un serveur de l’entreprise, on attribue un port sur le routeur dédié à ce serveur. Dès que le routeur reçoit une connexion de l’extérieur sur ce port, il transfère les paquets vers l’adresse privée du serveur.
Le port forwarding est utilisé abondamment dans les réseaux surtout depuis la virtualisation. Par exemple, VirtualBox définit par défaut un réseau NAT entre la machine hôte et la machine virtuelle invitée. Si vous installez un serveur dans la machine virtuelle invitée et que vous voulez y accéder depuis l’extérieur (votre machine hôte ici), vous devrez faire du port forwarding. Ceci n’est pas compliqué, il suffit de faire une association entre un port de la machine hôte et un port la machine virtuelle.
Exemple dans VBOX :
Dans cet exemple, nous relions le port hôte 2222 au port invité 22. Cela signifie que si vous vous connectez sur le port 2222 de votre machine hôte, vous allez être redirigé vers le port 22 de la machine virtuelle invitée. Autrement dit, si vous faites un Putty sur le port 2222 depuis votre machine hôte, vous vous connecterez en SSH (22 == SSH) sur votre machine virtuelle. Bien sûr il faut avoir installé SSH sur votre machine virtuelle au préalable.
• SNAT (source NAT)
◦ Usage le + fréquent : LAN → WAN
• DNAT (destination NAT → port forwarding)
◦ Usage le + fréquent : WAN → DMZ, LAN
Le travail d’un administrateur système consistera en l’installation de différents serveurs en vue de satisfaire les différents besoins des utilisateurs. Nous verrons surtout ici comment installer et configurer un serveur Linux (Distribution Debian) en vue d’y installer des services par après. L’installation d’un serveur Windows reste relativement simple. Celle-ci sera donc vue brièvement.
Contrairement aux environnements propriétaires (Windows), le fait que le noyau Linux soit libre a parmi à différentes communautés de proposer sa version de Linux. On parle de distribution Linux. On distingue différents types de distributions :
Type | Définition | Exemple |
---|---|---|
Communautaire | Maintenance et évolution du système assuré par une communauté sans lien avec une entreprise | Debian |
Commerciale | Maintenance et évolution du système assuré par une entreprise | Ubuntu, Red Hat |
Généraliste | Distribution multi-usage | Ubuntu, Debian |
Spécialisée | Distribution à usage précis | Gparted, Raspbian |
Dérivée | Distribution ayant comme base une autre distribution | Ubuntu |
Chaque distribution peut évidemment cumuler différents types. L’ administrateur système choisira une distribution suivant différents critères :
1. L'usage (type ci-dessus)
2. La stabilité
3. La documentation disponible / le support
4. Besoin d'une interface graphique ou pas
5. La licence (voir ci-dessous)
Faisons un petit point autour des licences. Ceci est aussi bien utile pour les développeurs que pour les administrateurs système. Il existe une variété impressionnante de licences, nous allons ici simplement nommer et expliquer brièvement les plus importantes.
Le logiciel libre se définit comme un logiciel qui peut être étudié, modifié et diffusé. Cela garantit donc l’accès au code source du programme et par cette occasion de vérifier la transparence et la sécurité du programme. Le logiciel libre a été initié par Richard Stallman qui créa en 1985 la FSF (Free Software Foundation). À partir de ce moment, de nombreux développeurs ont distribué leurs logiciels sous licence GPL (GNU Public Licence).
Cette licence se caractérise par 4 libertés à respecter :
La dernière liberté est la plus contraignante, car elle nécessite qu’un logiciel utilisant une licence GPL doive être distribué sous licence GPL. C’est pourquoi d’autres licences ont vu le jour pour mieux s’adapter aux réalités des entreprises.
La licence LGPL (Lesser GNU Public Licence) reprend les fondements de la licence GPL en supprimant la restriction sur l’hérédité de la licence GPL. Cette licence permet également la cohabitation de plusieurs licences (libres et propriétaires) au sein d’un logiciel. Il s’agit pour ces raisons de la licence préférée des développeurs de librairies.
La licence BSD (Berkeley System Distribution) reprend les fondements de la licence GPL en supprimant la restriction sur l’hérédité de la licence, la restriction sur la redistribution des copies. Cette licence permet également la cohabitation de plusieurs licences (libres et propriétaires) au sein d’un logiciel.
La licence MIT (Massachusetts Institute of Technology) permet de copier, modifier, redistribuer un logiciel, mais en incluant les copyrights des auteurs. Microsoft utilise cette licence dans certains de ses produits.
Gratuit ne veut pas dire libre ! La gratuité implique
simplement que l’on ne paye pas pour un produit.
Open source ne veut pas dire libre ! L’Open source implique simplement
que nous avons la possibilité d’avoir accès au code source.
La notion de logiciel libre fait référence aux 4 libertés citées
ci-dessus.
Il est important pour un serveur d’éviter toute panne de disque dur qui pourrait rendre le serveur indisponible.
Le RAID (Redundant Arrays of Inexpensive Disks) est un mécanisme de redondance de disques. Celui-ci a plusieurs objectifs combinables à savoir se prémunir contre la panne d’un disque et améliorer les performances en écriture sur les disques.
Le RAID peut s’effectuer directement par le système d’exploitation, on parle alors de RAID logiciel. Le RAID peut également être effectué par un composant physique (contrôleur RAID) à part entière, on parle alors de RAID matériel. Le RAID logiciel a l’avantage d’être moins coûteux tandis que le RAID matériel présente l’avantage du remplacement de disque à chaud (c’est-à-dire sans devoir arrêter le serveur). Il existe différents niveaux de RAID. Voici les plus importants :
Niveau | Explication | Avantages | Inconvénients |
---|---|---|---|
RAID 0 | Les données sont écrites en parallèle sur plusieurs disques | Gain en performance | Perte d’un disque == perte des données |
RAID 1 | Les données sont écrites sur des disque en miroir | Tolérance aux pannes disques | Coût -> disque en double |
RAID 5 | Les données sont écrites en parallèle sur au minimum 3 disques (2 disques de données + 1 disque de parité) | Tolérance aux pannes disques + performance | Minimum de 3 disques requis |
Tableau à connaître
Le RAID 5 s’appuie sur l’opérateur logique XOR. La parité de chaque écriture est calculée via cet opérateur. En cas de perte d’un disque, l’information peut être reconstituée à partir des 2 autres disques toujours via cet opérateur XOR.
Le partitionnement désigne l’opération de diviser un disque en partitions. Un partitionnement bien réfléchi facilitera la maintenance des serveurs. Une partition système et une partition “données utilisateur” faciliteront par exemple la mise en place de sauvegardes.
À l’installation, l’administrateur système devra réaliser un partitionnement. Cependant il est parfois difficile d’imaginer comment vont évoluer les données (la taille et la quantité des données) au cours du temps. Afin de répondre à ce problème, les systèmes d’exploitation proposent une gestion dynamique des partitions. Ces partitions pourront grandir par l’ajout de nouveaux disques.
LVM (Logical Volume Manager) est une solution permettant une gestion dynamique du partitionnement disponible sous Linux. Les partitions peuvent ainsi s’étendre sur plusieurs disques. LVM demande de créer des groupes de volumes physiques (VG). On peut facilement ajouter de nouveaux disques à ces groupes, ce qui peut faciliter l’agrandissement de partitions logiques (Logical Volume) . Voir ci-dessous.
Lors du choix du partitionnement, il sera nécessaire de préciser le système de fichiers de chaque partition. Voici les principaux :
Sous Linux, le montage des partitions est documenté/configuré dans le fichier /etc/fstab. Voir ci-dessous.
Les disques sont nommés sous Linux suivant le contrôleur physique qui les gère.
Ensuite vient un d pour disk suivi d’une lettre incrémentée automatiquement suivant le nombre de disques.
Il s’ensuit un chiffre également incrémenté qui représente le numéro de la partition.
Chaque ligne du fstab indique donc une partition, son point de montage, le système de fichiers utilisé, les options, si une sauvegarde doit être faite avec l’utilitaire dump (peu utilisé), l’ordre de vérification des disques lors d’une demande de vérification (fsck).
À noter qu’à la place d’une partition pour le premier point, on retrouve maintenant un UUID (un identifiant unique de partition) ou un label. L’avantage de ces 2 nouvelles méthodes est d’être moins sensible à un changement de disque. Un disque gardera toujours son label ou UUID et ceci peut donc être utilisé dans des scripts en toute sûreté.
Une partition non chiffrée peut être lue facilement sans autorisations particulières via un live-cd si on a un accès physique à une machine. Si on veut protéger ses données, il est donc nécessaire de crypter ses partitions pour éviter toute fuite de données. Ceci est particulièrement vrai pour les portables d’entreprises. Imaginez que le PDG d’une entreprise se fasse voler son portable dans le train, les voleurs pourront récupérer toutes les données du portable si les partitions ne sont pas cryptées.
Linux propose LUKS (Linux Unified Key Setup) qui permet un chiffrement des partitions (à l’installation ou plus tard). Windows propose, quant à lui, BitLocker pour crypter ses partitions.
Lors du démarrage d’une machine, un chargeur d’amorçage (bootloader) est lancé. Celui-ci s’occupera de lancer le système d’exploitation ou de présenter les différents systèmes d’exploitation dans le cas d’un multi-boot. Windows propose winload comme chargeur d’amorçage tandis que Linux propose essentiellement GRUB (GRand Unified Bootloader).
L’installation d’un serveur Windows est assez simple. C’est l’ajout de service, appelé rôle sous Windows, qui reste plus complexe. Les rôles permettent d’installer un Active Directory, un serveur DNS, DHCP, … .
Pour l’installation, Windows propose différents types d’installation :
Un aspect important sous Windows est la gestion des licences. Les licences serveur doivent être comptabilisées suivant le nombre de cœurs physiques du processeur. Il faut également comptabiliser les licences d’accès client (CAL).
Windows propose également différentes options pour l’installation d’un serveur.
Après l’installation d’un Windows, il est utile de changer son nom et d’ajouter la machine à un groupe de travail (workgroup) ou domaine. Les groupes de travail et les domaines permettent de regrouper un ensemble de machines dans le but de centraliser la sécurité, les accès. Les groupes de travail sont destinés à des petites structures tandis que les domaines visent des structures plus grandes. Les domaines seront gérés par un Active Directory (Voir Active Directory) .
Toutes les distributions Linux disposent d’un système de gestion des packages permettant l’installation facile de logiciels et services. Ce système de gestion de packages résout en outre les problèmes de dépendances. Sous Debian ce programme est APT. Nous ne donnerons ici qu’un résumé du fonctionnement de l’outil APT. Différents dépôts contenant des paquets Debian (.deb), c’est-à-dire des logiciels prêts à être installés, sont disponibles sur Internet. L’outil APT dispose d’un fichier de configuration (/etc/apt/sources.list) permettant de renseigner les dépôts à utiliser. Il suffit ensuite de mettre à jour depuis les dépôts (mise à jour du cache local) et de demander l’installation du logiciel à APT. L’outil installera automatiquement les dépendances nécessaires pour le logiciel demandé.
/etc/apt/sources.list
Mise à jour du dépôt local :
apt-get update
Mise à jour des logiciels installés :
apt-get upgrade
Installer un logiciel :
apt-get install <paquet1> <paquet2> ...
Supprimer un logiciel :
apt-get remove <paquet1> <paquet2> ...
Rechercher un logiciel/paquet :
apt-cache search <word>
Les systèmes Linux actuels sont le plus souvent gérés en ligne de commande (pas d’interface graphique) et à distance. Pour ce faire, on utilisait telnet mais ce protocole a le gros inconvénient de ne rien crypter. Une simple écoute réseau permet alors de récupérer le mot de passe root. C’est pour cette raison que SSH est venu remplacer telnet.
Nous ne donnerons ici qu’un résumé du fonctionnement du protocole SSH (Secure Socket Shell). Le protocole SSH effectue un échange de clés de chiffrement avant d’utiliser ces dernières pour crypter toutes les communications entre le client et le serveur. Le port 22 est le port par défaut utilisé par SSH.
SSH est un service qui est initialisé/démarré par systemd.
apt-get install ssh
Le fichier de configuration client est : /etc/ssh/ssh_config
Le fichier de configuration serveur est : /etc/ssh/sshd_config
Par défaut, SSH est installé pour permettre une authentification par login et mot de passe pour tous les utilisateurs présents sur le serveur (hormis root) ainsi que par clé (root compris).
Nous nous contenterons de ce comportement par défaut pour ce cours.
Si vous souhaitez changer ce comportement par défaut, il faut modifier les 2 fichiers de configuration et redémarrer le service pour que les modifications soient prises en compte.
Par défaut, l’option « PermitRootLogin » dans /etc/ssh/sshd_config est positionnée à «prohibit-password» ce qui indique que les connexions avec l’utilisateur root ne sont possibles qu’avec une clé. On peut changer cette valeur à “yes” pour autoriser le compte root à se connecter avec un mot de passe. C’est en général déconseillé pour des raisons de sécurité.
Il est également possible de restreindre l’utilisation uniquement depuis certaines machines et avec certains utilisateurs.
AllowUsers olivier@192.168.1.*
AllowUsers admin bob
Ici seuls les utilisateurs admin et bob sont autorisés ainsi que l’utilisateur olivier mais uniquement depuis le sous-réseau 192.168.1.0/24.
Une fois la nouvelle configuration enregistrée, le service ssh peut être redémarré.
systemctl restart ssh
Le client SSH a besoin des informations suivantes : un nom de machine ou une adresse IP, un login et un mot de passe. On peut remplacer l’authentification par login/mdp par une clé.
Comme client SSH, vous connaissez sans doute déjà le client SSH Windows par excellence : Putty.
Voici quelques astuces de configuration dans Putty pour + de confort et facilité :
Mémoriser cette configuration dans une session Putty (Save). Vous pourrez ensuite directement vous connecter en cliquant sur cette session.
Exemple :
Sous Linux (Ubuntu par ex.) :
ssh nomutilisateur@nommachineOUadresseIP
apt install putty putty-tools
Sous Mac :
ssh nomutilisateur@nommachineOUadresseIP
sudo brew putty putty-tools
Il est à noter que dès que vous avez un accès SSH, vous pouvez copier des fichiers entre votre machine hôte et invitée via SCP/SFTP. Ceci peut se faire en ligne de commande (Linux), avec le logiciel WinSCP (Windows) ou Cyberduck (Mac).
Exemple d’une copie de fichier depuis une machine physique vers une VM Azure en ligne de commande :
scp -i debian-och.pem monfichier.txt azureuser@20.15.56.87:/home/azureuser
Ceci copie le fichier monfichier.txt dans la home directory de l’utilisateur azureuser.
scp -i debian-och.pem -r mondossier azureuser@20.15.56.87:/home/azureuser
Avec l’option -r, on peut copier récursivement tout un dossier.
Sous Windows, copie de fichiers avec le logiciel WinSCP (logiciel gratuit à télécharger) :
Pour réaliser une authentification SSH par clé, les étapes suivantes sont nécessaires :
Attention si vous utiliser Puttygen → copier le contenu de la clé publique généré dans un fichier texte. N’utiliser pas le bouton « Save public key » car il enregistre la clé sous un format non reconnu sous Linux.
Exemple de connexion par clé via Putty :
La création d’un tunnel SSH permet de connecter 2 machines en encapsulant le trafic de la première et en le redirigeant vers la seconde. Cette technique est souvent appelée le VPN du pauvre car elle permet notamment de donner accès à une machine du réseau local de l’entreprise à des ordinateurs distants et à moindres frais (de configuration).
L’ idée est de connecter via SSH un port local d’une machine cliente à un port distant d’un serveur. Cela fait drôlement penser à du port forwarding comme on peut le faire avec du NAT (Voir NAT) et c’est le cas.
Exemple Linux :
ssh -L 2080:localhost:80 olivier@89.89.89.89
Dans cet exemple, on crée un tunnel sur le port 2080 de la machine locale et le port 80 du serveur 89.89.89.89. Le trafic de la machine locale sur le port 2080 sera donc envoyé vers le port 80 du serveur.
Exemple Windows (Putty) :
À accéder à un serveur de votre entreprise depuis la maison alors qu’il n’est pas directement accessible depuis Internet.
Un tunnel utilisant le SSH (OpenClassRoom) Attribution ©Wikipedia
Ces commandes sont suffisamment explicites. Consulter la documentation à ce sujet pour connaître les options intéressantes.
Il est à noter que adduser crée un profil pour l’utilisateur basé sur un répertoire squelette situé dans /etc/skel. Tout fichier placé par l’administrateur dans ce répertoire squelette sera copié par défaut dans le répertoire de l’utilisateur lors de l’appel à adduser.
Par défaut, la home directory créée par adduser est accessible en lecture à tout le monde (voir /etc/adduser.conf). Attention, ceci peut ne pas correspondre à votre politique de confidentialité. Ceci peut être changé dans /etc/adduser.conf.
Cette commande permet de changer d’utilisateur. Sans argument, elle permet de devenir root.
su admin
La commande sudo a pour objectif de permettre à des utilisateurs d’exécuter des commandes en tant que superutilisateur.
Pour qu’un utilisateur puisse exécuter une commande avec « sudo », il doit faire partie du groupe sudo.
apt-get install sudo
Pour ajouter un utilisateur au groupe sudo :
adduser toto sudo
Les avantages du SUDO sont les suivants:
Passwd permet de changer le mot de passe de son compte et de tous les comptes (pour le root). Il est également possible de verrouiller ou de désactiver le compte root. Verrouiller le compte root empêche simplement de pouvoir se connecter directement avec le compte root tandis que la désactivation le rend totalement inutilisable.
Le système d’exploitation Linux est né sur base du système d’exploitation Unix. Il a donc récupéré énormément de caractéristiques de ce système, notamment son système d’initialisation. Les systèmes Unix utilisent une architecture System V. Cette architecture possédait à l’origine de nombreux avantages - tels que la mémoire partagée, les sémaphores (cfr. cours Pgm Distribuée), etc. - qui sont d’ailleurs toujours utilisés aujourd’hui. Ce système d’initialisation était donc le premier processus (init, avec PID=1) que lançaient les systèmes Unix et Linux. L’architecture System V divisait l’environnement d’exécution en une série de runlevels et disposait d’un fichier inittab qui précisait quelles applications étaient lancées suivant le runlevel.
Les niveaux d’exécution :
Le système d’initialisation en System V :
Encore actuellement, vous verrez des commandes de démarrage de service tel que /etc/init.d/ssh restart qui constitue une trace de cette architecture. Cependant cette architecture date de 1983 et certains manquements ont commencé à apparaître par rapport à de nouveaux besoins. C’est ainsi que SystemD est apparu. SystemD reprend l’architecture SystemV en y ajoutant les fonctionnalités suivantes:
L’objectif principal de SystemD (tout comme SystemV) est de démarrer des services, appelés daemons dans le monde Linux. Il est donc normal que celui-ci propose différentes manières d’implémenter son service.
Voici les types de services:
Exemple de définition d’un service :
[Unit]
Description=add-client-identifier
Before=network-pre.target
Wants=network-pre.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/home/ipl/add-client-identifier.pl
ExecStop=
[Install]
WantedBy=multi-user.target
Les niveaux d’exécution en SystemD (assez similaires à System V) :
• 0 : poweroff.target
• 1 : rescue.target
• 3 : multi-user.target
• 2,4 : multi-user.target
• 5 : graphical.target
• 6 : reboot.target
• emergency.target
Ce chapitre a surtout pour but de vous aider pour les exercices.
Il est évident qu’un administrateur système devra installer tôt ou tard un serveur web dans son entreprise vu le nombre croissant d’applications Web. Différents Serveurs Web existent. Voici un tableau des principaux avec leurs caractéristiques.
Serveur Web | Caractéristiques |
---|---|
Apache | Leader historique, hautement configurable, modules chargés dynamiquement, présent sous Windows et Linux |
Nginx | Challenger, optimisé pour la performance (résolution problème CK10 - servir 1000 clients simultanément), modules compilés, présent sous Linux |
IIS | Serveur Web Windows, support ASP.NET |
Après ce bref tour d’horizon des serveurs Web, nous allons nous intéresser plus particulièrement à Apache.
apt-get install apache2
L’installation créée un compte et un groupe www-data. Apache 2 fonctionne par défaut sur ce compte et groupe pour des raisons de sécurité et tourne sur le port 80. Un site de base (page HTML) est placé dans /var/www ce qui permet de tester directement Apache2 après son installation: http://adresseip. Il est à noter que si vous voulez tester apache sur un serveur ne disposant pas d’interface graphique (et donc pas de navigateur classique), vous pouvez installer lynx qui est un navigateur en mode texte (c’est moche, mais cela permet de tester!).
Apache étant hautement configurable, il se caractérise par une configuration morcelée. Le fichier de configuration de base est /etc/apache2/apache2.conf. Ce fichier inclut tout simplement d’autres fichiers et répertoires à savoir:
Un administrateur système écrira/préparera ces configurations dans les répertoires «available» et il activera ensuite ces configurations via les commandes suivantes:
#activer/ désactiver un site
a2ensite/a2dissite <filenamesite>
#activer/ désactiver une configuration
a2enconf/a2disconf <filenameconf>
#activer/ désactiver un module
a2enmod/a2dismod <filenamemmod>
Les virtualhosts permettent de déployer plusieurs sites Web sur un même serveur (même adresse IP). La distinction se fait en général sur le nom du site, apache doit en effet savoir suivant l’URL quel site il doit présenter.
L’ajout d’un vhost se fait en créant un fichier dans /etc/apache2/sites-available/«monsite.conf».
Vhost de base:
<VirtualHost *:80>
ServerName monsite
ServerAdmin webmaster@localhost
DocumentRoot /var/www/htdocs/monsite
ErrorLog ${APACHE_LOG_DIR}/monsite_error.log
CustomLog ${APACHE_LOG_DIR}/monsite_access.log combined
<Directory /var/www/htdocs/monsite>
Require all granted
AllowOverride All
</Directory>
</VirtualHost>
Il est possible de déboguer et de vérifier la syntaxe du vhost avec la commande suivante :
apache2ctl configtest
Ensuite, il faut activer le site comme suit :
#activer un site
#commande à entrer dans /etc/apache2/sites-available
a2ensite monsite.conf
La directive «ServerName» est nécessaire pour qu’Apache fasse une distinction sur le nom du site. Toute URL comportant «monsite.be» utilisera ce vhost.
La directive «ServerAdmin» permet de préciser le responsable du site.
La directive «DocumenRoot» permet de préciser l’endroit où se trouve l’arborescence du site.
La directive «ErrorLog» et «CustomLog» permettent de préciser où les logs seront stockés.
On peut ensuite appliquer des règles/restrictions sur le site via la directive «Directory».
Ici on autorise tout le monde à voir le site «Require all granted» et on autorise les utilisateurs à redéfinir ces règles «AllowOverride All». Ceci permet par exemple de définir des .htaccess.
La directive «Require» peut autoriser ou interdire des adresses IPs, des utilisateurs…
Exemples :
# n’autoriser l’accès au site que depuis localhost
require ip localhost
# accès uniquement au site pour l’utilisateur admin
require user admin
# pas de redéfinition possible (pas de .htaccess)
AllowOverride None
Un proxy inverse est un serveur frontal c’est-à-dire un serveur exposé sur Internet et par lequel toutes les requêtes passeront. Ce serveur ne traitera pas les requêtes, mais se contentera de les rediriger vers d’autres serveurs internes à l’entreprise.
Les intérêts de ce mécanisme sont multiples. Vu qu’il n’y a qu’un seul point d’accès, la sécurité est plus facile à gérer. Cela permet également de mettre en œuvre du «load balancing» entre des serveurs internes. C’est également un moyen simple de rendre disponible un serveur interne sur le Web (pas besoin de configuration réseau).
Pour mettre en place un reverse proxy, il faut activer le module apache « proxy_http » et « proxy ».
/usr/sbin/a2enmod proxy proxy_http && systemctl restart apache2
Ensuite dans le fichier VirtualHost:
<VirtualHost *:80>
ServerName siteReverseProxy
ServerAdmin webmaster@localhost
# attention / final !!!
ProxyPass / http://www.example.com/
ProxyPassReverse / http://www.example.com/
ErrorLog ${APACHE_LOG_DIR}/siteReverse_error.log
CustomLog ${APACHE_LOG_DIR}/siteReverse_access.log combined
</VirtualHost>
Apache peut être configuré pour servir des pages PHP. Il suffit d’installer PHP ainsi que le module PHP pour apache et de redémarrer le service apache2.
apt-get install php php-mysql libapache2-mod-php && systemctl restart apache2
Un site PHP possède généralement une base de données MySQL ou MariaDB. C’est pourquoi nous avons inclus ci-dessus le package php-mysql.
Pour installer et utiliser MySQL/MariaDB, voir la section 9.2.3 consacrée à la base de données MySQL/MariaDB.
Un serveur Web doit être sécurisé ; en particulier les échanges entre le client et le serveur doivent être cryptés. Ceci se fait aisément grâce au paquet Openssl. Le port par défaut pour les communications https est le 443.
apt-get install openssl && /usr/sbin/a2enmod ssl && systemctl restart apache2
La commande openssl permet de créer un certificat ainsi qu’une clé associée à ce certificat.
mkdir /etc/apache2/ssl &&
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt
Ici la clé et le certificat seront déposés dans le répertoire /etc/apache2/ssl créé au préalable.
Le VirtualHost sera modifié de la sorte:
<VirtualHost *:443>
ServerName monsite.be
ServerAdmin webmaster@localhost
DocumentRoot /var/www/htdocs/monsite
ErrorLog ${APACHE_LOG_DIR}/monsite_error.log
CustomLog ${APACHE_LOG_DIR}/monsite_access.log combined
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
<Directory /var/www/htdocs/monsite>
Require all granted
AllowOverride All
</Directory>
</VirtualHost>
Let’s encrypt est une autorité de certification libre, gratuite et automatisée. Ceci permet d’obtenir un certificat valide pour son site Web sans trop d’effort. Cependant, la machine servant le site Web doit être «publiquement» accessible ainsi que le nom du domaine. Cela veut dire qu’en test, ce procédé n’est pas applicable.
En infrastructure, il est courant de répartir la charge sur plusieurs serveurs. Cela permet d’accélérer le temps de réponse aux clients. L’ensemble des requêtes sont alors balancées entre plusieurs serveurs Web.
# installation du module proxy si cela n'a pas encore été fait
/usr/sbin/a2enmod proxy
# installation du module proxy_http si cela n'a pas encore été fait
/usr/sbin/a2enmod proxy_http
# installation du module proxy_balancer
/usr/sbin/a2enmod proxy_balancer
#installation du module contenant la méthode de répartition de la charge
/usr/sbin/a2enmod lbmethod_byrequests
# redémarrer apache pour prendre en compte les modules
systemctl restart apache2
Ensuite dans le fichier VirtualHost :
<VirtualHost *:80>
ServerName monsite.be
<Proxy balancer://mycluster>
BalancerMember http://127.0.0.1:8080
BalancerMember http://127.0.0.1:8081
</Proxy>
ProxyPreserveHost On
ProxyPass / balancer://mycluster/
ProxyPassReverse / balancer://mycluster/
</VirtualHost>
NFS est un protocole réseau couramment employé pour partager des fichiers sur un réseau. NFS fonctionne en mode client-serveur. Les versions les plus utilisées sont la 2 et 3. Nous ne parlerons pas ici de la version 4. NFS est un protocole performant, mais sans sécurité accrue. Ce protocole est le protocole de partage réseau par excellence sous Linux/MacOS.
apt-get install nfs-kernel-server nfs-common
Les partages sont à définir dans /etc/exports et ont la forme suivante :
<share> <host1>(<options>) <hostN>(<options>)
Les hôtes sont des adresses IP ou des noms DNS de machines qui pourront accéder au partage. On peut utiliser le joker (*) pour spécifier plus facilement plusieurs machines ou un sous-réseau. Les options les plus courantes sont:
NFS vérifie l’identité des utilisateurs via les UID, GID. Il faut donc que les UID, GID de la machine distante et locale corresponde. L’UID de root est toujours le même (0).
Il est donc important de comprendre que NFS (v2,V3) ne demande pas aux utilisateurs de s’authentifier. En effet, on autorise via le fichier « exports » une série d’hôtes à se connecter et ensuite c’est via les permissions classiques UNIX/LINUX que les droits sont positionnés sur le répertoire du serveur NFS. NFS va ensuite simplement vérifier les UID, GID locaux (serveur NFS) et distants (client NFS).
Pour ces raisons, il est alors très facile de casser la sécurité NFS. C’est pourquoi il est presque exclusivement utilisé pour des partages en lecture seule généraliste ou pour faire des backups à distance.
/home/olivier 192.168.1.1(ro)
→ la machine ayant l’IP 192.168.1.1 peut monter le répertoire /home/olivier. Ce répertoire sera accessible en lecture seule.
/home/public *.ipl.be(rw,sync)
→ la machine ayant pour nom *.ipl.be peuvent monter le répertoire /home/bob. Ce répertoire sera accessible en lecture/écriture et toute opération d’écriture sera effectuée directement (sync).
/home/net 192.168.1.0/24 (rw,async,no_root_squash)
→ les machines du réseau 192.168.1.0/24 peuvent monter le répertoire /home/net en lecture/écriture.
mount -t nfs 192.168.1.1:/home/public /datas/public
# -o → options
mount -t nfs -o soft,intr,rsize=8192,wsize=8192 192.168.1.65:/volume1/BACKUP /home/nfs
showmount -e
SMB/CIFS est un protocole propriétaire utilisé sous Windows pour les partages réseau.
Vous connaissez certainement ces partages réseaux qui ont des paths UNC de la forme : \\machineserveur\partage.
Samba est un logiciel né sous Linux qui implémente ce protocole propriétaire SMB/CIFS. Il permet donc une interopérabilité entre les 2 mondes (Linux/Windows) notamment:
Samba fonctionne tout comme NFS en mode client-serveur. Samba possède une gestion plus élaborée au niveau de l’authentification et des droits des utilisateurs par rapport à NFS.
apt-get install samba samba-common-bin
La configuration s’effectue dans /etc/samba/smb.conf. Nous n’allons pas ici décrire tous les paramètres, mais voici les principaux. Les partages se définissent entre […] (section). Certaines sections sont prédéfinies comme :
À l’intérieur de ces sections, les paramètres se définissent de la sorte: paramètre = valeur Voici quelques exemples de configuration classique ci-dessous.
Le but est ici de donner accès à tout le monde en lecture seule à un répertoire situé sur le serveur.
[global]
server string = monserveurLinux
security = user
# les utilisateurs qui se connecte au partage seront mappés sur le compte anonyme
map to guest = Bad user
# compte anonyme pour les « Bad user »
guest account = nobody
# compatibilité protocole SMB et Windows 10
min protocol = LANMAN2
max protocol = NT1
[public]
# chemin local du partage
path = /home/samba/allusers
# accès possible en anonyme à ce partage
public = yes
readonly = yes
# répertoire visible dans l’explorateur de fichiers
browseable = yes
[partageEcriture]
# chemin local du partage
path = /home/samba/partageEcriture
browseable = yes
write list = user1, user2
Ici plus question d’accès anonyme, il est nécessaire d’ajouter un compte SAMBA avec mot de passe.
smbpasswd -a user1
Le but ici est permettre l’accès en écriture à leur home directory (depuis Windows par ex.) aux utilisateurs enregistrés sur le serveur Linux.
[global]
server string = monserveurLinux
security = user
[homes]
# inutile de rendre visibles à tout le monde ces partages
browseable = no
writable = yes
# les utilisateurs pouvant accéder à ce partage sont ceux
# correspondant à %S c’est-à-dire au nom du partage ...
# c’est-à-dire le nom de l’utilisateur ici
valid users = %S
systemctl restart samba
La commande «testparm» permet de vérifier la configuration de votre smb.conf.
Sous Windows, la commande «NET USE» (à taper dans une console DOS)
permet de voir les connexions SMB et de les supprimer. NET USE
Voici quelques paramètres intéressants:
On peut donner un groupe via @: valid users = @admins
Un VPN (Virtual Private Network) est un système permettant de relier 2 réseaux via un réseau non sûr tout en garantissant un trafic sécurisé (crypté) et de manière transparente. On parle de tunnel.
Les VPN sont de plus en plus utilisés, car ils permettent notamment de se protéger des écoutes sur un réseau public (NSA, …) et d’anonymiser sa connexion.
Il existe différents types de VPN à savoir:
Il est important de comprendre que le VPN crée un réseau et le configure pour que le réseau distant (LAN to LAN) ou PC distant (Road Warrior) soit considéré comme s’il était dans l’entreprise. L’utilisateur pourra donc utiliser tout ce qui accessible dans le LAN de l’entreprise (imprimantes … ).
Road Warrior
Image issue de : https://www.junmajinlong.com/files/Mastering_OpenVPN.pdf
Image issue de : https://www.junmajinlong.com/files/Mastering_OpenVPN.pdf
LAN-to-LAN / site-to site
Image issue de : https://openvpn.net/vpn-server-resources/site-to-site-routing-explained-in-detail/
Protocole | Couche Réseau | Remarques |
---|---|---|
PPTP (Point to Point Tunneling Protocol) | Couche Liaison des données | Road Warrior |
L2TP (Layer 2 Tunneling Protocol) | Couche Liaison des données | Road Warrior / Remplaçant PPTP |
IPSec | Couche Réseau | Site To Site / intégré à IPV6 / se configure essentiellement sur les routeurs-firewalls des entreprises |
OpenVPN | Couche Application | OpenVPN est un logiciel créant un VPN en se basant sur SSL/TLS – RoadWarrior ou Site to Site |
# Serveur VPN (server.conf)
mode server
proto udp
dev tun
topology subnet
# clé et certificat SSL
ca keys/ca.crt
cert keys/cert.crt
dh keys/dh2048.pem
# réseau créé
server 10.50.0.0 255.255.255.0
keepalive 10 120
# compression des échanges
comp-lzo
#client VPN (client.conf)
client
proto udp
dev tun
remote 89.89.89.89 1194
nobind
ca /etc/keys/ca.crt
cert /etc/keys/roadwarrior.crt
key /etc/keyroadwarrior.key
comp-lzo
Le FTP (File Transfer Protocol) est un protocole réseau standard. On le retrouve donc très facilement sous n’importe quel environnement (Windows/Linux). De nombreux clients (graphiques ou non) existent. On l’utilise encore fréquemment pour transférer du code source sur un serveur hébergé.
Comme son nom l’indique, ce protocole est fait pour transférer des fichiers entre ordinateurs. C’ est le protocole le plus efficace pour cette tâche. IL est dès lors très utilisé DNS les tâches de backups.
Le protocole FTP utilise un canal pour le transfert des données et un autre pour le contrôle. C’est pourquoi il utilise par défaut 2 ports ( 20→ données, 21 → contrôle). Le canal de contrôle permet d’envoyer les commandes FTP ( put, get, open, close, ls, …).
Il peut être sécurisé via SSL/TLS (FTPS) ou par SSH (SFTP). Regardez dans WinSCP, vous verrez que vous transférez par défaut vos fichiers par SFTP!
Le protocole FTP peut s’utiliser en mode actif ou passif.
Dans le mode actif, le client peut choisir son port de connexion pour la réception des données. Le serveur initialisera une connexion de son port 20 vers le port choisi par le client. Le client doit donc accepter les connexions entrantes sur le port choisi. Ceci pose souvent problème car les clients se trouvent généralement dans un LAN qui effectue du NAT vers l’extérieur. C’est pourquoi le mode actif est le moins utilisé.
Dans le mode passif, le serveur impose le port de connexion pour le transfert des données. Le port choisi par le serveur est envoyé au client qui initialise alors la connexion.
L’administration d’un serveur Linux se fait assez facilement via SSH. Le pendant dans le monde Windows est le Terminal Server aussi appelé Bureau à distance. Le Terminal Server repose sur le protocole RDP (Remote Desktop Protocol) développé par Microsoft.
Terminal Server permet non seulement la prise à distance d’un serveur avec son interface graphique, mais aussi de monter des lecteurs locaux sur le serveur distant.
SCP, Teamviewer, VNC, Nomachine, Citrix, … .
Dans un réseau d’entreprise, il devient rapidement nécessaire de centraliser les authentifications afin de faciliter la maintenance de la politique des accès, des droits, des stratégies de sécurité.
Le protocole LDAP (Lightweight Directory Access Protocol) a été défini pour permettre d’interroger et de modifier un annuaire. Il est depuis devenu une référence et un standard pour l’authentification.
LDAP est en fait devenu bien plus qu’un protocole, c’est une norme qui définit:
Différentes implémentations de la norme LDAP existent. OpenLDAP est la solution reconnue du monde libre (paquet slapd dans Debian). La solution Active Directory de Microsoft est sans doute la plus connue et répandue. Nous en parlerons plus longuement (Voir Active Directory).
Un annuaire sera élaboré à partir d’une structure de données de type arbre hiérarchique représentant l’organisation d’une entreprise. La racine de cet arbre sera un nom DNS (le nom DNS de l’entreprise généralement), les nœuds seront les divisions de l’entreprise (départements, sections, année d’étude …) et les feuilles seront les objets (machines ou utilisateurs principalement).
Voici le vocabulaire de base utilisé dans un annuaire LDAP:
Exemple :
DN:«cn=olivier.choquet,ou=professeurs, dc=ipl,dc=be» CN: «olivier.choquet»
LDAP s’impose comme moyen d’authentification car il est bien standardisé et documenté. De plus sa structure de données en arbre est bien adaptée en termes de performance à l’authentification (beaucoup de lectures et peu d’écriture).
LDAP a défini différentes méthodes permettant de modifier et consulter l’annuaire. Voici la liste des principales méthodes :
Une recherche dans l’annuaire devra préciser ces 3 éléments. La base indique l’endroit où la recherche commence dans l’annuaire (nœud dans l’arbre). La portée indique où l’on s’arrête et peut prendre comme valeur :
Les filtres permettent de ne prendre en compte dans la recherche que des éléments respectant certaines règles (élément ayant l’attribut …., ). LDAP fournit différents opérateurs pour construire les filtres :
= (égalité)
~= (approximation)
>= (supérieur / inférieur ou égal)
: (intersection)
& (ET logique)
! (négation)
Exemple : &(&(objectclass=prof)(cn=A*)(!(sexe=M))) Une recherche LDAP est également appelée Query LDAP. Un annuaire LDAP peut également être interrogé via une URL. Exemple: ldap://localhost:389/ou=professeurs,dc=ipl,dc=be?uid?sub
LDAP définit le modèle d’information suivant :
Exemple:
dn: cn=olivier.choquet, ou=profs, dc=ipl,dc=be\
objectClass: user\
cn: olivier.choquet\
mail: olivier.choquet@vinci.be\
bureau: A050\
Le transport des messages LDAP sera chiffré via SSL/TLS. LDAP présente différentes méthodes d’authentification. L’utilisateur, une fois authentifié (via un bind), aura accès aux données suivant les règles établies dans les ACL (Access Control List).
Un modèle de réplication est prévu dans la norme LDAP, mais il n’est pas encore standardisé. La réplication est un élément important pour assurer une redondance qui reste le moyen privilégié par les administrateurs système pour se prémunir des pannes. Les différentes implémentations LDAP (Active Directory, OpenLDAP, ..) ont développé leurs systèmes de réplication.
À noter également que LDAP fournit un format d’échange standard nommé LDIF (LDAP Data Interchange Format) qui permet d’échanger/sauvegarder de l’information entre serveurs LDAP. Cependant celui-ci ne permet pas une réplication aisée.
LDAP | SGBD |
---|---|
Optimiser pour la lecture, faible en écriture | Optimiser pour les lectures et écritures |
Isolation pas garantie | Support Transaction (ACID) |
Réplication aisée | Réplication plus complexe |
Attribut multi-valeurs | / |
Query LDAP | Query SQL |
Modèle de données défini, mais extensible facilement | Définition du modèle par le dévelopeur, extensible mais difficile |
A noter qu’une base de données peut être utilisée comme implémentation d’une solution serveur LDAP.
L’Active Directory est une implémentation Microsoft d’un annuaire LDAP. Cette implémentation est évidemment adaptée aux environnements Microsoft. L’Active Directory permettra de gérer l’authentification des utilisateurs d’un ou plusieurs domaines, de gérer les droits des utilisateurs via des groupes de sécurité. L’Active Directory introduit son propre vocabulaire en plus du vocabulaire LDAP.
Un Active Directory définira une forêt qui sera composée d’arbres (domaine parent avec des domaines enfants) et/ou de domaines. Les domaines seront, quant à eux, constitués d’unités d’organisation et enfin d’ordinateurs, de groupes et utilisateurs.
Image issue de ibm.com
Chaque domaine connaît ses objets, mais est incapable de localiser les objets d’un autre domaine. C’est pourquoi la forêt maintient un catalogue global qui sera consulté en cas de besoin par les domaines. Entre différentes forêts, on peut établir des relations d’approbations ce qui permet de s’authentifier dans la forêt 1 avec les identifiants de la forêt 2 et vice-versa.
Dans un Active Directory, nous allons retrouver différents objets. Les plus importants sont les utilisateurs, les ordinateurs du domaine, les groupes de sécurité, les GPO (Voir GPO), les unités d’organisation.
Un serveur hébergeant un Active Directory est appelé contrôleur de domaine. Il est conseillé d’avoir au minimum 2 contrôleurs de domaine par Active Directory pour se prémunir des pannes.
Une unité d’organisation est un regroupement d’objets de l’Active Directory. C’est un nœud dans l’arbre LDAP. Les unités d’organisation trouvent essentiellement leur utilité par le fait que des GPO puissent être définies à ce niveau.
Ne pas confondre les unités d’organisation et les groupes de sécurité. Des GPO ne peuvent pas être définies sur des groupes et des permissions ne peuvent pas être définies sur des unités d’organisations. Un objet (utilisateur) peut appartenir à plusieurs groupes, il ne pourra pas contre être placé que dans une seule unité d’organisation.
Il est évidemment bien plus aisé de gérer les droits des utilisateurs via des groupes. Il existe différentes étendues de groupe :
Microsoft propose une recommandation pour la gestion des droits et des groupes. Il s’agit de la recommandation AG(U)DLP.
Account → Global → (Universel) → Domain Local → Permission
L’idée est donc de placer les utilisateurs dans des groupes globaux, de placer ceux-ci dans groupe locaux et ensuite d’appliquer les permissions sur ses groupes. Éventuellement dans de grandes structures avec plusieurs domaines, un niveau de groupe universel peut être introduit.
Exemple :
Image labo-microsoft.supinfo.com / schéma utile à connaître pour
expliquer AG(U)DLP
Microsoft utilise le système de fichiers NTFS et dès lors les permissions seront des permissions NTFS. Les permissions NTFS sont très riches (beaucoup de possibilités).
Voici les permissions les plus communes:
Les permissions sont héritées. Le répertoire C:\test héritera des permissions mises sur C:\. Il existe la possibilité de bloquer l’héritage. Les permissions NTFS définissent différentes étendues (ce dossier, ce dossier et sous-dossier, uniquement fichiers …).
Les partages réseau sont des dossiers (présents généralement sur des serveurs) qui sont partagés et donc accessibles sur le réseau depuis n’importe quelle machine. Ces partages réseau utilisent le protocole SMB (Voir SAMBA).
Attention à ne pas confondre les permissions NTFS qui s’appliquent directement sur des fichiers et dossiers locaux (présents sur le système de fichiers) et les permissions de partage qui sont définies sur les partages réseau.
Les permissions de partage réseau sont plus limitées (R, M, FC). Lors de l’accès à un partage réseau, le système évalue tout d‘abord les permissions du partage réseau et ensuite les permissions NTFS (puisque tout partage réseau se retrouve toujours physiquement sur un système de fichiers).
Les GPO (Group Policy Object) permettent de définir des stratégies de sécurité et/ou de configurer des paramètres de manière centralisée pour un domaine ou une forêt. Par exemple, on peut imposer un proxy pour les clients, définir un fond d’écran, définir une politique de mot de passe (longueur, complexité …).
Les GPO, aussi appelées stratégie de groupe en français, permettent de déployer des stratégies/paramètres sur 2 types objets de l’Active Directory : les utilisateurs et les ordinateurs. Les GPO se créent le plus souvent sur des Organizational Unit.
Les GPO machines (configuration ordinateur) s’appliquent au démarrage de la machine. Les GPO utilisateurs (configuration utilisateur) s’appliquent à l’ouverture de session d’un utilisateur.
Console de gestion des GPO :
En tant que développeur, vous savez que la majorité des données sont stockées dans des bases de données. Nous allons donc nous intéresser à ce composant essentiel de l’entreprise du point de vue administration système.
Nous allons particulièrement au type de base de données le plus répandu à savoir les bases de données relationnelles. Nous prendrons PostGreSQL comme exemple.
Dans les grandes entreprises, il existe souvent des DBA (Database Administrator) qui sont en charge de gérer et documenter les bases de données. Dans les entreprises plus petites, c’est généralement l’administrateur système qui effectue ce travail.
Les rôles du DBA sont les suivants :
Un moteur de base de données est constitué de plusieurs programmes. PostgreSQL est composé d’un programme superviseur (postmaster), du serveur exécutant les requêtes (postgres) et d’un client interactif (psql).
apt-get install postgresql
PostgreSQL se configure via les fichiers postgresql.conf et pg_hba.conf. Le premier fichier permet de gérer les paramètres globaux (nombre maximum de connexions, SSL …) tandis que le deuxième permet de gérer les accès.
Il est important de sauvegarder les bases de données. Voici les erreurs à ne pas commettre :
Les sauvegardes de type fichiers ou instantanés ne conviennent pas aux bases de données. Il est préférable d’utiliser l’outil fourni par le moteur de base de données. Dans le cas de PostgreSQL, nous avons pg_dump.
Il est important de savoir que les limitations des bases de données se situent essentiellement du côté des composants sous-jacents (CPU, RAM, vitesse disque, capacité disque …).
Par exemple, la limite au niveau des tables pour PostgreSQL est actuellement de 64 To. Ce n’est donc pas ceci qui va poser problème. PostgreSQL reste stable et performant même avec des DB ≥ 30 GB.
Sachant ceci, il faut commencer par surveiller ces éléments via les commandes/outils du système d’exploitation. Par exemple : uptime pour la charge CPU, free pour la charge mémoire.
La performance passe également par l’ajout d’index. Un index peut accélérer par 1000 000 une requête ! PostgreSQL dispose de la commande EXPLAIN qui décrit le plan d’exécution d’une requête. Ceci s’avère être un outil puissant pour accélérer une requête problématique.
L’utilisation de LIMIT est également à envisager. Doit-on vraiment charger l’entièreté d’une table, les premiers résultats ne sont-ils pas suffisants ?
L’utilisation régulière de VACUUM pour supprimer définitivement les données expirées est à envisager, particulièrement sur les bases de données des développeurs qui créent et détruisent souvent leurs bases de données.
L’utilisation d’ANALYSE permet de collecter des statistiques en vue d’optimiser la base de données.
Un petit mot sur les ORM pour finir. Ceux-ci sont très utiles, mais l’optimisation s’avère souvent plus complexe à gérer vu que vous laissez l’ORM créer les requêtes SQL pour vous. En tant que développeur, posez-vous (ou à votre chef de projet) donc la question de la performance avant de vous décider.
Comme d’habitude, les administrateurs systèmes ou DBA vont vouloir se prémunir des pannes en installant de la redondance. Avec les bases de données, ceci peut se faire en activant la réplication. Ce mécanisme permet à 2 moteurs de base de données de partager des bases de données. Les données de ces bases de données se retrouvent alors répliquées/dupliquées au minimum sur 2 serveurs de bases de données.
La réplication la plus utilisée est celle dite du maître – esclave. Toutes les opérations sont faites sur le serveur maître et celui-ci envoie régulièrement au serveur esclave ses journaux de transactions. Ce dernier rejoue alors le journal de transactions sur sa base de données.
apt-get install default-mysql-server
Le seul compte créé par l’installation de MySQL/MariaDB est un compte nommé root sans mot de passe. Pour se connecter au moteur de base de données MySQL/MariaDB :
mysql –u root
Il est possible en se connectant d’injecter un fichier SQL (fichier de création DB, tables, …).
mysql -u root < file.sql
Une fois connecté, vous pouvez entrez des commandes SQL comme CREATE DATABASE, SELECT, … .
Voici quelques commandes SQL d’administration :
CREATE USER 'ipl'@'localhost' identified by 'ipl';
Ceci crée un compte “ipl” avec le mot de passe “ipl”.
GRANT ALL PRIVILEGES ON bdbn.* TO 'ipl'@'localhost' ;
Ceci donne tous les droits à l’utilisateur ipl sur la base de données bdbn.
USE bdbn;
Ceci permet de changer de base de données. Ici on change pour bdbn.
Un administrateur système sera en charge de la pérennité des données. Pour cette tâche, des sauvegardes ou backups seront nécessaires. Les sauvegardes permettent de réduire les risques liés à des pannes, virus (ransomware), erreurs humaines. Bien sûr il est souvent impossible de tout sauvegarder, c’est pourquoi il faut définir une politique de sauvegarde qui répond aux questions suivantes.
Différents types de données se retrouvent dans une entreprise à savoir:
Comme il est souvent impossible de tout sauvegarder (pour des raisons monétaires), il faut établir des priorités. Cette priorisation trouve souvent son origine dans la gestion des risques liés à l’entreprise.
Exemple: À l’IPL, les fichiers utilisateurs (U) ne sont pas sauvegardés. Ceci n’est pas prioritaire. Par contre, sa comptabilité et son fichier étudiant le sont.
Pour une entreprise, contrairement aux particuliers l’emploi de disques durs externes n’est pas efficace. Il est également vital de stocker les sauvegardes à distance. Stocker les sauvegardes au sein même de l’entreprise est une très mauvaise idée. Imaginez un incendie et vos données et backups disparaitront en même temps.
Les entreprises auront donc souvent recours à des NAS (Network Area Storage) ou SAN distants ou encore à un stockage dans le Cloud. Dans ce dernier cas, la confidentialité des données doit être évoquée.
Il existe différents types de sauvegarde à savoir :
Souvent la fréquence de sauvegarde va influencer le type de sauvegarde.
Les sauvegardes peuvent occuper beaucoup de place. Il est donc nécessaire à réfléchir au stockage et à comment gagner de la place. La compression des données est un moyen souvent utilisé. La déduplication est un autre moyen mis en place par les entreprises. Ce mécanisme est souvent intégré au SAN. Il s’agit de découper les données en bloc et toute nouvelle occurrence d’un bloc est remplacée par un pointeur. Ce mécanisme fonctionne très bien avec les backups car beaucoup de données se répètent. Imaginez une fréquence de backups complets tous les mois. Dans ces backups, beaucoup de données seront identiques.
Il est nécessaire de crypter ses backups pour éviter à une personne mal intentionnée de récupérer facilement les données de l’entreprise. L’utilisation grandissante du Cloud renforce également ce besoin.
Il existe bien évidemment différents logiciels sur le marché offrant la possibilité de réaliser les types de sauvegardes cités ci-dessus. Souvent ceux-ci se basent sur des outils/protocoles déjà fort connus comme le SSH ou FTP pour transférer les backups à distance, des outils zip pour la compression.
Sous Linux, l’outil rsync est fortement utilisé dans des scripts maison ou par le biais de logiciels.
Il existe une règle fortement conseillée pour les sauvegardes de données. Il s’agit de la fameuse règle 3-2-1.
Un administrateur système doit veiller à ce que les ressources soient utilisées de manière raisonnée. Il est également impératif que ces serveurs restent opérationnels et ne soient pas bloqués à cause d’un manque d’espace disque provoqué par un utilisateur.
Les quotas permettent donc de régler ce problème en imposant une limite aux utilisateurs. Le mécanisme de quotas propose une limite soft et une limite hard. Quand un utilisateur dépasse sa limite soft, il reçoit un avertissement lui indiquant qu’il peut continuer à travailler pour une période de grâce définie par l’administrateur. Une fois cette période grâce écoulée, il est bloqué s’il n’est pas redescendu en dessous de la limite soft.
Si l’utilisateur dépasse la limite hard, il est bloqué directement.
Exemple: si on définit que les utilisateurs ont droit à un espace de 100MB, on fixera une limite soft à 75MB et la limite hard à 100MB.
Malgré le fait que le terme virtualisation s’est popularisé depuis le début des années 2000 avec les solutions de virtualisation PC, cela reste un concept assez ancien qui date du début des années 80. On peut en fait virtualiser bien plus qu’un PC.
La virtualisation apporte des avantages certains dans un environnement informatique d’où l’engouement généré par ce concept actuellement. La définition de la virtualisation est la suivante :
La virtualisation consiste en l’abstraction d’un élément du monde réel en le rendant virtuel. Ceci dans l’objectif de rendre l’élément plus facilement :
À noter que chaque solution de virtualisation n’a pas forcément pour but de rencontrer l’ensemble de ces avantages.
Voici quelques exemples concrets :
OPTIMISATION : La virtualisation des serveurs permet d’optimiser l’allocation des ressources (mémoire, CPU) à la demande et donc d’éviter un gaspillage de ressources serveur. Au total, il faudra moins de serveurs physiques, cela va se répercuter positivement sur la facture électrique de l’entreprise.
TRANSPORT: Les solutions de virtualisation de systèmes d’exploitation (VirtualBox) permettent un transport facile de tout un système. Il s’agit de simples fichiers et VirtualBox peut s’installer sur n’importe quel système d’exploitation hôte.
CONFIGURABLE: Les VLAN (voir VLAN) permettent une configuration plus aisée des réseaux via une console Web. Sans les VLAN, on doit physiquement brancher/débrancher des câbles si on veut changer une machine de sous-réseau.
SÉCURITÉ: Les solutions de virtualisation de systèmes d’exploitation ou serveurs permettent de prendre des instantanés (snapshot) de l’état du système. Cela s’avère très utile et pratique avant toute mise à jour périlleuse.
DISPONIBILITÉ: Déploiement d’images de pc/serveurs à la demande
En informatique, on a essayé depuis très longtemps de virtualiser un maximum de composants/concepts afin de tirer profit des avantages de la virtualisation cités ci-dessus.
Type de virtualisation | But recherché | Exemple de solution |
---|---|---|
Serveurs | Regrouper/Diminuer le nombre de serveurs physiques | VMWare ESXi, HyperV |
Applications | Faciliter le déploiement | ThinApp, XenApp, Docker |
Poste de Travail | Faciliter le déploiement | Virtual Desktop Infrastructure (VDI) |
Stockage | Mutualiser le stockage, diminuer le nombre de disques | Storage Area Network (SAN) |
Réseau | Faciliter la configuration | Virtual LAN ( vLAN) |
À noter que même si Docker n’est pas un logiciel de virtualisation à proprement parlé (Voir Docker), son succès dépend également du fait qu’il permet de créer une image pour une application et donc de faciliter son déploiement. C’est pourquoi si on devait classer Docker dans ce tableau il serait dans la virtualisation d’applications.
L’inconvénient majeur de la virtualisation est l’ajout d’une couche de virtualisation entre le système physique et le composant virtualisé. Ceci permet d’obtenir les avantages cités ci-dessus, mais dégrade les performances.
Il existe également des dangers liés à la virtualisation. Un système virtualisé est plus complexe qu’un système purement physique. Cette complexité doit être maîtrisée par l’équipe informatique. Un autre danger est de croire que tout peut se virtualiser. La virtualisation progresse de plus en plus, mais il reste difficile de l’utiliser dans certaines situations comme par exemple :
La virtualisation des machines se fait via des hyperviseurs. Un hyperviseur est un logiciel de virtualisation permettant à plusieurs machines virtuelles de fonctionner simultanément sur un même système physique.
On distingue 2 types d’hyperviseurs : 1. Hyperviseur type 1 / natif / bare-metal 2. Hyperviseur type 2 / hosted
Un hyperviseur de type 1 sera utilisé dans le cadre de la virtualisation de serveurs. Il s’agit d’un système d’exploitation spécialement dédié à virtualisation qui s’exécute directement sur le matériel.
Un exemple: À l’IPL, nous avons 3 serveurs physiques sur lesquels est installé VMWare ESX (hyperviseur de type 1). Celui-ci permet ensuite de créer des serveurs virtuels qui seront répartis sur les 3 serveurs physiques. L’avantage est que l’administrateur système peut via cet hyperviseur contrôler assez finement l’allocation des ressources. Il peut notamment facilement reprendre des ressources d’un serveur (car moins utilisé à certains moments) et les attribuer à un autre serveur. Ceci est impossible à faire avec une architecture purement physique.
A noter que depuis l’apparition du Cloud, de nombreuses offres proposent des serveurs privés virtuel (VPS). Il s’agit d’une illustration de l’utilisation d’hyperviseur bare-metal par des hébergeurs Cloud.
Ce que vous connaissez le plus est certainement les hyperviseurs de type 2. Ces hyperviseurs s’installent dans un système d’exploitation comme un logiciel classique. On peut citer VirtualBox, VMWare Workstation dans cette catégorie. Cette catégorie d’hyperviseur est la moins performante, mais elle est très utile pour effectuer facilement des tests sans perturber l’existant. En effet, les machines virtuelles créées via ces hyperviseurs sont par défaut isolées du réseau physique (NAT) et on peut évidemment installer ce que l’on veut dans ces machines virtuelles sans perturbation pour la machine physique (hôte).
Lorsqu’on virtualise les serveurs, il devient rapidement intéressant et nécessaire que les ressources disques des serveurs virtuels soient également virtuelles. En effet, si on attribue des ressources disques physiques à un serveur virtuel, on ne pourra pas facilement augmenter ou diminuer les ressources disques consommées par ce serveur virtuel.
La virtualisation du stockage consiste donc en la création d’une baie de stockage (ensemble de disques physiques) qui sera présentée en un ou plusieurs ensembles logiques et dynamiques. On parle de LUN (Logical Unit Number). Une LUN est donc un espace de stockage logique et dynamique.
Ces baies de stockage sont accessibles via le réseau essentiellement via 2 protocoles (SMB, Fiber Channel). On parle de SAN (Storage Area Network). Un SAN est donc une baie de stockage avec des LUN accessibles via le réseau.
Dans une infrastructure, les administrateurs système virtualiseront le réseau. Ils auront recours essentiellement aux VLAN (Voir VLAN).
Les hyperviseurs vont également présenter aux serveurs virtuels des carte réseaux virtuelles que l’on pourra configurer (NAT, Bridge, Adresse IP, vlan, …).
Les hébergeurs Cloud ont également la nécessité de virtualiser leur réseau pour permettre à leurs clients de configurer l’environnement acheté/loué.
Virtualbox est une solution de virtualisation bien connue utile pour installer/tester d’autres systèmes sur sa machine sans la nécessité d’altérer celle-ci (pas de repartitionement, dual boot, …).
La possibilité de réaliser un instantané/snapshot dans les solutions de virtualisation est un énorme avantage. Ceci permet de revenir facilement à un état antérieur en cas de souci. Il est donc vivement conseillé de réaliser un instantané avant toute modification importante d’un système.
On peut facilement laisser des instructions/commentaires dans la zone description prévue par Virtualbox. Utile par exemple pour laisser les comptes/mot de passes de test, ils seront ainsi toujours au même endroit que vos fichiers du système virtualisé.
L’installation d’un système d’exploitation dans VirtualBox se fait la plupart du temps via un ISO (Debian, Windows) que l’on place dans le lecteur de cdrom virtuel.
Au niveau réseau, votre machine virtuelle Debian est configurée en NAT par défaut. Via cette configuration, vous ne pouvez pas par défaut accéder depuis votre machine (machine hôte) à la machine virtuelle Debian (machine invitée). Il est cependant utile de pouvoir accéder à votre machine invitée via le réseau afin de tester les différents services que vous installerez (Serveur Web, SSH, ….). Pour cela il faut simplement configurer la redirection de port du NAT (voir Port forwarding). L’idée est la suivante : faire correspondre un numéro de port de la machine hôte à un port de la machine invitée. Toutes les requêtes adressées alors sur le port de la machine hôte sont redirigées vers le port de la machine invitée. Un exemple:
Une autre manière de configurer sa carte réseau sous VirtualBox est de créer un pont. Votre machine virtuelle sera alors connectée directement au même réseau que votre machine hôte. La machine virtuelle pourra communiquer avec toutes les machines du réseau.
Il est souvent utile de reproduire en virtuel un environnement proche de la réalité. Celui-ci implique souvent le recours à plusieurs machines virtuelles. Exemple : pour tester un partage Samba présent sur un serveur Linux, il est utile d’avoir une machine virtuelle « client Windows ».
Comment faire alors pour que ces 2 machines virtuelles invitées communiquent entre elles ?
VirtualBox propose une solution simple : le host-only networking ou réseau privé d’hôte. En ajoutant une carte réseau configurée sur ce mode réseau, les machines virtuelles invitées pourront communiquer entre elles sans perturbation pour le « véritable » réseau physique connecté à la machine hôte. Il faudra cependant définir un réseau et des adresses IPs pour les machines virtuelles hôtes.
Docker est une solution d’architecture à base de conteneurs. Les architectures à base de conteneurs sont une évolution avantageuse de la virtualisation. La virtualisation permet une abstraction vis-à-vis de la couche matérielle et donc de déployer du code, des environnements plus facilement. Cependant la virtualisation au niveau matériel reste lourde en termes de performance et de stockage contrairement aux architectures à base de conteneurs.
On distingue donc actuellement la virtualisation matérielle par opposition à la virtualisation au niveau système d’exploitation aussi appelée architecture à base de conteneurs. C’est à cette catégorie qu’appartient Docker. Docker n’est donc pas un logiciel de virtualisation, mais un isolateur.
Pour réaliser cette isolation, Docker s’appuie sur 2 éléments introduits dans le noyau Linux : les cgroups et les namespaces.
Les cgroups (Control Groups) permettent de fixer/limiter les ressources (CPU, Réseau, disque, nombre de processus) allouées à un conteneur ou un ensemble de conteneurs.
Les namespaces permettent d’isoler des ressources. Ainsi un conteneur ou ensemble de conteneurs ne voient que les ressources de son namespace.
Les conteneurs sont proches des machines virtuelles, mais présentent un avantage important. Alors que la virtualisation consiste à exécuter de nombreux systèmes d’exploitation sur un seul et même système, les containers se partagent le même noyau de système d’exploitation et isolent les processus de l’application du reste du système.
Pour faire simple, plutôt que de virtualiser le hardware comme l’hyperviseur, le conteneur virtualise le système d’exploitation. Il est donc nettement plus efficient qu’un hyperviseur en termes de consommation des ressources système. Concrètement, il est possible d’exécuter près de 4 à 6 fois plus d’instances d’applications avec un container qu’avec des machines virtuelles sur le même hardware.
Les architectures à base de conteneurs sont très utilisées car elles permettent facilement des mises à l’échelle (scaling).
En effet, on peut facilement augmenter le nombre de conteneurs lorsqu’une application est fortement demandée. On appelle cela la mise à échelle horizontale (horizontal scaling). On peut également augmenter les ressources des conteneurs via les cgroups. On appelle cela la mise à échelle verticale (vertical scaling). On peut bien évidemment combiner les 2 mises à l’échelle. Quand la demande est moins forte, on peut réduire le nombre de conteneurs et/ou les ressources et par conséquent épargner de l’argent.
La grosse différence entre Docker et les systèmes de virtualisation classiques se situe au niveau de l’interaction avec le système d’exploitation hôte.
Image issue de : https://www.weave.works/blog/a-practical-guide-to-choosing-between-docker-containers-and-vms
Si on reprend les caractéristiques de la virtualisation pour comparaison :
Différences | Docker | Machine Virtuelle |
---|---|---|
Optimisation | léger (taille et empreinte mémoire) | + lourd (taille et empreinte mémoire) |
Transport | Transport facile (taille légère) | Taille élévée |
Disponibilité | Dockerhub et registry privée | Images sur Azure, … |
Configurable | moins d’options configurables | + options configurables |
Sécurité | moins de sécurité (partage du noyau par les conteneurs) | isolation peut être totale |
Il existe une version de Docker avec interface graphique nommée Docker-Desktop disponible pour Windows, Linux et Mac. Celle-ci est très utile pour les développeurs pour tester la conteneurisation de leurs applications.
Dans ce cours, nous installerons la version administrateur-système c’est-à-dire Docker Engine CE. Il s’agit simplement du moteur Docker version Community Edition sans interface graphique.
Sous Debian :
Supprimer éventuellement une ancienne version de docker :
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do apt-get remove $pkg; done
Ajouter le dépôt Docker :
# Add Docker's official GPG key:
apt-get update
apt-get install ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
Installer Docker et ses outils :
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Vérification de l’installation :
docker run hello-world
Voyons comment commencer avec Docker c’est-à-dire créer un conteneur pour une application.
Pour déployer une application via Docker, il y a donc 3 étapes essentielles :
docker build -t <imagename> <pathToDockerfile>
)docker run -d -p 9000:80 --name <containername> <imagename>
)Le schéma ci-dessous représente toutes les commandes Docker.
Remarquez l’enchainement des 3 étapes essentielles décrites ci-dessus.
Les points suivants de ce syllabus détailleront les différents éléments de ce schéma à savoir :
Image issue de https://www.atomit.fr/2016/10/les-bases-sur-docker/
La conteneurisation d’une application commence par la création d’un dossier contenant tout ce qui est nécessaire à l’application. Ce dossier doit contenir au minimum :
Voici les principales instructions à utiliser dans le Dockerfile :
On crée une image Docker pour notre application en se basant sur une image déjà existante (Debian, Apache, Nodejs, …). Ces images proviennent d’une registry. La registry par défaut est le DockerHub. Un Dockerfile commence donc toujours par l’instruction FROM.
FROM debian
La commande LABEL permet d’ajouter des métadonnées. Ceci n’est pas nécessaire au fonctionnement de l’image/conteneur. Cela sert plus de documentation. La syntaxe est LABEL key=value. Key et value sont libres.
LABEL maintainer="Olivier Choquet"
LABEL description="image custom SSH"
LABEL version="1.0"
La commande RUN permet d’ajouter à l’image de base des éléments en exécutant une/des commandes.
RUN apt-get install ssh -q
La commande COPY est indispensable. Elle permet de copier des fichiers/répertoires depuis la machine hôte dans l’image/conteneur. La syntaxe est COPY SRC (machine hôte) DST (image/conteneur). Les deux arguments doivent être soit des fichiers, soit des répertoires. Dans le cas d’un répertoire, COPY effectue une copie récursive du répertoire.
COPY maconfig.conf /etc/maconfig.conf
La commande CMD permet d’exécuter une commande une fois le conteneur démarré.
CMD npm start
Vous retrouverez plus de détails et plus de commandes dans la documentation Docker si nécessaire :
Quand votre Dockerfile est prêt, il est nécessaire de créer une image afin de pouvoir ensuite créer des conteneurs à partir de cette image.
La commande pour créer une image est build. Il est intéressant de tagger/donner un nom à son image. Cela se fait avec l’option -t. Il faut donner à la commande build le chemin vers le Dockerfile. Dans l’exemple ci-dessous, le Dockerfile se trouve dans le répertoire courant d’où le . en fin de commande.
Créer une image :
docker build -t "monimagessh" .
Lister les images :
docker images
Supprimer une image :
docker rmi monimagessh
La commande pour créer un conteneur est run
. Celle-ci
prend plusieurs arguments :
-p
: port forwarding-d
: exécution en tant que daemon, le prompt est
rendu--name
: donner un nom au conteneur (ce nom peut être
utilisé ensuite à la place du container_id)Créer un conteneur à partir d’une image :
docker run -d -p 2222:22 --name contssh monimagessh
Lister tous les conteneurs :
docker ps -a
Démarrer un conteneur :
docker start contssh
Arrêter un conteneur :
docker stop contssh
Supprimer un conteneur :
docker rm contssh
Se connecter à l’intérieur d’un conteneur :
docker exec -it contssh bash
Déboguer un conteneur :
docker logs contssh
Arrêter tous les conteneurs :
docker stop $(docker ps -aq)
Supprimer les conteneurs et images non utilisées pour plus de clarté :
docker system prune -a
Une registry Docker est simplement un dépôt avec des images Docker. La registry la plus connue et utilisée par défaut par Docker est le DockerHub. Celle-ci est publique et contient des images officielles pour la majorité des briques de base utilisées par les applications faites par les développeurs.
On peut par exemple y retrouver : Debian, Apache, NodeJS, MongoDB, MySQL, …
Le DockerHub est l’endroit où vous devez rechercher votre image de base !
Les images présentes sur le DockerHub ont des tags. Ces tags représentent des versions précises. Vous pouvez utilisez ces tags lorsque vous faites un FROM.
Exemple :
FROM apache:2.4
(https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)
Voici quelques points qui méritent attention.
A noter que Docker utilise un système de couche (layer) à des fins d’optimisation des build d’images. Une couche est une image intermédiaire.
Pour chaque ligne du Dockerfile, Docker crée une couche. Une image Docker est donc un empilement de couches c’est-à-dire d’images intermédiaires. Ainsi nul besoin pour Docker de tout refaire à chaque build, il va réutiliser les couches qui n’ont pas changé.
Il existe 2 instructions Docker pour exécuter “quelque chose”. Il s’agit de RUN et CMD.
Ces 2 instructions ne sont pas similaires. RUN crée une nouvelle couche (image intermédiaire) en incluant le résultat de la commande qu’on lui transmet. Cette instruction agit donc au niveau de l’image (docker build).
CMD exécute une commande à chaque démarrage d’un conteneur. Cette instruction agit donc au niveau du conteneur. Cette instruction est souvent nécessaire pour le démarrage de services (Apache, nodeJS, …).
Docker est prévu pour faire fonctionner des architectures microservices. Dans ce type d’architecture, on crée un conteneur par service.
Ceci a pour but de pouvoir multiplier le nombre de conteneurs suivant la demande. Imaginez un site Web PHP MVC, nous créerons un Dockerfile avec le code et le serveur Web et un autre Dockerfile avec la base de données. Le Dockerfile avec le code et le serveur Web peut facilement être multiplié en plusieurs conteneurs pour augmenter les performances. C’est ce que l’on appelle de la mise à échelle horizontale (horizontal scaling).
Ceci est bien beau mais :
C’est ici qu’intervient Docker Compose qui est un script Go permettant de simplifier la création de ces architectures microservices. Avec un seul fichier YAML, on pourra créer notre architecture. docker compose ajoutera tous les services (conteneurs) dans un même réseau ce qui permettra une communication entre les conteneurs.
docker compose permet également facilement la création de volumes. Ceci permet d’effectuer la persistance de données en dehors d’un conteneur. Ainsi lorsqu’un conteneur est détruit, les données ne sont pas perdues. Les données (DB, code source …) sont généralement stockées sur la machine hôte et un volume est créé dans le conteneur pour qu’il puisse utiliser ces données. Il s’agit tout simplement d’un point de montage entre le conteneur et la machine hôte.
docker compose a normalement déjà été installé avec docker.
Vérifier l’installation :
docker compose version
L’utilisation de docker compose se fait en 3 étapes :
Les fichiers YAML sont de simples fichiers textes dont le but est de fournir une description structurée et lisible. L’arborescence est créée par une indentation d’espaces.
Voici un exemple de base :
services :
myapp :
build :
context : ./dirWithDockerFile/
ports:
- 8000:80
mysql :
image: mariadb:10.4
volumes:
- mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: mydb
volumes :
mysql-data: {}
La directive «build» permet de construire une image Docker à partir d’un Dockerfile.
La directive «ports» permet d’effectuer la redirection de ports (port forwarding) entre la machine hôte et le conteneur. Cette directive attend un tableau, c’est pourquoi chaque élément commence par un «-».
La directive «volumes» permet de lier un répertoire de la machine hôte au conteneur. Les volumes ne sont pas détruits par défaut lors de la destruction du conteneur. C’est donc via ce biais que les données persistantes des conteneurs sont gérées. Deux manières sont utilisées pour la création des volumes :
Les noms des services (conteneurs) deviennent des noms réseaux. Imaginez que mon appplication ci-dessus doive accéder dans son code à la base de données MySQL. Cette base de données est située dans un autre conteneur nommé mysql. Je peux y accéder au niveau réseau en donnant le nom mysql.
Créer et lancer tous les services présents dans le compose.yaml :
docker compose up -d
Supprimer tous les services (conteneurs) présents dans le compose.yaml :
docker compose down
Supprimer tous les services (conteneurs) présents dans le compose.yaml ainsi que les volumes (données persistantes) :
docker compose down -v
Vérifier la syntaxe du fichier yaml :
docker compose config
Voir les conteneurs et leur état :
docker compose ps -a
Voir les logs (utile pour comprendre une erreur de déploiement) :
docker compose logs
Pour supprimer les images, conteneurs, réseaux et volumes : Ceci peut être utile pour effectuer un nettoyage complet
docker compose down --rmi all --volumes
docker compose a évolué au cours du temps. Nous utilisons actuellement docker compose version 2.
Vous trouverez encore sur Internet des exemples pour docker compose version 1. Les différences sont minimes.
La commande de docker compose version 1 comportait un tiret (docker-compose) et utilisait généralement un fichier compose.yaml. En outre, il fallait indiquer la version dans le fichier.
La conception de Docker s’est inspirée de la méthodologie des 12 facteurs, une méthodologie pour créer des applications SaaS [Modèles de service]. Voici un lien vers cette méthodologie [https://12factor.net/fr/]. Voyons comment Docker applique celle-ci.
Retenez cinq facteurs avec leurs exemples Docker.
Vu le succès des conteneurs, la majorité des applications sont maintenant déployées de la sorte. Il devient donc nécessaire d’avoir un outil pour gérer ces conteneurs. Kubernetes répond à cette demande. Kubernetes est un orchestrateur de conteneurs.
Kubernetes permet d’appréhender les défis liés à la gestion des conteneurs notamment :
Kubernetes est composé d’un nœud maître permettant la gestion du cluster k8s. Un cluster est un ensemble de machines physiques ou virtuelles. Chaque machine du cluster est appelée un “worker node” et contiennent une solution de déploiement de conteneurs (Docker par ex.).
Chaque “worker node” héberge un pod. Un pod est l’unité de déploiement d’une application dans k8s. Il s’agit d’un ou plusieurs conteneurs. Dans la pratique, le plus souvent un pod == un conteneur/un processus.
Un label est un couple “clé:valeur” que l’on peut attacher à un objet, notamment un pod. Les selectors permettent de sélectionner un objet k8s suivant son label
Image issue de : https://hub.alfresco.com/t5/alfresco-process-services/activiti-7-deep-dive-series-deploying-and-running-a-business/ba-p/288347
Image issue de : https://hub.alfresco.com/t5/alfresco-process-services/activiti-7-deep-dive-series-deploying-and-running-a-business/ba-p/288347
Un fichier deployment.yml permet de définir comment un Pod sera déployé. Ce fichier contient une instruction “replica” qui indiquera à K8s combien d’instances de ce Pod il devra lancer/maintenir.
Un fichier services.yml permet de définir et gérer le réseau à l’intérieur du cluster. Vu que les pods peuvent être créés, détruits et recréés, il est nécessaire qu’un service puisse cibler les pods encore actifs à un moment t.
Ingress est un load balancer qui permet de faire communiquer le monde extérieur avec le cluster k8s. Nginx peut fournir ce service.
Les Persistent Volume Claim (PVC) permettent de persister des données. Cela va beaucoup plus loin que l’utilisation de simples volumes (PV). Il s’agit d’une demande d’espace adressée à k8s. Celui-ci attribuera alors au pod un stockage suivant sa demande. A noter aussi que l’intérêt de k8s par rapport au stockage est de pouvoir utiliser des stockages variés (Amazon, Azure, Local, …).
Dans un développement de logiciel actuel, on ne livre plus seulement un exécutable au client. La livraison du logiciel inclut de plus en plus le déploiement de l’application et la mise à jour en continu. Ces 2 derniers points impliquent les administrateurs système.
Dans cette approche, il est donc nécessaire d’unifier 2 entités souvent séparées en entreprise : les développeurs et les administrateurs système aussi appelés opérationnels.
SysAdmin vs Developer
Il est important de savoir que les développeurs et les administrateurs système ont des objectifs différents et que par conséquent leurs réponses par défaut face à une demande seront différentes. Les développeurs vivent des besoins de leurs clients et sont donc toujours enclins à développer un nouveau logiciel. Ils répondent souvent par l’affirmative à une demande. Les administrateurs système ont pour objectif de préserver l’environnement informatique. À toute demande, ils vont donc privilégier une réponse négative si vous ne leur donnez pas un minimum de garantie.
DeVops est donc une approche visant à faire travailler ensemble les administrateurs système et les développeurs. DevOps mise sur la confiance entre les acteurs, incite les acteurs à expérimenter et s’inspire de la philosophie japonaise Kai Zen bien connue dans le monde l’industrie. Il s’agit en fait d’un état d’esprit et d’un processus d’amélioration continue.
Le déploiement d’une application faisant maintenant partie du produit ainsi que les mises à jour en continu, il est donc nécessaire d’avoir une infrastructure avec le concours des opérationnels pour mener à bien ce nouveau mode de développement logiciel.
DevOps en image :
Schéma à connaître
On voit sur cette image le cycle DevOps depuis le cahier des charges (Plan) jusqu’à la surveillance de l’application en production. Ce cycle se répète à l’infini.
L’approche DevOps mise également sur l’automatisation via des outils. On parlera souvent de pipeline de développement. Il s’agit d’une chaîne de production logicielle la plus automatisée possible jusqu’au client. Celle_ci se divise généralement en une partie CI (Continuous Integration) qui s’occupe de tester l’application et une partie CD (Continuous Deployment) qui s’occupe de déployer l’application pour les clients.
Sans surprise, les pipelines utiliseront les éléments vus dans les chapitres précédents surtout les conteneurs, les orchestrateurs, le Cloud et les outils de configurations.
Exemple pipeline :
Image issue de : (https://dzone.com/articles/dockerizing-jenkins-part-2-deployment-with-maven-a)
On peut remarquer que Docker reste un composant essentiel dans ces diagrammes. Il est donc nécessaire qu’il soit connu par les développeurs et les opérationnels.
DevOps du côté développeurs :
DevOps va privilégier une architecture microservice, car celle-ci permet un meilleur contrôle et une montée en charge facilitée. Dans ce cadre, les développeurs doivent faciliter un déploiement impliquant une montée en charge (cfr Docker par ex.). Ils doivent être également conscients que leur code va certainement appeler d’autres services. Il faudra donc prévoir un code résilient par rapport à cet état des choses (quid si un service dont je dépends ne répond pas ?). Il existe des patterns spécifiques aux architectures microservices ( Ex : retry pattern).
Le dépôt de code sera également structuré de manière à faciliter l’approche DevOps qui demande au minimum un environnement de développement, de tests et de production. Il existe plusieurs techniques de structuration du dépôt visant à atteindre cet objectif.
DevOps du coté des sysadmins :
Le rôle des sysadmins dans le DeVops sera notamment de mettre à disposition des développeurs de l’IaaS ou du PaaS ( voir Déploiement Cloud ci-dessous). Ils seront souvent également en charge de la partie CD (Continuous Deployment)dans la chaine DeVOps.Les outils utilisés par les sysadmins dans ce cadre sont des outils de gestion de configuration (Chef, Puppet, Ansible, ..), des outils de gestion et utilisation des conteneurs (Docker, K8s). Nous verrons Ansible en labos car il peut également être utile à un développeur.
Jenkins est un outil open source écrit en Java permettant notamment la création de pipelines. Il s’intègre parfaitement avec d’autres outils comme Docker , Github, … .
apt install fontconfig openjdk-17-jre -y
apt install wget -y
wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian/jenkins.io-2023.key
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc]" \
https://pkg.jenkins.io/debian binary/ | tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
apt-get update
apt-get install jenkins -y
Ensuite, jenkins sera accessible par défaut sur le port 8080. Un mot de passe initial vous sera demandé pour terminer l’installation.
Créez ensuite votre compte administrateur jenkins et installez les plugins suggérés.
Créez un pipeline via ajouter un “nouveau item”.
Voici un pipeline de base. Il s’agit d’une série simplement d’un série d’étape visant à construire, tester, déployer une application. Les 2 instructions les plus basiques à utiliser sont :
pipeline {
agent any
stages {
stage('Stage 1') {
steps {
echo 'Hello world!'
sh 'ls -l'
}
}
}
}
Jenkins possède un mécanisme de variables d’environnement. Certaines sont déjà définies par Jenkins et nous pouvons définir nos propres variables.
pipeline {
agent any
environment {
MAVAR = "World !"
}
stages {
stage('Stage 1') {
steps {
echo "Hello ${MAVAR}"
echo "Le numéro de BUILD JENKINS est : ${BUILD_ID}"
echo "Le workspace de JENKINS : ${env.WORKSPACE}"
}
}
}
}
Vous trouverez un lien pipeline syntax qui renvoie vers un assistant de création de morceaux de scripts pipeline. Vous pouvez notamment utiliser l’assistant ckeckout pour facilement créer le script de clonage d’un dépôt git. Vous trouverez également via ce biais de la documentation en ligne qui est bien fournie.
Pour les administrateurs systèmes, il est nécessaire de disposer d’outils pour automatiser les tâches d’installations et de configurations. En effet, les administrateurs systèmes doivent s’occuper d’un parc de machines et il est donc insensé de configurer toutes ses machines à la main.
Pour ce faire, il existe différents outils permettant d’automatiser les installations et configurations. Nous pouvons citer Puppet, Chef et Ansible. Nous verrons Ansible en labos car il peut également se révéler utile pour un développeur.
Ansible a défini son propre vocabulaire. On parle de contrôleur qui est est la machine qui exécute Ansible en tant que tel et de cibles qui sont les machines qu’Ansible configure. Les cibles sont définies dans l’inventaire d’Ansible, simple fichier reprenant des noms de machines ou IP de machines. A noter que le contrôleur et la cible peuvent être la même machine. Dans ce cas, cela signifie que nous automatisons alors simplement un ensemble de tâches pour une seule machine. Nous procéderons de cette manière durant les labos. Vous verrez que l’on précisera toujours dans notre fichier Ansible localhost comme cible !
Ansible se base sur SSH pour pouvoir se connecter et déployer des configurations sur les cibles. Ansible utilise des fichiers YAML. Je vous conseille d’utiliser VS Code pour faire votre fichier YAML, vous aurez ainsi déjà une vérification syntaxique. Vous pouvez utiliser l’extension Remote SSH de VSCode pour éditer un fichier sur votre VM à travers SSH !
Ansible parle de playbooks. Un playbook est simplement un fichier YAML décrivant un ensemble de tâches à effectuer sur un ensemble de cibles.
Ansible dispose de nombreux modules permettant d’effectuer des tâches. Voici les plus importants :
Ces modules sont disponibles dans la liste des modules builtin : (https://docs.ansible.com/ansible/latest/collections/ansible/builtin/index.html#plugins-in-ansible-builtin)
Voici la liste complète des modules et plugins : (https://docs.ansible.com/ansible/latest/collections/index_module.html) Utilisez la recherche par catégorie de modules ou par nom de module
Ansible dispose d’attributs spéciaux. Ceux peuvent être considérer comme des éléments du langage Ansible.
Exemples :
---
# gather facts, notify/handlers
- hosts: localhost
gather_facts: true
tasks:
- name: Install Nginx
package:
name: nginx
state: latest
when: ansible_distribution == 'CentOS'
notify: restart nginx
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
---
# loop ands item
- hosts: localhost
- name: Create new users
user:
name: '{{ item }}'
state: present
loop:
- john
- mike
- andrew
---
# become, vars , loop, gather facts
# gather facts true by default
- name: Install software
become: yes
hosts: all
vars:
packages:
- name: neofetch
required: True
- name: cpu-checker
required: True
- name: screenfetch
required: False
tasks:
- name: Install "{{ item.name }}" on Ubuntu
apt:
name: "{{ item.name }}"
state: present
when:
- item.required == True
- ansible_facts['distribution'] =="Ubuntu"
loop: "{{ packages }}"
apt-get install ansible
---
# hosts : liste des hosts où le playbook s'appliquera
- hosts: Web
tasks:
# name : description de la tâche
- name: "Install Apache Web Server"
# module ansible appelé (voir ansible modules)
apt:
name: apache2
state: latest
Voici comment lancer le playbook :
ansible-playbook playbook.yml
Vous devez être root pour lancer cette commande. D’autres options et subtilités existent dans Ansible mais nous nous limiterons pour ce cours à des playbook simples et lancés en tant que root.
Pour créer vos tâches, il est utile de consultez la liste des Modules Ansible disponibles
Vérifier la syntaxe de votre fichier YAML ansible.
ansible-playbook playbook.yml --syntax-check
Exécuter à blanc le playbook. Ceci permet de vérifier le déroulement du playbook mais ansible n’applique pas les modifications.
ansible-playbook playbook.yml --check
Déboguer un playbook. Il est possible également de lancer ansible-playbook en mode verbeux.
ansible-playbook playbook.yml -vvvv
Ansible permet de séparer un playbook dans plusieurs fichiers. On appelle cela un rôle Ansible. Un rôle Ansible est un répertoire contenant l’arborescence suivante :
La précédence pour la définition des variables est celle-ci (de la priorité la plus basse à la plus haute):
# Créer un rôle mongodb
# la commande suivante créera un répertoire mongodb avec l'arborescence décrite ci-dessus
ansible-galaxy init mongodb
Visuellement voici l’exemple du rôle mongodb :
L’avantage de ces rôles est la réutilisation.
Pour utiliser un rôle, il suffit de l’appeller dans un playbook.
---
- name: "test role"
hosts: localhost
gather_facts: false
roles:
- mongodb
L’utilisation de variables dans un playbook ou un rôle permet de faciliter la réutilisation.
Dans un playbook, on peut définir des variables directement après la directive hosts de la manière suivante :
---
- name: "test"
hosts: localhost
vars:
myvar: myvarvalue
tasks:
name: "show myvar value"
ansible.builtin.command: echo "{{ myvar }}"
Dans un rôle ansible, on peut définir des variables dans les dossiers suivants :
Lors de l’appel à un rôle ansible, on précise les valeurs des variables de la même manière que pour les playbooks.
Ansible propose également un mécanisme d’extension et de partage des rôles sous un format standardisé. Ceci s’appelle une collection Ansible. La commande ansible-galaxy permet de gérer ces collections.
Ceci ne fera pas l’objet de ce cours.
A l’origine, le terme Cloud (nuage) était la représentation d’Internet dans des schémas réseaux. Actuellement le Cloud désigne une infrastructure où tout est virtualisé et abstrait. On ne sait plus exactement où sont stockées les données, ni comment. Le plus souvent, ces données sont stockées dans des grands centres données connectés à Internet. On a vu apparaitre de grands acteurs du Cloud. Les plus connus étant Amazon et Azure (Microsoft).
Le Cloud est une abstraction de l’infrastructure. Le cloud est devenu très populaire car il permet d’accélérer la transition numérique pour de nombreuses entreprises. Par ces caractéristiques (ci-dessous), le Cloud permet aux entreprises d’être plus agiles et compétitives.
IaaS : Déploiement d’une infrastructure via les outils du fournisseur Cloud. L’utilisateur peut paramétrer le réseau, les serveurs, … . Ex: Amazon EC2, Azure VM, …
Terraform est certainement l’outil le plus utilisé pour déployer de l’IaaS. Il permet de créer des VM et d’autres éléments d’infrastructure sur AWS, Azure, … . Cet outil est décrit dans la section suivante.
PaaS : Déploiement d’une plateforme via les outils du fournisseur Cloud. L’utilisateur peut paramétrer la plateforme mais celui ci n’a aucun accès, vue sur l’infrastructure. Ceci est un des modèles de service Cloud les plus employés par les développeurs. Ex: Heroku, AWS Elastic Beanstalk, Cloud Foundry, …
FaaS: Déploiement d’une fonction dans le Cloud. Ici l’utilisateur ne paramètre rien. Il choisit son langage et écrit son code. Aucun accès, vue sur l’infrastructure, paramétrage. Ceci est un des modèles de service Cloud les plus employés par les développeurs. Ex: fonctions lambda AWS, …
SaaS: Accès à une application via Internet. Aucun accès, vue sur l’infrastructure, paramétrage par l’utilisateur limité. Ex: Gmail, Office365, …
Comparaison en schéma :
Image issue de : (https://cloudmeb.com/resource/saas-vs-paas-vs-iaas-quelle-est-la-difference-et-comment-choisir/?lang=fr)
Qu’est qu’une architecture multi-tenant ?
Dans une architecture multi-tenant, une même instance d’une application logicielle est utilisée par plusieurs clients, ces derniers étant des « tenants ».
Le modèle multi-tenant peut s’avérer économique, étant donné que les coûts liés au développement et à la maintenance des logiciels sont partagés.
Par opposition, une architecture single-tenant est une architecture dans laquelle chaque client possède sa propre instance de logiciel et peut avoir accès au code. Dans une architecture multi-tenant, le fournisseur n’exécute les mises à jour qu’une seule fois, alors que dans une architecture single-tenant, il doit gérer plusieurs instances du logiciel pour appliquer les mises à jour.
3 approches sont possibles :
Approches | Description | Avantages | Inconvénients |
---|---|---|---|
Multi-tenant | Les clients se partagent la même application et la même DB | Coût de location et maintenance faible, mise à l’échelle aisée, déploiement facile des mises à jour | Effets de bords liés aux colocataires (sécurité, performance) |
Multi-DB | Les clients se partagent la même application mais ont chacun leur propre base de données | Isolation totale des données (sécurité) | Coût location et maintenance plus élevé. Mise à l’échelle compliquée |
Multi-instances / Single tenant | Chaque client a sa propre instance d’application et sa propre DB | Isolation totale, mise à l’échelle aisée, personnalisations possibles | Coût très élevé |
Image issue de : https://www.techtarget.com/whatis/definition/multi-tenancy
Les modèles de service SaaS présentes dans le Cloud proposent souvent les approches multi-tenant et single-tenant. Ainsi suivant ses priorités et son budget, on peut effectuer un choix.
Terraform est un outil permettant de déployer des ressources dans le Cloud. En clair, il permet d’automatiser la création de ressources (VM, image docker, …) en local ou dans le Cloud. Il dispose de nombreux connecteurs (providers) permettant de créer des ressources aussi bien dans AWS (Amazon), Azure, en local, … Ce dernier point le rend particulièrement intéressant au sein des entreprises.
Terraform utilise le langage HCL (HashiCorp Configuration Language). Ce langage possède une syntaxe simple et lisible. Contrairement à certains langages de configuration plus verbeux, le HCL utilise une approche minimaliste qui le rend accessible aux développeurs, aux administrateurs système et à toute personne impliquée dans la gestion de l’infrastructure.
Chaque bloc définit une ressource. Dans l’exemple suivant, vous avez un bloc définissant la recherche d’une image de machine virtuelle sur Amazon (aws_ami pour Amazon Machine Image). Ensuite un deuxième créant une machine virtuelle Amazon (aws_instance) faisant référence à l’image recherchée (data.aws_ami.ubuntu.id).
Vous donnez un nom à chaque ressource pour y faire référence. Dans l’exemple suivant, “ubuntu” est le nom de référence choisi pour la ressource image de machine virtuelle (data “aws_ami”). De la même manière, “web” est le nom de référence choisi pour la ressource “aws_instance”.
Ces noms de référence doivent être en minuscules et sans caractères spéciaux (pas d’underscore !).
Exemple :
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
tags = {
Name = "HelloWorld"
}
}
apt-get update
apt-get install -y gnupg software-properties-common wget curl
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/hashicorp.list
apt update && apt install -y terraform
Terraform utilise des providers. Un provider est généralement un acteur du Cloud où il est possible de créer des ressources (stockage, FaaS, IaaS, SaaS, PaaS, …).
Les providers les plus connus et utilisés par Terraform sont AWS et Azure. Suivant le provider utilisé, il sera sans doute nécessaire de réaliser des installations/configurations supplémentaires. En général, ces configurations ont pour but de lier le provider terraform à un compte du provider. Et oui, la création de ressources dans le Cloud sur Azure ou Amazon n’est pas gratuite, même via terraform.
Pour utiliser Azure comme provider, il faut installer la console Azure CLI :
curl -sL https://aka.ms/InstallAzureCLIDeb | bash
az login --use-device-code
Ceci vous donnera en retour un affichage JSON où vous verrez la jonction avec votre abonnement Azure.
LocalStack est un provider un peu particulier qui émule les services Cloud d’AWS. Ceci permet donc de créer et tester des déploiements de ressources en local de la manière que si vous étiez sur AWS.
Nous utiliserons la version communautaire de LocalStack qui est entièrement gratuite. Nous ne pourrons pas tester tous les services d’Amazon mais les principaux.
LocalStack peut s’installer facilement via docker compose.
services:
localstack:
container_name: "${LOCALSTACK_DOCKER_NAME:-localstack-main}"
image: localstack/localstack
ports:
- "127.0.0.1:4566:4566" # LocalStack Gateway
- "127.0.0.1:4510-4559:4510-4559" # external services port range
environment:
# LocalStack configuration: https://docs.localstack.cloud/references/configuration/
- DEBUG=${DEBUG:-0}
volumes:
- "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
docker compose up -d
Même si son intérêt est plus limité que les providers précédents, il existe également un provider Docker. Ceci permet de créer/déployer des images et conteneurs Docker via Terraform en local ou à distance.
Le seul prérequis est d’avoir Docker installé sur la machine (locale ou distante) sur laquelle la configuration Terraform s’appliquera.
Une fois Terraform ainsi que les prérequis du ou des providers choisis installés, voici les étapes de déploiement des ressources :
terraform init
terraform plan
terraform apply
terraform destroy
Ceci peut se résumer via le schéma suivant :
Image issue de : https://blog.stephane-robert.info/docs/infra-as-code/provisionnement/terraform/introduction/
A noter que terraform enregistre un état de l’infrastructure que l’on déploie.
Concrètement, à la première exécution de terraform apply, terraform créera un fichier terraform.state pour conserver l’état de ce qui a été déployé. A chaque nouvel appel à terraform apply, terraform refraichira son état en interrogeant le provider pour s’assurer de la cohérence de l’infrastructure déployée (une ressource a pu être supprimée par exemple autrement que par terraform). Ensuite, terraform déterminera les changements faits dans main.tf par rapport à cet état et appliquera les changements. Cela explique que terraform apply prend toujours un peu de temps.
A noter aussi que le but de cet enregistrement est de garder l’état de votre infrastructure (toutes les ressources nécessaires pour votre infrastructure), cela n’agit pas comme un script sans prendre en compte les appels précédents.
Si vous voulez recommencer totalement à zéro, vous devrez effacer le fichier terraform.state.
Voici le code pour utiliser le provider Azure avec Terraform :
# Configure the Azure provider
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=3.80.0"
}
}
required_version = ">= 1.6.3"
}
provider "azurerm" {
features {}
skip_provider_registration = true
}
Voici le code de base pour déployer une App Service NodeJS :
# Generate a random integer to create a globally unique name
resource "random_integer" "ri" {
min = 10000
max = 99999
}
# Create the resource group
resource "azurerm_resource_group" "rg" {
name = "myResourceGroup-${random_integer.ri.result}"
location = "West Europe"
}
# Create the Linux App Service Plan
resource "azurerm_service_plan" "appserviceplan" {
name = "webapp-asp-${random_integer.ri.result}"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
os_type = "Linux"
sku_name = "F1"
}
# Create the web app, pass in the App Service Plan ID
resource "azurerm_linux_web_app" "webapp" {
name = "webapp-${random_integer.ri.result}"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
service_plan_id = azurerm_service_plan.appserviceplan.id
https_only = true
site_config {
minimum_tls_version = "1.2"
always_on = false // Required for F1 plan (even though docs say that it defaults to false)
use_32_bit_worker = true // Required for F1 plan
application_stack {
node_version = "16-lts"
}
}
}
# Deploy code from a public GitHub repo
resource "azurerm_app_service_source_control" "sourcecontrol" {
app_id = azurerm_linux_web_app.webapp.id
repo_url = "https://github.com/olivierchoquet/exoplanet_infra_terraform.git"
branch = "main"
use_manual_integration = true
use_mercurial = false
}
** Documentation azure ** Dans le cadre de ce cours, nous utiliserons uniquement Terraform pour déployer des App Service dans le Cloud Azure. Voici 2 liens vers la documentation la plus utile :
Comme indiqué plus haut, LocalStack est un émulateur local des services d’Amazon (AWS). Cela se remarque nettement dans la configuration ci-dessous.
provider "aws" {
access_key = "test"
secret_key = "test"
region = "us-east-1"
s3_use_path_style = false
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
endpoints {
dynamodb = "http://localhost:4566"
ec2 = "http://localhost:4566"
lambda = "http://localhost:4566"
iam = "http://localhost:4566"
s3 = "http://s3.localhost.localstack.cloud:4566"
}
}
Pour rappel, LocalStack permet d’émuler des services AWS en local. Nous n’utiliserons que quelques services (les principaux) d’AWS à savoir :
Voici le code de base pour déployer un bucket S3 :
# Définition d'un Bucket S3
# Son nom de référence dans ce fichier sera mybucket (attention pas underscore dans nom de référence !)
resource "aws_s3_bucket" "mybucket" {
bucket = "mybucketname"
}
# Définition d'une ACL (Access Control List) pour notre bucket
# Accès en lecture pour tous
resource "aws_s3_bucket_acl" "public_access_acl" {
# Remarquez la référence à note bucket -> mybucket après aws_s3_bucket
bucket = aws_s3_bucket.mybucket.id
acl = "public-read"
}
# Uploader un fichier dans le bucket
resource "aws_s3_object" "object_to_upload" {
# Donner la référence vers le bucket
bucket = "mybucketname"
key = "myobjectkey"
source = "path/to/file"
# Le bucket doit être créé avant de pouvoir uploader un fichier
depends_on = [aws_s3_bucket.mybucket]
}
Voici le code de base pour déployer une fonction lambda :
# Il est nécessaire de définir un rôle IAM (Identity and Access Management)
# Ici rôle basique donnant un accès à tous à la fonction lambda
data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role" "iam_for_lambda" {
name = "iam_for_lambda"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}
# On définit la fonction lambda.
# index.js est le fichier contenant le code (js) de cette fonction
data "archive_file" "lambda" {
type = "zip"
source_file = "index.js"
output_path = "lambda_function_payload.zip"
}
resource "aws_lambda_function" "test_lambda" {
# If the file is not in the current working directory you will need to include a
# path.module in the filename.
filename = "lambda_function_payload.zip"
function_name = "lambdaoch"
role = aws_iam_role.iam_for_lambda.arn
# search handler in index.js
handler = "index.handler"
source_code_hash = data.archive_file.lambda.output_base64sha256
runtime = "nodejs18.x"
environment {
variables = {
foo = "bar"
}
}
}
# Il est utile que cette fonction soit accessible directement via une URL
# On peut ainsi envoyer directement une requête avec lynx ou curl à la fonction lambda
resource "aws_lambda_function_url" "test_latest" {
function_name = aws_lambda_function.test_lambda.function_name
authorization_type = "NONE"
}
Pour tester les ressources déployées avec Terraform sur le Cloud Azure, rendez-vous sur le site https://portal.azure.com.
La commande awslocal vous permettra de voir les ressources déployées dans LocalStack. Voici comment l’installer :
apt install python3-full mandoc
python3 -m venv ~/venv && source ~/venv/bin/activate && cd ~/venv/bin && pip install awscli-local[ver1] && deactivate
Pour plus de facilité, vous pouvez créer un alias vers la commande awslocal et activer l’auto-complétion :
éditer le fichier .bashrc présent dans la home directory de votre compte utilisateur et ajouter ceci en fin de fichier :
alias awslocal='~/venv/bin/awslocal'
if [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
complete -C '~/venv/bin/aws_completer' awslocal
Une fois cette commande installée :
Pour avoir de l’aide c’est-à-dire les pages du manuel consacrée à awslocal :
awslocal help
Pour avoir de l’aide sur la commande s3 :
awslocal s3 help
Pour lister les s3 buckets :
awslocal s3 ls
Pour envoyer un objet dans un s3 bucket :
curl -X PUT http://localhost:4566/<mybucketname>/<myobjectkey> -T document.txt
Pour récupérer un objet dans un s3 bucket :
curl http://localhost:4566/<mybucketname>/<myobjectkey>
awslocal s3api get-object --bucket <bucket_name> --key <object_key> <outputfile>
Pour lister les fonctions lambda :
awslocal lambda list-functions
Pour appeler une fonction lambda :
awslocal lambda invoke --function-name <function_name> <output_file>
Pour appeler une fonction lambda avec paramètres :
awslocal lambda invoke --function-name addItemFunction --payload '{"item":"bonjour2"}' out
Pour voir la configuration d’une URL de fonction lambda :
awslocal lambda list-function-url-configs --function-name <function_name>
Pour voir le contenu d’une table DynamoDB :
awslocal dynamodb scan --table-name <my_table>
Pour voir les infos sur les instances créées :
awslocal ec2 describe-instances --query "Reservations[*].Instances[*].{IP:PublicIpAddress,ID:InstanceId,Type:InstanceType,State:State.Name,Name:Tags[0].Value}" --output=table
Se documenter sur Terraform n’est pas aisé. Terraform est dépendant des providers et essaie de faire au mieux pour rendre son utilisation la plus simple possible. Cependant il faut bien avouer qu’il vaut mieux connaître le provider pour réaliser une configuration Terraform correcte. En effet, il faut par exemple savoir que les machines virtuelles d’Amazon s’appellent des EC2, … .
13.6.6.1 Comment se documenter ?