skip to Main Content

i have a terraform config that create a kubernetes(GKE) on GCP, install ingress and cert-manager using Helm.
the only part missing is the letsencrypt ClusterIssuer (when i deploy the letsencrypt.yaml manually all works fine).

my Terraform config:

# provider
provider "kubernetes" {
  host                   = google_container_cluster.runners.endpoint
  cluster_ca_certificate = base64decode(google_container_cluster.runners.master_auth.0.cluster_ca_certificate)
  token                  = data.google_client_config.current.access_token
}

provider "helm" {
  kubernetes {
      host                   = google_container_cluster.runners.endpoint
      cluster_ca_certificate = base64decode(google_container_cluster.runners.master_auth.0.cluster_ca_certificate)
      token                  = data.google_client_config.current.access_token
  }
}

# create namespace for ingress controller
resource "kubernetes_namespace" "ingress" {
  metadata {
    name = "ingress"
  }
}
# deploy ingress controller
resource "helm_release" "ingress" {
  name       = "ingress"
  namespace = kubernetes_namespace.ingress.metadata[0].name

  repository = "https://kubernetes.github.io/ingress-nginx"
  chart      = "ingress-nginx"

  values = [
    "${file("./helm_values/ingress.yaml")}"
  ]
  set {
    name  = "controller.service.loadBalancerIP"
    value = google_compute_address.net_runner.address
  }
}

#create namespace for cert mananger
resource "kubernetes_namespace" "cert" {
  metadata {
    name = "cert-manager"
  }
}

#deploy cert maanger
resource "helm_release" "cert" {
  name       = "cert-manager"
  namespace = kubernetes_namespace.cert.metadata[0].name
  repository = "https://charts.jetstack.io"
  chart      = "cert-manager"
  depends_on = ["helm_release.ingress"]
  set {
    name  = "version"
    value = "v1.4.0"
  }
  set {
    name  = "installCRDs"
    value = "true"
  }
}

my letsencrypt.yaml:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    email: [email protected]
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx

any idea how to deploy the ClusterIssuer using terraform?

2

Answers


  1. You can apply the directly YAML file to the cluster

    provisioner "local-exec" {
        command = <<EOT
    cat <<EOF | kubectl --server=${aws_eks_cluster.demo.endpoint} --insecure-skip-tls-verify=true --token=${data.aws_eks_cluster_auth.demo.token} create -f -
    apiVersion: certmanager.k8s.io/v1alpha1
    kind: ClusterIssuer
    metadata:
      name: lets-encrypt
    spec:
      acme:
        server: https://acme-v02.api.letsencrypt.org/directory
        email: [email protected]
        privateKeySecretRef:
          name: letsencrypt
        http01: {}
    EOF
    EOT
      }
    

    or else you can also use the TF provider to apply the YAML file

    https://registry.terraform.io/providers/gavinbunney/kubectl/latest/docs#installation

    update :

    if you have not set up the Kubernetes provider to authenticate you can use from :
    https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs

    provider "kubernetes" {
      config_path    = "~/.kube/config"
      config_context = "my-context"
    }
    
    resource "kubernetes_namespace" "example" {
      metadata {
        name = "my-first-namespace"
      }
    }
    
    Login or Signup to reply.
  2. I recently did this most successfully using the Terraform tool tfk8s to migrate yaml files. You can also use Terraform yamldecode.

    1. Test your yaml files and make sure they are working exactly like you want before using the tool.
    2. Using tfk8s, run tfk8s cluster-issuer.yaml -o cluster-issuer.tf This will create a working kubernetes_manifest resource.

    Here is an example of my entire terraform script that installs it along with CRDs and ClusterIssuer.

    resource "helm_release" "cert-manager" {
      name       = "cert-manager"
      repository = "https://charts.jetstack.io"
      chart      = "cert-manager"
      version    = "1.7.1"
    
      namespace        = "cert-manager"
      create_namespace = true
    
      #values = [file("cert-manager-values.yaml")]
    
      set {
        name  = "installCRDs"
        value = "true"
      }
    
    }
    
    resource "kubernetes_manifest" "clusterissuer_letsencrypt_prod" {
      manifest = {
        "apiVersion" = "cert-manager.io/v1"
        "kind" = "ClusterIssuer"
        "metadata" = {
          "name" = "letsencrypt-prod"
        }
        "spec" = {
          "acme" = {
            "email" = "[email protected]"
            "privateKeySecretRef" = {
              "name" = "letsencrypt-prod"
            }
            "server" = "https://acme-v02.api.letsencrypt.org/directory"
            "solvers" = [
              {
                "http01" = {
                  "ingress" = {
                    "class" = "nginx"
                  }
                }
              },
            ]
          }
        }
      }
    }
    

    NOTE This tool creates a resource type kubernetes_manifest, and Terraform docs state that it’s not a stable resource to use with an initial apply command. In other words, create the cluster, etc first, then add the files and apply again. Otherwise, you need to manually migrate each kubernetes_manifest into its own dedicated resource type (deployment, service, etc).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search