Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cc:temp [2022/10/30 12:26]
florin.mihalache [Tipuri de variabile]
cc:temp [2022/11/11 23:12] (current)
florin.mihalache [Deployments & virtual machines în AWS]
Line 1: Line 1:
-====== Laboratorul ​- Terraform ====== +====== Laboratorul ​05 - Terraform ​+ AWS ======
-===== Ce este Terraform? ===== +
-===== Instalare Terraform ===== +
-Folosim site-ul oficial al Terraform pentru a instala tool-ul. Găsiți toate detaliile necesare aici: https://​www.terraform.io/​downloads+
  
-Pentru ​instala Terraform pe o mașinp cu un sistem de operare Ubuntu / Debian, folosim următoarele comenzi: +===== Deployments & virtual machines în AWS ===== 
-<code bash> +În cadrul acestui laborator veți învățcum să creați ​mașini virtuale în cadru AWS (Amazon Web Services), care reprezintă o platformă care furnizează servicii de tip cloud computing, baze de date, stocare de fișiere, device farms, ​etc.
-wget -O- https://​apt.releases.hashicorp.com/​gpg | gpg --dearmor | sudo tee /​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 -csmain" | sudo tee /etc/​apt/​sources.list.d/​hashicorp.list +
-sudo apt update && sudo apt install terraform +
-</​code>​+
  
-Pentru ​a verifica dacă instalarea fost efectuată cu succes, încercăm să obținem versiunea de Terraform instalată: ''​terraform -version''​+Pentru ​acest laborator presupunem că avem deja Terraform instalat de la laboratorul precedent. Dacă nu avețTerraform instalat, puteți urma pașii din laboratorul anterior.
  
