'Traefik (v2.2) Ingress on Kubernetes: HTTP and HTTPS cannot co-exist

I am using Traefik (v2.2) on Kubernetes, using a wildcard domain certificate for HTTPS access.

The following are my Traefik deployment and Ingress configurations:

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: ingress-traefik
  name: traefik
  labels:
    app: traefik

spec:
  replicas: 1
  selector:
    matchLabels:
      app: traefik
  template:
    metadata:
      labels:
        app: traefik
    spec:
      serviceAccountName: traefik-ingress-controller
      containers:
        - name: traefik
          image: traefik:v2.2
          ports:
            - name: web
              containerPort: 80
            - name: websecure
              containerPort: 443
            - name: admin
              containerPort: 8080
          args:
            - --providers.kubernetesingress
            - --entrypoints.web.Address=:80
            - --entrypoints.websecure.Address=:443
            - --ping.entryPoint=web

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: traefik-ingress
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.ingress.kubernetes.io/router.entrypoints: web, websecure

    # remark the following line, HTTPS will return "404 page not found"
    # enable the following line, HTTP will return "404 page not found"
    traefik.ingress.kubernetes.io/router.tls: "true"

    cert-manager.io/cluster-issuer: letsencrypt-prod

spec:
  tls:
    - secretName: cert-stage-wildcard

  rules:
    - host: user.example.io
      http:
        paths:
        - path: /
          backend:
            serviceName: user-service
            servicePort: http

I want to have both HTTP and HTTPS working, but seems cannot do both:

If I comment the annotation 'traefik.ingress.kubernetes.io/router.tls: "true"' of the ingress, HTTP will work but HTTPS will not:

$ curl -v https://user.example.io
*   Trying 159.203.52.215:443...
* TCP_NODELAY set
* Connected to user.example.io (159.203.52.215) port 443 (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /home/ken.tsoi/anaconda3/ssl/cacert.pem
  CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=*.example.io
*  start date: Oct 28 16:10:10 2020 GMT
*  expire date: Jan 26 16:10:10 2021 GMT
*  subjectAltName: host "user.example.io" matched cert's "*.example.io"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: user.example.io
> User-Agent: curl/7.68.0
> Accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Wed, 28 Oct 2020 21:45:38 GMT
< Content-Length: 19
< 
404 page not found
* Connection #0 to host user.example.io left intact

If I enable the annotation line, HTTP will return "404 page not found":

$ curl -v http://user.example.io
*   Trying 159.203.52.215:80...
* TCP_NODELAY set
* Connected to user.example.io (159.203.52.215) port 80 (#0)
> GET / HTTP/1.1
> Host: user.example.io
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Wed, 28 Oct 2020 21:49:07 GMT
< Content-Length: 19
< 
404 page not found
* Connection #0 to host user.example.io left intact

I guess there should be some small error with the setting, can anyone find out where the problem is ?



Solution 1:[1]

From the document of traefik/v2.2/routing/routers/tls, it says that " When a TLS section is specified, it instructs Traefik that the current router is dedicated to HTTPS requests only (and that the router should ignore HTTP (non TLS) requests). ".

That explains all what I have encountered.

My solution to this was to create two ingress routers, one for HTTP and another for HTTPS.

Solution 2:[2]

I had to activate the redirect globally. That can be done by uncommenting

redirectTo: websecure

in my Traefik's values.yaml Helmchart. So you need to look at your Traefik config, in order to check this one out.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ken Tsoi
Solution 2 Joe Inner