[{"data":1,"prerenderedAt":2694},["ShallowReactive",2],{"labs-list":3},[4,571,1466,2065],{"id":5,"title":6,"body":7,"date":557,"description":558,"doc":559,"extension":560,"git":559,"image":561,"isExperimentation":130,"meta":562,"navigation":130,"path":563,"seo":564,"stem":565,"tags":566,"type":567,"updatedAt":559,"website":559,"__hash__":570},"laboratoire\u002Flaboratoire\u002Fterraform_gcp_vm_hackaton.md","Terraform  - GCP VM",{"type":8,"value":9,"toc":553},"minimark",[10,15,19,22,25,28,41,46,49,53,56,59,65,161,164,169,172,218,223,226,229,549],[11,12,14],"h1",{"id":13},"terraform-gcp-vm-hackaton","Terraform - GCP VM Hackaton",[16,17,18],"p",{},"L'objectfi de ce LAB étais d'allier les compétences de mes étudiants avec les miennes. Le but principal étais pour moi de déployer une toute petite infrastrcuture avec Google Cloud project composer de 3 VM Linux sous débian 12 grace a Terraform, d'attribuer de créer un utilisateur IAM et de lui attribuer les bon droit pour pouvoir garder l'environement des VM sécuriser pour mes étudiants et pour moi même. J'ai du rajouter également des règles réseaux pour autoriser les connexion ssh, HTTP, HTTPs pour pouvoir afficher le résulat du Hackaton. J'ai également rediriger les DNS de 3 nom de domaine différents vers l'IP publique des VM respectives.",[16,20,21],{},"L'objectif de mes étudiants étais de se connecter a ses VM avec la clef ssh fournie et de déployer une petite application Frontend,, de configurer un reverse proxy en utilisant Caddy, de sécuriser également le server avec les règles de base bloquer tout les port sauf ce utilse (80,443,22...) et également d'installer un Fail2ban.",[16,23,24],{},"Pour les plus motiver, l'idée étais de pouvoir également installer un Database de type Mariadb sur le server de créer un petit script PHP également qui affiche la date du jours et récupère quelques informations de la base de données et les affiche dans l'application Frontend.",[16,26,27],{},"Voici les éléments que j'ai pu fournir à mes étudiants :",[29,30,31,35,38],"ul",{},[32,33,34],"li",{},"Une clef SSH pour pouvoir se connecter a ses VM.",[32,36,37],{},"Un PDF avec les pistes pour reussir le LAB.",[32,39,40],{},"3 Nom de domaines pointant vers les VM respectives.",[42,43,45],"h2",{"id":44},"objectif-pédagogique-du-projet","Objectif pédagogique du projet",[16,47,48],{},"L'objectif étais avant tout de permetre a des étudiants de première année de découvrir un enviroment de production professionel de manière a comprendre comment fonctionne les serveurs, et de découvrir l'envers du décors également. Et également de pouvoir mettre a profis leur connaisance sur la mise en place d'outils tiers grace au documentations, IA et au projets devops qu'il on pue avoir au part avant.",[42,50,52],{"id":51},"infrastructure-deployer","Infrastructure deployer",[16,54,55],{},"Pour ce faire j'ai du configurer une petite infrastructure sur Google Cloud avec Terraform.",[16,57,58],{},"Voici le code terraform que j'ai utilisé :",[16,60,61],{},[62,63,64],"strong",{},"Provider.tf",[66,67,72],"pre",{"className":68,"code":69,"language":70,"meta":71,"style":71},"language-yaml shiki shiki-themes material-theme-lighter github-light monokai","terraform {\nrequired_providers {\ngoogle = {\nsource  = \"hashicorp\u002Fgoogle\"\nversion = \"~> 5.0\"\n}\n}\n}\n\nprovider \"google\" {\nproject = \"sys-hack-2026\"\nregion  = \"europe-west9\"\nzone    = \"europe-west9-a\"\n}\n","yaml","",[73,74,75,84,90,96,102,108,115,120,125,132,138,144,150,156],"code",{"__ignoreMap":71},[76,77,80],"span",{"class":78,"line":79},"line",1,[76,81,83],{"class":82},"sqNgn","terraform {\n",[76,85,87],{"class":78,"line":86},2,[76,88,89],{"class":82},"required_providers {\n",[76,91,93],{"class":78,"line":92},3,[76,94,95],{"class":82},"google = {\n",[76,97,99],{"class":78,"line":98},4,[76,100,101],{"class":82},"source  = \"hashicorp\u002Fgoogle\"\n",[76,103,105],{"class":78,"line":104},5,[76,106,107],{"class":82},"version = \"~> 5.0\"\n",[76,109,111],{"class":78,"line":110},6,[76,112,114],{"class":113},"s_bef","}\n",[76,116,118],{"class":78,"line":117},7,[76,119,114],{"class":113},[76,121,123],{"class":78,"line":122},8,[76,124,114],{"class":113},[76,126,128],{"class":78,"line":127},9,[76,129,131],{"emptyLinePlaceholder":130},true,"\n",[76,133,135],{"class":78,"line":134},10,[76,136,137],{"class":82},"provider \"google\" {\n",[76,139,141],{"class":78,"line":140},11,[76,142,143],{"class":82},"project = \"sys-hack-2026\"\n",[76,145,147],{"class":78,"line":146},12,[76,148,149],{"class":82},"region  = \"europe-west9\"\n",[76,151,153],{"class":78,"line":152},13,[76,154,155],{"class":82},"zone    = \"europe-west9-a\"\n",[76,157,159],{"class":78,"line":158},14,[76,160,114],{"class":113},[16,162,163],{},"Ce fichier de configuration simple me permet de dire a terraform que je veux travailler avec Google Cloud et que je veux utiliser le provider google. La region et la zone sont défini pour que terraform sache ou déployer les ressources.",[16,165,166],{},[62,167,168],{},"variables.tf",[16,170,171],{},"Déclaration des variables utilisées dans le projet. On y trouve l'utilisateur SSH et le chemin de la clé SSH.",[66,173,175],{"className":68,"code":174,"language":70,"meta":71,"style":71},"variable \"ssh_user\" {\ntype    = string\ndefault = \"debian\"\n}\n\nvariable \"ssh_pub_key_path\" {\ntype    = string\ndefault = \"~\u002F.ssh\u002Fhackaton_epitech.pub\"\n}\n",[73,176,177,182,187,192,196,200,205,209,214],{"__ignoreMap":71},[76,178,179],{"class":78,"line":79},[76,180,181],{"class":82},"variable \"ssh_user\" {\n",[76,183,184],{"class":78,"line":86},[76,185,186],{"class":82},"type    = string\n",[76,188,189],{"class":78,"line":92},[76,190,191],{"class":82},"default = \"debian\"\n",[76,193,194],{"class":78,"line":98},[76,195,114],{"class":113},[76,197,198],{"class":78,"line":104},[76,199,131],{"emptyLinePlaceholder":130},[76,201,202],{"class":78,"line":110},[76,203,204],{"class":82},"variable \"ssh_pub_key_path\" {\n",[76,206,207],{"class":78,"line":117},[76,208,186],{"class":82},[76,210,211],{"class":78,"line":122},[76,212,213],{"class":82},"default = \"~\u002F.ssh\u002Fhackaton_epitech.pub\"\n",[76,215,216],{"class":78,"line":127},[76,217,114],{"class":113},[16,219,220],{},[62,221,222],{},"main.tf",[16,224,225],{},"Ce fichier main retrace toute les ressources necessaire au deployement de l'infrastructure.",[16,227,228],{},"On y retrouve les 3 VM linux, leurs service account respectif avec les permissions necessaire pour que les étudiants puissent travailler sur les VM.",[66,230,232],{"className":68,"code":231,"language":70,"meta":71,"style":71},"esource \"google_compute_instance\" \"default\" {\ncount        = 3\nname         = \"vm-${count.index + 1}\"\nmachine_type = \"e2-micro\"\nzone         = \"europe-west9-b\"\ntags         = [\"web-server\"]\n\nboot_disk {\ninitialize_params {\nimage = \"debian-cloud\u002Fdebian-12\"\n}\n}\n\nnetwork_interface {\nnetwork = \"default\"\naccess_config {}\n}\n\nmetadata = {\nssh-keys = \"${var.ssh_user}:${file(var.ssh_pub_key_path)}\"\n}\n\nservice_account {\nemail  = google_service_account.vm_sa.email\nscopes = [\"cloud-platform\"]\n}\n}\n\nresource \"google_service_account\" \"vm_sa\" {\naccount_id   = \"vm-service-account\"\ndisplay_name = \"Custom VM Service Account\"\n}\n\nresource \"google_project_iam_member\" \"vm_sa_logging\" {\nproject = \"sys-hack-2026\"\nrole    = \"roles\u002Flogging.logWriter\"\nmember  = \"serviceAccount:${google_service_account.vm_sa.email}\"\n}\n\nresource \"google_compute_firewall\" \"allow_http_https\" {\nname    = \"allow-http-https\"\nnetwork = \"default\"\n\nallow {\nprotocol = \"tcp\"\nports    = [\"80\", \"443\"]\n}\n\nsource_ranges = [\"0.0.0.0\u002F0\"]\ntarget_tags   = [\"web-server\"]\n}\n\noutput \"instance_names\" {\nvalue = google_compute_instance.default[*].name\n}\n\noutput \"instance_ips\" {\nvalue = google_compute_instance.default[*].network_interface[0].access_config[0].nat_ip\n}\n",[73,233,234,239,244,249,254,259,264,268,273,278,283,287,291,295,300,306,312,317,322,328,334,339,344,350,356,362,367,372,377,383,389,395,400,405,411,416,422,428,433,438,444,450,455,460,466,472,478,483,488,494,500,505,510,516,522,527,532,538,544],{"__ignoreMap":71},[76,235,236],{"class":78,"line":79},[76,237,238],{"class":82},"esource \"google_compute_instance\" \"default\" {\n",[76,240,241],{"class":78,"line":86},[76,242,243],{"class":82},"count        = 3\n",[76,245,246],{"class":78,"line":92},[76,247,248],{"class":82},"name         = \"vm-${count.index + 1}\"\n",[76,250,251],{"class":78,"line":98},[76,252,253],{"class":82},"machine_type = \"e2-micro\"\n",[76,255,256],{"class":78,"line":104},[76,257,258],{"class":82},"zone         = \"europe-west9-b\"\n",[76,260,261],{"class":78,"line":110},[76,262,263],{"class":82},"tags         = [\"web-server\"]\n",[76,265,266],{"class":78,"line":117},[76,267,131],{"emptyLinePlaceholder":130},[76,269,270],{"class":78,"line":122},[76,271,272],{"class":82},"boot_disk {\n",[76,274,275],{"class":78,"line":127},[76,276,277],{"class":82},"initialize_params {\n",[76,279,280],{"class":78,"line":134},[76,281,282],{"class":82},"image = \"debian-cloud\u002Fdebian-12\"\n",[76,284,285],{"class":78,"line":140},[76,286,114],{"class":113},[76,288,289],{"class":78,"line":146},[76,290,114],{"class":113},[76,292,293],{"class":78,"line":152},[76,294,131],{"emptyLinePlaceholder":130},[76,296,297],{"class":78,"line":158},[76,298,299],{"class":82},"network_interface {\n",[76,301,303],{"class":78,"line":302},15,[76,304,305],{"class":82},"network = \"default\"\n",[76,307,309],{"class":78,"line":308},16,[76,310,311],{"class":82},"access_config {}\n",[76,313,315],{"class":78,"line":314},17,[76,316,114],{"class":113},[76,318,320],{"class":78,"line":319},18,[76,321,131],{"emptyLinePlaceholder":130},[76,323,325],{"class":78,"line":324},19,[76,326,327],{"class":82},"metadata = {\n",[76,329,331],{"class":78,"line":330},20,[76,332,333],{"class":82},"ssh-keys = \"${var.ssh_user}:${file(var.ssh_pub_key_path)}\"\n",[76,335,337],{"class":78,"line":336},21,[76,338,114],{"class":113},[76,340,342],{"class":78,"line":341},22,[76,343,131],{"emptyLinePlaceholder":130},[76,345,347],{"class":78,"line":346},23,[76,348,349],{"class":82},"service_account {\n",[76,351,353],{"class":78,"line":352},24,[76,354,355],{"class":82},"email  = google_service_account.vm_sa.email\n",[76,357,359],{"class":78,"line":358},25,[76,360,361],{"class":82},"scopes = [\"cloud-platform\"]\n",[76,363,365],{"class":78,"line":364},26,[76,366,114],{"class":113},[76,368,370],{"class":78,"line":369},27,[76,371,114],{"class":113},[76,373,375],{"class":78,"line":374},28,[76,376,131],{"emptyLinePlaceholder":130},[76,378,380],{"class":78,"line":379},29,[76,381,382],{"class":82},"resource \"google_service_account\" \"vm_sa\" {\n",[76,384,386],{"class":78,"line":385},30,[76,387,388],{"class":82},"account_id   = \"vm-service-account\"\n",[76,390,392],{"class":78,"line":391},31,[76,393,394],{"class":82},"display_name = \"Custom VM Service Account\"\n",[76,396,398],{"class":78,"line":397},32,[76,399,114],{"class":113},[76,401,403],{"class":78,"line":402},33,[76,404,131],{"emptyLinePlaceholder":130},[76,406,408],{"class":78,"line":407},34,[76,409,410],{"class":82},"resource \"google_project_iam_member\" \"vm_sa_logging\" {\n",[76,412,414],{"class":78,"line":413},35,[76,415,143],{"class":82},[76,417,419],{"class":78,"line":418},36,[76,420,421],{"class":82},"role    = \"roles\u002Flogging.logWriter\"\n",[76,423,425],{"class":78,"line":424},37,[76,426,427],{"class":82},"member  = \"serviceAccount:${google_service_account.vm_sa.email}\"\n",[76,429,431],{"class":78,"line":430},38,[76,432,114],{"class":113},[76,434,436],{"class":78,"line":435},39,[76,437,131],{"emptyLinePlaceholder":130},[76,439,441],{"class":78,"line":440},40,[76,442,443],{"class":82},"resource \"google_compute_firewall\" \"allow_http_https\" {\n",[76,445,447],{"class":78,"line":446},41,[76,448,449],{"class":82},"name    = \"allow-http-https\"\n",[76,451,453],{"class":78,"line":452},42,[76,454,305],{"class":82},[76,456,458],{"class":78,"line":457},43,[76,459,131],{"emptyLinePlaceholder":130},[76,461,463],{"class":78,"line":462},44,[76,464,465],{"class":82},"allow {\n",[76,467,469],{"class":78,"line":468},45,[76,470,471],{"class":82},"protocol = \"tcp\"\n",[76,473,475],{"class":78,"line":474},46,[76,476,477],{"class":82},"ports    = [\"80\", \"443\"]\n",[76,479,481],{"class":78,"line":480},47,[76,482,114],{"class":113},[76,484,486],{"class":78,"line":485},48,[76,487,131],{"emptyLinePlaceholder":130},[76,489,491],{"class":78,"line":490},49,[76,492,493],{"class":82},"source_ranges = [\"0.0.0.0\u002F0\"]\n",[76,495,497],{"class":78,"line":496},50,[76,498,499],{"class":82},"target_tags   = [\"web-server\"]\n",[76,501,503],{"class":78,"line":502},51,[76,504,114],{"class":113},[76,506,508],{"class":78,"line":507},52,[76,509,131],{"emptyLinePlaceholder":130},[76,511,513],{"class":78,"line":512},53,[76,514,515],{"class":82},"output \"instance_names\" {\n",[76,517,519],{"class":78,"line":518},54,[76,520,521],{"class":82},"value = google_compute_instance.default[*].name\n",[76,523,525],{"class":78,"line":524},55,[76,526,114],{"class":113},[76,528,530],{"class":78,"line":529},56,[76,531,131],{"emptyLinePlaceholder":130},[76,533,535],{"class":78,"line":534},57,[76,536,537],{"class":82},"output \"instance_ips\" {\n",[76,539,541],{"class":78,"line":540},58,[76,542,543],{"class":82},"value = google_compute_instance.default[*].network_interface[0].access_config[0].nat_ip\n",[76,545,547],{"class":78,"line":546},59,[76,548,114],{"class":113},[550,551,552],"style",{},"html pre.shiki code .sqNgn, html code.shiki .sqNgn{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#E6DB74}html pre.shiki code .s_bef, html code.shiki .s_bef{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#F8F8F2}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":71,"searchDepth":86,"depth":86,"links":554},[555,556],{"id":44,"depth":86,"text":45},{"id":51,"depth":86,"text":52},"2026-04-29","Création d'une structure de base sur GCP avec Terraform (VM) pour un Hackaton étudiant",null,"md","\u002Flaboratoire\u002Fterraform_gcp_vm_hackaton.png",{},"\u002Flaboratoire\u002Fterraform_gcp_vm_hackaton",{"title":6,"description":558},"laboratoire\u002Fterraform_gcp_vm_hackaton",[567,568,569],"devops","terraform","gcp","mN156FM7SaITRGEeJV_DMo7tkZ8VekVWAyggrs8sPDw",{"id":572,"title":573,"body":574,"date":1456,"description":1457,"doc":559,"extension":560,"git":559,"image":1458,"isExperimentation":130,"meta":1459,"navigation":130,"path":1460,"seo":1461,"stem":1462,"tags":1463,"type":567,"updatedAt":559,"website":559,"__hash__":1465},"laboratoire\u002Flaboratoire\u002Fterraform_aws_ec2_rds.md","Terraform  - AWS EC2 + RDS",{"type":8,"value":575,"toc":1448},[576,580,583,587,590,601,738,749,755,759,762,824,835,839,854,985,989,996,1007,1014,1020,1023,1040,1403,1408,1445],[11,577,579],{"id":578},"terraform-aws-ec2-rds-postgresql","Terraform  - AWS EC2 + RDS PostgreSQL",[16,581,582],{},"Cette experimentation consiste a deployer une instance EC2 et une base de donnees RDS PostgreSQL, puis a les integrer dans une architecture reseau AWS coherente.\nL'objectif est de construire une base d'infrastructure simple avec Terraform, en incluant le VPC, les subnets, le routage et les regles de securite.",[42,584,586],{"id":585},"configuration-et-monitoring-rapide","Configuration et monitoring rapide",[16,588,589],{},"Dans un premier temps, on configure le provider AWS et un mecanisme d'alerte budgetaire.\nL'idee est de limiter les risques de depassement de cout pendant les tests.",[16,591,592,593,596,597,600],{},"On cree un fichier ",[73,594,595],{},"provider.tf"," avec les informations de base (pensez a executer ",[73,598,599],{},"aws configure"," au prealable) :",[66,602,604],{"className":68,"code":603,"language":70,"meta":71,"style":71},"terraform {\n  required_providers {\n    aws = {\n      source  = \"hashicorp\u002Faws\"\n      version = \"~> 6.0\"\n    }\n  }\n}\n\nprovider \"aws\" {\n  region = \"eu-west-3\"\n}\n\nresource \"aws_budgets_budget\" \"example\" {\n  name         = \"EC2_RDS_BUDGET\"\n  budget_type  = \"COST\"\n  time_unit    = \"MONTHLY\"\n  limit_amount = \"1\"\n  limit_unit   = \"USD\"\n\n  notification {\n    comparison_operator        = \"GREATER_THAN\"\n    threshold                  = 50\n    threshold_type             = \"PERCENTAGE\"\n    notification_type          = \"ACTUAL\"\n    subscriber_email_addresses = [\"contact@kernellab.fr\"]\n  }\n}\n",[73,605,606,610,615,620,625,630,635,640,644,648,653,658,662,666,671,676,681,686,691,696,700,705,710,715,720,725,730,734],{"__ignoreMap":71},[76,607,608],{"class":78,"line":79},[76,609,83],{"class":82},[76,611,612],{"class":78,"line":86},[76,613,614],{"class":82},"  required_providers {\n",[76,616,617],{"class":78,"line":92},[76,618,619],{"class":82},"    aws = {\n",[76,621,622],{"class":78,"line":98},[76,623,624],{"class":82},"      source  = \"hashicorp\u002Faws\"\n",[76,626,627],{"class":78,"line":104},[76,628,629],{"class":82},"      version = \"~> 6.0\"\n",[76,631,632],{"class":78,"line":110},[76,633,634],{"class":113},"    }\n",[76,636,637],{"class":78,"line":117},[76,638,639],{"class":113},"  }\n",[76,641,642],{"class":78,"line":122},[76,643,114],{"class":113},[76,645,646],{"class":78,"line":127},[76,647,131],{"emptyLinePlaceholder":130},[76,649,650],{"class":78,"line":134},[76,651,652],{"class":82},"provider \"aws\" {\n",[76,654,655],{"class":78,"line":140},[76,656,657],{"class":82},"  region = \"eu-west-3\"\n",[76,659,660],{"class":78,"line":146},[76,661,114],{"class":113},[76,663,664],{"class":78,"line":152},[76,665,131],{"emptyLinePlaceholder":130},[76,667,668],{"class":78,"line":158},[76,669,670],{"class":82},"resource \"aws_budgets_budget\" \"example\" {\n",[76,672,673],{"class":78,"line":302},[76,674,675],{"class":82},"  name         = \"EC2_RDS_BUDGET\"\n",[76,677,678],{"class":78,"line":308},[76,679,680],{"class":82},"  budget_type  = \"COST\"\n",[76,682,683],{"class":78,"line":314},[76,684,685],{"class":82},"  time_unit    = \"MONTHLY\"\n",[76,687,688],{"class":78,"line":319},[76,689,690],{"class":82},"  limit_amount = \"1\"\n",[76,692,693],{"class":78,"line":324},[76,694,695],{"class":82},"  limit_unit   = \"USD\"\n",[76,697,698],{"class":78,"line":330},[76,699,131],{"emptyLinePlaceholder":130},[76,701,702],{"class":78,"line":336},[76,703,704],{"class":82},"  notification {\n",[76,706,707],{"class":78,"line":341},[76,708,709],{"class":82},"    comparison_operator        = \"GREATER_THAN\"\n",[76,711,712],{"class":78,"line":346},[76,713,714],{"class":82},"    threshold                  = 50\n",[76,716,717],{"class":78,"line":352},[76,718,719],{"class":82},"    threshold_type             = \"PERCENTAGE\"\n",[76,721,722],{"class":78,"line":358},[76,723,724],{"class":82},"    notification_type          = \"ACTUAL\"\n",[76,726,727],{"class":78,"line":364},[76,728,729],{"class":82},"    subscriber_email_addresses = [\"contact@kernellab.fr\"]\n",[76,731,732],{"class":78,"line":369},[76,733,639],{"class":113},[76,735,736],{"class":78,"line":374},[76,737,114],{"class":113},[16,739,740,741,744,745,748],{},"La region choisie est ",[73,742,743],{},"eu-west-3"," (Paris).\nLa ressource ",[62,746,747],{},"aws_budgets_budget"," permet de definir un seuil de depense mensuel.",[750,751,752],"note",{},[16,753,754],{},"Ici, une notification email est envoyee quand 50% du budget defini (1 USD pour le test) est atteint.",[42,756,758],{"id":757},"creation-de-linstance-ec2","Creation de l'instance EC2",[16,760,761],{},"Ensuite, on declare l'instance EC2 :",[66,763,765],{"className":68,"code":764,"language":70,"meta":71,"style":71},"resource \"aws_instance\" \"ec2_instance\" {\n  ami                         = \"ami-007dcf089b8078f1a\"\n  instance_type               = \"t3.micro\"\n  subnet_id                   = aws_subnet.subnet.id\n  vpc_security_group_ids      = [aws_security_group.security_group.id]\n  associate_public_ip_address = true\n  key_name                    = \"master-key\"\n\n  tags = {\n    Name = \"Ubuntu-terraform\"\n  }\n}\n",[73,766,767,772,777,782,787,792,797,802,806,811,816,820],{"__ignoreMap":71},[76,768,769],{"class":78,"line":79},[76,770,771],{"class":82},"resource \"aws_instance\" \"ec2_instance\" {\n",[76,773,774],{"class":78,"line":86},[76,775,776],{"class":82},"  ami                         = \"ami-007dcf089b8078f1a\"\n",[76,778,779],{"class":78,"line":92},[76,780,781],{"class":82},"  instance_type               = \"t3.micro\"\n",[76,783,784],{"class":78,"line":98},[76,785,786],{"class":82},"  subnet_id                   = aws_subnet.subnet.id\n",[76,788,789],{"class":78,"line":104},[76,790,791],{"class":82},"  vpc_security_group_ids      = [aws_security_group.security_group.id]\n",[76,793,794],{"class":78,"line":110},[76,795,796],{"class":82},"  associate_public_ip_address = true\n",[76,798,799],{"class":78,"line":117},[76,800,801],{"class":82},"  key_name                    = \"master-key\"\n",[76,803,804],{"class":78,"line":122},[76,805,131],{"emptyLinePlaceholder":130},[76,807,808],{"class":78,"line":127},[76,809,810],{"class":82},"  tags = {\n",[76,812,813],{"class":78,"line":134},[76,814,815],{"class":82},"    Name = \"Ubuntu-terraform\"\n",[76,817,818],{"class":78,"line":140},[76,819,639],{"class":113},[76,821,822],{"class":78,"line":146},[76,823,114],{"class":113},[16,825,826,827,830,831,834],{},"Cette instance utilise une image Ubuntu (",[73,828,829],{},"ami-007dcf089b8078f1a",") et un type ",[73,832,833],{},"t3.micro",".\nElle est placee dans un subnet du VPC, associee a un security group dedie, et recoit une IP publique pour l'acces distant.",[42,836,838],{"id":837},"creation-du-groupe-de-securite","Creation du groupe de securite",[16,840,841,842,845,846,849,850,853],{},"On cree ensuite un security group rattache au VPC.\nDeux regles d'entree sont ajoutees : le port ",[73,843,844],{},"22"," (SSH) et le port ",[73,847,848],{},"5432"," (PostgreSQL).\nLe SSH est volontairement restreint à mon IP publique courante (recupérée dynamiquement), ce qui est une bonne pratique de securite.\nLe port PostgreSQL est ici ouvert sur ",[73,851,852],{},"0.0.0.0\u002F0"," pour simplifier l'experimentation, mais en production il doit etre limite a des sources connues (par exemple un autre security group ou un CIDR prive).",[66,855,857],{"className":68,"code":856,"language":70,"meta":71,"style":71},"# Groupe de sécurité\nresource \"aws_security_group\" \"security_group\" {\n  name        = \"security_group\"\n  description = \"Security group for EC2 instance\"\n  vpc_id      = aws_vpc.vpc.id\n\n  ingress {\n    from_port   = 22\n    to_port     = 22\n    protocol    = \"tcp\"\n    cidr_blocks = [\"${data.http.my_ip.response_body}\u002F32\"]\n  }\n\n  ingress {\n    from_port   = 5432\n    to_port     = 5432\n    protocol    = \"tcp\"\n    cidr_blocks = [\"0.0.0.0\u002F0\"]\n  }\n\n  egress {\n    from_port   = 0\n    to_port     = 0\n    protocol    = \"-1\"\n    cidr_blocks = [\"0.0.0.0\u002F0\"]\n  }\n}\n",[73,858,859,865,870,875,880,885,889,894,899,904,909,914,918,922,926,931,936,940,945,949,953,958,963,968,973,977,981],{"__ignoreMap":71},[76,860,861],{"class":78,"line":79},[76,862,864],{"class":863},"skxtS","# Groupe de sécurité\n",[76,866,867],{"class":78,"line":86},[76,868,869],{"class":82},"resource \"aws_security_group\" \"security_group\" {\n",[76,871,872],{"class":78,"line":92},[76,873,874],{"class":82},"  name        = \"security_group\"\n",[76,876,877],{"class":78,"line":98},[76,878,879],{"class":82},"  description = \"Security group for EC2 instance\"\n",[76,881,882],{"class":78,"line":104},[76,883,884],{"class":82},"  vpc_id      = aws_vpc.vpc.id\n",[76,886,887],{"class":78,"line":110},[76,888,131],{"emptyLinePlaceholder":130},[76,890,891],{"class":78,"line":117},[76,892,893],{"class":82},"  ingress {\n",[76,895,896],{"class":78,"line":122},[76,897,898],{"class":82},"    from_port   = 22\n",[76,900,901],{"class":78,"line":127},[76,902,903],{"class":82},"    to_port     = 22\n",[76,905,906],{"class":78,"line":134},[76,907,908],{"class":82},"    protocol    = \"tcp\"\n",[76,910,911],{"class":78,"line":140},[76,912,913],{"class":82},"    cidr_blocks = [\"${data.http.my_ip.response_body}\u002F32\"]\n",[76,915,916],{"class":78,"line":146},[76,917,639],{"class":113},[76,919,920],{"class":78,"line":152},[76,921,131],{"emptyLinePlaceholder":130},[76,923,924],{"class":78,"line":158},[76,925,893],{"class":82},[76,927,928],{"class":78,"line":302},[76,929,930],{"class":82},"    from_port   = 5432\n",[76,932,933],{"class":78,"line":308},[76,934,935],{"class":82},"    to_port     = 5432\n",[76,937,938],{"class":78,"line":314},[76,939,908],{"class":82},[76,941,942],{"class":78,"line":319},[76,943,944],{"class":82},"    cidr_blocks = [\"0.0.0.0\u002F0\"]\n",[76,946,947],{"class":78,"line":324},[76,948,639],{"class":113},[76,950,951],{"class":78,"line":330},[76,952,131],{"emptyLinePlaceholder":130},[76,954,955],{"class":78,"line":336},[76,956,957],{"class":82},"  egress {\n",[76,959,960],{"class":78,"line":341},[76,961,962],{"class":82},"    from_port   = 0\n",[76,964,965],{"class":78,"line":346},[76,966,967],{"class":82},"    to_port     = 0\n",[76,969,970],{"class":78,"line":352},[76,971,972],{"class":82},"    protocol    = \"-1\"\n",[76,974,975],{"class":78,"line":358},[76,976,944],{"class":82},[76,978,979],{"class":78,"line":364},[76,980,639],{"class":113},[76,982,983],{"class":78,"line":369},[76,984,114],{"class":113},[42,986,988],{"id":987},"creation-du-vpc-des-subnets-et-du-routage","Creation du VPC, des subnets et du routage",[16,990,991,992,995],{},"Cette section est le coeur reseau de l'infrastructure.\nOn cree un VPC (",[73,993,994],{},"10.0.0.0\u002F16",") avec le support DNS active, ce qui permet aux ressources de resoudre les noms internes et de beneficier d'hostnames AWS.",[16,997,998,999,1002,1003,1006],{},"On ajoute ensuite deux subnets dans deux zones de disponibilite differentes (",[73,1000,1001],{},"eu-west-3a"," et ",[73,1004,1005],{},"eu-west-3b",").\nCe choix ameliore la disponibilite et permet de preparer le terrain pour RDS, qui s'appuie sur un groupe de subnets.",[16,1008,1009,1010,1013],{},"La ressource ",[73,1011,1012],{},"aws_db_subnet_group"," indique explicitement à RDS quels subnets utiliser pour placer la base.\nMeme dans une architecture simple, c'est un élément important pour organiser proprement le plan d'adréssage.",[16,1015,1016,1017,1019],{},"On cree aussi une Internet Gateway, attachee au VPC, afin de donner un acces Internet aux subnets qui en ont besoin.\nLa table de routage ajoute une route par defaut (",[73,1018,852],{},") vers cette gateway.\nEnfin, les associations lient cette table de routage aux deux subnets pour rendre la route effective.",[16,1021,1022],{},"En resume :",[29,1024,1025,1028,1031,1034,1037],{},[32,1026,1027],{},"le VPC isole logiquement l'infrastructure ;",[32,1029,1030],{},"les subnets segmentent l'espace reseau ;",[32,1032,1033],{},"l'Internet Gateway ouvre l'acces sortant\u002Fentrant selon les regles ;",[32,1035,1036],{},"la route table definit le chemin du trafic ;",[32,1038,1039],{},"les associations appliquent ce routage a chaque subnet cible.",[66,1041,1043],{"className":68,"code":1042,"language":70,"meta":71,"style":71},"#Création du VPC\nresource \"aws_vpc\" \"vpc\" {\n  cidr_block           = \"10.0.0.0\u002F16\"\n  enable_dns_support   = true\n  enable_dns_hostnames = true\n\n  tags = {\n    Name = \"vpc-terraform\"\n  }\n}\n\n#Création du subnet\nresource \"aws_subnet\" \"subnet\" {\n  vpc_id                  = aws_vpc.vpc.id\n  cidr_block              = \"10.0.0.0\u002F24\"\n  availability_zone       = \"eu-west-3a\"\n  map_public_ip_on_launch = true\n\n  tags = {\n    Name = \"subnet-ec2-db-1\"\n  }\n}\n\nresource \"aws_subnet\" \"subnet_2\" {\n  vpc_id                  = aws_vpc.vpc.id\n  cidr_block              = \"10.0.1.0\u002F24\"\n  availability_zone       = \"eu-west-3b\"\n  map_public_ip_on_launch = true\n\n  tags = {\n    Name = \"subnet-ec2-db-2\"\n  }\n}\n\nresource \"aws_db_subnet_group\" \"db_subnet_group\" {\n  name       = \"db-subnet-group\"\n  subnet_ids = [aws_subnet.subnet.id, aws_subnet.subnet_2.id]\n\n  tags = {\n    Name = \"My DB subnet group\"\n  }\n}\n\n#Création de l'internet gateway\nresource \"aws_internet_gateway\" \"internet_gateway\" {\n  vpc_id = aws_vpc.vpc.id\n\n  tags = {\n    Name = \"internet-gateway-terraform\"\n  }\n}\n\n#Création du route table\nresource \"aws_route_table\" \"route_table\" {\n  vpc_id = aws_vpc.vpc.id\n\n  route {\n    cidr_block = \"0.0.0.0\u002F0\"\n    gateway_id = aws_internet_gateway.internet_gateway.id\n  }\n\n  tags = {\n    Name = \"route-table-terraform\"\n  }\n}\n\n#Association du route table au subnet\nresource \"aws_route_table_association\" \"route_table_association\" {\n  route_table_id = aws_route_table.route_table.id\n  subnet_id      = aws_subnet.subnet.id\n}\n\nresource \"aws_route_table_association\" \"route_table_association_2\" {\n  route_table_id = aws_route_table.route_table.id\n  subnet_id      = aws_subnet.subnet_2.id\n}\n\n",[73,1044,1045,1050,1055,1060,1065,1070,1074,1078,1083,1087,1091,1095,1100,1105,1110,1115,1120,1125,1129,1133,1138,1142,1146,1150,1155,1159,1164,1169,1173,1177,1181,1186,1190,1194,1198,1203,1208,1213,1217,1221,1226,1230,1234,1238,1243,1248,1253,1257,1261,1266,1270,1274,1278,1283,1288,1292,1296,1301,1306,1311,1316,1321,1326,1332,1337,1342,1347,1353,1359,1365,1371,1376,1381,1387,1392,1398],{"__ignoreMap":71},[76,1046,1047],{"class":78,"line":79},[76,1048,1049],{"class":863},"#Création du VPC\n",[76,1051,1052],{"class":78,"line":86},[76,1053,1054],{"class":82},"resource \"aws_vpc\" \"vpc\" {\n",[76,1056,1057],{"class":78,"line":92},[76,1058,1059],{"class":82},"  cidr_block           = \"10.0.0.0\u002F16\"\n",[76,1061,1062],{"class":78,"line":98},[76,1063,1064],{"class":82},"  enable_dns_support   = true\n",[76,1066,1067],{"class":78,"line":104},[76,1068,1069],{"class":82},"  enable_dns_hostnames = true\n",[76,1071,1072],{"class":78,"line":110},[76,1073,131],{"emptyLinePlaceholder":130},[76,1075,1076],{"class":78,"line":117},[76,1077,810],{"class":82},[76,1079,1080],{"class":78,"line":122},[76,1081,1082],{"class":82},"    Name = \"vpc-terraform\"\n",[76,1084,1085],{"class":78,"line":127},[76,1086,639],{"class":113},[76,1088,1089],{"class":78,"line":134},[76,1090,114],{"class":113},[76,1092,1093],{"class":78,"line":140},[76,1094,131],{"emptyLinePlaceholder":130},[76,1096,1097],{"class":78,"line":146},[76,1098,1099],{"class":863},"#Création du subnet\n",[76,1101,1102],{"class":78,"line":152},[76,1103,1104],{"class":82},"resource \"aws_subnet\" \"subnet\" {\n",[76,1106,1107],{"class":78,"line":158},[76,1108,1109],{"class":82},"  vpc_id                  = aws_vpc.vpc.id\n",[76,1111,1112],{"class":78,"line":302},[76,1113,1114],{"class":82},"  cidr_block              = \"10.0.0.0\u002F24\"\n",[76,1116,1117],{"class":78,"line":308},[76,1118,1119],{"class":82},"  availability_zone       = \"eu-west-3a\"\n",[76,1121,1122],{"class":78,"line":314},[76,1123,1124],{"class":82},"  map_public_ip_on_launch = true\n",[76,1126,1127],{"class":78,"line":319},[76,1128,131],{"emptyLinePlaceholder":130},[76,1130,1131],{"class":78,"line":324},[76,1132,810],{"class":82},[76,1134,1135],{"class":78,"line":330},[76,1136,1137],{"class":82},"    Name = \"subnet-ec2-db-1\"\n",[76,1139,1140],{"class":78,"line":336},[76,1141,639],{"class":113},[76,1143,1144],{"class":78,"line":341},[76,1145,114],{"class":113},[76,1147,1148],{"class":78,"line":346},[76,1149,131],{"emptyLinePlaceholder":130},[76,1151,1152],{"class":78,"line":352},[76,1153,1154],{"class":82},"resource \"aws_subnet\" \"subnet_2\" {\n",[76,1156,1157],{"class":78,"line":358},[76,1158,1109],{"class":82},[76,1160,1161],{"class":78,"line":364},[76,1162,1163],{"class":82},"  cidr_block              = \"10.0.1.0\u002F24\"\n",[76,1165,1166],{"class":78,"line":369},[76,1167,1168],{"class":82},"  availability_zone       = \"eu-west-3b\"\n",[76,1170,1171],{"class":78,"line":374},[76,1172,1124],{"class":82},[76,1174,1175],{"class":78,"line":379},[76,1176,131],{"emptyLinePlaceholder":130},[76,1178,1179],{"class":78,"line":385},[76,1180,810],{"class":82},[76,1182,1183],{"class":78,"line":391},[76,1184,1185],{"class":82},"    Name = \"subnet-ec2-db-2\"\n",[76,1187,1188],{"class":78,"line":397},[76,1189,639],{"class":113},[76,1191,1192],{"class":78,"line":402},[76,1193,114],{"class":113},[76,1195,1196],{"class":78,"line":407},[76,1197,131],{"emptyLinePlaceholder":130},[76,1199,1200],{"class":78,"line":413},[76,1201,1202],{"class":82},"resource \"aws_db_subnet_group\" \"db_subnet_group\" {\n",[76,1204,1205],{"class":78,"line":418},[76,1206,1207],{"class":82},"  name       = \"db-subnet-group\"\n",[76,1209,1210],{"class":78,"line":424},[76,1211,1212],{"class":82},"  subnet_ids = [aws_subnet.subnet.id, aws_subnet.subnet_2.id]\n",[76,1214,1215],{"class":78,"line":430},[76,1216,131],{"emptyLinePlaceholder":130},[76,1218,1219],{"class":78,"line":435},[76,1220,810],{"class":82},[76,1222,1223],{"class":78,"line":440},[76,1224,1225],{"class":82},"    Name = \"My DB subnet group\"\n",[76,1227,1228],{"class":78,"line":446},[76,1229,639],{"class":113},[76,1231,1232],{"class":78,"line":452},[76,1233,114],{"class":113},[76,1235,1236],{"class":78,"line":457},[76,1237,131],{"emptyLinePlaceholder":130},[76,1239,1240],{"class":78,"line":462},[76,1241,1242],{"class":863},"#Création de l'internet gateway\n",[76,1244,1245],{"class":78,"line":468},[76,1246,1247],{"class":82},"resource \"aws_internet_gateway\" \"internet_gateway\" {\n",[76,1249,1250],{"class":78,"line":474},[76,1251,1252],{"class":82},"  vpc_id = aws_vpc.vpc.id\n",[76,1254,1255],{"class":78,"line":480},[76,1256,131],{"emptyLinePlaceholder":130},[76,1258,1259],{"class":78,"line":485},[76,1260,810],{"class":82},[76,1262,1263],{"class":78,"line":490},[76,1264,1265],{"class":82},"    Name = \"internet-gateway-terraform\"\n",[76,1267,1268],{"class":78,"line":496},[76,1269,639],{"class":113},[76,1271,1272],{"class":78,"line":502},[76,1273,114],{"class":113},[76,1275,1276],{"class":78,"line":507},[76,1277,131],{"emptyLinePlaceholder":130},[76,1279,1280],{"class":78,"line":512},[76,1281,1282],{"class":863},"#Création du route table\n",[76,1284,1285],{"class":78,"line":518},[76,1286,1287],{"class":82},"resource \"aws_route_table\" \"route_table\" {\n",[76,1289,1290],{"class":78,"line":524},[76,1291,1252],{"class":82},[76,1293,1294],{"class":78,"line":529},[76,1295,131],{"emptyLinePlaceholder":130},[76,1297,1298],{"class":78,"line":534},[76,1299,1300],{"class":82},"  route {\n",[76,1302,1303],{"class":78,"line":540},[76,1304,1305],{"class":82},"    cidr_block = \"0.0.0.0\u002F0\"\n",[76,1307,1308],{"class":78,"line":546},[76,1309,1310],{"class":82},"    gateway_id = aws_internet_gateway.internet_gateway.id\n",[76,1312,1314],{"class":78,"line":1313},60,[76,1315,639],{"class":113},[76,1317,1319],{"class":78,"line":1318},61,[76,1320,131],{"emptyLinePlaceholder":130},[76,1322,1324],{"class":78,"line":1323},62,[76,1325,810],{"class":82},[76,1327,1329],{"class":78,"line":1328},63,[76,1330,1331],{"class":82},"    Name = \"route-table-terraform\"\n",[76,1333,1335],{"class":78,"line":1334},64,[76,1336,639],{"class":113},[76,1338,1340],{"class":78,"line":1339},65,[76,1341,114],{"class":113},[76,1343,1345],{"class":78,"line":1344},66,[76,1346,131],{"emptyLinePlaceholder":130},[76,1348,1350],{"class":78,"line":1349},67,[76,1351,1352],{"class":863},"#Association du route table au subnet\n",[76,1354,1356],{"class":78,"line":1355},68,[76,1357,1358],{"class":82},"resource \"aws_route_table_association\" \"route_table_association\" {\n",[76,1360,1362],{"class":78,"line":1361},69,[76,1363,1364],{"class":82},"  route_table_id = aws_route_table.route_table.id\n",[76,1366,1368],{"class":78,"line":1367},70,[76,1369,1370],{"class":82},"  subnet_id      = aws_subnet.subnet.id\n",[76,1372,1374],{"class":78,"line":1373},71,[76,1375,114],{"class":113},[76,1377,1379],{"class":78,"line":1378},72,[76,1380,131],{"emptyLinePlaceholder":130},[76,1382,1384],{"class":78,"line":1383},73,[76,1385,1386],{"class":82},"resource \"aws_route_table_association\" \"route_table_association_2\" {\n",[76,1388,1390],{"class":78,"line":1389},74,[76,1391,1364],{"class":82},[76,1393,1395],{"class":78,"line":1394},75,[76,1396,1397],{"class":82},"  subnet_id      = aws_subnet.subnet_2.id\n",[76,1399,1401],{"class":78,"line":1400},76,[76,1402,114],{"class":113},[1404,1405,1407],"h3",{"id":1406},"sorties-utiles-ec2-et-bdd","Sorties utiles (EC2 et BDD)",[66,1409,1411],{"className":68,"code":1410,"language":70,"meta":71,"style":71},"output \"ec2_instance_public_ip\" {\n  value = aws_instance.ec2_instance.public_ip\n}\n\noutput \"db_instance_endpoint\" {\n  value = aws_db_instance.default.endpoint\n}\n",[73,1412,1413,1418,1423,1427,1431,1436,1441],{"__ignoreMap":71},[76,1414,1415],{"class":78,"line":79},[76,1416,1417],{"class":82},"output \"ec2_instance_public_ip\" {\n",[76,1419,1420],{"class":78,"line":86},[76,1421,1422],{"class":82},"  value = aws_instance.ec2_instance.public_ip\n",[76,1424,1425],{"class":78,"line":92},[76,1426,114],{"class":113},[76,1428,1429],{"class":78,"line":98},[76,1430,131],{"emptyLinePlaceholder":130},[76,1432,1433],{"class":78,"line":104},[76,1434,1435],{"class":82},"output \"db_instance_endpoint\" {\n",[76,1437,1438],{"class":78,"line":110},[76,1439,1440],{"class":82},"  value = aws_db_instance.default.endpoint\n",[76,1442,1443],{"class":78,"line":117},[76,1444,114],{"class":113},[550,1446,1447],{},"html pre.shiki code .sqNgn, html code.shiki .sqNgn{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#E6DB74}html pre.shiki code .s_bef, html code.shiki .s_bef{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#F8F8F2}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .skxtS, html code.shiki .skxtS{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#88846F;--shiki-dark-font-style:inherit}",{"title":71,"searchDepth":86,"depth":86,"links":1449},[1450,1451,1452,1453],{"id":585,"depth":86,"text":586},{"id":757,"depth":86,"text":758},{"id":837,"depth":86,"text":838},{"id":987,"depth":86,"text":988,"children":1454},[1455],{"id":1406,"depth":92,"text":1407},"2026-04-13","Création d'une structure de base sur AWS avec Terraform (EC2 + RDS + VPC)","\u002Flaboratoire\u002Fterraform_aws_ec2_rds.png",{},"\u002Flaboratoire\u002Fterraform_aws_ec2_rds",{"title":573,"description":1457},"laboratoire\u002Fterraform_aws_ec2_rds",[567,568,1464],"aws","R9CLP5c6w03gagklV3k8q-mX-wvqZL-gV1SFvRiIApg",{"id":1467,"title":1468,"body":1469,"date":2052,"description":2053,"doc":2054,"extension":560,"git":559,"image":2057,"isExperimentation":130,"meta":2058,"navigation":130,"path":2059,"seo":2060,"stem":2061,"tags":2062,"type":567,"updatedAt":559,"website":559,"__hash__":2064},"laboratoire\u002Flaboratoire\u002Fterraform_aws_lambda_01.md","Terraform - AWS Lambda",{"type":8,"value":1470,"toc":2040},[1471,1474,1477,1480,1491,1495,1498,1501,1505,1509,1512,1516,1519,1522,1528,1531,1534,1645,1649,1652,1655,1658,1687,1691,1694,1697,1747,1751,1774,1777,1914,1918,1921,1935,1940,1943,1945,2030,2034,2037],[11,1472,1468],{"id":1473},"terraform-aws-lambda",[16,1475,1476],{},"Cette expérimentation consiste à mettre en place une fonction Lambda sur AWS avec Terraform.",[16,1478,1479],{},"L'infrastructure est composée de :",[29,1481,1482,1485,1488],{},[32,1483,1484],{},"Une fonction Lambda",[32,1486,1487],{},"Un lien URL pour accéder à la fonction Lambda",[32,1489,1490],{},"Un budget pour surveiller les coûts de la Lambda",[42,1492,1494],{"id":1493},"objectif","Objectif",[16,1496,1497],{},"L'objectif est de comprendre les fonctions Lambda et leur intérêt dans une architecture serverless.",[16,1499,1500],{},"Ainsi que de mettre en place un budget pour surveiller les coûts de la Lambda.",[42,1502,1504],{"id":1503},"technique","Technique",[1404,1506,1508],{"id":1507},"lambda","Lambda",[16,1510,1511],{},"Je vais détailler dans ce post les étapes mises en place pour créer une fonction Lambda sur AWS avec Terraform.",[1404,1513,1515],{"id":1514},"budget","Budget",[16,1517,1518],{},"Commençons par le budget, j'ai choisi de mettre en place un budget de 1$ par mois pour surveiller les coûts de la Lambda. Même si l'utilisation de la Lambda est gratuite, il est toujours intéressant de mettre en place un budget pour surveiller les coûts.",[16,1520,1521],{},"D'autant plus que la version que j'ai mise en place est une version gratuite non restreinte d'accès : aucun VPC n'a été mis en place ni aucun groupe de sécurité.",[1523,1524,1525],"warning",{},[16,1526,1527],{},"N'importe qui peut accéder à la Lambda via l'URL. Je précise que l'objectif était pédagogique et l'instance a été détruite instantanément.",[16,1529,1530],{},"Les alertes sont envoyées par e-mail à l'adresse configurée dans le code.\nJ'ai fixé à 50% la première alerte et une prévision de 100% pour la seconde alerte.",[16,1532,1533],{},"Voici un extrait du code Terraform qui m'a permis de créer un budget :",[66,1535,1537],{"className":68,"code":1536,"language":70,"meta":71,"style":71},"resource \"aws_budgets_budget\" \"ec2_budget\" {\n  name         = \"budget-lambda-alerte\"\n  budget_type  = \"COST\"\n  limit_amount = \"1\"\n  limit_unit   = \"USD\"\n  time_unit    = \"MONTHLY\"\n\n  # Alerte 1 : 50% du budget réel consommé\n  notification {\n    comparison_operator        = \"GREATER_THAN\"\n    threshold                  = 50\n    threshold_type             = \"PERCENTAGE\"\n    notification_type          = \"ACTUAL\"\n    subscriber_email_addresses = [\"contact@kernellab.fr\"]\n  }\n\n  # Alerte 2 : Prévision de dépassement de 100%\n  notification {\n    comparison_operator        = \"GREATER_THAN\"\n    threshold                  = 100\n    threshold_type             = \"PERCENTAGE\"\n    notification_type          = \"FORECASTED\"\n    subscriber_email_addresses = [\"contact@kernellab.fr\"]\n  }\n}\n",[73,1538,1539,1544,1549,1553,1557,1561,1565,1569,1574,1578,1582,1586,1590,1594,1598,1602,1606,1611,1615,1619,1624,1628,1633,1637,1641],{"__ignoreMap":71},[76,1540,1541],{"class":78,"line":79},[76,1542,1543],{"class":82},"resource \"aws_budgets_budget\" \"ec2_budget\" {\n",[76,1545,1546],{"class":78,"line":86},[76,1547,1548],{"class":82},"  name         = \"budget-lambda-alerte\"\n",[76,1550,1551],{"class":78,"line":92},[76,1552,680],{"class":82},[76,1554,1555],{"class":78,"line":98},[76,1556,690],{"class":82},[76,1558,1559],{"class":78,"line":104},[76,1560,695],{"class":82},[76,1562,1563],{"class":78,"line":110},[76,1564,685],{"class":82},[76,1566,1567],{"class":78,"line":117},[76,1568,131],{"emptyLinePlaceholder":130},[76,1570,1571],{"class":78,"line":122},[76,1572,1573],{"class":863},"  # Alerte 1 : 50% du budget réel consommé\n",[76,1575,1576],{"class":78,"line":127},[76,1577,704],{"class":82},[76,1579,1580],{"class":78,"line":134},[76,1581,709],{"class":82},[76,1583,1584],{"class":78,"line":140},[76,1585,714],{"class":82},[76,1587,1588],{"class":78,"line":146},[76,1589,719],{"class":82},[76,1591,1592],{"class":78,"line":152},[76,1593,724],{"class":82},[76,1595,1596],{"class":78,"line":158},[76,1597,729],{"class":82},[76,1599,1600],{"class":78,"line":302},[76,1601,639],{"class":113},[76,1603,1604],{"class":78,"line":308},[76,1605,131],{"emptyLinePlaceholder":130},[76,1607,1608],{"class":78,"line":314},[76,1609,1610],{"class":863},"  # Alerte 2 : Prévision de dépassement de 100%\n",[76,1612,1613],{"class":78,"line":319},[76,1614,704],{"class":82},[76,1616,1617],{"class":78,"line":324},[76,1618,709],{"class":82},[76,1620,1621],{"class":78,"line":330},[76,1622,1623],{"class":82},"    threshold                  = 100\n",[76,1625,1626],{"class":78,"line":336},[76,1627,719],{"class":82},[76,1629,1630],{"class":78,"line":341},[76,1631,1632],{"class":82},"    notification_type          = \"FORECASTED\"\n",[76,1634,1635],{"class":78,"line":346},[76,1636,729],{"class":82},[76,1638,1639],{"class":78,"line":352},[76,1640,639],{"class":113},[76,1642,1643],{"class":78,"line":358},[76,1644,114],{"class":113},[1404,1646,1648],{"id":1647},"fonction-python","Fonction Python",[16,1650,1651],{},"Pour pouvoir envoyer le code Python sur AWS, il faut le compresser dans un fichier zip.",[16,1653,1654],{},"Pour ce faire, j'ai mis une ressource en place qui va compresser le code Python qui se situe à la racine du repository dans un fichier zip.",[16,1656,1657],{},"Voici un extrait du code Terraform qui m'a permis de créer un fichier zip :",[66,1659,1661],{"className":68,"code":1660,"language":70,"meta":71,"style":71},"data \"archive_file\" \"lambda\" {\n  type        = \"zip\"\n  source_file = \"${path.module}\u002F..\u002Fmain.py\"\n  output_path = \"${path.module}\u002F..\u002Ffunction.zip\"\n}\n",[73,1662,1663,1668,1673,1678,1683],{"__ignoreMap":71},[76,1664,1665],{"class":78,"line":79},[76,1666,1667],{"class":82},"data \"archive_file\" \"lambda\" {\n",[76,1669,1670],{"class":78,"line":86},[76,1671,1672],{"class":82},"  type        = \"zip\"\n",[76,1674,1675],{"class":78,"line":92},[76,1676,1677],{"class":82},"  source_file = \"${path.module}\u002F..\u002Fmain.py\"\n",[76,1679,1680],{"class":78,"line":98},[76,1681,1682],{"class":82},"  output_path = \"${path.module}\u002F..\u002Ffunction.zip\"\n",[76,1684,1685],{"class":78,"line":104},[76,1686,114],{"class":113},[1404,1688,1690],{"id":1689},"logs-et-metrics","Logs et metrics",[16,1692,1693],{},"Pour pouvoir surveiller les logs et les métriques de la Lambda, j'ai mis une ressource en place qui va créer un log group et un dashboard.",[16,1695,1696],{},"Voici un extrait du code Terraform qui m'a permis de créer un log group sur CloudWatch :",[66,1698,1700],{"className":68,"code":1699,"language":70,"meta":71,"style":71},"resource \"aws_cloudwatch_log_group\" \"example\" {\n  name              = \"\u002Faws\u002Flambda\u002Flambda_function_python\"\n  retention_in_days = 14\n\n  tags = {\n    Environment = \"production\"\n    Application = \"example\"\n  }\n\n}\n",[73,1701,1702,1707,1712,1717,1721,1725,1730,1735,1739,1743],{"__ignoreMap":71},[76,1703,1704],{"class":78,"line":79},[76,1705,1706],{"class":82},"resource \"aws_cloudwatch_log_group\" \"example\" {\n",[76,1708,1709],{"class":78,"line":86},[76,1710,1711],{"class":82},"  name              = \"\u002Faws\u002Flambda\u002Flambda_function_python\"\n",[76,1713,1714],{"class":78,"line":92},[76,1715,1716],{"class":82},"  retention_in_days = 14\n",[76,1718,1719],{"class":78,"line":98},[76,1720,131],{"emptyLinePlaceholder":130},[76,1722,1723],{"class":78,"line":104},[76,1724,810],{"class":82},[76,1726,1727],{"class":78,"line":110},[76,1728,1729],{"class":82},"    Environment = \"production\"\n",[76,1731,1732],{"class":78,"line":117},[76,1733,1734],{"class":82},"    Application = \"example\"\n",[76,1736,1737],{"class":78,"line":122},[76,1738,639],{"class":113},[76,1740,1741],{"class":78,"line":127},[76,1742,131],{"emptyLinePlaceholder":130},[76,1744,1745],{"class":78,"line":134},[76,1746,114],{"class":113},[1404,1748,1750],{"id":1749},"création-de-la-lambda","Création de la lambda",[16,1752,1753,1754,1757,1758,1761,1762,1765,1766,1769,1770,1773],{},"Cet extrait de code permet de créer la fonction Lambda sur AWS. On peut remarquer l'utilisation de la variable ",[62,1755,1756],{},"filename"," qui est le chemin du fichier zip créé précédemment. On utilise également la variable ",[62,1759,1760],{},"function_name"," qui est le nom de la fonction Lambda, ainsi que le ",[62,1763,1764],{},"role"," IAM qui sera utilisé pour son exécution. Le ",[62,1767,1768],{},"handler"," définit le point d'entrée du code et ",[62,1771,1772],{},"code_sha256"," assure l'intégrité du fichier zip.",[16,1775,1776],{},"Voici un exemple du code:",[66,1778,1780],{"className":68,"code":1779,"language":70,"meta":71,"style":71},"resource \"aws_lambda_function\" \"example\" {\n  filename      = data.archive_file.lambda.output_path\n  function_name = \"example_lambda_function\"\n  role          = aws_iam_role.example.arn\n  handler       = \"main.lambda_handler\"\n  code_sha256   = data.archive_file.lambda.output_base64sha256\n\n  runtime = \"python3.10\"\n\n  environment {\n    variables = {\n      ENVIRONMENT = \"production\"\n      LOG_LEVEL   = \"info\"\n    }\n  }\n\n  tags = {\n    Environment = \"production\"\n    Application = \"example\"\n  }\n\n  logging_config {\n    log_format            = \"JSON\"\n    application_log_level = \"INFO\"\n    system_log_level      = \"WARN\"\n  }\n\n  depends_on = [aws_cloudwatch_log_group.example]\n}\n",[73,1781,1782,1787,1792,1797,1802,1807,1812,1816,1821,1825,1830,1835,1840,1845,1849,1853,1857,1861,1865,1869,1873,1877,1882,1887,1892,1897,1901,1905,1910],{"__ignoreMap":71},[76,1783,1784],{"class":78,"line":79},[76,1785,1786],{"class":82},"resource \"aws_lambda_function\" \"example\" {\n",[76,1788,1789],{"class":78,"line":86},[76,1790,1791],{"class":82},"  filename      = data.archive_file.lambda.output_path\n",[76,1793,1794],{"class":78,"line":92},[76,1795,1796],{"class":82},"  function_name = \"example_lambda_function\"\n",[76,1798,1799],{"class":78,"line":98},[76,1800,1801],{"class":82},"  role          = aws_iam_role.example.arn\n",[76,1803,1804],{"class":78,"line":104},[76,1805,1806],{"class":82},"  handler       = \"main.lambda_handler\"\n",[76,1808,1809],{"class":78,"line":110},[76,1810,1811],{"class":82},"  code_sha256   = data.archive_file.lambda.output_base64sha256\n",[76,1813,1814],{"class":78,"line":117},[76,1815,131],{"emptyLinePlaceholder":130},[76,1817,1818],{"class":78,"line":122},[76,1819,1820],{"class":82},"  runtime = \"python3.10\"\n",[76,1822,1823],{"class":78,"line":127},[76,1824,131],{"emptyLinePlaceholder":130},[76,1826,1827],{"class":78,"line":134},[76,1828,1829],{"class":82},"  environment {\n",[76,1831,1832],{"class":78,"line":140},[76,1833,1834],{"class":82},"    variables = {\n",[76,1836,1837],{"class":78,"line":146},[76,1838,1839],{"class":82},"      ENVIRONMENT = \"production\"\n",[76,1841,1842],{"class":78,"line":152},[76,1843,1844],{"class":82},"      LOG_LEVEL   = \"info\"\n",[76,1846,1847],{"class":78,"line":158},[76,1848,634],{"class":113},[76,1850,1851],{"class":78,"line":302},[76,1852,639],{"class":113},[76,1854,1855],{"class":78,"line":308},[76,1856,131],{"emptyLinePlaceholder":130},[76,1858,1859],{"class":78,"line":314},[76,1860,810],{"class":82},[76,1862,1863],{"class":78,"line":319},[76,1864,1729],{"class":82},[76,1866,1867],{"class":78,"line":324},[76,1868,1734],{"class":82},[76,1870,1871],{"class":78,"line":330},[76,1872,639],{"class":113},[76,1874,1875],{"class":78,"line":336},[76,1876,131],{"emptyLinePlaceholder":130},[76,1878,1879],{"class":78,"line":341},[76,1880,1881],{"class":82},"  logging_config {\n",[76,1883,1884],{"class":78,"line":346},[76,1885,1886],{"class":82},"    log_format            = \"JSON\"\n",[76,1888,1889],{"class":78,"line":352},[76,1890,1891],{"class":82},"    application_log_level = \"INFO\"\n",[76,1893,1894],{"class":78,"line":358},[76,1895,1896],{"class":82},"    system_log_level      = \"WARN\"\n",[76,1898,1899],{"class":78,"line":364},[76,1900,639],{"class":113},[76,1902,1903],{"class":78,"line":369},[76,1904,131],{"emptyLinePlaceholder":130},[76,1906,1907],{"class":78,"line":374},[76,1908,1909],{"class":82},"  depends_on = [aws_cloudwatch_log_group.example]\n",[76,1911,1912],{"class":78,"line":379},[76,1913,114],{"class":113},[1404,1915,1917],{"id":1916},"url-daccès-à-la-lambda","URL d'accès à la Lambda",[16,1919,1920],{},"Pour pouvoir déclencher la fonction, j'ai décidé de l'utiliser via une URL. J'ai donc mis en place une ressource qui va créer une URL d'accès public.",[16,1922,1923,1924,1926,1927,1930,1931,1934],{},"On peut remarquer l'utilisation de la variable ",[62,1925,1760],{}," et du type d'autorisation (",[62,1928,1929],{},"authorization_type","). On configure également les paramètres ",[62,1932,1933],{},"cors"," pour l'accès.",[750,1936,1937],{},[16,1938,1939],{},"Le CORS est volontairement configuré sur \"*\" pour permettre l'accès à n'importe qui. Dans un contexte de production, il faudrait mettre en place une authentification et restreindre les origines.",[16,1941,1942],{},"L'output permet également de récupérer l'URL directement dans le terminal après la construction.",[16,1944,1776],{},[66,1946,1948],{"className":68,"code":1947,"language":70,"meta":71,"style":71},"resource \"aws_lambda_function_url\" \"example\" {\n  function_name      = aws_lambda_function.example.function_name\n  authorization_type = \"NONE\"\n\n  cors {\n    allow_credentials = true\n    allow_origins     = [\"*\"]\n    allow_methods     = [\"GET\"]\n    allow_headers     = [\"date\", \"keep-alive\"]\n    expose_headers    = [\"keep-alive\", \"date\"]\n    max_age           = 86400\n  }\n}\n\noutput \"lambda_url\" {\n  value = aws_lambda_function_url.example.function_url\n}\n",[73,1949,1950,1955,1960,1965,1969,1974,1979,1984,1989,1994,1999,2004,2008,2012,2016,2021,2026],{"__ignoreMap":71},[76,1951,1952],{"class":78,"line":79},[76,1953,1954],{"class":82},"resource \"aws_lambda_function_url\" \"example\" {\n",[76,1956,1957],{"class":78,"line":86},[76,1958,1959],{"class":82},"  function_name      = aws_lambda_function.example.function_name\n",[76,1961,1962],{"class":78,"line":92},[76,1963,1964],{"class":82},"  authorization_type = \"NONE\"\n",[76,1966,1967],{"class":78,"line":98},[76,1968,131],{"emptyLinePlaceholder":130},[76,1970,1971],{"class":78,"line":104},[76,1972,1973],{"class":82},"  cors {\n",[76,1975,1976],{"class":78,"line":110},[76,1977,1978],{"class":82},"    allow_credentials = true\n",[76,1980,1981],{"class":78,"line":117},[76,1982,1983],{"class":82},"    allow_origins     = [\"*\"]\n",[76,1985,1986],{"class":78,"line":122},[76,1987,1988],{"class":82},"    allow_methods     = [\"GET\"]\n",[76,1990,1991],{"class":78,"line":127},[76,1992,1993],{"class":82},"    allow_headers     = [\"date\", \"keep-alive\"]\n",[76,1995,1996],{"class":78,"line":134},[76,1997,1998],{"class":82},"    expose_headers    = [\"keep-alive\", \"date\"]\n",[76,2000,2001],{"class":78,"line":140},[76,2002,2003],{"class":82},"    max_age           = 86400\n",[76,2005,2006],{"class":78,"line":146},[76,2007,639],{"class":113},[76,2009,2010],{"class":78,"line":152},[76,2011,114],{"class":113},[76,2013,2014],{"class":78,"line":158},[76,2015,131],{"emptyLinePlaceholder":130},[76,2017,2018],{"class":78,"line":302},[76,2019,2020],{"class":82},"output \"lambda_url\" {\n",[76,2022,2023],{"class":78,"line":308},[76,2024,2025],{"class":82},"  value = aws_lambda_function_url.example.function_url\n",[76,2027,2028],{"class":78,"line":314},[76,2029,114],{"class":113},[42,2031,2033],{"id":2032},"conclusion","Conclusion",[16,2035,2036],{},"Cette expérimentation m'a permis de comprendre les fonctions Lambda et leur intérêt dans une architecture serverless, tout en mettant en place un monitoring des coûts via un budget AWS.",[550,2038,2039],{},"html pre.shiki code .sqNgn, html code.shiki .sqNgn{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#E6DB74}html pre.shiki code .skxtS, html code.shiki .skxtS{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#88846F;--shiki-dark-font-style:inherit}html pre.shiki code .s_bef, html code.shiki .s_bef{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#F8F8F2}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":71,"searchDepth":86,"depth":86,"links":2041},[2042,2043,2051],{"id":1493,"depth":86,"text":1494},{"id":1503,"depth":86,"text":1504,"children":2044},[2045,2046,2047,2048,2049,2050],{"id":1507,"depth":92,"text":1508},{"id":1514,"depth":92,"text":1515},{"id":1647,"depth":92,"text":1648},{"id":1689,"depth":92,"text":1690},{"id":1749,"depth":92,"text":1750},{"id":1916,"depth":92,"text":1917},{"id":2032,"depth":86,"text":2033},"2026-04-09","Création d'une fonction Lambda Python sur AWS avec Terraform",[2055,2056],"https:\u002F\u002Fregistry.terraform.io\u002Fproviders\u002F-\u002Faws\u002Flatest\u002Fdocs\u002Fresources\u002Flambda_function_url","https:\u002F\u002Fdeveloper.hashicorp.com\u002Fterraform\u002Ftutorials\u002Faws-get-started\u002Faws-create","\u002Flaboratoire\u002Fterraform_aws_lambda_01.png",{},"\u002Flaboratoire\u002Fterraform_aws_lambda_01",{"title":1468,"description":2053},"laboratoire\u002Fterraform_aws_lambda_01",[567,568,1464,2063,1507,1514],"python","dIBE-Ro7KrbtMnM9EiRnSlP2X5qgqmgfbl5P_bTKzik",{"id":2066,"title":2067,"body":2068,"date":2685,"description":2686,"doc":559,"extension":560,"git":559,"image":2687,"isExperimentation":130,"meta":2688,"navigation":130,"path":2689,"seo":2690,"stem":2691,"tags":2692,"type":567,"updatedAt":559,"website":559,"__hash__":2693},"laboratoire\u002Flaboratoire\u002Fterraform_aws_exp_01.md","Terraform  - AWS",{"type":8,"value":2069,"toc":2674},[2070,2074,2077,2080,2103,2105,2108,2111,2113,2117,2120,2213,2216,2222,2228,2234,2240,2246,2252,2256,2259,2396,2402,2408,2414,2420,2426,2430,2575,2581,2587,2593,2605,2608,2627,2631,2655,2659,2662,2665,2669,2672],[11,2071,2073],{"id":2072},"terraform-aws","Terraform - AWS",[16,2075,2076],{},"Cette expériementation consiste à mettre en place une structure de base sur AWS avec Terraform.",[16,2078,2079],{},"l'infrastructure est composée de :",[29,2081,2082,2085,2088,2091,2094,2097,2100],{},[32,2083,2084],{},"un VPC",[32,2086,2087],{},"Une passerelle internet",[32,2089,2090],{},"une table de routage",[32,2092,2093],{},"un groupe de sécurité",[32,2095,2096],{},"une instance EC2 t3.micro (free tier)",[32,2098,2099],{},"Une IP elastique",[32,2101,2102],{},"Un volume EBS (gp3)",[42,2104,1494],{"id":1493},[16,2106,2107],{},"L'objectif de cette expérimentation étais de monter en compétence sur AWS et Terraform en même temps.",[16,2109,2110],{},"De comprendre comment fonctionne Terraform et comment il interagit avec AWS.",[42,2112,1504],{"id":1503},[1404,2114,2116],{"id":2115},"ec2","EC2",[16,2118,2119],{},"Voici un extrait du code Terraform qui ma permis de créer une instance EC2:",[66,2121,2123],{"className":68,"code":2122,"language":70,"meta":71,"style":71},"resource \"aws_instance\" \"ubuntu\" {\n  count         = var.nb_instance\n  ami           = var.ami\n  instance_type = var.instance_type\n  key_name      = var.key_name\n  subnet_id     = aws_subnet.ubuntu-subnet.id\n\n  vpc_security_group_ids      = [aws_security_group.allow_ssh.id]\n  user_data_replace_on_change = true\n\n  root_block_device {\n    volume_size = 10\n    volume_type = \"gp3\"\n  }\n\n  tags = {\n    Name = \"Ubuntu-terraform-${count.index}\"\n  }\n}\n",[73,2124,2125,2130,2135,2140,2145,2150,2155,2159,2164,2169,2173,2178,2183,2188,2192,2196,2200,2205,2209],{"__ignoreMap":71},[76,2126,2127],{"class":78,"line":79},[76,2128,2129],{"class":82},"resource \"aws_instance\" \"ubuntu\" {\n",[76,2131,2132],{"class":78,"line":86},[76,2133,2134],{"class":82},"  count         = var.nb_instance\n",[76,2136,2137],{"class":78,"line":92},[76,2138,2139],{"class":82},"  ami           = var.ami\n",[76,2141,2142],{"class":78,"line":98},[76,2143,2144],{"class":82},"  instance_type = var.instance_type\n",[76,2146,2147],{"class":78,"line":104},[76,2148,2149],{"class":82},"  key_name      = var.key_name\n",[76,2151,2152],{"class":78,"line":110},[76,2153,2154],{"class":82},"  subnet_id     = aws_subnet.ubuntu-subnet.id\n",[76,2156,2157],{"class":78,"line":117},[76,2158,131],{"emptyLinePlaceholder":130},[76,2160,2161],{"class":78,"line":122},[76,2162,2163],{"class":82},"  vpc_security_group_ids      = [aws_security_group.allow_ssh.id]\n",[76,2165,2166],{"class":78,"line":127},[76,2167,2168],{"class":82},"  user_data_replace_on_change = true\n",[76,2170,2171],{"class":78,"line":134},[76,2172,131],{"emptyLinePlaceholder":130},[76,2174,2175],{"class":78,"line":140},[76,2176,2177],{"class":82},"  root_block_device {\n",[76,2179,2180],{"class":78,"line":146},[76,2181,2182],{"class":82},"    volume_size = 10\n",[76,2184,2185],{"class":78,"line":152},[76,2186,2187],{"class":82},"    volume_type = \"gp3\"\n",[76,2189,2190],{"class":78,"line":158},[76,2191,639],{"class":113},[76,2193,2194],{"class":78,"line":302},[76,2195,131],{"emptyLinePlaceholder":130},[76,2197,2198],{"class":78,"line":308},[76,2199,810],{"class":82},[76,2201,2202],{"class":78,"line":314},[76,2203,2204],{"class":82},"    Name = \"Ubuntu-terraform-${count.index}\"\n",[76,2206,2207],{"class":78,"line":319},[76,2208,639],{"class":113},[76,2210,2211],{"class":78,"line":324},[76,2212,114],{"class":113},[16,2214,2215],{},"On peut remarque que l'utilisation des variable est omni présente ce qui vas permettre d'améliorer et changer des paramètre sans toucher au code existant.",[16,2217,2218,2221],{},[62,2219,2220],{},"root_block_device"," est une ressource qui permet de configurer le disque dur de l'instance EC2. Dans ce cas précis, il permet de configurer la taille et le type du disque dur de l'instance EC2. Nous pourrions noter la présence d'un disque de type gp3 qui est plus performant que le gp2 et égalemet 20% moins chère avec un volume standard de 10Go.",[16,2223,2224,2227],{},[62,2225,2226],{},"count"," définie le nombre d'instance que l'on veut créer. Dans ce cas précis, il permet de créer 1 instance EC2. Mais on pourrait très bien imaginer créer 3 instances EC2 en changeant simplement la valeur de la variable count.",[16,2229,2230,2233],{},[62,2231,2232],{},"key_name"," est le nom de la clé SSH qui sera utilisée pour se connecter à l'instance EC2. Dans ce cas précis, il permet de se connecter à l'instance EC2 avec la clé SSH qui sera créée. Il est important de noter que la clé SSH doit être créée au préalable sur AWS.",[16,2235,2236,2239],{},[62,2237,2238],{},"subnet_id"," est l'identifiant du sous-réseau dans lequel l'instance EC2 sera créée. Dans ce cas précis, il permet de se connecter à l'instance EC2 avec la clé SSH qui sera créée.",[16,2241,2242,2245],{},[62,2243,2244],{},"vpc_security_group_ids"," est l'identifiant du groupe de sécurité qui sera utilisé pour se connecter à l'instance EC2. Dans ce cas précis, il permet de se connecter à l'instance EC2 avec la clé SSH qui sera créée.",[16,2247,2248,2251],{},[62,2249,2250],{},"user_data_replace_on_change"," est une variable qui permet de configurer l'instance EC2. Dans ce cas précis, il permet de configurer l'instance EC2 avec la clé SSH qui sera créée.",[1404,2253,2255],{"id":2254},"vpc","VPC",[16,2257,2258],{},"Voici un extrait du code Terraform qui ma permis de créer un VPC:",[66,2260,2262],{"className":68,"code":2261,"language":70,"meta":71,"style":71},"resource \"aws_vpc\" \"ubuntu-vpc\" {\n  cidr_block = \"10.0.0.0\u002F16\"\n\n  tags = {\n    Name = \"ubuntu-vpc\"\n  }\n}\n\nresource \"aws_subnet\" \"ubuntu-subnet\" {\n  vpc_id     = aws_vpc.ubuntu-vpc.id\n  cidr_block = \"10.0.0.0\u002F16\"\n}\n\nresource \"aws_internet_gateway\" \"ubuntu-igw\" {\n  vpc_id = aws_vpc.ubuntu-vpc.id\n}\n\nresource \"aws_route_table\" \"ubuntu-rt\" {\n  vpc_id = aws_vpc.ubuntu-vpc.id\n\n  route {\n    cidr_block = \"0.0.0.0\u002F0\"\n    gateway_id = aws_internet_gateway.ubuntu-igw.id\n  }\n}\n\nresource \"aws_route_table_association\" \"ubuntu-rta\" {\n  subnet_id      = aws_subnet.ubuntu-subnet.id\n  route_table_id = aws_route_table.ubuntu-rt.id\n}\n",[73,2263,2264,2269,2274,2278,2282,2287,2291,2295,2299,2304,2309,2313,2317,2321,2326,2331,2335,2339,2344,2348,2352,2356,2360,2365,2369,2373,2377,2382,2387,2392],{"__ignoreMap":71},[76,2265,2266],{"class":78,"line":79},[76,2267,2268],{"class":82},"resource \"aws_vpc\" \"ubuntu-vpc\" {\n",[76,2270,2271],{"class":78,"line":86},[76,2272,2273],{"class":82},"  cidr_block = \"10.0.0.0\u002F16\"\n",[76,2275,2276],{"class":78,"line":92},[76,2277,131],{"emptyLinePlaceholder":130},[76,2279,2280],{"class":78,"line":98},[76,2281,810],{"class":82},[76,2283,2284],{"class":78,"line":104},[76,2285,2286],{"class":82},"    Name = \"ubuntu-vpc\"\n",[76,2288,2289],{"class":78,"line":110},[76,2290,639],{"class":113},[76,2292,2293],{"class":78,"line":117},[76,2294,114],{"class":113},[76,2296,2297],{"class":78,"line":122},[76,2298,131],{"emptyLinePlaceholder":130},[76,2300,2301],{"class":78,"line":127},[76,2302,2303],{"class":82},"resource \"aws_subnet\" \"ubuntu-subnet\" {\n",[76,2305,2306],{"class":78,"line":134},[76,2307,2308],{"class":82},"  vpc_id     = aws_vpc.ubuntu-vpc.id\n",[76,2310,2311],{"class":78,"line":140},[76,2312,2273],{"class":82},[76,2314,2315],{"class":78,"line":146},[76,2316,114],{"class":113},[76,2318,2319],{"class":78,"line":152},[76,2320,131],{"emptyLinePlaceholder":130},[76,2322,2323],{"class":78,"line":158},[76,2324,2325],{"class":82},"resource \"aws_internet_gateway\" \"ubuntu-igw\" {\n",[76,2327,2328],{"class":78,"line":302},[76,2329,2330],{"class":82},"  vpc_id = aws_vpc.ubuntu-vpc.id\n",[76,2332,2333],{"class":78,"line":308},[76,2334,114],{"class":113},[76,2336,2337],{"class":78,"line":314},[76,2338,131],{"emptyLinePlaceholder":130},[76,2340,2341],{"class":78,"line":319},[76,2342,2343],{"class":82},"resource \"aws_route_table\" \"ubuntu-rt\" {\n",[76,2345,2346],{"class":78,"line":324},[76,2347,2330],{"class":82},[76,2349,2350],{"class":78,"line":330},[76,2351,131],{"emptyLinePlaceholder":130},[76,2353,2354],{"class":78,"line":336},[76,2355,1300],{"class":82},[76,2357,2358],{"class":78,"line":341},[76,2359,1305],{"class":82},[76,2361,2362],{"class":78,"line":346},[76,2363,2364],{"class":82},"    gateway_id = aws_internet_gateway.ubuntu-igw.id\n",[76,2366,2367],{"class":78,"line":352},[76,2368,639],{"class":113},[76,2370,2371],{"class":78,"line":358},[76,2372,114],{"class":113},[76,2374,2375],{"class":78,"line":364},[76,2376,131],{"emptyLinePlaceholder":130},[76,2378,2379],{"class":78,"line":369},[76,2380,2381],{"class":82},"resource \"aws_route_table_association\" \"ubuntu-rta\" {\n",[76,2383,2384],{"class":78,"line":374},[76,2385,2386],{"class":82},"  subnet_id      = aws_subnet.ubuntu-subnet.id\n",[76,2388,2389],{"class":78,"line":379},[76,2390,2391],{"class":82},"  route_table_id = aws_route_table.ubuntu-rt.id\n",[76,2393,2394],{"class":78,"line":385},[76,2395,114],{"class":113},[16,2397,2398,2401],{},[62,2399,2400],{},"aws_vpc"," est une ressource qui permet de créer un VPC (Virtual Private Cloud). C'est un réseau privé virtuel qui permet de isoler ses ressources AWS du reste d'Internet.",[16,2403,2404,2407],{},[62,2405,2406],{},"aws_subnet"," est une ressource qui permet de créer un sous-réseau. C'est une partie d'un VPC qui permet d'isoler ses ressources AWS du reste d'Internet.",[16,2409,2410,2413],{},[62,2411,2412],{},"aws_internet_gateway"," est une ressource qui permet de créer une passerelle Internet. C'est une passerelle qui permet de connecter son VPC au reste d'Internet.",[16,2415,2416,2419],{},[62,2417,2418],{},"aws_route_table"," est une ressource qui permet de créer une table de routage. C'est une table qui permet de router le trafic entre son VPC et le reste d'Internet.",[16,2421,2422,2425],{},[62,2423,2424],{},"aws_route_table_association"," est une ressource qui permet de créer une association de table de routage. C'est une association qui permet de connecter son VPC au reste d'Internet.",[1404,2427,2429],{"id":2428},"groupe-de-sécurité","Groupe de sécurité",[66,2431,2433],{"className":68,"code":2432,"language":70,"meta":71,"style":71},"resource \"aws_security_group\" \"allow_ssh\" {\n  name        = \"allow_ssh\"\n  description = \"Allow SSH inbound traffic\"\n  vpc_id      = aws_vpc.ubuntu-vpc.id\n\n  ingress {\n    from_port   = 22\n    to_port     = 22\n    protocol    = \"tcp\"\n    cidr_blocks = [\"${data.http.my_ip.response_body}\u002F32\"]\n  }\n\n  ingress {\n    from_port   = 80\n    to_port     = 80\n    protocol    = \"tcp\"\n    cidr_blocks = [\"0.0.0.0\u002F0\"]\n  }\n\n  ingress {\n    from_port   = 443\n    to_port     = 443\n    protocol    = \"tcp\"\n    cidr_blocks = [\"0.0.0.0\u002F0\"]\n  }\n\n  egress {\n    from_port   = 0\n    to_port     = 0\n    protocol    = \"-1\"\n    cidr_blocks = [\"0.0.0.0\u002F0\"]\n  }\n}\n",[73,2434,2435,2440,2445,2450,2455,2459,2463,2467,2471,2475,2479,2483,2487,2491,2496,2501,2505,2509,2513,2517,2521,2526,2531,2535,2539,2543,2547,2551,2555,2559,2563,2567,2571],{"__ignoreMap":71},[76,2436,2437],{"class":78,"line":79},[76,2438,2439],{"class":82},"resource \"aws_security_group\" \"allow_ssh\" {\n",[76,2441,2442],{"class":78,"line":86},[76,2443,2444],{"class":82},"  name        = \"allow_ssh\"\n",[76,2446,2447],{"class":78,"line":92},[76,2448,2449],{"class":82},"  description = \"Allow SSH inbound traffic\"\n",[76,2451,2452],{"class":78,"line":98},[76,2453,2454],{"class":82},"  vpc_id      = aws_vpc.ubuntu-vpc.id\n",[76,2456,2457],{"class":78,"line":104},[76,2458,131],{"emptyLinePlaceholder":130},[76,2460,2461],{"class":78,"line":110},[76,2462,893],{"class":82},[76,2464,2465],{"class":78,"line":117},[76,2466,898],{"class":82},[76,2468,2469],{"class":78,"line":122},[76,2470,903],{"class":82},[76,2472,2473],{"class":78,"line":127},[76,2474,908],{"class":82},[76,2476,2477],{"class":78,"line":134},[76,2478,913],{"class":82},[76,2480,2481],{"class":78,"line":140},[76,2482,639],{"class":113},[76,2484,2485],{"class":78,"line":146},[76,2486,131],{"emptyLinePlaceholder":130},[76,2488,2489],{"class":78,"line":152},[76,2490,893],{"class":82},[76,2492,2493],{"class":78,"line":158},[76,2494,2495],{"class":82},"    from_port   = 80\n",[76,2497,2498],{"class":78,"line":302},[76,2499,2500],{"class":82},"    to_port     = 80\n",[76,2502,2503],{"class":78,"line":308},[76,2504,908],{"class":82},[76,2506,2507],{"class":78,"line":314},[76,2508,944],{"class":82},[76,2510,2511],{"class":78,"line":319},[76,2512,639],{"class":113},[76,2514,2515],{"class":78,"line":324},[76,2516,131],{"emptyLinePlaceholder":130},[76,2518,2519],{"class":78,"line":330},[76,2520,893],{"class":82},[76,2522,2523],{"class":78,"line":336},[76,2524,2525],{"class":82},"    from_port   = 443\n",[76,2527,2528],{"class":78,"line":341},[76,2529,2530],{"class":82},"    to_port     = 443\n",[76,2532,2533],{"class":78,"line":346},[76,2534,908],{"class":82},[76,2536,2537],{"class":78,"line":352},[76,2538,944],{"class":82},[76,2540,2541],{"class":78,"line":358},[76,2542,639],{"class":113},[76,2544,2545],{"class":78,"line":364},[76,2546,131],{"emptyLinePlaceholder":130},[76,2548,2549],{"class":78,"line":369},[76,2550,957],{"class":82},[76,2552,2553],{"class":78,"line":374},[76,2554,962],{"class":82},[76,2556,2557],{"class":78,"line":379},[76,2558,967],{"class":82},[76,2560,2561],{"class":78,"line":385},[76,2562,972],{"class":82},[76,2564,2565],{"class":78,"line":391},[76,2566,944],{"class":82},[76,2568,2569],{"class":78,"line":397},[76,2570,639],{"class":113},[76,2572,2573],{"class":78,"line":402},[76,2574,114],{"class":113},[16,2576,2577,2580],{},[62,2578,2579],{},"aws_security_group"," est une ressource qui permet de créer un groupe de sécurité. C'est un groupe de sécurité qui permet de contrôler le trafic entre son VPC et le reste d'Internet.",[16,2582,2583,2586],{},[62,2584,2585],{},"ingress"," est une ressource qui permet de créer une règle d'entrée. C'est une règle qui permet de contrôler le trafic entrant dans son VPC.",[16,2588,2589,2592],{},[62,2590,2591],{},"egress"," est une ressource qui permet de créer une règle de sortie. C'est une règle qui permet de contrôler le trafic sortant de son VPC.",[750,2594,2595],{},[16,2596,2597,2598,2604],{},"A noter que dans l'ingress du protocole SSH j'utilise une ",[2599,2600,2601],"em",{},[62,2602,2603],{},"data"," dynamique qui me permet de récupérer directement mon adresse IP actuel et l'envoyer l'or de la création de l'intance.",[16,2606,2607],{},"Voici un exemple",[66,2609,2611],{"className":68,"code":2610,"language":70,"meta":71,"style":71},"data \"http\" \"my_ip\" {\n  url = \"https:\u002F\u002Fifconfig.me\u002Fip\"\n}\n",[73,2612,2613,2618,2623],{"__ignoreMap":71},[76,2614,2615],{"class":78,"line":79},[76,2616,2617],{"class":82},"data \"http\" \"my_ip\" {\n",[76,2619,2620],{"class":78,"line":86},[76,2621,2622],{"class":82},"  url = \"https:\u002F\u002Fifconfig.me\u002Fip\"\n",[76,2624,2625],{"class":78,"line":92},[76,2626,114],{"class":113},[1404,2628,2630],{"id":2629},"ip-elastique","IP Elastique",[66,2632,2634],{"className":68,"code":2633,"language":70,"meta":71,"style":71},"resource \"aws_eip\" \"docker_ip\" {\n  instance = aws_instance.ubuntu[0].id\n  domain   = \"vpc\"\n}\n",[73,2635,2636,2641,2646,2651],{"__ignoreMap":71},[76,2637,2638],{"class":78,"line":79},[76,2639,2640],{"class":82},"resource \"aws_eip\" \"docker_ip\" {\n",[76,2642,2643],{"class":78,"line":86},[76,2644,2645],{"class":82},"  instance = aws_instance.ubuntu[0].id\n",[76,2647,2648],{"class":78,"line":92},[76,2649,2650],{"class":82},"  domain   = \"vpc\"\n",[76,2652,2653],{"class":78,"line":98},[76,2654,114],{"class":113},[42,2656,2658],{"id":2657},"résultat","Résultat",[16,2660,2661],{},"Le résultat de cette expérimentation est une infrastructure de base sur AWS avec Terraform. Je suis assez satisfait du résultat, j'ai pu mettre en place une infrastructure de base sur AWS avec Terraform et comprendre comment fonctionne Terraform et comment il interagit avec AWS.",[16,2663,2664],{},"Surtout au niveau du VPC ou j'ai pu comprendre comment fonctionne les VPC, les sous-réseaux, les passerelles Internet et les tables de routage.",[42,2666,2668],{"id":2667},"suite","Suite",[16,2670,2671],{},"La suite est donc de compléter ce mini projets en ajoutant une partie Ansible pour configurer l'instance EC2. Et déployer une mini application web (caddy + fastapi) sur l'instance EC2.",[550,2673,552],{},{"title":71,"searchDepth":86,"depth":86,"links":2675},[2676,2677,2683,2684],{"id":1493,"depth":86,"text":1494},{"id":1503,"depth":86,"text":1504,"children":2678},[2679,2680,2681,2682],{"id":2115,"depth":92,"text":2116},{"id":2254,"depth":92,"text":2255},{"id":2428,"depth":92,"text":2429},{"id":2629,"depth":92,"text":2630},{"id":2657,"depth":86,"text":2658},{"id":2667,"depth":86,"text":2668},"2026-04-08","Création d'une structure de base sur AWS avec Terraform","\u002Flaboratoire\u002Fterraform_aws_exp_01.png",{},"\u002Flaboratoire\u002Fterraform_aws_exp_01",{"title":2067,"description":2686},"laboratoire\u002Fterraform_aws_exp_01",[567,568,1464],"JedYTjPHbcHUJnUkQs8hIA4UQ1oNiE9ItMWVUX3IkGI",1777912143193]