En introduktion till Terraform för nybörjare – Tutorial för Terraform

By rik

Utforska Terraform: En Djupdykning i Infrastruktur som Kod

Har du någonsin undrat vad Terraform egentligen är? Låt oss utforska detta kraftfulla verktyg.

Infrastruktur som kod (IaC) har blivit ett nyckelbegrepp inom DevOps. Det innebär att hantera och etablera hela din IT-infrastruktur – oavsett om det handlar om fysiska eller virtuella maskiner – genom maskinläsbara konfigurationsfiler. Detta tillvägagångssätt är inte bara effektivt, det ger även ett mjukvarubaserat perspektiv på drift. Genom att använda skript kan vi automatisera hela datacenterhanteringen.

Även om Infrastruktur som kod erbjuder många fördelar, finns det utmaningar att övervinna:

  • Det krävs kunskaper inom kodning.
  • Det kan vara svårt att förutse konsekvenserna av ändringar.
  • Ändringar kan behöva återställas.
  • Det kan vara en utmaning att spåra gjorda förändringar.
  • Vissa resurser kanske inte kan automatiseras.
  • Infrastrukturen kan spridas över flera miljöer.

Det är här Terraform kommer in, som en lösning på dessa problem.

Vad är Terraform?

Terraform, utvecklat av HashiCorp, är ett verktyg med öppen källkod för infrastruktur som kod. Terraform tillåter oss att definiera och etablera all vår infrastruktur med hjälp av ett lättläst och deklarativt språk.

Detta verktyg gör det möjligt att lagra konfigurationen av din molninfrastruktur som kod. Det liknar andra verktyg, som CloudFormation, som är specialiserat på automatisering av AWS-infrastruktur, men med en viktig skillnad: Terraform är inte begränsat till en specifik molnplattform. Du kan använda det på många olika moln.

Här är några av de fördelar som Terraform erbjuder:

  • Det möjliggör orkestrering av resurser, inte bara konfigurationshantering.
  • Det stöder flera molnleverantörer som AWS, Azure, GCP, DigitalOcean och fler.
  • Det skapar en oföränderlig infrastruktur där konfigurationsändringar genomförs smidigt.
  • Det använder ett lättförståeligt språk, HCL (HashiCorp Configuration Language).
  • Det är enkelt att flytta konfigurationen mellan olika leverantörer.
  • Det har en klientarkitektur, vilket eliminerar behovet av ytterligare konfigurationshantering på en server.

Grundläggande Koncept i Terraform

Här är de centrala begrepp och termer som används i Terraform:

  • Variabler: Dessa är nyckel-värde-par som används av Terraform-moduler för att göra anpassning möjlig.
  • Leverantör: Ett plugin som interagerar med API:er för olika tjänster för att hantera resurser.
  • Modul: En mapp med Terraform-mallar som innehåller all konfiguration.
  • Status: Cachad information om den infrastruktur som Terraform hanterar och dess tillhörande konfigurationer.
  • Resurser: Byggstenar av infrastrukturen, som datorsystem, virtuella nätverk, etc., som används för att konfigurera och hantera infrastruktur.
  • Datakälla: Används av leverantörer för att hämta information om externa objekt till Terraform.
  • Utdatavärden: Värden som returneras av en Terraform-modul, som kan användas av andra konfigurationer.
  • Plan: En process som fastställer vilka åtgärder som krävs för att överföra infrastrukturen från dess nuvarande till önskat tillstånd (skapa, uppdatera eller ta bort).
  • Tillämpa: Steget där de planerade ändringarna faktiskt genomförs, vilket leder till önskat infrastrukturstatus.

Terraforms Livscykel

Terraforms livscykel består av fyra steg: initiera, planera, tillämpa och förstöra.

  • Terraform init: Initialiserar arbetskatalogen och läser in alla konfigurationsfiler.
  • Terraform plan: Skapar en plan för att uppnå önskat infrastrukturstatus genom att analysera konfigurationsfiler och nuvarande status.
  • Terraform apply: Tillämpar de planerade ändringarna och etablerar den önskade infrastrukturen.
  • Terraform destroy: Tar bort alla infrastrukturresurser som har flaggats efter appliceringsfasen.

Hur Fungerar Terraform?

Terraforms arkitektur består av två huvudkomponenter:

Terraform Kärna

Terraforms kärna bearbetar två informationskällor.

Den första är Terraform-konfigurationen som definieras av användaren. Här specificeras vilka resurser som ska skapas. Den andra är staten, där Terraform lagrar den aktuella statusen för infrastrukturen.