-=== Terraform ​autocomplete === +Pe langa Terraform, avem nevoie de AWS CLI instalat. ​Pentru a instala, urmati pasii de [[https://​docs.aws.amazon.com/​cli/​latest/​userguide/​getting-started-install.html | aici]].
-Pentru a putea utiliza funcția ​de autocomplete cu Terraform''​terraform ​-install-autocomplete''​+
  
-===== Terraform + Docker ===== +Pe lângă astaavem nevoie de un cont pentru Amazon AWSDupă ce ați făcut pașii ​pentru ​a avea propriul cont AWS, vrem sa conectăm AWS CLI la consola de AWS. 
-În laboratorul curent o să folosim Terraform împreună cu Dockercu care suntem deja familiariÎncepem prin crea un director nou pentru ​configuratia noastră: + 
-<code bash> +Pentru a face asta, mergem în AWS și intrăm în secțiunea IAM
-mkdir lab4cc +{{ :​cc:​laboratoare:​lab-5-image3.png?​700 |}} 
-cd lab4cc ​ + 
-</​code>​+Apoi mergem la "My security credentials":​ 
 +{{ :​cc:​laboratoare:​lab-5-image1.png?​700 |}} 
 + 
 +Următorul pas este să mergem la "​Access Keys" și să apăsăm pe butonul de ''​Create New Access Key'':​ 
 +{{ :​cc:​laboratoare:​lab-5-image5.png?​700 |}} 
 + 
 +Păstrați fișierul generat. Rulați comanda ''​aws configure''​ și introduceți datele generate în fisierul creat anterior (''​AWSAccessKeyId''​ și ''​AWSSecretKey''​).
  
-Creăm un fișier cu numele ''​main.tf''​ și introducem ​următorul ​cod:+Pentru a crea o instanță simplă de EC2 (o mașina virtuală) folosim ​următorul ​fișier de Terraform:
 <code terraform>​ <code terraform>​
 terraform { terraform {
  ​required_providers {  ​required_providers {
-   docker ​= { +   aws = { 
-     ​source = "kreuzwerker/docker+     ​source ​ = "hashicorp/aws
-     ​version = "​~> ​2.13.0"+     ​version = "​~> ​4.16"
    }    }
  }  }
 + 
 + ​required_version = ">= 1.2.0"
 } }
    
-provider "docker" {} +provider "aws" { 
-  + region ​= "us-west-2" ​# regiunea in care o sa se faca deploy la resurse
-resource "​docker_image"​ "​nginx"​ { +
- ​name ​        = "nginx:​latest" +
- ​keep_locally = false+
 } }
    
-resource "docker_container" "nginx" { +resource "aws_instance" "app_server" { 
- image docker_image.nginx.latest + ami           "​ami-830c94e3"​ # tipul de masina folosita (ami = Amazon Machine Image) 
- name  ​= "tutorial+ instance_type ​= "t2.micro" ​# tipul de instanta (resursele pe care le are masina) 
- ports { +  
-   internal ​80 + tags { 
-   external ​8000+   Name "​labAwsTerraform"​
  }  }
 } }
 </​code>​ </​code>​
  
 +Rulați comenzile cunoscute pentru a face deployment acestei infrastructuri:​
 +<code bash>
 +terraform init
 +terraform fmt
 +terraform plan
 +terraform apply
 +</​code>​
  
-Să analizăm pe rând fiecare bloc de cod introdus: +Pentru a verifica ca mașina virtuală a fost deployedcăutăm serviciul EC2: 
-  * ''​terraform {}''​ - conține setarile de Terraform, inclusiv provider-ul pe care urmează să îl folosim. ​Pentru ​fiecare provider, câmpul ''​source''​ definește numele provider-ului. By default, Terraform folosește Terraform Registry pentru ​instala un provider. Astfel, în exemplul nostru, ''​kreuzwerker/​docker''​ este un provider care se găsește în registrul Terraform la path-ul ''​registry.terraform.io/​kreuzwerker/​docker''​. Câmpul ''​version''​ este opțional, dacă nu îl folosimTerraform o să descarce by default ultima versiune disponibilă. +{:cc:laboratoare:​lab-5-image7.png?700 |}}
-  * ''​provider ​{}''​ - un block de tipul provider conține configurările necesare pentru ca acel provider să poată fi folosit. În cazul nostru, am folosit ''​docker''​. Un provider este doar un plugin pe care Terraform îl folosește pentru a crea și pentru a gestiona resursele. +
-  * Blocurile de tip resource - un astfel de bloc, așa cum sugerează și numele, este folosit pentru a defini resurse ale infrastructurii noastre. Așa cum putem observa, un bloc de tip resursă are 2 labels''​resource "​docker_image"​ "​nginx"''​. În acest exemplu, ''​docker_image''​ este tipul de resursă, iar ''​nginx''​ este numele resursei. Fiecare astfel de bloc are mai multe proprietăți,​ acestea diferă de la resursă la resursă. Exempluîn laboratorul viitor o sa configurăm o mașină virtuală într-un provider de cloud unde o să folosim parametrii ca tipul de masină, hard disk, dimensiune hard disk, regiunea în care să fie deployed masina, etc.+
  
-Recapitulare cod: +Ajungem în pagina următoare în care vedem că nu avem nicio instanță up and running, ​deși planul nostru de Terraform a fost executat ​cu succesDe ce? 
-  - Am populat block-ul ''​terraform''​ cu config-ul unde am specificat providerul ''​docker''​ și versiunea dorită+{{ :​cc:​laboratoare:​lab-5-image4.png?700 |}}
-  - Am inițializat providerul ''​docker''​. +
-  - Am creat o resursă de tipul ''​docker_image'' ​cu numele ''​nginx''​ (numele variabilei)+
-  Am creat o resursă de tipul ''​docker_container''​ cu numele ''​nginx''​. În această resursă, pentru imagine am folosit imaginea definită mai sus, iar numele container-ului este dat de câmpul ''​name''​.+
  
-Pentru a pune in picioare infrastructura:​ +Observați diferențde regiuni (Frankfurt, ​în cazul din imaginea anterioară,​ față de us-west-în Terraform). Pentru a modifica regiunea ​în care facem deployment la resurse modificăm codul TerraformÎn cazul de față, putem să facem click pe Frankfurt și să selectăm us-west-2 (Oregon). În acest moment putem vedea că avem o instanță up and running: 
-  - Initializare:​ ''​terraform init''​. Urmăriți output-ul comenzii pentru ​a înțelege ce face această comandă. +{{ :​cc:​laboratoare:​lab-5-image2.png?​700 |}}
-  ​Formatarea codului. Acest pas este opțional, dar foarte util: ''​terraform fmt''​ +
-  ​Validarea configurării (și acest pas este optional, ​în cazul în care mergem mai departe cu o configurare invalidă, o să primim eroare): ''​terraform validate''​ +
-  - Rulăm comanda ''​terraform plan''​Această comandă este un dry-rundeci putem observa cum o să arate infrastructura noastră după ce o să aplicăm configurarea creată anterior. **Atenție**, această comandă nu modifică infrastructura. +
-  Aplicăm configurația:​ ''​terraform apply''​+
  
 <note tip> <note tip>
-Task: urmati instrucțiunile din shell-ul interactiv șfaceți deploy la infrastructură. Observați ​output-ul comenzii. +În codul Terraform modificați numele masinii din ''​labAwsTerraform''​ în ''​testUpdate''​. 
- +Rulatț comenzile obișnuite pentru a vedea planul. 
-Pentru a observa state-ul: ''​terraform show''​+Observați ​că această modificare nu implică distrugerea mașinii existente, ci doar modificarea in-place.
 </​note>​ </​note>​
  
-<note tip> +{{ :cc:​laboratoare:​lab-5-image6.png?​700 |}}
-Taskmodificarea unei infrastructuri existente ​modificati fișierul anterior, astfel încât container-ul să folosească portul 8080, nu 8000+
  
-Rulați comanda pentru ​vedea planulModificarea este facută in-place?+===== Cluster Kubernetes în AWS ===== 
 +Pentru ​face deployment unui cluster de Kubernetes în AWS avem 2 opțiuni. 
 +  - Facem deploy la mai multe mașini virtuale și instalăm și configurăm un cluster de mână. 
 +  ​Folosim serviciul AWS special conceput pentru clusters de Kubernetes, AWS EKS Cluster
  
-Ștergere infrastructură - rulați comanda ''​terraform destroy''​ +În cazul acestui laborator, o să facem deployment la un cluster folosind EKS.
-</​note>​+
  
-===== Variabile în Terraform ===== +Pentru a urma best practices recomandate de hashicorp, o să spargem codul în mai multe fișiere. 
-Avem următorul fișier'' ​outputs.tf''​, unde avem acest bloc:+ 
 +Fișierul ​''​variables.tf'' ​o sa conțină o simplă variabilă în care definim zona în care vrem să facem deployment:
 <code terraform>​ <code terraform>​
-output ​"Lab" { +variable ​"region" { 
-  value="lab4 first output"+ description ​= "AWS region"​ 
 + ​type ​       = string 
 + ​default ​    = "​us-west-2"
 } }
 </​code>​ </​code>​
  
-Am creat primul output în Terraform. Pentru a observa comportamentulurmați pașii din exercițiul anterior pentru a "​aplica"​ infrastructura. +Mai departe avem nevoie de un VPCdeci vom crea un nou fisier ''​vpc.tf''​. Mai multe despre ce este un VPC[[https://​docs.aws.amazon.com/​vpc/​latest/​userguide/​what-is-amazon-vpc.html | aici]]. 
- +<​code>​ 
-Avem acest bloc cu următorul cod+module ​"vpc" { 
-<​code ​terraform+ source ​ = "​terraform-aws-modules/​vpc/​aws
-variable ​"LabCCTerraform" { + version = "​3.14.2"​ 
-  ​description ​= "primul lab in terraform"​ +  
-  ​default ​= "valoare default a primului lab in terraform"+ name = "​cc-vpc"​ 
 +  
 + cidr = "​10.0.0.0/​16"​ 
 + ​azs ​ ​= ​slice(data.aws_availability_zones.available.names,​ 0, 3) 
 +  
 + ​private_subnets = ["10.0.1.0/24", "​10.0.2.0/​24",​ "​10.0.3.0/​24"​] 
 + ​public_subnets ​ = ["​10.0.4.0/​24",​ "​10.0.5.0/​24",​ "​10.0.6.0/​24"​] 
 +  
 + ​enable_nat_gateway ​  = true 
 + ​single_nat_gateway ​  = true 
 + ​enable_dns_hostnames = true 
 +  
 + ​public_subnet_tags = { 
 +   "​kubernetes.io/​cluster/​${local.cluster_name}"​ = "​shared"​ 
 +   "​kubernetes.io/​role/​elb" ​                     = 1 
 + } 
 +  
 + ​private_subnet_tags = { 
 +   "​kubernetes.io/​cluster/​${local.cluster_name}"​ = "​shared"​ 
 +   "​kubernetes.io/​role/​internal-elb" ​            = 1 
 + }
 } }
 </​code>​ </​code>​
-Aplicați planul și observați comportamentul. 
  
-==== Prioritatea variabilelor ==== +Mai multe detalii despre modulul ​de Terraform ​pentru VPC: [[https://​registry.terraform.io/​providers/​hashicorp/​aws/​latest/​docs/​resources/​vpc | aici]].
-Un alt mod de a seta variabile în Terraform ​este prin variabile de mediuBy default, Terraform caută variabilele de mediu care încep cu ''​F_VAR_''​De exemplu, o variabilă de mediu cu numele ''​TF_VAR_MYTESTVAR=myvalue''​ o să atribuie valoarea myvalue unei variabile cu numele ''​MYTESTVAR''​. Variabila cu numele ''​MYTESTVAR''​ trebuie sa fie totuși declarată in configurația noastră de Terraform.+
  
-<note tip> +În continuare avem nevoie ​de 2 security groups, pe care o să le folosească cluster-ul nostru. Așadar creăm un nou fișier cu numele ​''​securityGroups.tf''​ cu următorul conținut:​ 
-Task: +<​code>​ 
-  * Creați o variabilă ​de mediu care sa suprascrie variabilă folosită de noi: ''​export TF_VAR_LabCCTerraform="Value from environment"''​ +resource "​aws_security_group"​ "​node_group_one"​ { 
-  ​* Rulați din nou comanda ''​terraform apply''​ pentru a observa comportamentul+ ​name_prefix ​= "node_group_one
-</note>+ vpc_id ​     = module.vpc.vpc_id 
 +  
 + ​ingress { 
 +   ​from_port = 22 
 +   ​to_port ​  = 22 
 +   ​protocol ​ = "​tcp"​ 
 +  
 +   ​cidr_blocks = [ 
 +     "​10.0.0.0/​8",​ 
 +   ] 
 + } 
 +
 +  
 +resource "​aws_security_group"​ "​node_group_two"​ { 
 + ​name_prefix = "​node_group_two"​ 
 + ​vpc_id ​     = module.vpc.vpc_id 
 +  
 + ​ingress { 
 +   ​from_port = 22 
 +   ​to_port ​  = 22 
 +   ​protocol ​ = "​tcp"​ 
 +  
 +   ​cidr_blocks = [ 
 +     "​192.168.0.0/​16",​ 
 +   ] 
 + } 
 +} 
 +</code>
  
-==== Fișiere tfvars ==== +Ne putem gândi la un security group ca la un firewallMai multe detalii în [[https://aviatrix.com/​learn-center/​cloud-security/​aws-security-groups/​ | documentație]]Documentația unui security group de AWS în Terraform: [[https://​registry.terraform.io/providers/​hashicorp/​aws/​latest/​docs/​resources/​security_group | aici]].
-<note tip> +
-Task: +
-  * Creați ​un nou fișier cu numele terraform.tfvars si adăugați următoarea linie de cod''​LabCCTerraform="​Value from tfvars file"''​Acest fișier, deși are extensia diferită față de cele anterioare foloseste exact aceeași sintaxă. +
-  * Folosiți din nou comanda ​terraform ​apply pentru a observa comportamentul. +
-</note>+
  
-==== Injectare variabile din linia de comandă ==== 
-Un alt mod prin care putem atribui o valoare unei variabile este prin linia de comandă. 
  
-Rulați următoarea comandă''​terraform apply -var LabCCTerraform=valueFromCommandLine''​ +Până acum am definit doar componentele de care o să ne folosim în momentul în care configurăm cluster-ul nostru. Pentru a face asta, avem un nou fișier ​''​cluster.tf'' ​cu următoarea ​configurație
- +<​code>​ 
-In urma acestui exercițiu, am aflat ca ordinea de prioritizare a variabilelor este următoarea:​ +module "​eks"​ { 
-  - linie de comandă + source ​ = "​terraform-aws-modules/​eks/​aws"​ 
-  - fișier tfvars + version = "​18.26.6"​ 
-  - varibila de mediu +  
-  ​valoarea default + ​cluster_name ​   ​local.cluster_name 
- + ​cluster_version ​"​1.22"​ 
-==== Tipuri de variabile ​==== +  
-Un alt tip de variabilă pe care îl putem folosi este lista: + ​vpc_id ​    module.vpc.vpc_id 
-<code terraform>​ + ​subnet_ids ​module.vpc.private_subnets 
-variable ​"mylist" ​{ +  
-  ​default ​= ["ana""are""mere"]+ ​eks_managed_node_group_defaults ​
 +   ​ami_type ​"​AL2_x86_64"​ 
 +  
 +   ​attach_cluster_primary_security_group ​true 
 +  
 +   # Disabling and using externally provided security groups 
 +   ​create_security_group ​false 
 + } 
 +  
 + eks_managed_node_groups = { 
 +   one = { 
 +     name = "node-group-1
 +  
 +     ​instance_types ​= ["t3.small"
 +  
 +     ​min_size ​    = 1 
 +     ​max_size ​    = 3 
 +     ​desired_size = 2 
 +  
 +     ​pre_bootstrap_user_data = <<​-EOT 
 +     echo 'foo bar' 
 +     EOT 
 +  
 +     ​vpc_security_group_ids = [ 
 +       ​aws_security_group.node_group_one.id 
 +     ] 
 +   } 
 +  
 +   two = { 
 +     name = "node-group-2" 
 +  
 +     ​instance_types = ["t3.medium"] 
 +  
 +     ​min_size ​    = 1 
 +     ​max_size ​    = 2 
 +     ​desired_size = 1 
 +  
 +     ​pre_bootstrap_user_data = <<​-EOT 
 +     echo 'foo bar' 
 +     EOT 
 +  
 +     ​vpc_security_group_ids = [ 
 +       ​aws_security_group.node_group_two.id 
 +     ] 
 +   } 
 + }
 } }
 </​code>​ </​code>​
-Pentru a accesa un element dintr-o listă ​avem 2 variante. + 
-  * folosind o funcție: +Mai avem doar de creat un fișier ''​main.tf''​ cu următoarea configurație: 
-<​code ​terraform+<​code>​ 
-output ​"getelement" { +provider ​"kubernetes" { 
-  ​value ​element(var.mylist,1)+ host                   module.eks.cluster_endpoint 
 + ​cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
 } }
-</​code>​ +  
-  * folosind accesare direct cu indexul: +provider ​"aws" { 
-<code terraform>​ + region ​= var.region
-output ​"useindex" { +
-  ​value ​= var.mylist[1]+
 } }
-</​code>​ +  
- +data "aws_availability_zones"​ "​available" {} 
-Liste nested: +  
-<code terraform>​ +locals { 
-variable ​"nestedlist" { + ​cluster_name ​= "cc-eks-${random_string.suffix.result}"
-  type = list +
-    ​default ​+
-      ["item1", "​item2"​],​ +
-      ["​item3",​ "​item4"​] +
-    ]+
 } }
-</​code>​ +  
-Pentru a accesa elementele dintr-o listă nested, folosim sintaxa asemănătoare:​ +resource ​"random_string"​ "​suffix" { 
-<code terraform>​ + length ​ ​= ​
-output ​"nestedlist" { + ​special = false
-  ​value var.nestedlist[1][1]+
 } }
 </​code>​ </​code>​
  
-Maps+Pentru a afișa câteva informații legate de infrastructura noastră avem nevoie de câteva outputs. Așa cum am învățat data trecută, facem un fișier separat în care definim acest outputs
-<​code ​terraform+<​code>​ 
-variable mymap { +output ​"cluster_id" ​{ 
-  default = { + description ​= "EKS cluster ID
-    us = "United States+ value       module.eks.cluster_id
-    ​eu ​= "Europe+
-    ​apac ​"​Asia/​Pacific"​ +
-  }+
 } }
-output "my_region_map" { +  
-  value = var.mymap+output "cluster_endpoint" { 
 + description = "​Endpoint for EKS control plane"​ 
 + value       ​module.eks.cluster_endpoint
 } }
-</​code>​+  
 +output "​cluster_security_group_id"​ { 
 + ​description = "​Security group ids attached to the cluster control plane"​ 
 + ​value ​      = module.eks.cluster_security_group_id 
 +
 +  
 +output "​region"​ { 
 + ​description = "AWS region"​ 
 + ​value ​      = var.region 
 +
 +  
 +output "​cluster_name"​ { 
 + ​description = "​Kubernetes Cluster Name"​ 
 + ​value ​      = local.cluster_name 
 +
 +</​code> ​
  
-Pentru ​accesa elementele dintr-un map, folosim functia lookup, mai multe detalii gasiți în link-ul: https://developer.hashicorp.com/​terraform/​language/functions/​lookup +Rulăm comenzile obișnuite pentru ​crea infrastructura. Observați ca sunt foarte ​multe resurse care urmează să se construiască. 
-<code terraform+ 
-output ​"oneMapElement" { +In cazul in care ați realizat ca lipsește ceva (nu am definit niciunde ce versiuni ale provider-ilor vrem să folosim), best practices recomandă să avem un fișier numit ''​terraform.tf''​ care să conțină această configurație: 
-  ​value lookup(var.mymap, ​"us")+<​code>​ 
 +terraform { 
 + ​required_providers { 
 +   aws = { 
 +     ​source ​ = "​hashicorp/aws" 
 +     ​version = "~> 4.15.0" 
 +   } 
 +  
 +   ​random = { 
 +     ​source ​ = "​hashicorp/random"​ 
 +     version = "~3.1.0" 
 +   } 
 +  
 +   tls = { 
 +     ​source ​ = "hashicorp/​tls" 
 +     ​version = "~> 3.4.0"​ 
 +   } 
 +  
 +   ​cloudinit = 
 +     source ​ ​= ​"​hashicorp/​cloudinit"​ 
 +     ​version = "~> 2.2.0" 
 +   } 
 +  
 +   ​kubernetes = { 
 +     ​source ​ = "hashicorp/​kubernetes"​ 
 +     ​version = "~> 2.12.1"​ 
 +   } 
 + }
 } }
 </​code>​ </​code>​
-==== Organizarea codului Terraform ==== 
-Având în vedere că deja devine greu de urmărit codul nostru, avem nevoie de o refactorizare. 
  
-Best practices Terraform recomandă ​să avem fișiere separate pentru variabile ​și outputsSimplu spustoate variabilele stau într-un fișier ''​variables.tf''​toate output-urile stau într-un fișier ​''​outputs.tf''​. ​+Asteptați ca planul ​să se termine de rulat sș verificaținfrastructura creată în AWS (o să dureze în jur de 15-20 minute)Apoipentru a ne conecta la cluster-ul nostru proaspăt creat de Kubernetesfolosim următoarea comandă: 
 +<code bash> 
 +aws eks --region $(terraform ​output -raw region) update-kubeconfig \ 
 +    --name $(terraform output -raw cluster_name) 
 +</​code>​ 
 + 
 +Verificați conexiunea cu următoarea comandă: ​''​kubectl cluster-info''​ 
 + 
 +În acest moment avem un cluster configurat în AWS EKS și suntem conectați la el. Orice comandă de kubectl rulată o să fie executată pe cluster-ul nostru. 
  
cc/temp.1667125599.txt.gz · Last modified: 2022/10/30 12:26 by florin.mihalache
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0