Einige Hintergrundinformationen:
Ich habe mit dem vpc von Amazon ein mäßig komplexes Netzwerk erstellt. Es ist ein dreistufiges Netzwerk in zwei Verfügbarkeitszonen. Jede Schicht hat ein Subnetz in Zone a und Zone b. Die Präsentationsebene befindet sich oben, eine Anwendungsebene in der Mitte und eine Kernebene unten.
Alle Sicherheitsgruppen und ACLs für die Subnetze erlauben derzeit ALLEN eingehenden und ausgehenden Datenverkehr, um die Oberfläche des Problems zu reduzieren.
Die Routing-Tabelle der Präsentationsschicht verweist den gesamten Datenverkehr auf ein Internet-Gateway. Das NAT-Gateway befindet sich in einem getrennten Subnetz und verweist den gesamten Datenverkehr auf das Internet-Gateway.
Meine Anwendung besteht aus zwei Komponenten, einer Benutzeroberfläche (React.js) und einer API (Node / Express). Sie werden als Docker-Images bereitgestellt. Vor jedem steht ein klassischer Load Balancer.
Die UI-ELB ist mit dem Internet verbunden und befindet sich in der Präsentationsschicht. Sie leitet den Datenverkehr von 80/443 an Port 8080 weiter und ist meiner App-ec2 zugeordnet, die sich im Subnetz der Anwendungsschicht befindet.
Meine API verfügt über einen internen Load Balancer. Der API-ELB befindet sich in der Anwendungsschicht (im selben Subnetz wie der app-ec2) und nimmt den Datenverkehr auf Port 80/443 auf und leitet ihn an den api-ec2 im Core auf Port 3000 weiter.
Beide Load Balancer entladen das Zertifikat, bevor sie Datenverkehr an ihre Instanzen weiterleiten.
Ich habe meine beiden Load Balancer in Route53 als Alias verknüpft und in den Anwendungen durch ihre hübsche URL ( https://app.website.com ) referenziert . Jeder Load Balancer besteht die definierten Integritätsprüfungen und meldet alle verwendeten ec2-Instanzen.
Zuletzt habe ich auf der API cors mit dem Paket cors nodejs aktiviert.
Hier ist ein schnelles und schmutziges Diagramm meines Netzwerks.
Das Problem:
Die APP-ELB leitet mich erfolgreich zur Anwendung weiter. Wenn die App jedoch versucht, eine GET-Anforderung an die API-ELB zu senden, sendet sie zuerst eine OPTIONS-Anforderung, die mit dem Fehlercode 408 übereinstimmt.
Wo es komisch wird
Einige der seltsamsten Dinge, denen ich beim Debuggen begegnet bin, sind:
- Ich kann SSH in die App-ec2-Instanz und kann eine erfolgreiche Curl gegen die API-ELB ausführen. Ich habe viele ausprobiert und alle funktionieren. Einige Beispiele sind:
curl -L https://api.website.com/system/healthcheck
undcurl -L -X OPTIONS https://api.website.com/system/healthcheck
. Es werden immer die gewünschten Informationen zurückgegeben. - Ich habe die gesamte Anwendung aus meinem Netzwerk in einen öffentlichen Standard-VPC verschoben und sie funktioniert wie vorgesehen.
- Ich habe die api-ec2 alle Netzwerkanforderungen an die Konsole schreiben. Während die Healthcheck-Anforderungen angezeigt werden, werden keine Anforderungen von app-ec2 angezeigt. Dies lässt mich glauben, dass der Verkehr nicht einmal die API erreicht.
Wirklich das Größte, was mich völlig ratlos macht, ist, dass das Einrollen des internen API-Elbs funktioniert, die Axios-Anforderung an dieselbe exakte URL jedoch nicht. Das ergibt für mich überhaupt keinen Sinn.
Was ich versucht habe
Ich habe ursprünglich viel Zeit damit verbracht, mit ACL-Regeln und Sicherheitsgruppen zu spielen, weil ich dachte, ich hätte etwas falsch gemacht. Schließlich sagte ich nur "Scheiß drauf" und öffnete alles, um zu versuchen, dieses Stück aus der Gleichung herauszunehmen.
Ich habe viel zu viel Zeit damit verbracht, mit Cors auf meiner API zu spielen. Irgendwann auf der Konfiguration landen, die ich jetzt habe, das ist der Standard- app.use(cors())
Rückruf, der vom cors-Knotenpaket bereitgestellt wird. Ich habe auch das app.options('*', cors())
empfohlen, was in der Dokumentation empfohlen wird.
Ich habe alles unter der Sonne googelt, aber speziell, ob ich mit den Elbs einige spezielle benutzerdefinierte Header definieren muss? Kann aber scheinbar nichts finden. Außerdem hat es gut funktioniert, als ich meine App aus dem Netzwerk entfernt habe.
Ich bin sicher, ich habe viele andere Dinge ausprobiert, aber diese scheinen am relevantesten zu sein. Was vermisse ich? Mir ist klar, dass dies möglicherweise ein sehr vages und weit gefasstes Thema und ein enormer Beitrag ist, aber ich schätze jeden Einblick und Ihre Zeit beim Lesen!
curl -X OPTIONS 127.0.0.1...
auf app-ec2? Nur OPTIONS
ist kaputt? Die ELBs sind "Classic", nicht "Application", richtig? Können alle Instanzen über NAT korrekt auf das Internet zugreifen, z curl ipv4.icanhazip.com
. (Ja, ich frage nach einem Grund, der dunkel erscheinen mag.)