【问题标题】:Istio Gateway and Kubernetes Ingress on same hostname because of cert-manager HTTP01 ACME challenge: can this work?由于 cert-manager HTTP01 ACME 挑战,Istio 网关和 Kubernetes Ingress 在同一主机名上:这可行吗?
【发布时间】:2022-10-13 21:41:09
【问题描述】:

我部署了一个 Istio 服务网格,并将其网关控制器用于入口。我设置了将 ssl 证书传递给网关的 cert-manager。使用自签名证书,此设置可以正常工作,但是在使用letsencrypt时,我在cert-manager的自动临时入口和istio网关之间存在冲突。

这是用于 httpbin 的结果设置:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  annotations:
    meta.helm.sh/release-name: httpbin-ingress
    meta.helm.sh/release-namespace: httpbin
  creationTimestamp: "2022-10-13T08:07:33Z"
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: httpbin-ingress
  namespace: istio-ingress
  resourceVersion: "5243"
  uid: d4087649-2609-40c0-8d4a-55b9a420fda9
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - httpbin.example.com
    port:
      name: http
      number: 80
      protocol: HTTP
    tls:
      httpsRedirect: true
  - hosts:
    - httpbin.example.com
    port:
      name: https
      number: 443
      protocol: HTTPS
    tls:
      credentialName: httpbin-ssl-certificate-secret
      mode: SIMPLE
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  annotations:
    meta.helm.sh/release-name: httpbin-ingress
    meta.helm.sh/release-namespace: httpbin
  creationTimestamp: "2022-10-13T08:07:33Z"
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: httpbin-ingress
  namespace: istio-ingress
  resourceVersion: "5246"
  uid: ef5b6397-2c7a-408c-b142-4528e8f28a20
spec:
  gateways:
  - httpbin-ingress
  hosts:
  - httpbin.example.com
  http:
  - match:
    - uri:
        prefix: /outpost.goauthentik.io
    route:
    - destination:
        host: authentik.authentik.svc.cluster.local
        port:
          number: 80
  - match:
    - uri:
        regex: ^\/[^\.]+.*
    - uri:
        exact: /
    route:
    - destination:
        host: httpbin.httpbin.svc.cluster.local
        port:
          number: 14001
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: istio
    nginx.ingress.kubernetes.io/whitelist-source-range: 0.0.0.0/0,::/0
  creationTimestamp: "2022-10-13T08:07:38Z"
  generateName: cm-acme-http-solver-
  generation: 1
  labels:
    acme.cert-manager.io/http-domain: "1703151793"
    acme.cert-manager.io/http-token: "1233129203"
    acme.cert-manager.io/http01-solver: "true"
  name: cm-acme-http-solver-gtgxg
  namespace: istio-ingress
  ownerReferences:
  - apiVersion: acme.cert-manager.io/v1
    blockOwnerDeletion: true
    controller: true
    kind: Challenge
    name: httpbin-ssl-certificate-ct48l-1136457683-1300359052
    uid: dd19a50c-5944-46b8-ae09-8345bef9c114
  resourceVersion: "5308"
  uid: 5d5578a5-3371-4705-9a8c-e031be5f4d7c
spec:
  rules:
  - host: httpbin.example.com
    http:
      paths:
      - backend:
          service:
            name: cm-acme-http-solver-rkr2g
            port:
              number: 8089
        path: /.well-known/acme-challenge/YKCZwQz6T9HezJtPwzev-esq-Q4WaLHoUC_CafmPJUk
        pathType: ImplementationSpecific
status:
  loadBalancer: {}

我面临的问题如下。使用此设置:

  • curl --resolve httpbin.example.com:443:127.0.0.1 https://httpbin.example.com/ -k 有效。
  • curl --resolve httpbin.example.com:443:127.0.0.1 https://httpbin.example.com/.well-known/acme-challenge/YKCZwQz6T9HezJtPwzev-esq-Q4WaLHoUC_CafmPJUk -Ik 提供 http 代码 404。
  • 如果我删除网关httpbin-ingresscurl --resolve httpbin.example.com:80:127.0.0.1 http://httpbin.example.com/.well-known/acme-challenge/YKCZwQz6T9HezJtPwzev-esq-Q4WaLHoUC_CafmPJUk -Ik 使用 http 代码 200 按预期工作。

