Global http to https redirect in v2

I'm sorry to hear you see it this way.

Let me tell you this - changing the kubernetes manifests for dozens of deployments from Ingress to Ingress route is no fun. I wish that there were an easier path. They do provide Traefik Migration Tool that easies the pain somewhat, but even then it is not ideal. So I totally hear you.

However, I also understand their reasoning. Breaking backward compatibility is a huge pain for the end users. In most places in the industry this is a big no-no. For example, in Microsoft world, products such as .Net framework and Powershell, carry tonnes of sub-optimally designed "features" that are left there just for backward compatibility reasons. It's not uncommon to ask developers to "finally fix" something because everyone agrees that currently it's not ideal, and hear back, "sorry we cannot, because we have to be backward compatible".

Putting on a developer hat, I tell you that this is as frustrating. I often see that my product would work better if I designed it a bit differently. Or a lot differently. And I often want to go back to drawing board and to re-implement things to make them, easier, better, more stream-lined. In a business enterprise context I rarely have this opporunity. Why? Because it's cost in-effective, there is already something that is working and it costs less to keep band-aiding it, rather than do a major rewrite.

Traefik team decided that they've learned enough from the v1, that it warrants such a re-design. They saw what worked and what did not. In particular the idea of router, middlewares and services, is something that became obvious only after a lot of feedback about the v1 model has been gathered. Also when the developers wanted to implement or fix something that was tricky because of v1 design shortcomings - that informed their descision to switch to new approach too.

They blogged about it, you probably can easily find those blog posts if you are interested in reading them.

In short, in order to switch to a new design, they had to make many things work differently in traefik 2. And this is what you are experiencing.

In particular, customer experience with Ingress was not that great, configuring things via labels were a pain, so they decided to improve that via CRDs, which is, in my opinion a very logical thing to do. You simply cannot model everything that Traefik has to offer within constraints of Kubernetes Ingress object. This means that focus of the development now shifted to CRDs, which is also undestandable, there is only so many things you can do and only so many hours in a day, so it clearly makes sense to invest in the better and more flexible system that in the older one, that is being phased out.

The good thing is, that there is no big pressure to switch from v1, at least not right now. You can plan and execute that migration at your own pace. They did acnowledge that the situation with http redirect needs to be improved, since a lot of people voiced that, they did not say what their solution is going to be but they are aware of the complaint and would like to make improvements.

3 Likes

Argh^^ My scenario does actually work. I just got it during writing my answer here (at the bottom).
I have enabled both the kubernetesIngress and kubernetescrd provider and have many classic Ingresses.
I did create a catch all IngressRoute with a https redirectScheme. My errors was to assume that priority 1 is the highest. Using priority 50 does actually work. My catchall IngressRoute with a dummy service (The need for a dummy service seems odd) works now and does a https redirect to all Ingresses.
With what priority are Ingresses handled? 1?

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  creationTimestamp: "2019-09-24T13:45:07Z"
  generation: 13
  name: https-redirect
  namespace: kube-system
  resourceVersion: "26129541"
  selfLink: /apis/traefik.containo.us/v1alpha1/namespaces/kube-system/ingressroutes/https-redirect
  uid: 18e85b17-70a7-4ec7-931d-43793f5fc168
spec:
  entryPoints:
  - http
  - https
  routes:
  - kind: Rule
    match: HostRegexp(`{host:.+}`)
    middlewares:
    - name: redirect-https
    priority: 50
    services:
    - name: dummy
      passHostHeader: true
      port: 8080


Don't get me wrong I completely understand the reason behind this move, its fine work.
I just don't like the fact that this is completely traefik specific and not portable. We have dozens of apps which rely on very simple Ingresses (/ => service) and that's it. The only thing they all have in common is a simple https redirect which seems not to work now. And now we should migrate to something traefik specific only because of the https redirect? Seems odd. I'd like to combine simplicity and complexity, meaning using simple ingresses and for more complex stuff IngressRoutes. I just don't see simple https redirects as "complex".

From my experience ingerss on perm looks different from ingerss in cloud, and I suspect, althought I do not know for sure that they also may look different between azure, aws and gce, so it's already something that varies. So while I kind of see where you are coming from I feel like I'm missing some information.

What platform are you hosting kubernetes in? What type of ingress did you use before traefik that used to be compatible?

Well yeah probably Ingresses are not quite portable between cloud vendors. My case here belongs to a k8s on premise. We've been using traefik v1 from the beginning. But still, I like portability. Maybe someone can point out portability of Ingresses between cloud vendors here.

But since the combination of IngressRoutes and Ingresses actually works there is nothing to complain about. That's the combination of simplicity and complexity I was writing about. Only the v2 docs lack some information here and there. The thing with the priority should be documented better. As well the combination of Ingresses And IngressRoute, I had to spend some hours yesterday to figure the v2 stuff out.

It's a bit a hijack :wink:

This one don't catch the http in the catchall. It don't redirect http to https.

