Рубрики
Uncategorized

Грязные терраформные взломы

Написано Дэвидом Чанином Помечено терраформи, DevOps, IAC.

Написано Дэвид Чанин

Terraform — это удивительный инструмент для управления инфраструктурой, и он достаточно прост, чтобы обернуться всего за несколько часов. Однако, как только вы начнете использовать Terraform, вы быстро столкнетесь с задачами, которые кажутся простыми, но не имеют очевидного решения. Давайте рассмотрим некоторые трюки и взломы, чтобы помочь вам получить максимальную отдачу от популярной инфраструктуры в качестве решения кода (IAC).

Используйте счет как выключатель для ресурсов

Одной из сильных сторон Terraform является его способность превращать блоки ресурсов и данных в многократные модули. В рамках этого процесса вам часто понадобится способ отключить создание определенных ресурсов на основе входной переменной. В настоящее время нет атрибута, как resource_enabled Отключить создание ресурса. К счастью, вы можете добиться аналогичного эффекта, установив счет Отключить создание ресурсов или счет Чтобы включить это.

счет можно использовать для создания массива ресурсов вместо одного ресурса, поэтому настройка считать Создаст множество ресурсов длины 0, эффективно отключив ресурс. Эта техника распространена даже в официальных модулях терраформ. Например, следующий сокращенный фрагмент кода взят из официального Terraform-Aws-Autoscaling Модульный исходный код.

resource "aws_launch_configuration" "this" {
  count = var.create_lc ? 1 : 0

  image_id                    = var.image_id
  instance_type               = var.instance_type
  # ...
}

Этот код создает AWS Autoscaling Launch Configuration Если переменная create_lc установлен на Верно При использовании модуля.

Настройка счет Приводит к тому, что ресурс становится массивом вместо одного элемента, поэтому, если вам нужно получить доступ к свойствам этого ресурса, вам нужно получить доступ к ним в качестве массива. Например, если вам нужно получить доступ к id атрибут из вышеупомянутого aws_launch_configuration , вам нужно написать что -то вроде concat (aws_launch_configuration.this.*. id, [""]) [0] безопасно вытащить id из массива ресурсов.

Запустите локальные команды с помощью null_resource

Иногда встроенной функциональности Terraform предоставляет просто недостаточно. Например, вам может потребоваться выполнить какую -то команду на машине, которая запускает Terraform. Вы можете сделать это, используя таинственно названное null_resource Анкет Это действует как обычный ресурс на графике ресурсов Terraform, но на самом деле ничего не делает.

Почему это полезно? Потому что null_resource может запустить предварительных заведений, как и любой обычный ресурс, включая Local-Exec Предоставщик, который запускает команду на локальной машине. Вы можете контролировать, когда этот предварительный завод запускается путем прохождения в Триггеры карта.

Например, если у поставщика Terraform Kubernetes нет всей необходимой вам функциональности, вы можете вручную запустить kubectl применить команда с использованием null_resource , как показано ниже.

variable "config_path" {
  description = "path to a kubernetes config file"
}
variable "k8s_yaml" {
  description = "path to a kubernetes yaml file to apply"
}

resource "null_resource" "kubectl_apply" {
  triggers = {
    config_contents = filemd5(var.config_path)
    k8s_yaml_contents = filemd5(var.k8s_yaml)
  }

  provisioner "local-exec" {
    command = "kubectl apply --kubeconfig ${var.config_path} -f ${var.k8s_yaml}"
  }
}

В приведенном выше примере любые изменения в содержании файла конфигурации Kubernetes или Kubernetes Yaml приведут к повторному зазору команды. К сожалению, нет простого способа получить вывод Local-Exec Команда, используя этот метод и сохраните его в состояние Terraform. Вам также необходимо убедиться, что у машины, работающей Terraform, установлена зависимости для запуска фактической команды, указанной Local-Exec проводник.

Разбить зависимых поставщиков в поэтапные пробеги Terraform

Если вы создаете большую инфраструктуру в Terraform, вам, вероятно, необходимо создать услугу в Terraform, а затем настроить эту услугу через отдельного поставщика Terraform. Terraform отлично справляется с зависимостью между ресурсами, но не может справиться с ситуациями, когда поставщик Terraform зависит от создания ресурса у другого поставщика.

Например, вы столкнетесь с проблемами, если вам нужно создать кластер Kubernetes с помощью Terraform, а затем настроить тот же кластер, используя поставщика Terraform Kubernetes после его создания. Это связано с тем, что Terraform попытается подключиться ко всем определенным предназначению и прочитать состояние всех определенных ресурсов во время планирования, но он не может подключиться к поставщику Kubernetes, потому что кластер еще не существует.

Было бы здорово, если бы Terraform мог справиться с зависимостями между поставщиками, подобными этому, но вы можете решить эту дилемму куриного яика, разбив свой проект Terraform на более мелкие проекты, которые можно запустить в цепочке.

Предполагая, что вы используете удаленное состояние для Terraform, вы можете импортировать состояние Terraform из предыдущих прогонов, используя terraform_remote_state источник данных. Это позволяет выходам из предыдущих прогонов Terraform выступать в качестве входа в следующий запуск Terraform.

