Terraform配置K8s Ingress证书时加密私钥解密处理问题
问题根因
- Nginx Ingress控制器加载TLS证书时,要求关联Secret内的
tls.key必须是无口令保护的PEM格式私钥,加密私钥会导致TLS握手失败,请求无法正常转发。terraform apply无报错是因为Kubernetes API不会校验Secret内的证书、私钥内容合法性,只有Ingress控制器实际加载配置时才会抛出错误。 - 你当前配置存在三个显性问题:
- 传入的
private_key为加密状态,不符合Ingress加载要求 kubernetes_secret资源的data字段要求传入原始明文内容,Terraform Kubernetes Provider会自动完成base64编码存入集群,你直接传入已base64编码的证书、私钥,会造成双重base64编码,Secret存储的内容格式完全错误- Secret所在命名空间为
my-namespace(中划线),Ingress配置中写的命名空间为my_namespace(下划线),命名空间不匹配会导致Ingress无法找到目标Secret
- 传入的
修复方案
- 先在Terraform配置中声明依赖的官方Provider:
terraform { required_providers { kubernetes = { source = "hashicorp/kubernetes" version = ">= 2.0.0" } tls = { source = "hashicorp/tls" version = ">= 4.0.0" } } }
- 定义敏感变量传入私钥解密口令,禁止将口令硬编码在配置文件中:
variable "private_key_passphrase" { type = string sensitive = true description = "加密TLS私钥的解密口令" }
- 解码base64格式的证书、加密私钥,通过TLS Provider解密私钥得到无密码PEM内容:
locals { # 解码base64编码的证书内容 cert_pem_raw = base64decode(data.my_data.my-configuration-secret.data["certificate_pem"]) # 解码base64编码的加密私钥 encrypted_private_key_raw = base64decode(data.my_data.my-configuration-secret.data["private_key"]) } # 解密带口令的私钥,输出标准无密码PEM格式 data "tls_private_key" "parsed_tls_key" { content_pem = local.encrypted_private_key_raw passphrase = var.private_key_passphrase }
- 修正Secret配置,显式指定Secret类型为TLS,传入明文证书和解密后的私钥:
resource "kubernetes_secret" "my-secret" { data = { "tls.crt" = local.cert_pem_raw "tls.key" = data.tls_private_key.parsed_tls_key.private_key_pem } metadata { name = "my-secret" # 注意和Ingress所在命名空间保持一致 namespace = "my-namespace" } # 显式指定Secret类型为TLS,避免默认Opaque类型导致的兼容问题 type = "kubernetes.io/tls" }
- 修正Ingress配置中的命名空间错误,和Secret保持在同一个命名空间下,其余注解配置无需调整。
部署后校验
- 执行
terraform plan时检查输出的Secret内容,确认tls.crt以-----BEGIN CERTIFICATE-----开头,tls.key以-----BEGIN PRIVATE KEY-----开头,无乱码 - 部署完成后执行
kubectl describe ingress my-sni -n my-namespace查看Ingress事件,确认无证书加载、Secret找不到类报错 - 直接通过HTTPS访问域名验证证书是否正常生效,不需要额外重启Ingress控制器,证书更新后Ingress会自动重载配置
内容的提问来源于stack exchange,提问作者kouemo Jeff
相关产品推荐
相关产品推荐

