Uploading Terraform states to Object Storage
This guide describes the steps for uploading a Terraform state to Yandex Object Storage.
A Terraform state describes the current deployed infrastructure and is stored in files with the .tfstate
extension. The state file is created after the infrastructure is deployed and can be immediately uploaded to Object Storage. The uploaded state file is updated as the infrastructure you created changes.
In this example, the saved state allows other users to get the ID of one of the created subnets to connect a new VM to it.
To configure Terraform state storage in Object Storage and use it to create new resources:
- Prepare your cloud.
- Required paid resources.
- Install Terraform.
- Create a Terraform configuration file.
- Configure a provider.
- Create a service account and static access key.
- Create a bucket.
- Configure the backend.
- Deploy the configuration.
- Check the saved state.
- Retrieve the state from the backend.
If you no longer need the resources you created, delete them.
Terraform and its providers are distributed under the Business Source License
Prepare your cloud
Sign up for Yandex Cloud and create a billing account:
- Go to the management console
and log in to Yandex Cloud or create an account if you do not have one yet. - On the Billing
page, make sure you have a billing account linked and it has theACTIVE
orTRIAL_ACTIVE
status. If you do not have a billing account, create one.
If you have an active billing account, you can go to the cloud page
Learn more about clouds and folders.
Required paid resources
Alert
All resources created using Terraform are chargeable. Make sure to check the configuration prior to creating any resources.
In this use case, you will create three VMs with public IP addresses, a virtual network, and two subnets.
The cost of supporting this infrastructure includes:
- Data storage fees (see Object Storage pricing).
- Charge for the disks and continuously running VMs (see Yandex Compute Cloud pricing).
- 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 mirrorPATH
variable:
export PATH=$PATH:/path/to/terraform
From the Hashicorp website
Use one of the following methods:
-
Download a Terraform distribution
and follow this guide to install it. -
Install Terraform using the Chocolatey
package manager and the command below:choco install terraform
Download a Terraform distribution
Use one of the following methods:
-
Download a Terraform distribution
and follow this guide to install it. -
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,
yandex-cloud-terraform
. It will store the Terraform configuration files. - Create a configuration file with the
.tf
extension in this directory, for example,example.tf
.
Configure a provider
Note
These settings apply to Terraform 0.13
and higher. We recommend using the latest stable version of Terraform.
-
If you previously had a provider from the Hashicorp registry configured, save its settings:
Linux/macOSWindowsmv ~/.terraformrc ~/.terraformrc.old
mv $env:APPDATA/terraform.rc $env:APPDATA/terraform.rc.old
-
Specify the source the provider will be installed from.
Linux/macOSWindowsOpen the Terraform CLI configuration file:
nano ~/.terraformrc
Note
The
.terraformrc
file must be in the user's home root folder, e.g.,/home/user/
or/User/user/
.Open the Terraform CLI configuration file named
terraform.rc
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" { zone = "<default_availability_zone>" }
Where:
-
source
: Provider's global source address . -
required_version
: The minimum version of Terraform the provider is compatible with. -
provider
: The provider name. -
zone
: Availability zone where all cloud resources will be created by default.
-
-
Run the
terraform init
command in the folder containing the.tf
configuration file. This command initializes the providers specified in the configuration files and allows you to work with the provider resources and data sources.
If the provider installation failed, create a support
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=<platform_name_1> -platform=<platform_name_2> yandex-cloud/yandex
Where:
-net-mirror
: Address of the mirror to upload the provider from.-platform
: Platforms to use the configuration on. The possible values include:windows_amd64
: 64-bit Windowslinux_amd64
: 64-bit Linuxdarwin_arm64
: 64-bit macOS
If you used the Terraform modules, first run terraform init
, then delete the lock file. After that, run the terraform providers lock
command.
For more information about the terraform providers lock
command, see the Terraform documentation
Create a service account and static access key
- Create a service account with the editor role for the folder specified in the provider settings.
- Get a static access key. Save the key ID and secret key: you will need them in the next steps.
Create a bucket
Create a bucket with restricted access. It stores the Terraform state file.
Configure the backend
-
Add the previously obtained key ID and secret key to environment variables:
BashPowerShellexport ACCESS_KEY="<key_ID>" export SECRET_KEY="<secret_key>"
$Env:ACCESS_KEY="<key_ID>" $Env:SECRET_KEY="<secret_key>"
-
Add provider and backend settings to the configuration file:
terraform { required_providers { yandex = { source = "yandex-cloud/yandex" } } backend "s3" { endpoints = { s3 = "storage.yandexcloud.net" } bucket = "<bucket_name>" region = "ru-central1" key = "<path_to_state_file_in_bucket>/<state_file_name>.tfstate" skip_region_validation = true skip_credentials_validation = true skip_requesting_account_id = true # This option is required to describe backend for Terraform version 1.6.1 or higher. skip_s3_checksum = true # This option is required to describe backend for Terraform version 1.6.3 or higher. } } provider "yandex" { token = "<service_account_OAuth_or_static_key>" cloud_id = "<cloud_ID>" folder_id = "<folder_ID>" zone = "<default_availability_zone>" }
To read more about the state storage backend, see the Terraform site
. -
Run the following command in the folder with the configuration file:
terraform init -backend-config="access_key=$ACCESS_KEY" -backend-config="secret_key=$SECRET_KEY"
Deploy the configuration
In this example, we will create two VMs: terraform1
and terraform2
. They will be connected to subnet-1
in the ru-central1-a
availability zone. The subnet will be in the network-1
cloud network.
The VMs will have different vCPU and RAM configurations: 1 vCPU and 2 GB of RAM for terraform1
and 2 vCPU 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 subnet-1
. The VMs will run Ubuntu OS and host the public part of the key to enable SSH access to the VMs.
-
Save the following configuration to
example.tf
:terraform { required_providers { yandex = { source = "yandex-cloud/yandex" } } backend "s3" { endpoints = { s3 = "storage.yandexcloud.net" } bucket = "<bucket_name>" region = "ru-central1" key = "<path_to_state_file_in_bucket>/<state_file_name>.tfstate" skip_region_validation = true skip_credentials_validation = true skip_requesting_account_id = true # This option is required to describe backend for Terraform version 1.6.1 or higher. skip_s3_checksum = true # This option is required to describe backend for Terraform version 1.6.3 or higher. } } provider "yandex" { zone = "ru-central1-a" } resource "yandex_compute_image" "ubuntu_2004" { source_family = "ubuntu-2004-lts" } resource "yandex_compute_disk" "boot-disk-vm1" { name = "boot-disk-1" type = "network-hdd" zone = "ru-central1-a" size = "20" image_id = yandex_compute_image.ubuntu_2004.id } resource "yandex_compute_disk" "boot-disk-vm2" { name = "boot-disk-2" type = "network-hdd" zone = "ru-central1-a" size = "20" image_id = yandex_compute_image.ubuntu_2004.id } resource "yandex_compute_instance" "vm-1" { name = "terraform1" resources { cores = 2 memory = 2 } boot_disk { disk_id = yandex_compute_disk.boot-disk-vm1.id } network_interface { subnet_id = yandex_vpc_subnet.subnet-1.id nat = true } metadata = { ssh-keys = "ubuntu:${file("<path_to_public_SSH_key>")}" } } resource "yandex_compute_instance" "vm-2" { name = "terraform2" resources { cores = 2 memory = 4 } boot_disk { disk_id = yandex_compute_disk.boot-disk-vm2.id } network_interface { subnet_id = yandex_vpc_subnet.subnet-1.id nat = true } metadata = { ssh-keys = "ubuntu:${file("<path_to_public_SSH_key>")}" } } 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 } output "subnet-1" { value = yandex_vpc_subnet.subnet-1.id }
Where:
bucket
: Bucket name.key
: Object key in the bucket (name and path to the Terraform state file in the bucket).ssh-keys
: Path to the file with a public SSH key to authenticate the user on the VM. For more information, see Creating an SSH key pair.
-
Check the configuration using the
terraform plan
command. -
Deploy the configuration using the
terraform apply
command.
Check the saved state
Make sure that the state file is uploaded to Object Storage:
- Open the management console
and select the folder with the bucket created. - Select Object Storage.
- In the bucket list, select the bucket you saved the Terraform state to.
- Make sure the state file is in the bucket.
Retrieve the state from the backend
You can request the Object Storage state saved in Terraform from another configuration to expand the infrastructure you created.
Create another configuration and use the saved state to create another VM in one of the existing subnets:
-
Create the
remote-state
directory. -
Go to the created directory and create the configuration file
remote-state.tf
:terraform { required_providers { yandex = { source = "yandex-cloud/yandex" } } } provider "yandex" { token = "<service_account_OAuth_or_static_key>" cloud_id = "<cloud_ID>" folder_id = "<folder_ID>" zone = "ru-central1-a" } data "terraform_remote_state" "vpc" { backend = "s3" config = { endpoint = "storage.yandexcloud.net" bucket = "<bucket_name>" region = "ru-central1" key = "<path_to_state_file_in_bucket>/<state_file_name>.tfstate" skip_region_validation = true skip_credentials_validation = true } } resource "yandex_compute_instance" "vm-3" { name = "terraform3" resources { cores = 2 memory = 2 } boot_disk { initialize_params { image_id = "fd87va5cc00gaq2f5qfb" } } network_interface { subnet_id = data.terraform_remote_state.vpc.outputs.subnet-1 nat = true } metadata = { ssh-keys = "ubuntu:${file("~/.ssh/id_ed25519.pub")}" } }
-
Run the
terraform init
command. -
Run the
terraform plan
command. The terminal will display the plan for creating the VM. -
Run the
terraform apply
command. -
Go to the management console and make sure you can see the
terraform3
instance in the Compute Cloud section.
Delete the resources you created
To delete the resources you created, run the terraform destroy
command; start with the second configuration, and then proceed to the first.