Kubernetes中Cert-manager HTTP-01挑战超时问题求助
我有一个单节点裸金属Kubernetes集群,已部署MetalLB和Nginx Ingress Controller用于集群流量路由。
- Kubernetes v1.28.3
- MetalLB v0.13.12
- Nginx Ingress Controller v1.8.0
- Cert-manager v1.13.2
我创建了Ingress资源将请求路由到集群内部署的ArgoCD实例,并安装了cert-manager Helm Chart用于TLS证书管理。
ClusterIssuer状态正常:
$ kubectl get clusterissuer -o wide NAME READY STATUS AGE letsencrypt-production True The ACME account was registered with the ACME server 4d1h letsencrypt-staging True The ACME account was registered with the ACME server 4d1h selfsigned True 4d1h
ArgoCD的Ingress资源配置如下:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: cert-manager.io/cluster-issuer: letsencrypt-production kubernetes.io/tls-acme: "true" nginx.ingress.kubernetes.io/backend-protocol: HTTPS nginx.ingress.kubernetes.io/ssl-passthrough: "true" labels: app.kubernetes.io/component: server app.kubernetes.io/environment: develop app.kubernetes.io/instance: argocd app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: argocd-server app.kubernetes.io/part-of: argocd app.kubernetes.io/version: v2.8.6 helm.sh/chart: argo-cd-5.50.1 name: argocd-server namespace: develop spec: ingressClassName: nginx rules: - host: argocd.mydomain.com http: paths: - backend: service: name: argocd-server port: number: 443 path: / pathType: Prefix tls: - hosts: - argocd.mydomain.com secretName: argocd-secret
但ACME挑战无法完成,Challenge、Order和Certificate资源一直处于Pending状态:
Waiting for HTTP-01 challenge propagation: failed to perform self check GET request 'http://argocd.mydomain.com/.well-known/acme-challenge/Scy7Eh4E8LvN6yM1rT3y4qcCYKfEVZ6MHJdQNqKJN7M'.
Get "http://argocd.mydomain.com/.well-known/acme-challenge/Scy7Eh4E8LvN6yM1rT3y4qcCYKfEVZ6MHJdQNqKJN7M": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
奇怪的是,集群外机器curl该URL能正常响应,但集群节点或集群内Pod中请求超时。DNS解析正常:
$ nslookup argocd.mydomain.com Server: 127.0.0.53 Address: 127.0.0.53#53 Non-authoritative answer: argocd.mydomain.com canonical name = mydoamin.com. Name: mydomain.com Address: xx.xx.xx.xx
用节点内网IP加Host头curl正常:
curl http://192.168.1.1/.well-known/acme-challenge/Scy7Eh4E8LvN6yM1rT3y4qcCYKfEVZ6MHJdQNqKJN7M -H "Host: argocd.mydomain.com"
但用FQDN请求就超时。Ingress Nginx Controller Service配置:
spec: allocateLoadBalancerNodePorts: true clusterIP: 10.96.108.180 clusterIPs: - 10.96.108.180 externalTrafficPolicy: Local healthCheckNodePort: 30708 internalTrafficPolicy: Cluster ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - appProtocol: http name: http nodePort: 31629 port: 80 protocol: TCP targetPort: http - appProtocol: https name: https nodePort: 30634 port: 443 protocol: TCP targetPort: https
cm-acme-http-solver已创建,日志显示收到挑战请求:
I1113 18:50:06.845744 1 solver.go:87] cert-manager/acmesolver: got successful challenge request, writing key" host="mydomain.com" path="/.well-known/acme-challenge/1yJeWYLrQ_EP5MjWH_0Ztq8NodV81kaFkPHQ6Kz41CM" base_path="/.well-known/acme-challenge" token="1yJeWYLrQ_EP5MjWH_0Ztq8NodV81kaFkPHQ6Kz41CM
更换CNI(weave-net→Calico)后问题依旧,公网IP请求挑战URL超时,但用LoadBalancer内网IP请求正常。
1. 修复集群内部回环流量问题
核心原因是单节点集群的hairpin NAT缺失:当集群内部Pod请求FQDN解析到公网IP后,因Ingress Controller的externalTrafficPolicy: Local配置,流量无法正确回传到Ingress服务。
修改Ingress Controller Service的流量策略:
kubectl patch service ingress-nginx-controller -n ingress-nginx -p '{"spec":{"externalTrafficPolicy":"Cluster"}}'
等待Service刷新后,重新触发证书挑战:
kubectl delete certificate argocd-secret -n develop
2. 临时调整SSL Passthrough配置
Ingress中的nginx.ingress.kubernetes.io/ssl-passthrough: "true"会让Nginx直接转发HTTPS流量到ArgoCD,可能干扰HTTP-01挑战的路由逻辑。
临时移除该注解,等证书颁发后再恢复:
# 从Ingress的metadata.annotations中删除以下行 nginx.ingress.kubernetes.io/ssl-passthrough: "true"
更新Ingress后重新触发挑战。
3. 检查节点防火墙/iptables规则
确认节点防火墙未拦截集群内部到节点公网IP的80端口流量:
iptables -L -n | grep 80
确保存在允许Pod网段访问节点80端口的规则,若缺失需手动添加。
4. 验证MetalLB ARP配置
检查MetalLB的ConfigMap,确认IP池属于节点内网网段,且ARP模式配置正确:
kubectl get configmap metallb-config -n metallb-system -o yaml
单节点环境下,确保MetalLB分配的LoadBalancer IP与节点内网IP在同一网段。
5. 切换到DNS01挑战(备选)
若HTTP-01挑战始终无法解决,可改用DNS01挑战,无需集群内部回环流量。修改Ingress注解指定挑战类型:
# 在Ingress metadata.annotations中添加 cert-manager.io/acme-challenge-type: dns01
需确保域名服务商支持DNS API自动更新解析记录,同时对应ClusterIssuer已配置DNS服务商的API密钥。
内容的提问来源于stack exchange,提问作者Jose Rodriguez

