From d7804132f38901b139cff4ee3d320744e62a6cf3 Mon Sep 17 00:00:00 2001 From: Lee Chapman Date: Sun, 4 Oct 2026 17:23:25 -0700 Subject: [PATCH] feat(cert-manager): pin v1.21.2, real gateway-shim, safe fallback - Default/example cert_manager_version v1.19.2 -> v1.21.2 (latest 1.21 patch; k8s 1.33-1.36). Live clusters already run v1.21.1 from a manual Helm upgrade on 2026-07-31. - Helm values: crds.enabled/crds.keep instead of deprecated installCRDs; config.gatewayAPI.enabled=true instead of --controllers=*,gateway-shim, which registers the shim but never starts its informers (>=1.15). - Refuse to delete CRDs/namespace when the Helm release is not found unless cleanup_unmanaged_install=true; detect release via helm status. Co-authored-by: Cursor --- CHANGELOG.md | 4 ++ terraform/modules/cert_manager/main.tf | 57 ++++++++++++++--------- terraform/modules/rancher_cluster/main.tf | 2 +- terraform/terraform.tfvars.example | 2 +- terraform/variables.tf | 2 +- 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e02039..d7011cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Rancher login via Authentik SAML (Rancher "Keycloak (SAML)" provider, site access `required`, allow-listed principals only) alongside local auth; `kubeconfig-generate-token=false`, `kubeconfig-default-token-ttl-minutes=129600` (live settings, not managed by Terraform) - Docs: Rancher API token path is `config/.rancher-api-token` and expires after 90 days (`auth-token-max-ttl-minutes`), not "never"; current-state notes in downstream registration, deployment, troubleshooting, ops notes; RKE2/Rancher version examples updated to `v1.36.2+rke2r1` / `v2.15.0`; README license corrected to Apache-2.0 +- **cert-manager** pin `v1.19.2` → **`v1.21.2`** (latest 1.21 patch; supports Kubernetes 1.33–1.36). Live clusters were already on `v1.21.1` via manual Helm (2026-07-31); Terraform now owns the version again +- cert-manager module: Helm values `crds.enabled=true,crds.keep=true` (replaces deprecated `installCRDs`) and `config.gatewayAPI.enabled=true` for the gateway-shim (replaces `--controllers=*,gateway-shim`, which has not started the shim since cert-manager 1.15) + ### Fixed +- cert-manager module no longer deletes the cert-manager CRDs/namespace (and with them every Certificate/Issuer) when it cannot see the Helm release; it fails unless `cleanup_unmanaged_install = true`. Release detection uses `helm status` instead of grepping `helm list` - Broken doc links (`TERRAFORM_VARIABLES.md`) and an unterminated code fence in `RANCHER_DOWNSTREAM_MANAGEMENT.md` - Docs no longer claim `~/.kube/.yaml` are RKE2 admin kubeconfigs (they were overwritten by Rancher-proxied ones); break-glass is `~/.kube/-rke2.yaml` - poc-apps wildcard certificate copy re-synced: gitops-core `cert-sync` uses direct RKE2 admin credentials for all clusters and fails loudly ([gitops-core#6](https://github.com/DataKnifeAI/gitops-core/pull/6)) diff --git a/terraform/modules/cert_manager/main.tf b/terraform/modules/cert_manager/main.tf index 734802c..ad62523 100644 --- a/terraform/modules/cert_manager/main.tf +++ b/terraform/modules/cert_manager/main.tf @@ -20,7 +20,7 @@ variable "kubeconfig_path" { variable "cert_manager_version" { description = "cert-manager Helm chart version" type = string - default = "v1.19.2" + default = "v1.21.2" } variable "namespace" { @@ -29,6 +29,18 @@ variable "namespace" { default = "cert-manager" } +variable "cleanup_unmanaged_install" { + description = "Delete a non-Helm cert-manager install (CRDs, RBAC, webhooks, namespace) before installing. Deleting the CRDs deletes every Certificate/Issuer on the cluster." + type = bool + default = false +} + +locals { + # Gateway API support (gateway-shim) is enabled via controller config since cert-manager 1.15; + # --controllers=*,gateway-shim alone registers the shim but never starts its informers. + helm_set_args = "--set crds.enabled=true --set crds.keep=true --set config.gatewayAPI.enabled=true" +} + output "kubeconfig_path" { value = var.kubeconfig_path } @@ -42,11 +54,10 @@ resource "null_resource" "deploy_cert_manager" { # Trigger recreation when version changes or Helm configuration changes triggers = { cert_manager_version = var.cert_manager_version - cluster_name = var.cluster_name - kubeconfig_path = var.kubeconfig_path - namespace = var.namespace - # Include extraArgs in trigger to force upgrade when gateway-shim is enabled - extra_args_config = "--controllers=*,gateway-shim" + cluster_name = var.cluster_name + kubeconfig_path = var.kubeconfig_path + namespace = var.namespace + helm_set_args = local.helm_set_args } provisioner "local-exec" { @@ -117,7 +128,7 @@ resource "null_resource" "deploy_cert_manager" { # Check if Helm release exists HELM_RELEASE_EXISTS=false - if helm list -n ${var.namespace} 2>/dev/null | grep -q cert-manager; then + if helm status cert-manager -n ${var.namespace} >/dev/null 2>&1; then HELM_RELEASE_EXISTS=true fi @@ -128,8 +139,7 @@ resource "null_resource" "deploy_cert_manager" { echo " Enabling controllers: ingress-shim (default) + gateway-shim (for Gateway API)" helm upgrade cert-manager jetstack/cert-manager \ --namespace ${var.namespace} \ - --set installCRDs=true \ - --set 'extraArgs[0]=--controllers=*\,gateway-shim' \ + ${local.helm_set_args} \ --version "${var.cert_manager_version}" \ --wait \ --timeout 10m \ @@ -138,9 +148,13 @@ resource "null_resource" "deploy_cert_manager" { exit 1 } else - echo " ⚠ cert-manager exists but is not managed by Helm" + echo " ⚠ cert-manager exists but no Helm release 'cert-manager' was found in ${var.namespace}" + if [ "${var.cleanup_unmanaged_install}" != "true" ]; then + echo "ERROR: refusing to delete the existing install (deleting the CRDs deletes all Certificates and Issuers)." + echo " Check 'helm status cert-manager -n ${var.namespace}' and kubeconfig access, or set cleanup_unmanaged_install = true." + exit 1 + fi echo " Cleaning up existing installation to ensure clean Helm-managed installation..." - echo " (This is safe - cert-manager will be reinstalled immediately)" # Delete cert-manager CRDs first (cluster-scoped, not in namespace) if [ "$CERT_MANAGER_CRDS_EXIST" = "true" ]; then @@ -327,13 +341,12 @@ resource "null_resource" "deploy_cert_manager" { fi # Install cert-manager (either fresh install or after cleanup) - if ! helm list -n ${var.namespace} 2>/dev/null | grep -q cert-manager; then + if ! helm status cert-manager -n ${var.namespace} >/dev/null 2>&1; then echo " Installing cert-manager ${var.cert_manager_version}..." echo " Enabling controllers: ingress-shim (default) + gateway-shim (for Gateway API)" helm upgrade --install cert-manager jetstack/cert-manager \ --namespace ${var.namespace} \ - --set installCRDs=true \ - --set 'extraArgs[0]=--controllers=*\,gateway-shim' \ + ${local.helm_set_args} \ --version "${var.cert_manager_version}" \ --wait \ --timeout 10m \ @@ -364,10 +377,10 @@ resource "null_resource" "deploy_cert_manager" { if kubectl get clusterrole cert-manager-controller-ingress-shim &>/dev/null; then echo " ✓ ingress-shim controller enabled" fi - if kubectl get clusterrole cert-manager-controller-gateway-shim &>/dev/null; then - echo " ✓ gateway-shim controller enabled" + if kubectl get configmap cert-manager -n ${var.namespace} -o jsonpath='{.data.config\.yaml}' 2>/dev/null | grep -A1 '^gatewayAPI:' | grep -q 'enabled: true'; then + echo " ✓ gateway-shim controller enabled (config gatewayAPI.enabled)" else - echo " ⚠ gateway-shim controller not found (may need upgrade)" + echo " ⚠ gatewayAPI.enabled not found in cert-manager controller config" fi echo "" echo "==========================================" @@ -398,11 +411,11 @@ resource "null_resource" "verify_cert_manager" { # Trigger recreation when version changes (will also be recreated when deploy_cert_manager changes due to depends_on) triggers = { cert_manager_version = var.cert_manager_version - cluster_name = var.cluster_name - kubeconfig_path = var.kubeconfig_path - namespace = var.namespace - deploy_resource_id = null_resource.deploy_cert_manager.id - extra_args_config = "--controllers=*,gateway-shim" + cluster_name = var.cluster_name + kubeconfig_path = var.kubeconfig_path + namespace = var.namespace + deploy_resource_id = null_resource.deploy_cert_manager.id + helm_set_args = local.helm_set_args } provisioner "local-exec" { diff --git a/terraform/modules/rancher_cluster/main.tf b/terraform/modules/rancher_cluster/main.tf index 682cc11..170ded6 100644 --- a/terraform/modules/rancher_cluster/main.tf +++ b/terraform/modules/rancher_cluster/main.tf @@ -48,7 +48,7 @@ variable "rancher_hostname" { variable "cert_manager_version" { description = "cert-manager Helm chart version" type = string - default = "v1.19.2" + default = "v1.21.2" } output "kubeconfig_path" { diff --git a/terraform/terraform.tfvars.example b/terraform/terraform.tfvars.example index 61aa312..b794a0b 100644 --- a/terraform/terraform.tfvars.example +++ b/terraform/terraform.tfvars.example @@ -170,7 +170,7 @@ vm_id_start_poc_apps = 430 # POC Apps: 430-432 servers, 433-435 primary workers # CERT-MANAGER CONFIGURATION # ============================================================================ -cert_manager_version = "v1.19.2" +cert_manager_version = "v1.21.2" # Enable Rancher deployment (default: true) # Rancher installs on manager cluster after it's ready, then apps cluster deploys diff --git a/terraform/variables.tf b/terraform/variables.tf index b316f94..0157d85 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -92,7 +92,7 @@ variable "vm_id_start_poc_apps" { variable "cert_manager_version" { description = "cert-manager Helm chart version" type = string - default = "v1.19.2" + default = "v1.21.2" } variable "ubuntu_cloud_image_url" {