Force_https funktioniert nicht mit GCP Ingress

Ich habe eine Kubernetes-Instanz auf GCP. Alles scheint in Ordnung zu sein, aber irgendwie erzwingt force_https keine Umleitung, und die Seite kann noch über http:// abgerufen werden.

Meine vorläufige Lösung bestand darin, diesen Abschnitt zu app.yml hinzuzufügen:

    - replace:
        filename: /etc/nginx/conf.d/discourse.conf
        from: '    add_header ETag "";'
        to: |
                  add_header ETag "";
                  if ($thescheme = "http") {
                    return 301 https://$host$request_uri;
                  }

(Und ich würde gerne verstehen, wie man pups dazu bringt, die eingefügten Zeilen korrekt einzurücken, aber das sei dahingestellt.)

Irgendwann nach dieser Änderung scheint der Ingress-Controller aufgehört zu haben, die Seite auszuliefern, obwohl er zumindest eine Weile funktioniert hat – und ordnungsgemäß umgeleitet hat.

Offensichtlich handelt es sich hier um eine unsupported-install, aber falls jemand eine Idee hat, wo ich als Nächstes suchen sollte, wäre ich dankbar.

Verwenden Sie einen HTTP-Loadbalancer oder einen TCP-Loadbalancer? Bei HTTP kann das am Ingress sichtbare Protokoll in einem nicht standardkonformen Header verpackt sein, den Discourse nicht sucht.

So sieht das vollständig verwaltete Setup aus:

$ gcloud compute addresses create discourse-ip-address --global
#                                 ^~~~~~~~~~~~~~~~~~~~ benutzerdefinierter Name
# WARNUNG: Die Reservierung einer IP-Adresse ohne Nutzung führt zu einer Gebühr von 0,010 USD/Stunde
---
apiVersion: networking.gke.io/v1beta1
kind: ManagedCertificate
metadata:
  name: discourse-cert
spec:
  domains:
    - discourse.example.com  # anpassen
---
apiVersion: extensions/v1beta1
# ab Version 1.14:
# apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: discourse-web-ingress
  annotations:
    networking.gke.io/managed-certificates: discourse-cert
    kubernetes.io/ingress.global-static-ip-name: discourse-ip-address
spec:
  backend:
    serviceName: discourse-web  # prüfen, ob dies korrekt ist
    servicePort: 80

Quellen:

Vielen Dank, @riking! Ja, es scheint, dass der Load Balancer mein Problem ist. Ich denke, Ingress ist in Ordnung (und ich habe jetzt eine gewisse Vorstellung davon, dass es einen Unterschied gibt). Ich bin auf die von dir gezeigte Konfiguration umgestiegen und erhalte dieselben Ergebnisse wie mit einer etwas komplizierteren Konfiguration. Ich vermute, der nächste Schritt wäre, tcpdump zu verstehen und zu prüfen, was in diesen Headern steht. . .

EDIT: Es sieht so aus, als ob es funktionieren sollte. Hier ist, was ich sehe:

GET /thisisatest HTTP/1.1
User-Agent: Wget/1.19.4 (linux-gnu)
Accept: */*
Accept-Encoding: identity
Host: community.example.com
X-Cloud-Trace-Context: 72c9f7219e6b541cad01153c52fb92c5/13509441707361831434
Via: 1.1 google
X-Forwarded-For: MEINE-IP-ADRESSE, INGRESS-IP
X-Forwarded-Proto: http
Connection: Keep-Alive

Ich habe eine set_real_ip_from-Regel mit der Ingress-IP (und IP-Adressen werden ordnungsgemäß protokolliert).

@pfaffman Ich könnte dabei helfen – ich arbeite mit GCP und habe dieses Problem bereits gelöst. Ich bin jedoch für ein paar Stunden gebunden. Wenn du mir deine Load-Balancer-Konfiguration (zusammen mit den Health-Check-Einstellungen) hier oder privat sendest, kann ich versuchen, das Problem zu finden.

PS: Sowohl TCP als auch HTTP funktionieren.

Vielen Dank, @p16!

Nun, hier ist der Health Check. Ich habe den Pfad zu /srv/status geändert, aber ich sehe immer noch, dass “GoogleHC/1.0” auf / zugreift.

Danke, wird das Backend im Load Balancer als gesund angezeigt? Bitte fügen Sie www.yoursite.com auch unter „Host“ (unter „Mehr“) hinzu.

Hier ist zudem, was ich zu meiner app.yml hinzufüge:

  after_web_config:
    - replace:
       filename: "/etc/nginx/conf.d/discourse.conf"
       from: /server.+{/
       to: |
         server {
           if ($http_x_forwarded_proto = 'http'){
            return 301 https://$host$request_uri;
           }

Das wird nicht lange notwendig sein, da Google noch in diesem Quartal einen Redirect von HTTP zu HTTPS hinzufügen wird.

Ja, es scheint jetzt zu funktionieren! Ich bin mir zwar noch unsicher bezüglich des magischen Ports 30182, aber das ist wohl eine Art k8s-Magie, die ich mir später noch genauer ansehen werde.
Ich werde deinen after_web_config:-Absatz ausprobieren. Das wirkt etwas übersichtlicher als meine bisherige Lösung.

Vielen Dank!