Перейти к содержанию

s3e21

Глобальное потепление

Если у тебя многоуровневый проект, зачастую требуется иметь доступ к переменным, которые будут доступны на глобальном уровне, то есть не в рамках одной папки и стека, а прям везде. Звучит сумбурно, давай сразу потыкаем палкой и добавим прозрачности.

Сразу скажу, что для этих дел, лучше использовать remote state, мы его реализовывали в первых уроках (s3e02), тот самый S3. Напомню, что выглядит это примерно так:

  backend "s3" {
    bucket = "factorystates"
    key    = "linuxfactory.tfstate"
    region = "ru-7"

    endpoints = {
      s3 = "https://s3.ru-7.storage.selcloud.ru"
    }

    skip_credentials_validation = true
    skip_region_validation      = true
    skip_metadata_api_check     = true
    skip_requesting_account_id  = true
    force_path_style            = true
  }

В корневом проекте создаем папку globalvars и закидываем в него файл main.tf с содержимым нашего провайдера, настройками для S3 и несколькими outputs:

terraform {
  required_providers {
    selectel = {
      source = "selectel/selectel"
    }
    openstack = {
      source = "terraform-provider-openstack/openstack"
    }
  }

  backend "s3" {
    bucket = "factorystates"
    key    = "linuxfactory.tfstate"
    region = "ru-7"

    endpoints = {
      s3 = "https://s3.ru-7.storage.selcloud.ru"
    }

    skip_credentials_validation = true
    skip_region_validation      = true
    skip_metadata_api_check     = true
    skip_requesting_account_id  = true
    force_path_style            = true
  }
}

provider "openstack" {
  auth_url    = "https://cloud.api.selcloud.ru/identity/v3"
  domain_name = "123456"
  tenant_id   = selectel_vpc_project_v2.vpc.id
  user_name   = ""
  password    = ""
  region      = "ru-7"
}

output "welcome_message" {
  value = "Hello Linux Factory"
}

output "author" {
  value = "Shubin Roman Olegovich"
}

output "images_name" {
  value = "Debian 2026"
}

output "tags" {
  value = {
    release = "1.2.3"
    build   = "master"
  }
}

Теперь делаем такое:

cd glovalvars
terraform init
terraform init -reconfigure -backend-config=secret.backend.tfvars

Отлично, terraform инициализировался и подключился S3, в reconfigure мы подкинули файл с секретами от S3.

bucket     = "factorystates"
access_key = "2f79510b6b044"
secret_key = "1f9e9fb587944"

Выполняем: terraform apply и получаем:

Ничего не добавлено, не изменено, ни уничтожено. На экран вывелась информацию по нашим output. А в S3 появился state.

Если открыть этот файл, то увидим «глобальные переменные», которые мы задавали через output.

Теперь из любой другой директории в проекте, мы можем дергать эти переменные. В корне создаем еще одну папку testdir и закинем в него файл main.tf:

terraform {
  required_providers {
    selectel = {
      source = "selectel/selectel"
    }
    openstack = {
      source = "terraform-provider-openstack/openstack"
    }
  }
}

provider "openstack" {
  auth_url    = "https://cloud.api.selcloud.ru/identity/v3"
  domain_name = "123456"
  tenant_id   = selectel_vpc_project_v2.vpc.id
  user_name   = ""
  password    = ""
  region      = "ru-7"
}

data "terraform_remote_state" "global" {
  backend = "s3"

  config = {
    bucket = "factorystates"
    key    = "linuxfactory.tfstate"
    region = "ru-7"

    endpoints = {
      s3 = "https://s3.ru-7.storage.selcloud.ru"
    }

    access_key = ""
    secret_key = ""

    skip_credentials_validation = true
    skip_region_validation      = true
    skip_metadata_api_check     = true
    skip_requesting_account_id  = true

    use_path_style = true
  }
}

locals {
  author  = data.terraform_remote_state.global.outputs.author
  image   = data.terraform_remote_state.global.outputs.images_name
  welcome = data.terraform_remote_state.global.outputs.welcome_message
  tags    = data.terraform_remote_state.global.outputs.tags
}

output "author" {
  value = local.author
}

output "image" {
  value = local.image
}

output "welcome" {
  value = local.welcome
}

output "tags" {
  value = local.tags
}

Обрати внимание на ресурс terraform_remote_state, суть такая — этот код залезет в state с глобальными переменными, выгребет их и выведет на экран.

По классике:

terraform init
terraform apply

В результате получаем:

Получается что terraform залез в нужный s3 backet в глобальными переменными, выгреб их в себя и затем вывел на экран совершенно из другого проекта.

Теперь эти переменные можно использовать для создания ресурсов и всего что тебе заблагорассудиться. Это очень удобно, когда нужно передавать данные между проектами, ну и по сути это отдельный state который не зависит ни от чего. Меняешь переменные, потом любой проект идет за ними в этот state и вуаля.

У коллег SSL сертификаты так раскатываются, SSL хранятся как раз в глобальных переменных, переодически обновляются, а куча независимых проектов просто ходит в этот state и забирает их.

С виду муторно, но если один раз всё настроить по уму, будет офигенно удобно.


Домашнее задание

  • Повтори и пофикси все проблемы которые у тебя вылезут. Они у тебя вылезут обязательно, потому что я некоторые моменты в коде нарочно не дописал. Ну а если не вылезли, значит у тебя рука набита и ты сразу сделал всё правильно.