version: "3.3"

networks:
    traefik:
        external: true

services:

  traefik:
    image: "traefik:v2.0"
    container_name: "traefik"
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web-secure.address=:443"
      - "--certificatesresolvers.myhttpchallenge.acme.httpchallenge=true"
      - "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web-secure"
      #- "--certificatesresolvers.myhttpchallenge.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory"
      - "--certificatesresolvers.myhttpchallenge.acme.email=me@mail.com"
      - "--certificatesresolvers.myhttpchallenge.acme.storage=/letsencrypt/acme.json"
    labels:
      - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.entrypoints=web"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https@docker"
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    networks:
      - "traefik"
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  inner-whoami:
    image: "containous/whoami"
    container_name: "inner-whoami"
    networks:
      - "traefik"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.inner-whoami.rule=Host(`sub.domaine.com`)"
      - "traefik.http.routers.inner-whoami.entrypoints=web"
      - "traefik.http.routers.inner-whoami-secured.rule=Host(`sub.domaine.com`)"
      - "traefik.http.routers.inner-whoami-secured.entrypoints=web-secure"
      - "traefik.http.routers.inner-whoami-secured.tls=true"
      - "traefik.http.routers.inner-whoami-secured.tls.certresolver=myhttpchallenge"

I tried to comment the lines of whoami related to the router for http but it just makes http going into a 404 error.

1 Like

@Thibd could you resolve your problem? I'm having the same problem and I'm using similar configs...
Could you share your solution if you found one?

Hi @Dan42

I tried to use labels for redirect on each service and I still had errors. After getting some help it was that the http challenge has to be done on port 80, so that, .

- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web-secure"

Has to be replaced by :

- "--certificatesresolvers.myhttpchallenge.acme.httpchallenge.entrypoint=web"

I did not re-test it with the above code. I will stick with on adding labels on each service because this is for a remote dev environement and it gives some flexibility. Tell me if if you had some success.

Regards

Hi @Thibd,
my cert configs were correct.
I played around, but in the end I only got it working with the provided (Post #3) dynamic .toml file configs.
Setting the redirect with labels didn't work out for me and I don't know why. The middleware and the router didn't show up in traefik dashboard. Adding the suggested noop service via labels didn't change anything.

same I am also stuck on this http to https redirect

Indeed it seems crazy I'm going to have to deploy a service in kubernetes that is never hit. As-is, when deploying the almost exact manifest you provided it yields Cannot create service: service not found traefik/dummy.

@raffis what did you use for a dummy service, something that takes almost no resources I presume? Advice welcome.

EDIT: I found a small test image I had around to test rolling updates - rosskevin/example-nginx:1.0

what did you use for a dummy service, something that takes almost no resources I presume?

It appears that you are mixing up a service and a pod. Otherwise resource usage of a service would be no concern.

A service is not live without a deployment and the subsequent running/ready pod which consumes resources, all for what should be an inconsequential config.

No, I'm not mixed up at all.

"not live"? What do you mean?

An IngressRoute won't be live unless there is a live kubernetes service (see the error I posted). A kubernetes service won't be live without a ready kubernetes deployment/pod.

In order to create a global https redirect, I need all of the above, and the running pod (that is never hit) consumes resources.

It appears that you use "live" in some colloquial meaning but you do not define what that meaning is. If you look at kubertens documentation there is no categorization of kubernetes objects or CRDs to live and not-live (except for liveness probe that only applies to pods). They either exist in the cluster or they do not.

So when you say:

A service is not live without a deployment

This is either incorrect (it's perfectly possible to create a service without a depoyment), or irrelevant (the fact that a service is not related to other kubernetes object does not matter for traefik).

So I'm asking again, what do you mean by saying that a service (or IngressRoute ) is "live"?

Ok, please provide a sample of an IngressRoute with a kubernetes service that is "registered" with kubernetes and has no errors in the log that can satisfy this global https redirect case. Can you? I do not believe you can.

Live is in referring to a liveness probe, a kubernetes term from the the deployment manifest measures a pod's state. A service is useless without a deployment, just as an IngressRoute without a service. Colloquial no, transitive, yes. A service cannot transitively be live unless it is linked to a pod that is both "ready" and "live".

Feel free to parse semantics all you like, as far as I can tell, you need all of the above to perform a global https redirect.

All I'm saying, and I feel I'm repeating myself is that you can create a service without pod or deployment, and this will be enough for the purpose of IngressRoute. The error that you cited is because you did not created the service.

No arrguments, that having a dummy service just for the purpose of pleasuring traefik seems unnescessary, the point is, it does not cost any non-trivial resources, and you do not need deployment and/or pods for that to work.

You can not. As I posted above, a service descriptor pointed at a non-existent deployment yields:

Cannot create service: service not found traefik/dummy.

Where traefik is the namespace and dummy is the non-existent deployment.

Well that must be because you need to point and IngressRoute to a service, not to a deployment, no?