Теоретически можно ссылаться на ресурсы от провайдера GCP в K8S (или любом другом) провайдере так же, как вы ссылаетесь на ресурсы или источники данных в контексте одного провайдера.
provider "google" {
region = "us-west1"
}
data "google_compute_zones" "available" {}
resource "google_container_cluster" "primary" {
name = "the-only-marcellus-wallace"
zone = "${data.google_compute_zones.available.names[0]}"
initial_node_count = 3
additional_zones = [
"${data.google_compute_zones.available.names[1]}"
]
master_auth {
username = "mr.yoda"
password = "adoy.rm"
}
node_config {
oauth_scopes = [
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
]
}
}
provider "kubernetes" {
host = "https://${google_container_cluster.primary.endpoint}"
username = "${google_container_cluster.primary.master_auth.0.username}"
password = "${google_container_cluster.primary.master_auth.0.password}"
client_certificate = "${base64decode(google_container_cluster.primary.master_auth.0.client_certificate)}"
client_key = "${base64decode(google_container_cluster.primary.master_auth.0.client_key)}"
cluster_ca_certificate = "${base64decode(google_container_cluster.primary.master_auth.0.cluster_ca_certificate)}"
}
resource "kubernetes_namespace" "n" {
metadata {
name = "blablah"
}
}
Однако на практике это может работать не так, как ожидалось, из-за известной ошибки ядра, нарушающей зависимости между поставщиками, см. https://github.com/hashicorp/terraform/issues/12393 и https://github.com/hashicorp/terraform/issues/4149 соответственно.
Альтернативное решение будет:
- Используйте 2-ступенчатое применение и цель сначала кластер GKE, затем все, что от него зависит, то есть
terraform apply -target=google_container_cluster.primary
, а затем terraform apply
- Отделение конфигурации кластера GKE от конфигураций K8S, предоставление им полностью изолированного рабочего процесса и подключение их через удаленное состояние .
/terraform-gke/main.tf
terraform {
backend "gcs" {
bucket = "tf-state-prod"
prefix = "terraform/state"
}
}
provider "google" {
region = "us-west1"
}
data "google_compute_zones" "available" {}
resource "google_container_cluster" "primary" {
name = "the-only-marcellus-wallace"
zone = "${data.google_compute_zones.available.names[0]}"
initial_node_count = 3
additional_zones = [
"${data.google_compute_zones.available.names[1]}"
]
master_auth {
username = "mr.yoda"
password = "adoy.rm"
}
node_config {
oauth_scopes = [
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
]
}
}
output "gke_host" {
value = "https://${google_container_cluster.primary.endpoint}"
}
output "gke_username" {
value = "${google_container_cluster.primary.master_auth.0.username}"
}
output "gke_password" {
value = "${google_container_cluster.primary.master_auth.0.password}"
}
output "gke_client_certificate" {
value = "${base64decode(google_container_cluster.primary.master_auth.0.client_certificate)}"
}
output "gke_client_key" {
value = "${base64decode(google_container_cluster.primary.master_auth.0.client_key)}"
}
output "gke_cluster_ca_certificate" {
value = "${base64decode(google_container_cluster.primary.master_auth.0.cluster_ca_certificate)}"
}
Здесь мы выставляем всю необходимую конфигурацию через output
s и используем backend для сохранения состояния вместе с этими выходами в удаленном местоположении, GCS в этом случае. Это позволяет нам ссылаться на него в конфигурации ниже.
/terraform-k8s/main.tf
data "terraform_remote_state" "foo" {
backend = "gcs"
config {
bucket = "tf-state-prod"
prefix = "terraform/state"
}
}
provider "kubernetes" {
host = "https://${data.terraform_remote_state.foo.gke_host}"
username = "${data.terraform_remote_state.foo.gke_username}"
password = "${data.terraform_remote_state.foo.gke_password}"
client_certificate = "${base64decode(data.terraform_remote_state.foo.gke_client_certificate)}"
client_key = "${base64decode(data.terraform_remote_state.foo.gke_client_key)}"
cluster_ca_certificate = "${base64decode(data.terraform_remote_state.foo.gke_cluster_ca_certificate)}"
}
resource "kubernetes_namespace" "n" {
metadata {
name = "blablah"
}
}
Что может быть или не быть очевидным здесь, так это то, что кластер должен быть создан / обновлен перед созданием / обновлением каких-либо ресурсов K8S (если такое обновление зависит от обновлений кластера).
Выбор 2-го подхода обычно целесообразен в любом случае (даже если / если ошибка не была фактором и сработали ссылки между поставщиками), так как он уменьшает радиус взрыва и определяет более четкую ответственность. Для такого развертывания (IMO) характерно, что один человек / группа отвечает за управление кластером, а другой - за управление ресурсами K8S.
Хотя, безусловно, могут быть совпадения - например, Операторы хотят развернуть инфраструктуру ведения журналов и мониторинга поверх нового кластера GKE, поэтому зависимости между поставщиками направлены на удовлетворение таких случаев использования. По этой причине я бы рекомендовал подписаться на проблемы GH, упомянутые выше.