cert-manager 的证书资源带有注释

    cert-manager.io/issue-temporary-certificate: "true"

并且有效(网关使用自签名证书设置,直到letsencrypt成功),所以我使用httpsRedirect: true的事实不应该是罪魁祸首。

我的问题是:是否可以设置网关cert-manager 是否成功通过 HTTP01 挑战?我的想法是,在将“/.well-known/...”的网关转发流量到 cert-manager 的入口时,我必须忽略一些事情。

我查看了这个问题,Using Gateway + VirtualService + http01 + SDS,但我无法找到我的配置不同的地方。我尝试将端口 80 上的网关协议从 HTTP 更改为 HTTP2,并将 curling 和 --http1.1 更改为 .well-known 路径,但这并没有解决问题。

【问题讨论】:

    标签: kubernetes kubernetes-ingress cert-manager istio-gateway


    【解决方案1】:

    我的解决方案最终是:

    • 在每个网关的端口 80 上添加一个* 主机到服务器,
    • 放弃使用内置httpsRedirect: true函数,
    • 并为 http 到 https 编写稍微更手动的重定向规则,该规则仅匹配非 ACME 路径。

    似乎你不能为同一个端口和主机名拥有多个 Istio 网关,除非主机名包括 *。如果我错了,有人纠正我。

    我现在有效的配置是:

    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      annotations:
        meta.helm.sh/release-name: httpbin-ingress
        meta.helm.sh/release-namespace: httpbin
      creationTimestamp: "2022-10-13T13:24:27Z"
      generation: 1
      labels:
        app.kubernetes.io/managed-by: Helm
      name: httpbin-ingress
      namespace: istio-ingress
      resourceVersion: "54782"
      uid: d36977db-20a2-4d43-a137-ba4cbfeccf8d
    spec:
      selector:
        istio: ingressgateway
      servers:
      - hosts:
        - '*'
        - httpbin.example.com
        port:
          name: http
          number: 80
          protocol: HTTP
      - hosts:
        - httpbin.example.com
        port:
          name: https
          number: 443
          protocol: HTTPS
        tls:
          credentialName: httpbin-ssl-certificate-secret
          mode: SIMPLE
    
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      annotations:
        meta.helm.sh/release-name: httpbin-ingress
        meta.helm.sh/release-namespace: httpbin
      creationTimestamp: "2022-10-13T13:24:27Z"
      generation: 1
      labels:
        app.kubernetes.io/managed-by: Helm
      name: httpbin-ingress
      namespace: istio-ingress
      resourceVersion: "54783"
      uid: 3a1d988c-c287-49a8-942a-9aaf41a4b2b5
    spec:
      gateways:
      - httpbin-ingress
      hosts:
      - httpbin.example.com
      http:
      - match:
        - headers:
            x-forwarded-proto:
              exact: https
          uri:
            prefix: /outpost.goauthentik.io
        route:
        - destination:
            host: authentik.authentik.svc.cluster.local
            port:
              number: 80
      - match:
        - headers:
            x-forwarded-proto:
              exact: https
          uri:
            regex: ^/[^.]+.*
        - headers:
            x-forwarded-proto:
              exact: https
          uri:
            exact: /
        route:
        - destination:
            host: httpbin.httpbin.svc.cluster.local
            port:
              number: 14001
      - match:
        - headers:
            x-forwarded-proto:
              exact: http
          uri:
            regex: ^/[^.]+.*
        - headers:
            x-forwarded-proto:
              exact: http
          uri:
            exact: /
        - headers:
            x-forwarded-proto:
              exact: http
          uri:
            exact: /
        redirect:
          scheme: https
    

    并且无需从 cert-manager 重新发布生成的入口,因为这并没有改变!

    如您所见,我详细阐述了 VirtualService,现在每个匹配项都明确验证协议(http 与 https),匹配 http 的行仅适用于不匹配 ACME 挑战的路径(/.well-known ...)。

    如果您的服务使用以点开头的路径,那么您将不得不在匹配中添加更多规则以避免匹配 ACME,但允许您的 .-paths。

    PS 如果有人知道更智能的 RE2-regex 使其适合一行,请告诉!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-07
      • 2021-05-26
      • 1970-01-01
      • 2019-07-27
      • 2018-08-05
      • 2023-01-28
      • 1970-01-01
      • 2021-12-02
      相关资源
      最近更新 更多