From Ingress to IngressRoute with CertManager, HTTP01 Challenge and Let's Encrypt ClusterIssuer
Asked Answered
L

2

6

I have a Kubernetes (v1.25.2) cluster running with cert-manager 1.11.0 and Traefik 2.9.6. For some services I want Let's Encrypt to auto sign certificates. For some reason, it feels nicer, to use IngressRoute instead of Ingress. I just can't get the IngressRoute to create the certificate.
Now, I have the a ClusterIssuer:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: [email protected]
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
      - http01:
          ingress:
            class: traefik

and, working, corresponding Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-name-websecure
  annotations:
   cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: traefik
  rules:
    - host: my.host.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: linkingservice
                port:
                  number: 80
  tls:
    - hosts:
       - my.host.com
      secretName: some-secret-name-tls

This works, nice. Instead, with IngressRoute the base resource is this:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: myapp-other-name-websecure
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`other.host.com`)
      kind: Rule
      services:
        - name: linkingservice
          port: 80
  tls:
    # certResolver: ??? # resolve what? Doesn't link with the ClusterIssuer
    # issuerRef: ??? # doesn't exist (anymore)

Now, I've tried to:

  • just as for the Ingress to use the annotations: cert-manager.io/cluster-issuer: letsencrypt-prod. Which is being ignored
  • use the tls.certResolver, which doesn't work, because it doesn't exist. Should I create one? I expect The ClusterIssuer to create the certificate and secret, just as it does for Ingress.
  • I also saw the issuerRef as option in the tls section, but that doesn't appear to exist.

I thought I read that the IngressRoute is like a layer on top of the k8s default Ingress, so it should be something logical/similar


FYI: the ClusterIssuer and Ingress will also work for Nginx, when you replace the solvers.http01.ingress.class with nginx, likewise for the Ingress's spec.ingressClassName. (perhaps also without, but I can't test)

Lyse answered 28/1, 2023 at 11:30 Comment(0)
L
6

Now, I did find a way, but still feels like more work than should be necessary. The thing here is to create the Certificate and link that to the ClusterIssuer, that certificate then creates a Secret. This secret needs to be added to the spec.tls.secretName, like:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: my.host.com-cert
spec:
  secretName: my.host.com-secret
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
    - my.host.com
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
spec:
...
  tls:
    secretName: my.host.com-secret

I've also tried for, certResolver. But the CertificateResolver from cert-manager was discontinued in v0.15.0; alternatively the CertificateRequest, but this was also discontinued in cert-manager version 0.9.0. The suggested way seems to be the previous described one.


I revisited the Traefik deployment values.yaml where I found there is a field with certResolvers, from their file:

certResolvers:
  letsencrypt:
    # for challenge options cf. https://doc.traefik.io/traefik/https/acme/
    email: [email protected]
    dnsChallenge:
      # also add the provider's required configuration under env
      # or expand then from secrets/configmaps with envfrom
      # cf. https://doc.traefik.io/traefik/https/acme/#providers
      provider: digitalocean
      # add futher options for the dns challenge as needed
      # cf. https://doc.traefik.io/traefik/https/acme/#dnschallenge
      delayBeforeCheck: 30
      resolvers:
        - 1.1.1.1
        - 8.8.8.8
    tlsChallenge: true
    httpChallenge:
      entryPoint: "web"
    # It has to match the path with a persistent volume
    storage: /data/acme.json

Which makes me wonder. If you set this up, then probably the:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
spec:
  tls:
    certResolver: letsencrypt

can work

Lyse answered 28/1, 2023 at 11:36 Comment(0)
C
3

The reason your tls section in the IngressRoute doesn't work like the Ingress is that cert-manager has a component called Ingress-shim, which monitors Ingress resources in the cluster and creates certificates for any missing secrets listed in the Ingress.

It simply isn't built to monitor IngressRoute yet. Now that Traefik, Nginx and other Ingress Controllers are moving to CRD's, I assume that cert-manager will have to add a way to monitor Ingress-like CRD's too, not just native Ingresses.

Like you said, you'll need to create a separate Certificate resource to request the certificate, then specify the secret name in the IngressRoute. The certResolver things you mentioned are for Traefik's built-in Let's Encrypt issuer. But you can't use this to replace Cert-Manager unless you're using Traefik Enterprise.

I'm personally trying to figure out how (if) I can link multiple Certificate secrets to a single IngressRoute, like I was able to to in an Ingress. In other words, an IngressRoute with multiple hostnames and a Certificate for each hostname, that is managed by Cert-Manager.

Cameral answered 2/12, 2023 at 1:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.