Terraforms kärna analyserar dessa informationskällor och tar fram en plan. Den jämför nuvarande och önskat läge och bestämmer vad som behöver göras: skapas, uppdateras eller raderas för att uppnå önskad infrastruktur.

Leverantörer

Den andra komponenten är leverantörer av specifik teknologi. Det kan vara molnleverantörer som AWS, Azure, GCP eller infrastruktur som tjänst-plattformar. Det kan även vara högre nivåer som Kubernetes eller andra plattforms-som-en-tjänst-verktyg, eller till och med programvaror.

Detta ger dig flexibilitet att bygga infrastruktur på flera nivåer.

Exempelvis kan du skapa en AWS-infrastruktur, bygga ett Kubernetes-kluster ovanpå den, och sedan distribuera tjänster inuti klustret.

Terraform har över hundra leverantörer för olika teknologier. Varje leverantör ger Terraform-användare tillgång till sina resurser. Med AWS-leverantören har du tillgång till många AWS-resurser som EC2-instanser och AWS-användare, och med Kubernetes-leverantören får du tillgång till tjänster, distributioner och namnutrymmen.

Terraform strävar efter att hjälpa dig att hantera hela applikationsmiljön, från infrastruktur till applikationer.

Låt oss nu gå in på lite praktiskt arbete. 👨‍💻

Vi ska installera Terraform på Ubuntu och konfigurera en enkel infrastruktur.

Installera Terraform

Börja med att ladda ner det senaste Terraform-paketet.

Gå till den officiella nedladdningssidan för att hitta den senaste versionen för ditt operativsystem.

    [email protected]:~$ wget https://releases.hashicorp.com/terraform/0.13.0/terraform_0.13.0_linux_amd64.zip
    --2020-08-14 16:55:38--
    https://releases.hashicorp.com/terraform/0.13.0/terraform_0.13.0_linux_amd64.zip
    Resolving releases.hashicorp.com (releases.hashicorp.com)... 151.101.153.183, 2a04:4e42:24::439
    Connecting to releases.hashicorp.com (releases.hashicorp.com)|151.101.153.183|:443... connected.
    HTTP request sent, awaiting response... 200 OK
    Length: 34851622 (33M) [application/zip]
    Saving to: ‘terraform_0.13.0_linux_amd64.zip’

    terraform_0.13.0_linux_amd64.zip
    100%[=================================================================>] 33.24M
    90.3KB/s in 5m 28s

    2020-08-14 17:01:06 (104 KB/s) - ‘terraform_0.13.0_linux_amd64.zip’ saved [34851622/34851622]
    

Extrahera det nedladdade paketet.

    [email protected]:~$ unzip terraform_0.13.0_linux_amd64.zip
    Archive:  terraform_0.13.0_linux_amd64.zip
    inflating: terraform
    

Flytta den körbara terraform-filen till den angivna sökvägen. Kontrollera därefter Terraform-versionen.

    [email protected]:~$ sudo mv terraform /usr/local/bin/
    [sudo] password for adminvista.com:
    [email protected]:~$ terraform -v
    Terraform v0.13.0
    

Nu kan du se de tillgängliga kommandona för Terraform.

    [email protected]:~$ terraform
    Usage: terraform [-version] [-help]  [args]

    The available commands for execution are listed below.
    The most common, useful commands are shown first, followed by
    less common or more advanced commands. If you're just getting
    started with Terraform, stick with the common commands. For the
    other commands, please read the help and docs before usage.

    Common commands:
    apply     Builds or changes infrastructure
    console   Interactive console for Terraform interpolations
    destroy   Destroy Terraform-managed infrastructure
    env       Workspace management
    fmt       Rewrites config files to canonical format
    get       Download and install modules for the configuration
    graph     Create a visual graph of Terraform resources
    import    Import existing infrastructure into Terraform
    init      Initialize a Terraform working directory
    login     Obtain and save credentials for a remote host
    logout    Remove locally-stored credentials for a remote host
    output    Read an output from a state file
    plan      Generate and show an execution plan
    providers Prints a tree of the providers used in the configuration
    refresh   Update local state file against real resources
    show      Inspect Terraform state or plan
    taint     Manually mark a resource for recreation
    untaint   Manually unmark a resource as tainted
    validate  Validates the Terraform files
    version   Prints the Terraform version
    workspace Workspace management

    All other commands:
    0.12upgrade Rewrites pre-0.12 module source code for v0.12
    0.13upgrade Rewrites pre-0.13 module source code for v0.13
    debug     Debug output management (experimental)
    force-unlock Manually unlock the terraform state
    push      Obsolete command for Terraform Enterprise legacy (v1)
    state     Advanced state management
    

