gharbi.bdr
gharbi.bdr

Reputation: 167

setup letsencrypt ClusterIssuer with terraform

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: example@example.com
    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?

Upvotes: 6

Views: 8768

Answers (2)

Harsh Manvar
Harsh Manvar

Reputation: 30198

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: mymail@gmail.com
    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"
  }
}

Upvotes: 7

user658182
user658182

Reputation: 2360

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" = "myemail@email.com"
        "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).

Upvotes: 6

Related Questions