代码之家  ›  专栏  ›  技术社区  ›  Borek Bernard

Terraform:如何使用名称空间在Google云(GKE)上创建Kubernetes集群?

  •  2
  • Borek Bernard  · 技术社区  · 6 年前

    我在寻找一个可以实现以下功能的示例:

    1. 通过Terraform的 google_container_cluster
    2. 。。。并继续在其中创建名称空间,我想通过 kubernetes_namespace

    我不确定的是如何连接新创建的集群和名称空间定义。例如,添加时 google_container_node_pool ,我可以这样做 cluster = "${google_container_cluster.hosting.name}" 但我看不到任何类似的 kubernetes\u命名空间

    1 回复  |  直到 6 年前
        1
  •  13
  •   Radek Simko    6 年前

    理论上,可以在K8S(或任何其他)提供者中引用来自GCP提供者的资源,就像在单个提供者的上下文中引用资源或数据源一样。

    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"
      }
    }
    

    然而,在实践中,由于已知的核心bug破坏了跨提供程序依赖关系,它可能无法按预期工作,请参阅 https://github.com/hashicorp/terraform/issues/12393 https://github.com/hashicorp/terraform/issues/4149 分别地

    替代解决方案是:

    1. 使用两阶段应用和 target 首先是GKE集群,然后是依赖于它的任何其他集群,即。 terraform apply -target=google_container_cluster.primary 然后 terraform apply
    2. 将GKE集群配置与K8S配置分开,为它们提供完全隔离的工作流,并通过 remote state

    /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 并使用后端将状态以及这些输出存储在远程位置, 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资源之前,必须创建/更新集群(如果此类更新依赖于集群的更新)。


    无论哪种方式,采取第二种方法通常都是可取的(即使bug不是一个因素,跨提供者引用也有效),因为它减少了爆炸半径,并定义了更明确的责任。这种部署通常有一个人/团队负责管理集群,另一个人/团队负责管理K8S资源。

    当然也可能有重叠-例如,希望部署日志记录和;在新的GKE集群上监控基础设施,因此跨提供者依赖关系旨在满足此类用例。因此,我建议订阅上述GH问题。