Etablera en AWS EC2-instans med Terraform

I denna demonstration ska vi starta en ny AWS EC2-instans med Terraform.

Skapa en arbetskatalog för denna Terraform-demo.

    [email protected]:~$ mkdir terraform_demo
    

Navigera till katalogen och skapa en terraform-konfigurationsfil där du definierar leverantören och resurserna för att starta en AWS EC2-instans.

    [email protected]:~$ cd terraform_demo/
    [email protected]:~/terraform_demo$ gedit awsec2.tf

    provider "aws" {
    access_key = "B5KG6Fe5GUKIATUF5UD"
    secret_key = "R4gb65y56GBF6765ejYSJA4YtaZ+T6GY7H"
    region = "us-west-2"
    }

    resource "aws_instance" "terraform_demo" {
    ami = "ami-0a634ae95e11c6f91"
    instance_type = "t2.micro"
    }
    

Obs: Åtkomst- och hemliga nycklar har ändrats i detta exempel. Du måste använda dina egna.

I konfigurationen ser du att leverantören är inställd på AWS. Inuti leverantören anges AWS-användaruppgifter och regionen där instansen ska startas.

Under resurser ges information om AMI för Ubuntu (ami-0a634ae95e11c6f91) och instanstypen anges till t2.micro.

Konfigurationsfilen är lätt att läsa och förstå, även om du inte är en erfaren kodare.

terraform init

Det första steget är att initiera Terraform.

    [email protected]:~/terraform_demo$ terraform init

    Initializing the backend...

    Initializing provider plugins...
    - Using previously-installed hashicorp/aws v3.2.0

    The following providers do not have any version constraints in configuration,
    so the latest version was installed.

    To prevent automatic upgrades to new major versions that may contain breaking
    changes, we recommend adding version constraints in a required_providers block
    in your configuration, with the constraint strings suggested below.

    * hashicorp/aws: version = "~> 3.2.0"

    Terraform has been successfully initialized!

    You may now begin working with Terraform. Try running "terraform plan" to see
    any changes that are required for your infrastructure. All Terraform commands
    should now work.

    If you ever set or change modules or backend configuration for Terraform,
    rerun this command to reinitialize your working directory. If you forget, other
    commands will detect it and remind you to do so if necessary.
    

terraform plan

Nästa steg är planen, där utförandeplanen skapas för att etablera infrastrukturen.

    [email protected]:~/terraform_demo$ terraform plan
    Refreshing Terraform state in-memory prior to plan...
    The refreshed state will be used to calculate this plan, but will not be
    persisted to local or remote state storage.

    ------------------------------------------------------------------------

    An execution plan has been generated and is shown below.
    Resource actions are indicated with the following symbols:
    + create

    Terraform will perform the following actions:

    # aws_instance.terraform_demo will be created
    + resource "aws_instance" "terraform_demo" {
    + ami                         = "ami-0a634ae95e11c6f91"
    + arn                         = (known after apply)
    + associate_public_ip_address = (known after apply)
    + availability_zone           = (known after apply)
    + cpu_core_count              = (known after apply)
    + cpu_threads_per_core        = (known after apply)
    + get_password_data           = false
    + host_id                     = (known after apply)
    + id                          = (known after apply)
    + instance_state              = (known after apply)
    + instance_type               = "t2.micro"
    + ipv6_address_count          = (known after apply)
    + ipv6_addresses              = (known after apply)
    + key_name                    = (known after apply)
    + outpost_arn                 = (known after apply)
    + password_data               = (known after apply)
    + placement_group             = (known after apply)
    + primary_network_interface_id = (known after apply)
    + private_dns                 = (known after apply)
    + private_ip                  = (known after apply)
    + public_dns                  = (known after apply)
    + public_ip                   = (known after apply)
    + secondary_private_ips       = (known after apply)
    + security_groups             = (known after apply)
    + source_dest_check           = true
    + subnet_id                   = (known after apply)
    + tenancy                     = (known after apply)
    + volume_tags                 = (known after apply)
    + vpc_security_group_ids      = (known after apply)

    + ebs_block_device {
    + delete_on_termination = (known after apply)
    + device_name           = (known after apply)
    + encrypted             = (known after apply)
    + iops                  = (known after apply)
    + kms_key_id            = (known after apply)
    + snapshot_id           = (known after apply)
    + volume_id             = (known after apply)
    + volume_size           = (known after apply)
    + volume_type           = (known after apply)
    }

    + ephemeral_block_device {
    + device_name  = (known after apply)
    + no_device    = (known after apply)
    + virtual_name = (known after apply)
    }

    + metadata_options {
    + http_endpoint              = (known after apply)
    + http_put_response_hop_limit = (known after apply)
    + http_tokens                = (known after apply)
    }

    + network_interface {
    + delete_on_termination = (known after apply)
    + device_index           = (known after apply)
    + network_interface_id  = (known after apply)
    }

    + root_block_device {
    + delete_on_termination = (known after apply)
    + device_name           = (known after apply)
    + encrypted             = (known after apply)
    + iops                  = (known after apply)
    + kms_key_id            = (known after apply)
    + volume_id             = (known after apply)
    + volume_size           = (known after apply)
    + volume_type           = (known after apply)
    }
    }

    Plan: 1 to add, 0 to change, 0 to destroy.

    ------------------------------------------------------------------------

    Note: You didn't specify an "-out" parameter to save this plan, so Terraform
    can't guarantee that exactly these actions will be performed if
    "terraform apply" is subsequently run.
    

