kubernetes Kuberbetes中的Cert-manager:在等待头时超过了Client.

tzdcorbm  于 12个月前  发布在  Kubernetes
关注(0)|答案(1)|浏览(126)

描述问题:

有一个带有单个节点的裸金属Kubernetes集群,安装了用于将流量路由到集群的部署MetalLB和Nginx Ingress Controller。

  • Kubernetes v1.28.3
  • MetalLB v0.13.12
  • Nginx Ingress Controller v1.8.0
  • 证书管理器v1.13.2

我创建了一个Ingress资源来将请求路由到集群中部署的ArgoCD示例,并安装了用于TLS证书管理的证书管理器Helm chart。
看起来已正确安装了安全问题解决器。

$ 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挑战无法完成,并且资源挑战、订单和证书停留在 * 待定 * 状态。
正在等待HTTP-01质询传播:无法执行自检GET请求“http://argocd.mydomain.com/.well-known/acme-challenge/Scy7Eh4E8LvN6yM1rT3y4qcCYKfEVZ6MHJdQNqKJN7M”。
获取“http://argocd.mydomain.com/.well-known/acme-challenge/Scy7Eh4E8LvN6yM1rT3y4qcCYKfEVZ6MHJdQNqKJN7M“:超过上下文截止日期(等待标头时超过客户端. xml)
有趣的事情开始了,如果我在集群外的机器上对该url执行curl命令,它会工作,我会得到响应。但是如果我从节点或集群内的另一个pod执行,我会得到超时。
看起来不是网络中的DNS问题,因为从集群内的节点或容器执行nslookup命令工作正常:

$ 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


从节点执行curl请求,在任何容器之外,使用网络中节点的IP,响应是OK的。

curl http://192.168.1.1/.well-known/acme-challenge/Scy7Eh4E8LvN6yM1rT3y4qcCYKfEVZ6MHJdQNqKJN7M -H "Host: argocd.mydomain.com"


但是,将本地IP地址替换为IP地址,我得到了超时。
以下是Ingress Nginx控制器服务的规范:

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* 在ingress的同一个命名空间中创建,日志条目如下:
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,我有同样的行为。而且看起来不像DNS问题,因为DNS条目可以在网络中的集群内部或外部解析。如果使用Public IP执行curl命令失败:

curl -v -D- http://public.ip/.well-known/acme-challenge/1yJeWYLrQ_EP5MjWH_0Ztq8NodV81kaFkPHQ6Kz41CM


但是用网络中LoadBalancer服务的私有IP替换公共IP可以正常工作。
有谁可以指导或帮助我解决这个问题吗?

sr4lhrrt

sr4lhrrt1#

cm-acme-http-solver* 是在ingress的同一名称空间中创建的
正在创建cm-acme-http-solver pod并记录成功的质询请求是一个好迹象。这表明cert-manager正在运行并能够响应ACME质询请求。但是,当这些质询请求来自集群外部时,问题似乎在于这些质询请求的路由。
从互联网到Kubernetes集群的流量看起来像这样:

[ Internet ] --- [ MetalLB (LoadBalancer) ] --- [ Nginx Ingress Controller ]
                     |                              |
                     |                              `-- [ Ingress: ArgoCD ]
                     |                                 (Routes traffic to ArgoCD service)
                     |
                     `-- [ Public IP vs. Private IP Routing Issue ]
                           |
                           `-- [ cm-acme-http-solver Pod ]
                                (Handles ACME challenge requests)
                                |
                                `-- [ Logs: Successful Challenge Requests ]
                                     (But external requests timing out)

字符串
MetalLB LoadBalancer负责将外部流量路由到集群内的正确服务。然后Nginx Ingress Controller将此流量路由到相应的Ingress资源,在本例中为ArgoCD service
处理ACME质询请求的cm-acme-http-solver pod正在记录成功的质询请求,这表明它在群集中正常工作。
但是,将外部请求路由到cm-acme-http-solver存在一个问题,特别是在使用公共IP时。
使用LoadBalancer服务的私有IP成功进行curl测试,但使用公共IP失败,表明外部流量路由到群集的方式可能存在问题。这可能是MetalLB的配置问题,或者是您的网络处理路由到群集的流量的方式。
由于MetalLB被用作LoadBalancer,因此请确保它被正确配置为处理公共和私有IP地址。MetalLB应将公共IP上的传入流量正确路由到集群内的相应服务。

kubectl logs -n metallb-system -l component=speaker


检查Nginx Ingress Controller是否正确配置为处理来自LoadBalancer的流量。这包括确保SSL passthrough按预期工作。
仔细检查是否有任何网络限制(如防火墙规则或网络安全组设置)可能会阻止公共IP上的传入流量。
您可能需要跟踪网络数据包以查看路由失败的位置。tcpdumptraceroute等工具应该会有所帮助。

tcpdump -i <network-interface> 'port 80 and host <public-ip>'


此外,请更详细地查看cert-manager挑战和日志,以确认挑战确实到达了群集并得到了正确的响应。

kubectl describe challenge -n <namespace>


在集群中,我将CNI更改为Calico,并将入口更改为HAProxy,行为是相同的,唯一的区别是我可以使用HTTPS从集群中的Pod内的ACME获得响应,但通过HTTP它仍然会给我超时。
你必须验证SSL直通配置。我记得这里有一些与Weave和Calico兼容的问题metallb.universe.tf/installation/network-addons。
随着向HA Proxy, make sure SSL passthrough is configured correctly的转变,HAProxy处理SSL直通的方式与Nginx不同,确保SSL流量正确转发到后端而不会在Ingress级别终止至关重要。
检查HA Proxy configuration以确保其正确设置为处理HTTP和HTTPS流量。此外,检查日志中的任何错误或警告。

kubectl logs -n <haproxy-namespace> -l app=<haproxy-label>
kubectl describe svc <haproxy-service-name> -n <haproxy-namespace>


Calico提供强大的network policy enforcement。验证没有策略无意中阻止或错误路由HTTP流量。检查入口和出口策略。

kubectl get networkpolicies --all-namespaces

相关问题