How To Run kubectl apply commands in terraform

Sunil Gajula picture Sunil Gajula · Jan 8, 2019 · Viewed 14.3k times · Source

I have developed a terraform script to create a k8 cluster on GKE.

Post successful creation of cluster, I have set of yaml files to be applied on k8 cluster.

How can I invoke the below command in my terraform script?

kubectl create <.yaml>

Answer

david_g picture david_g · Jan 28, 2020

You can use the Terraform kubectl third party provider. Follow the installation instructions here: Kubectl Terraform Provider

Then simply define a kubectl_manifest pointing to your YAML file like:

# Get your cluster-info
data "google_container_cluster" "my_cluster" {
  name     = "my-cluster"
  location = "us-east1-a"
}

# Same parameters as kubernetes provider
provider "kubectl" {
  load_config_file       = false
  host                   = "https://${data.google_container_cluster.my_cluster.endpoint}"
  token                  = "${data.google_container_cluster.my_cluster.access_token}"
  cluster_ca_certificate = "${base64decode(data.google_container_cluster.my_cluster.master_auth.0.cluster_ca_certificate)}"
}

resource "kubectl_manifest" "my_service" {
    yaml_body = file("${path.module}/my_service.yaml")
}

This approach has the big advantage that everything is obtained dynamically and does not rely on any local config file (very important if you run Terraform in a CI/CD server or to manage a multicluster environment).

Multi-object manifest files

The kubectl provider also offers data sources that help to handle files with multiple objest very easily. From the docs kubectl_filename_list:

data "kubectl_filename_list" "manifests" {
    pattern = "./manifests/*.yaml"
}

resource "kubectl_manifest" "test" {
    count = length(data.kubectl_filename_list.manifests.matches)
    yaml_body = file(element(data.kubectl_filename_list.manifests.matches, count.index))
}

Extra points: You can templatize your yaml files. I interpolate the cluster name in the multi-resource autoscaler yaml file as follows:

resource "kubectl_manifest" "autoscaler" {
  yaml_body = templatefile("${path.module}/autoscaler.yaml", {cluster_name = var.cluster_name })
}