terraform apply

Appliceringssteget kommer att köra konfigurationsfilen och starta en AWS EC2-instans. När du kör apply-kommandot kommer det att fråga ”Vill du utföra dessa åtgärder?”, du måste skriva yes och trycka på enter.

    [email protected]:~/terraform_demo$ terraform apply

    An execution plan has been generated and is shown below.
    Resource actions are indicated with the following symbols:
    + create

    Terraform will perform the following actions:

    # aws_instance.terraform_demo will be created
    + resource "aws_instance" "terraform_demo" {
    + ami                         = "ami-0a634ae95e11c6f91"
    + arn                         = (known after apply)
    + associate_public_ip_address = (known after apply)
    + availability_zone           = (known after apply)
    + cpu_core_count              = (known after apply)
    + cpu_threads_per_core        = (known after apply)
    + get_password_data           = false
    + host_id                     = (known after apply)
    + id                          = (known after apply)
    + instance_state              = (known after apply)
    + instance_type               = "t2.micro"
    + ipv6_address_count          = (known after apply)
    + ipv6_addresses              = (known after apply)
    + key_name                    = (known after apply)
    + outpost_arn                 = (known after apply)
    + password_data               = (known after apply)
    + placement_group             = (known after apply)
    + primary_network_interface_id = (known after apply)
    + private_dns                 = (known after apply)
    + private_ip                  = (known after apply)
    + public_dns                  = (known after apply)
    + public_ip                   = (known after apply)
    + secondary_private_ips       = (known after apply)
    + security_groups             = (known after apply)
    + source_dest_check           = true
    + subnet_id                   = (known after apply)
    + tenancy                     = (known after apply)
    + volume_tags                 = (known after apply)
    + vpc_security_group_ids      = (known after apply)

    + ebs_block_device {
    + delete_on_termination = (known after apply)
    + device_name           = (known after apply)
    + encrypted             = (known after apply)
    + iops                  = (known after apply)
    + kms_key_id            = (known after apply)
    + snapshot_id           = (known after apply)
    + volume_id             = (known after apply)
    + volume_size           = (known after apply)
    + volume_type           = (known after apply)
    }

    + ephemeral_block_device {
    + device_name  = (known after apply)
    + no_device    = (known after apply)
    + virtual_name = (known after apply)
    }

    + metadata_options {
    + http_endpoint              = (known after apply)
    + http_put_response_hop_limit = (known after apply)
    + http_tokens                = (known after apply)
    }

    + network_interface {
    + delete_on_termination = (known after apply)
    + device_index           = (known after apply)
    + network_interface_id  = (known after apply)
    }

    + root_block_device {
    + delete_on_termination = (known after apply)
    + device_name           = (known after apply)
    + encrypted             = (known after apply)
    + iops                  = (known after apply)
    + kms_key_id            = (known after apply)
    + volume_id             = (known after apply)
    + volume_size           = (known after apply)
    + volume_type           = (known after apply)
    }
    }

    Plan: 1 to add, 0 to change, 0 to destroy.

    Do you want to perform these actions?
    Terraform will perform the actions described above.
    Only 'yes' will be accepted to approve.

    Enter a value: yes

    aws_instance.terraform_demo: Creating...
    aws_instance.terraform_demo: Still creating... [10s elapsed]
    aws_instance.terraform_demo: Still creating... [20s elapsed]
    aws_instance.terraform_demo: Still creating... [30s elapsed]
    aws_instance.terraform_demo: Still creating... [40s elapsed]
    aws_instance.terraform_demo: Creation complete after 44s [id=i-0eec33286ea4b0740]

    Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
    

