Getting started with Terraform
With Terraform, you can quickly create a cloud infrastructure in Yandex Cloud and manage it by configuration files. They store the infrastructure description in HashiCorp Configuration Language (HCL). Terraform and its providers are distributed under the Mozilla Public License.
For more information about the provider resources, see the documentation on the Terraform site or mirror site.
If you change the configuration files, Terraform automatically determines which part of your configuration is already deployed and what should be added or removed.
To create your first infrastructure in Yandex Cloud using Terraform:
- Before you start.
- Install Terraform.
- Create a Terraform configuration file.
- Configure a provider.
- Prepare an infrastructure plan.
- Check and format your configuration files.
- Create resources.
If you no longer need the resources, delete them.
Before you start
Before working, you need to register in Yandex Cloud and create a billing account:
- Go to the management console. Then log in to Yandex Cloud or sign up if don't already have an account.
- On the billing page, make sure you linked a billing account, and it has the
ACTIVE
orTRIAL_ACTIVE
status. If you don't have a billing account, create one.
If you have an active billing account, you can create or select a folder to run your VM in from the Yandex Cloud page.
Learn more about clouds and folders.
Required paid resources
The cost of Terraform-created resources includes:
- A fee for continuously running virtual machines (see Yandex Compute Cloud pricing).
- A fee for using a dynamic public IP address (see Yandex Virtual Private Cloud pricing).
Install Terraform
From a mirror
You can download a Terraform distribution for your platform from a mirror. When the download is complete, add the path to the folder with the executable to the PATH
variable:
export PATH=$PATH:/path/to/terraform
From the Hashicorp website
Use one of the following methods:
-
Download a Terraform distribution and install it by following the instructions.
-
Install Terraform using the Chocolatey package manager. To do this, run the command:
choco install terraform
Download a Terraform distribution and install it by following the instructions.
Use one of the following methods:
-
Download a Terraform distribution and install it by following the instructions.
-
Install Terraform using the Homebrew package manager and the command below:
brew install terraform
Create a Terraform configuration file
-
Create a directory with any name, for example,
cloud-terraform
. It stores the configuration files and saved states for Terraform and your infrastructure.Warning
Each configuration must be in a separate directory.
-
Create a configuration file with the
.tf
extension in this directory, such asmain.tf
.
Configure a provider
Note
The settings apply to Terraform 0.13
and higher.
-
Specify the source the provider will be installed from.
Linux and macOSWindowsOpen the Terraform CLI configuration file:
nano ~/.terraformrc
Open the Terraform CLI
terraform.rc
configuration file located in your user's%APPDATA%
folder.Add the following section to the file:
provider_installation { network_mirror { url = "https://terraform-mirror.yandexcloud.net/" include = ["registry.terraform.io/*/*"] } direct { exclude = ["registry.terraform.io/*/*"] } }
For more information about setting up mirrors, see the documentation.
-
Add the following sections at the top of the
.tf
configuration file:terraform { required_providers { yandex = { source = "yandex-cloud/yandex" } } required_version = ">= 0.13" } provider "yandex" { token = "<OAuth>" cloud_id = "<cloud ID>" folder_id = "<folder ID>" zone = "<default availability zone>" }
Where:
source
: Provider's global source address.version
: The minimum provider version that the module is compatible with. You can find the version number on the provider's page (click USE PROVIDER in the top right corner).provider
: The provider name.token
: OAuth token for Yandex Cloud access.cloud_id
: ID of the cloud where Terraform will create resources.folder_id
: ID of the folder where resources will be created by default.zone
: The availability zone where all cloud resources will be created by default.
-
If you previously had a provider from the Hashicorp registry configured, delete its settings:
rm -rf .terraform*
-
Execute the
terraform init
command in the folder containing the.tf
configuration file. This command initializes the providers specified in the configuration files and lets you work with the provider resources and data sources.
If the provider installation failed, create a support request indicating the provider name and version.
If you used the .terraform.lock.hcl
file, run the terraform providers lock
command before initializing, specifying the URL of the mirror that the provider will be uploaded from and the platforms that the configuration will be used on:
terraform providers lock -net-mirror=https://terraform-mirror.yandexcloud.net -platform=linux_amd64 -platform=darwin_arm64 yandex-cloud/yandex
If you used modules, first run terraform init
, then delete the lock file. After that, run the terraform providers lock
command.
Prepare an infrastructure plan
Using Terraform in Yandex Cloud, you can create cloud resources of any type, such as virtual machines, disks, images, and so on. For detailed information on resources you can create with Terraform, see the provider documentation.
To create a resource, specify a set of required and optional parameters that define the resource properties. Such resource descriptions make up an infrastructure plan.
The plan includes creating two virtual machines: terraform1
and terraform2
, as well as a cloud network called network-1
with a subnet named subnet-1
.
Resource names must meet the following requirements:
- The length can be from 3 to 63 characters.
- It may contain lowercase Latin letters, numbers, and hyphens.
- The first character must be a letter. The last character can't be a hyphen.
The machines will have different vCPU and memory configurations: 2 vCPUs and 2 GB of RAM for terraform1
and 4 vCPUs and 4 GB of RAM for terraform2
. The VMs will automatically get public and private IP addresses from the 192.168.10.0/24
range in the subnet-1
subnet located in the ru-central1-a
availability zone and belonging to the network-1
cloud network. The Ubuntu OS will be installed on the VMs and the public part of the key used to access the VMs via SSH will be stored on them.
In the VM configuration, you'll need to specify the boot disk image ID. You can retrieve a list of available public images by using the CLI command yc compute image list --folder-id standard-images
.
To access the VMs over SSH, generate an SSH key pair and pass the public key to the virtual machine in the ssh-keys
parameter in the metadata
section.
Resource configurations are specified immediately after the provider's configuration:
terraform {
required_providers {
yandex = {
source = "yandex-cloud/yandex"
}
}
}
provider "yandex" {
token = "<OAuth>"
cloud_id = "<cloud-id>"
folder_id = "<folder-id>"
zone = "<ru-central1-a>"
}
resource "yandex_compute_instance" "vm-1" {
name = "terraform1"
}
According to the plan, the following resources are created:
- A cloud network named
network-1
with a subnet namedsubnet-1
in theru-central1-a
availability zone. - Two Linux VMs:
terraform1
(2 cores and 2 GB of RAM) andterraform2
(4 cores and 4 GB of RAM). The VMs are automatically assigned public and private IP addresses from the range192.168.10.0/24
insubnet-1
.
-
Get the ID of the boot disk image from Cloud Marketplace, such as Ubuntu 16.04 LTS, that will be installed on the VM. Get a list of available public images by running the following command in the CLI:
yc compute image list --folder-id standard-images
-
Generate an SSH key pair to access the VM over SSH.
-
Describe the resource parameters in the
main.tf
file:- In the
ssh-keys
parameter undermetadata
, specify the path to the public part of the SSH key. - In the
image_id
parameter, set the boot disk image ID.
File main.tf<provider settings> resource "yandex_compute_instance" "vm-1" { name = "terraform1" resources { cores = 2 memory = 2 } boot_disk { initialize_params { image_id = "fd87va5cc00gaq2f5qfb" } } network_interface { subnet_id = yandex_vpc_subnet.subnet-1.id nat = true } metadata = { ssh-keys = "ubuntu:${file("~/.ssh/id_rsa.pub")}" } } resource "yandex_compute_instance" "vm-2" { name = "terraform2" resources { cores = 4 memory = 4 } boot_disk { initialize_params { image_id = "fd87va5cc00gaq2f5qfb" } } network_interface { subnet_id = yandex_vpc_subnet.subnet-1.id nat = true } metadata = { ssh-keys = "ubuntu:${file("~/.ssh/id_rsa.pub")}" } } resource "yandex_vpc_network" "network-1" { name = "network1" } resource "yandex_vpc_subnet" "subnet-1" { name = "subnet1" zone = "ru-central1-a" network_id = yandex_vpc_network.network-1.id v4_cidr_blocks = ["192.168.10.0/24"] } output "internal_ip_address_vm_1" { value = yandex_compute_instance.vm-1.network_interface.0.ip_address } output "internal_ip_address_vm_2" { value = yandex_compute_instance.vm-2.network_interface.0.ip_address } output "external_ip_address_vm_1" { value = yandex_compute_instance.vm-1.network_interface.0.nat_ip_address } output "external_ip_address_vm_2" { value = yandex_compute_instance.vm-2.network_interface.0.nat_ip_address }
- In the
According to the plan, the following resources are created:
- A cloud network named
ya-network
with a subnet namedya-network
in the default availability zone. - Two Windows VMs:
terraform1
(2 cores and 4 GB of RAM) andterraform2
(4 cores and 4 GB of RAM). The VM will automatically get public and private IP addresses from the range192.168.10.0/24
in theya-network
subnet.
Create the following files:
-
main.tf
: The main file with the infrastructure description.Content of file main.tfterraform { required_providers { yandex = { source = "yandex-cloud/yandex" } } } provider "yandex" { cloud_id = var.cloud_id folder_id = var.folder_id zone = var.zone token = var.token } resource "yandex_vpc_network" "default" { name = var.network } resource "yandex_vpc_subnet" "default" { network_id = yandex_vpc_network.default.id name = var.subnet v4_cidr_blocks = var.subnet_v4_cidr_blocks zone = var.zone } data "yandex_compute_image" "default" { family = var.image_family } data "template_file" "default" { template = file("${path.module}/init.ps1") vars = { user_name = var.user_name user_pass = var.user_pass admin_pass = var.admin_pass } } resource "yandex_compute_instance" "default" { name = var.name hostname = var.name zone = var.zone resources { cores = var.cores memory = var.memory } boot_disk { initialize_params { image_id = data.yandex_compute_image.default.id size = var.disk_size type = var.disk_type } } network_interface { subnet_id = yandex_vpc_subnet.default.id nat = var.nat } metadata = { user-data = data.template_file.default.rendered } timeouts { create = var.timeout_create delete = var.timeout_delete } } output "name" { value = yandex_compute_instance.default.name } output "address" { value = yandex_compute_instance.default.network_interface.0.nat_ip_address }
-
variables.tf
: A file that describes variables for the resources being created.File variables.tfvariable "cloud_id" { type = string } variable "folder_id" { type = string } variable "zone" { type = string default = "ru-central1-a" } variable "token" { type = string } variable "network" { type = string default = "ya-network" } variable "subnet" { type = string default = "ya-network" } variable "subnet_v4_cidr_blocks" { type = list(string) default = ["192.168.10.0/16"] } variable "nat" { type = bool default = true } variable "image_family" { type = string default = "windows-2019-dc-gvlk" } variable "name" { type = string } variable "cores" { type = number default = 2 } variable "memory" { type = number default = 4 } variable "disk_size" { type = number default = 50 } variable "disk_type" { type = string default = "network-nvme" } variable "user_name" { default = "" type = string } variable "user_pass" { default = "" type = string } variable "admin_pass" { default = "" type = string } variable "timeout_create" { default = "10m" } variable "timeout_delete" { default = "10m" }
-
terraform.tfvars
: A file that stores the values of variables for accounts created inside the VM and access tokens.File terraform.tfvarstoken = "<token>" cloud_id = "<cloud_id>" folder_id = "<folder_id>" name = "<my_server_name>" user_name = "<my_user>" user_pass = "<my_password>" admin_pass = "<my_password>"
Create users
To add a user to the created VM, specify the user-data
parameter with user metadata under metadata
. To do this:
-
Create a text metadata file, for example:
#cloud-config users: - name: <username> groups: sudo shell: /bin/bash sudo: ['ALL=(ALL) NOPASSWD:ALL'] ssh-authorized-keys: - ssh-rsa AAAAB3Nza......OjbSMRX user@example.com - ssh-rsa AAAAB3Nza......Pu00jRN user@desktop
-
In the
main.tf
file, replacessh-keys
with theuser-data
parameter and specify the metadata file path:metadata = { user-data = "${file("<file path>/meta.txt")}" }
To learn more about working with metadata, see VM instance metadata.
You can create a user and set the Administrator account password on a VM in Yandex Cloud using the cloudbase-init agent. To do this, create a script named init.ps1
that the agent will run on the initial boot of the system. Variables from the variables.tf
file will be used as credentials.
#ps1
# ^^^ 'ps1' is only for cloudbase-init, some sort of sha-bang in linux
# logging
Start-Transcript -Path "$ENV:SystemDrive\provision.txt" -IncludeInvocationHeader -Force
"Bootstrap script started" | Write-Host
# inserting value's from terraform
$MyUserName = "${ user_name }"
$MyPlainTextPassword = "${ user_pass }"
if (-not [string]::IsNullOrEmpty($MyUserName) -and -not [string]::IsNullOrEmpty($MyPlainTextPassword))
{
"Create user" | Write-Host
$MyPassword = $MyPlainTextPassword | ConvertTo-SecureString -AsPlainText -Force
$MyUser = New-LocalUser -Name $MyUserName -Password $MyPassword -PasswordNeverExpires -AccountNeverExpires
$MyUser | Add-LocalGroupMember -Group 'Administrators'
$MyUser | Add-LocalGroupMember -Group 'Remote Management Users'
}
# inserting value's from terraform
$MyAdministratorPlainTextPassword = "${ admin_pass }"
if (-not [string]::IsNullOrEmpty($MyAdministratorPlainTextPassword)) {
"Set local administrator password" | Write-Host
$MyAdministratorPassword = $MyAdministratorPlainTextPassword | ConvertTo-SecureString -AsPlainText -Force
# S-1-5-21domain-500 is a well-known SID for Administrator
# https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/security-identifiers-in-windows
$MyAdministrator = Get-LocalUser | Where-Object -Property "SID" -like "S-1-5-21-*-500"
$MyAdministrator | Set-LocalUser -Password $MyAdministratorPassword
}
"Bootstrap script ended" | Write-Host
Check and format the configuration files
-
Check the configuration using the command:
terraform validate
If the configuration is valid, the following message is returned:
Success! The configuration is valid.
-
Format the configuration files in the current folder and subfolders:
terraform fmt
Result:
main.tf variables.tf
Create resources
-
After checking the configuration, run the command:
terraform plan
The terminal will display a list of resources with parameters. This is a test step. No resources are created. If there are errors in the configuration, Terraform points them out.
Alert
You're charged for all resources created using Terraform. Check the plan carefully.
-
To create resources, run the command:
terraform apply
-
Confirm the resource creation: type
yes
in the terminal and press Enter.Terraform will create all the required resources and the terminal will display the IP addresses of the created VMs. You can check resource availability and their settings in the management console.
How to delete created resources
To delete resources created using Terraform:
-
Run the command:
terraform destroy
After the command is executed, the terminal will display a list of resources to be deleted.
-
Type
yes
to confirm their deletion and press Enter.
You can use the management console to check that the resources have been deleted.