Допустим, прогон Terraform создает кластер Kubernetes и выводит информацию об соединении для этого кластера. Следующий запуск Terraform может импортировать это состояние с первого запуска и прочитать информацию о подключении кластера в провайдеру Terraform Kubernetes.

Техника показана ниже. Первый этап может выглядеть примерно так:

# stage1/main.tf

provider "aws" {
  region  = "us-east-1"
}

terraform {
  backend "s3" {
    bucket = "my-terraform-state-bucket"
    key    = "stage1.tfstate"
    region = "us-east-1"
  }
}

resource "aws_eks_cluster" "k8s" {
  name = "sample-kubernetes-cluster"
  # ...
}

# Output connection info for the kubernetes cluster into the Terraform state
output "k8s_endpoint" {
  value = aws_eks_cluster.k8s.endpoint
}

output "k8s_ca_data" {
  value = aws_eks_cluster.k8s.certificate_authority.0.data
}

Второй этап конфигурации Terraform затем появится следующим образом.

# stage2/main.tf

provider "aws" {
  region  = "us-east-1"
}

terraform {
  backend "s3" {
    bucket = "my-terraform-state-bucket"
    key    = "stage2.tfstate"
    region = "us-east-1"
  }
}

# Import the state from stage 1 and read the outputs
data "terraform_remote_state" "stage1" {
  backend = "s3"

  config = {
    bucket = "my-terraform-state-bucket"
    key    = "stage1.tfstate"
    region = "us-east-1"
  }
}

provider "kubernetes" {
  cluster_ca_certificate = base64decode(data.terraform_remote_state.stage1.outputs.k8s_ca_data)
  host = data.terraform_remote_state.stage1.outputs.endpoint
  # ...
}

resource "kubernetes_deployment" "example" {
  # ... continue configuring cluster
}

В приведенном выше примере мы запустили первый этап, чтобы создать кластер Kubernetes и информацию о выводе подключения для кластера в состояние Terraform. Затем второй этап импортировал состояние Terraform первого этапа как данные и прочитайте информацию об соединении, чтобы настроить кластер.

Обработка файловых зависимостей между ресурсами с помощью Templatefile ()

Terraform позволяет легко взять выходы из одного ресурса и передавать их в качестве входов в другой ресурс. Тем не менее, он борется, когда ресурс пишет файл в локальной файловой системе, который должен читать другой ресурс в качестве ввода.

В идеале ресурсы никогда не будут этого делать, но на самом деле поставщики иногда записывают выходы в локальные файлы вместо возврата вывода в качестве строки. Terraform не может выяснить, что между ресурсами существует зависимость, когда эта зависимость возникает в форме написания и чтения из локального файла.

К счастью, вы можете обмануть Terraform в реализацию этой зависимости, используя Templatefile () функция Эта функция считывает файл из файловой системы и заменяет любые переменные, которые вы передаете функции в файл, когда он его читает. Однако, если эти переменные поступают из выходов другого ресурса, то Terraform должен ждать, пока этот ресурс применяет перед чтением файла.

Это показано ниже, используя alicloud_cs_managed_kubernetes Ресурс с платформы Alicloud. Этот ресурс создает кластер Kubernetes и записывает конфигурацию кластера в файл на локальном диске. Затем мы читаем этот файл, используя Templatefile () и написать его содержимое на вывод.

resource "alicloud_cs_managed_kubernetes" "k8s" {
  name_prefix               = "sample kubernetes cluster"
  kube_config               = "${path.module}/kube.config"
  # ...
}

output "k8s_cluster_config_contents" {
  value = templatefile("${path.module}/kube.config", {
    # This variable creates a dependency on the cluster before reading the file
    cluster_id = alicloud_cs_managed_kubernetes.k8s.id
  })
}

В приведенном выше примере Kube.config Файл читается через Templatefile () Функция с переменной, которая зависит от вывода ресурса кластера. cluster_id переменная фактически не используется; Только там, чтобы заставить Terraform ждать создания кластера, прежде чем он попытается прочитать Kube.config содержимое Если вы используете эту технику, вам нужно будет создать файл в локальной файловой системе вручную перед первым запуском, поскольку Terraform ожидает, что файл будет существовать до его начала.

Вывод

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

Счастливого терраформирования!

Plug: Logrocket, DVR для веб -приложений

Logrocket это инструмент регистрации фронта, который позволяет вам воспроизводить проблемы, как будто они произошли в вашем собственном браузере. Вместо того, чтобы догадаться, почему возникают ошибки, или просить пользователей экрана и журнала дамп, Logrocket позволяет воспроизвести сеанс, чтобы быстро понять, что пошло не так. Он отлично работает с любым приложением, независимо от фреймворта, и имеет плагины для регистрации дополнительного контекста из Redux, Vuex и @ngrx/Store. В дополнение к журналам Redux и состоянию регистрации журналы консоли Logrocket записывают, ошибки JavaScript, StackTraces, сетевые запросы/ответы с заголовками + BODES, метаданные браузера и пользовательские журналы. Он также приказывает DOM записывать HTML и CSS на странице, воссоздавая видеопроблемные видео даже самых сложных одностраничных приложений. Попробуйте бесплатно Анкет

Пост Грязные Terraform Hacks появился первым на Logrocke Blog Анкет

Оригинал: «https://dev.to/bnevilleoneill/dirty-terraform-hacks-5d89»