GKE中Nginx Ingress+Cert-manager通配符证书配置故障求助
问题分析与解决方案
核心原因
Let's Encrypt签发通配符域名证书必须使用DNS-01挑战方式,HTTP-01挑战不支持通配符域名验证。你的cert-manager Issuer/ClusterIssuer仅配置了HTTP-01 solver(默认或显式设置),因此普通单域名(如wordpress.domain.com)能正常完成验证并签发证书,但通配符域名(*.domain.com、*.api.domain.com)找不到可用的挑战方式,导致证书签发失败。
解决步骤
1. 配置支持DNS-01挑战的ClusterIssuer
由于你使用GKE,对应Google Cloud DNS,创建支持双挑战方式的ClusterIssuer:
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-production spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: your-email@domain.com # 替换为你的有效邮箱 privateKeySecretRef: name: letsencrypt-production solvers: # HTTP-01挑战:用于普通单域名验证 - http01: ingress: class: nginx # DNS-01挑战:用于通配符域名验证(适配Google Cloud DNS) - dns01: cloudDNS: project: your-gcp-project-id # 替换为你的GCP项目ID serviceAccountSecretRef: name: cloud-dns-service-account key: key.json
先创建GCP服务账号密钥的Secret:
# 假设已下载服务账号JSON密钥文件key.json kubectl create secret generic cloud-dns-service-account --from-file=key.json
2. 修正Ingress配置的问题
你的Ingress存在两个影响访问的问题:根域名domain.com无单独规则、通配符规则覆盖不全。修正后的配置如下:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-production # 关联上述ClusterIssuer spec: tls: - hosts: - domain.com - "*.domain.com" secretName: certificate-wildcard-domain - hosts: - wordpress.domain.com secretName: certificate-wordpress-domain - hosts: - api.domain.com - "*.api.domain.com" secretName: certificate-api-domain rules: # 根域名指向React应用 - host: domain.com http: paths: - path: / pathType: Prefix backend: service: name: react port: { number: 80 } # 通配符子域名指向React应用 - host: "*.domain.com" http: paths: - path: / pathType: Prefix backend: service: name: react port: { number: 80 } # WordPress单独规则 - host: wordpress.domain.com http: paths: - path: / pathType: Prefix backend: service: name: wordpress port: { number: 80 } # API根域名指向Express服务 - host: api.domain.com http: paths: - path: / pathType: Prefix backend: service: name: api port: { number: 9000 } # API通配符子域名指向Express服务 - host: "*.api.domain.com" http: paths: - path: / pathType: Prefix backend: service: name: api port: { number: 9000 }
3. 验证证书与服务状态
应用配置后,检查证书是否就绪:
kubectl get certificates
当证书状态变为Ready,说明签发成功。同时验证Ingress的外部IP是否正确关联DNS记录:
kubectl get ingress
4. 确保Cookie跨子域生效
为了让a.domain.com与api.a.domain.com共享Cookie,需在Express API的Cookie设置中添加domain=.domain.com参数。
内容的提问来源于stack exchange,提问作者user5580950
相关产品推荐
相关产品推荐