Gå till din AWS EC2-instrumentpanel, där du kommer att se att en ny instans med det ID som nämns i slutet av apply-kommandot har skapats.

Du har nu framgångsrikt lanserat en AWS EC2-instans med Terraform.

terraform destroy

Slutligen, om du vill ta bort infrastrukturen kör du destroy-kommandot.

    [email protected]:~/terraform_demo$ terraform destroy
    aws_instance.terraform_demo: Refreshing state... [id=i-0eec33286ea4b0740]

    An execution plan has been generated and is shown below.
    Resource actions are indicated with the following symbols:
    - destroy

    Terraform will perform the following actions:

    # aws_instance.terraform_demo will be destroyed
    - resource "aws_instance" "terraform_demo" {
    - ami                         = "ami-0a634ae95e11c6f91" -> null
    - arn                         = "arn:aws:ec2:us-west-2:259212389929:instance/i-0eec33286ea4b0740" -> null
    - associate_public_ip_address = true -> null
    - availability_zone           = "us-west-2c" -> null
    - cpu_core_count              = 1 -> null
    - cpu_threads_per_core        = 1 -> null
    - disable_api_termination     = false -> null
    - ebs_optimized               = false -> null
    - get_password_data           = false -> null
    - hibernation                 = false -> null
    - id                          = "i-0eec33286ea4b0740" -> null
    - instance_state              = "running" -> null
    - instance_type               = "t2.micro" -> null
    - ipv6_address_count          = 0 -> null
    - ipv6_addresses              = [] -> null
    - monitoring                  = false -> null
    - primary_network_interface_id = "eni-02a46f2802fd15634" -> null
    - private_dns                 = "ip-172-31-13-160.us-west-2.compute.internal" -> null
    - private_ip                  = "172.31.13.160" -> null
    - public_dns                  = "ec2-34-221-77-94.us-west-2.compute.amazonaws.com" -> null
    - public_ip                   = "34.221.77.94" -> null
    - secondary_private_ips       = [] -> null
    - security_groups             = [
    - "default",
    ] -> null
    - source_dest_check           = true -> null
    - subnet_id                   = "subnet-5551200c" -> null
    - tags                        = {} -> null
    - tenancy                     = "default" -> null
    - volume_tags                 = {} -> null
    - vpc_security_group_ids      = [
    - "sg-b5b480d1",
    ] -> null

    - credit_specification {
    - cpu_credits = "standard" -> null
    }

    - metadata_options {
    - http_endpoint              = "enabled" -> null
    - http_put_response_hop_limit = 1 -> null
    - http_tokens                = "optional" -> null
    }

    - root_block_device {
    - delete_on_termination = true -> null
    - device_name           = "/dev/sda1" -> null
    - encrypted             = false -> null
    - iops                  = 100 -> null
    - volume_id             = "vol-0be2673afff6b1a86" -> null
    - volume_size           = 8 -> null
    - volume_type           = "gp2" -> null
    }
    }

    Plan: 0 to add, 0 to change, 1 to destroy.

    Do you really want to destroy all resources?
    Terraform will destroy all your managed infrastructure, as shown above.
    There is no undo. Only 'yes' will be accepted to confirm.

    Enter a value: yes

    aws_instance.terraform_demo: Destroying... [id=i-0eec33286ea4b0740]
    aws_instance.terraform_demo: Still destroying... [id=i-0eec33286ea4b0740, 10s elapsed]
    aws_instance.terraform_demo: Still destroying... [id=i-0eec33286ea4b0740, 20s elapsed]
    aws_instance.terraform_demo: Still destroying... [id=i-0eec33286ea4b0740, 30s elapsed]
    aws_instance.terraform_demo: Destruction complete after 34s

    Destroy complete! Resources: 1 destroyed.
    

När du kollar din EC2-instrumentpanel igen ser du att instansen har avslutats.

Slutsats

Jag hoppas att denna genomgång ger dig en grundläggande förståelse för Terraform och hur du kommer igång. Prova gärna exemplet vi just gick igenom.

Det finns också andra programvaror för infrastrukturautomatisering som kan vara värda att utforska.

Om du vill lära dig mer, rekommenderar jag att du kollar in kursen Lär dig DevOps med Terraform.