Как мы можем создать один и тот же ресурс в нескольких поставщиках терраформирования?

#kubernetes #terraform #terraform-provider-kubernetes

Вопрос:

Я использую terraform для создания пространства имен Kubernetes. Пример ниже

 resource "kubernetes_namespace" "test1" {
  metadata {
    name = local.ns_name
  }

}
 

Я пытаюсь создать сине-зеленое развертывание с использованием terraform, перейдя по этой ссылке. В рамках этого я создал два кластера kubernetes. Один из синего, а другой для зеленой стороны, и к настоящему времени у меня есть два поставщика kubernetes

 provider "kubernetes" {
  alias                  = "kubernetes_blue"
}

provider "kubernetes" {
  alias                  = "kubernetes_green"
}
 

Я хочу понять, есть ли способ, чтобы у меня было какое-то условие kubernetes_namespace , чтобы, в зависимости от флагов var.enable_green_side и var.enable_blue_side , я мог создать одно и то же пространство имен в нескольких кластерах kubernetes без необходимости повторять весь блок ресурсов следующим образом

 resource "kubernetes_namespace" "test1" {
  metadata {
    name = local.ns_name
  }

  provider = kubernetes.kubernetes_blue  
}

resource "kubernetes_namespace" "test2" {
  metadata {
    name = local.ns_name
  }

  provider = kubernetes.kubernetes_green  
}
 

Заранее спасибо.

Ответ №1:

Модель Terraform требует, чтобы каждый resource блок принадлежал ровно одной конфигурации поставщика, поэтому невозможно избежать двойного объявления ресурса, но вы можете, по крайней мере, уменьшить количество дублирования, которое вызывает, разложив его на модуль и дважды вызвав этот модуль, а не дублируя resource блок напрямую:

 provider "kubernetes" {
  alias = "blue"
}

provider "kubernetes" {
  alias = "green"
}

module "blue" {
  source = "../modules/bluegreen"

  # (any settings the module needs from the root)

  providers = {
    kubernetes = kubernetes.blue
  }
}

module "blue" {
  source = "../modules/bluegreen"

  # (any settings the module needs from the root)

  providers = {
    kubernetes = kubernetes.green
  }
}
 

Специальный providers аргумент в module блоке позволяет вам предоставить дочернему модулю другое «представление» объявленных конфигураций поставщика, чем у вызывающего. В module "blue" приведенном выше блоке providers аргумент гласит: «Внутри этого экземпляра модуля любая ссылка на kubernetes конфигурацию поставщика по умолчанию означает использование kubernetes.blue конфигурации от вызывающего абонента».

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

Будет ли это разложение на модули полезным, конечно, будет зависеть от того, какой объем контекста из вызывающего модуля в конечном итоге понадобится дочернему модулю. Если в вашем module блоке окажется почти столько же аргументов, сколько в resource блоке(блоках), которые вы разлагаете, то, вероятно, было бы лучше просто сохранить resource блоки на верхнем уровне и избежать косвенности.

Комментарии:

1. Что ж, тогда мне придется пройти путь рефакторинга для моих существующих ресурсов. Спасибо за объяснение.

Ответ №2:

Из вопроса неясно, зачем вам понадобятся два определения поставщика. Но для примера мы можем рассмотреть приведенные ниже распространенные варианты использования для развертывания синего/зеленого:

  • ориентируйтесь на различные кластеры
  • ориентируйтесь на разные контексты

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

Учитывая определение переменной, например (с использованием string типа, но bool также может использоваться a):

 variable "kubernetes_deployment" {
  type    = string
  default = "blue"
}
 

Допустим, я хочу ориентироваться на разные кластеры:

  • кластер 1 для синего
  • кластер 2 для зеленых

Затем поставщик может быть настроен ( kubeconfig например, с помощью) в зависимости от значения переменной. Для этого мы можем использовать троичное условие.

 provider "kubernetes" {
  config_path = var.kubernetes_deployment == "blue" ? "~/.kube/cluster1.config" : "~/.kube/cluster2.config"
}

resource "kubernetes_namespace" "mynamespace" {
  metadata {
    name = local.ns_name
  }

  provider = kubernetes
}
 

Это гарантирует, что ресурсы (в данном случае пространство имен) будут созданы в «кластере 1» для синего развертывания и в «кластере 2» для зеленого развертывания.

Это условие может быть применено к другим параметрам конфигурации поставщика. Пример использования одного и того же кластера, но в разных контекстах:

 provider "kubernetes" {
  config_path = "~/.kube/cluster1.config"
  config_context = var.kubernetes_deployment == "blue" ? "context1" : "context2"
}
 

Комментарии:

1. Подход с использованием троичного оператора не будет работать, когда я хочу создать два кластера одновременно. Когда я захочу опробовать какое-либо новое обновление в кластере kubernetes, мне нужно будет запустить второй кластер, протестировать его и только затем начать отправлять на него трафик, прежде чем демонтировать первый.

2. Если вы рассматриваете этот проект (каталог) как модуль , должна быть возможность вызывать этот модуль с соответствующими флагами несколько раз.