Hintergrund
Es ist schon eine Weile her seit meinem letzten Blog. Das lag vor allem an einem Problem, auf das wir bei einem Kunden mit seiner CDK-Anwendung gestoßen sind. Im Moment arbeite ich immer noch für ein Unternehmen im Finanzsektor, wo ich einem Datenanalyseteam beigetreten bin, das eine Datenplattform in AWS aufbaut. Diese Datenplattform nutzt Dienste wie DataSync, S3, Glue, EMR, Athena, LakeFormation und Managed Workflow for Apache Airflow (MWAA).
Die gesamte Anwendung wurde mit CDK in Python erstellt. Sie nutzt CDK Pipelines, um die Anwendung auf mehreren AWS-Konten bereitzustellen.
Nachdem unsere CDK-Datenplattformanwendung auf dem AWS-Testkonto bereit war, wollten wir sie auch für die UAT (Abnahme) bereitstellen. Da wir CDK-Pipelines verwenden, fügen wir einfach eine zusätzliche Stufe zur Pipeline hinzu, wobei die Stufe das AWS-Konto darstellt. Da wir auf die Bereitstellung der DataSync VM vor Ort warten mussten, haben wir eine Teilmenge der Stacks für das UAT-Konto bereitgestellt. Bei diesen Untergruppen handelte es sich im Wesentlichen um IAM-Rollen, die S3-Buckets sowie Glue-Crawler und -Aufträge erstellen.
Alles war gut, bis zu einem bestimmten Moment. Die Synthese war nicht mehr das, was sie einmal war. OK, das ist jetzt etwas dramatisch, aber es fühlte sich an wie dieser typische Montagmorgen, an dem alles den Bach runtergeht. Hatte ich meinen Kaffee vergessen? War es eine Änderung der Betriebssystempakete, so dass wir wenigstens jemandem/etwas die Schuld geben konnten...?
Aber nein...
Die einzige Nachricht, die wir erhielten, war:
Fehlerhafte Anfrage, Feld "API" ist erforderlich.
Da dieser Fehler für uns keinen Sinn ergab, begannen wir mit der Fehlersuche. Ich möchte Sie mitnehmen auf unser Abenteuer, was wir getan haben und wie wir den Fehler irgendwie umgehen konnten.
Voraussetzungen
Ich beschreibe hier unser Abenteuer bei der Fehlersuche und -umgehung in Bezug auf unser CDK-Synthesizer-Problem, daher ist keine wirkliche Erfahrung erforderlich.
Installation
Also lehnen Sie sich zurück, trinken Sie eine Tasse Kaffee und folgen Sie uns.
Szenario der realen Welt
Wie im Abschnitt "Hintergrund" beschrieben, passierte an diesem typischen Montagmorgen etwas, das dazu führte, dass wir unsere CDK-Anwendung nicht mehr synthetisieren konnten. Normalerweise sah unser Arbeitsablauf so aus: lokale Entwicklung, CDK-Synthese und anschließende Tests, um sicherzustellen, dass alles in Ordnung ist, Pull-Requests, Überprüfung durch jemanden (4-Augen-Prinzip), Zusammenführen und die Pipeline ihre Arbeit tun lassen. Die lokale Entwicklung fand in einer Windows VDI mit Visual Studio Code statt. Diesmal wurde beim Ausführen der CDK synth Befehl lokal ausgeführt wurde, führte dies zu einem Stack-Trace-Fehler:
(.venv) PS H:Coderepository> cdk synth C:Users******AppDataLocalTemp1tmp5uqjk38xlibprogram.js:9764 throw new Error('Fehlerhafte Anfrage, Feld "api" ist erforderlich'); ^ Fehler: Fehlerhafte Anfrage, Feld "api" ist erforderlich at KernelHost.processRequest (C:Users******AppDataLocalTemp1tmp5uqjk38xlibprogram.js:9764:27) at KernelHost.run (C:Users******AppDataLocalTemp1tmp5uqjk38xlibprogram.js:9732:22) at Unmittelbar.<anonymous> (C:Users******AppDataLocalTemp1tmp5uqjk38xlibprogram.js:9733:46) bei processImmediate (intern/timers.js:464:21)
Und was nun? Nun, natürlich fragen Sie Google, was das fehlerhafte Anfrage Fehler bedeutet. Die erste Antwort, die Google Ihnen gibt, ist ein Github-Ausgabe des CDK-Projekts. Was für eine Erleichterung, wir waren nicht allein mit diesem Problem. Aber wenn man sich mit dem Thema befasst, sieht es so aus, als ob die Untersuchung, die durchgeführt wurde, nicht für unser Problem geeignet war. Letztendlich haben wir nicht mehr als 500 Ressourcen erstellt. Der größte "Stapel" bestand aus nur 115 Ressourcen. Und alle Stapel zusammen lagen unter 200. Was ist also als nächstes zu tun?
Wir haben die GitHub-Ausgabe mit unserem eigenen Teil der Geschichte aktualisiert. Informieren Sie sich hier darüber. Außerdem haben wir ein AWS-Support-Ticket erstellt, da der Kunde einen Unternehmensvertrag mit AWS hat.
Abhilfe
In der Zwischenzeit haben wir versucht, unser Problem zu umgehen. Eine Möglichkeit war, unsere CloudFormation-Ausgaben zu minimieren. Da wir versuchten, die Phase der Leistungs- und Sicherheitstests eines kleinen Teils der Anwendung in UAT zu beginnen, mussten wir nicht die gesamte Anwendung wie in DevTest bereitstellen. Die Anwendung wurde also nur teilweise in UAT bereitgestellt, und zwar nur so viele Ressourcen, dass die Anfrage Malformed nicht ausgelöst wurde.
Aber mit dieser teilweisen Bereitstellung saßen wir nun fest. Das Hinzufügen zusätzlicher Ressourcen würde bedeuten, dass wir erneut den Fehler "Malformed request" auslösen. Was war es also, das diesen Fehler überhaupt erst ausgelöst hat? Wir sahen uns die Codebasis an, um zu prüfen, ob Schleifen oder andere Dinge als Ursache gefunden werden konnten. War es das zusätzliche AWS-Konto, das hinzugefügt wurde? War es ein Upgrade der Knotenversion oder sogar der CDK-Version?
Es wurden alle möglichen Ursachenszenarien durchgespielt, aber keines brachte wirklich Zufriedenheit oder eine genaue Ursache für das Problem. Wir hatten das Gefühl, dass wir uns im Kreis drehten. Da das AWS-Support-Ticket und das Github-Problem noch nicht gelöst waren, war es an der Zeit, nach Alternativen zu suchen.
Also haben wir eine Liste mit vier alternativen Optionen erstellt, um unser unbekanntes Problem mit dem ausgelösten CDK-Synth zu lösen. Alle mit Argumenten, Vor- und Nachteilen.
Option 1: Manuelle Bereitstellung in UAT/PRD
Sobald wir unsere Codebasis zur Verfügung haben, können wir uns mit der manuellen Bereitstellung von Ressourcen in UAT und eventuell PRD befassen.
Änderung erforderlich:
Die Arbeit, die getan werden musste, war das Umschreiben der aktuellen app.py Datei umzuschreiben und lose Stapel für die UAT- und PRD-Konten bereitzustellen, anstatt dies der CDK-Pipeline zu überlassen.
Hindernisse:
Das Hindernis dabei ist, dass wir keinen Zugriff auf die Bereitstellung von Ressourcen mit der Entwicklerrolle in UAT und PRD haben. Wir müssen mit dem Plattformteam und dem Sicherheitsteam klären, ob wir einen Weaver dafür bekommen können. Da sich dies jedoch stark auf die Sicherheit auswirkt, scheint dies keine Option zu sein.
Option 2: Verwenden Sie den CodeBuild-Dienst zur manuellen Verteilung an UAT/PRD
Im Grunde ist dies also eine Erweiterung von Option 1. Die Idee basiert darauf, wie die Konten im Moment eingerichtet sind. Im Entwicklungskonto ist eine Rolle verfügbar, die der CodeBuild-Dienst übernehmen kann, um Ressourcen in den Anwendungskonten DevTest, UAT und PRD bereitzustellen. Im Moment sorgt der CDK Pipeline-Dienst für die Korrektheit der Bereitstellungen für diese Konten. Es ist jedoch auch möglich, separate Stacks über den CodeBuild-Dienst bereitzustellen. Wo wir also die Synth-Aktion durchführen, um die CloudFormation-Vorlagen innerhalb von CodeBuild zu generieren, können wir auch eine "cdk-Bereitstellung" durchführen, um Stacks bereitzustellen.
Änderung erforderlich:
Schreiben Sie in der CDK-Pipeline die CodeBuild buildspec-Datei um, um Stacks manuell bereitzustellen. Sie können auch mehrere CodeBuild-Projekte erstellen, die nur zum Einsatz kommen. Eine Pipeline würde also wie folgt aussehen:
CodeCommit -> CodeBuild (Synthetisieren von Vorlagen) -> CodeBuild DevTest (Bereitstellen von Vorlagen) -> CodeBuild UAT (Bereitstellen von Vorlagen) -> manuelle Genehmigung -> CodeBuild PRD (Bereitstellen von Vorlagen)
Hindernisse:
Es ist manuelle Arbeit, die CodeBuild buildspec-Dateien zwischen den Konten synchron zu halten. Im Moment übernimmt die CDK-Pipeline diese Aufgabe für uns. Ich weiß nicht, ob wir die Rechte haben, um mit CodeBuild ein "cdk deploy" auszuführen und den CodeBuild-Dienst den CloudFormation-Dienst in UAT und Produktion aufrufen zu lassen. Das muss noch getestet werden.
Option 3: Separate CDK-Pipelines pro Stapel
Da wir also jetzt eine Wenn Sie nur eine Codebasis und ein CDK-Projekt haben, bleibt die Synthese an der erreichten unbekannten Grenze hängen. Da wir die manuelle Arbeit so weit wie möglich einschränken möchten, können wir auch mehrere CDK-Pipelines erstellen, die für eine einzige Stack-Aufgabe statt für mehrere Stacks zuständig sind. Ein Beispiel: Unsere Pipeline besteht derzeit aus Phasen, wobei eine Phase eine AWS-Umgebung darstellt (DevTest, UAT, PRD). Innerhalb einer solchen Phase werden Stacks für jede Teilmenge der Anwendung bereitgestellt. Sie sind unterteilt in Konsum-, Ingestion-, Integrations-, Überwachungs-, Orchestrierungs-, Onboarding- und Voraussetzung-Stacks. Für jede Phase werden also alle diese Stacks bereitgestellt. Da die Menge der Stacks zum Syntheseproblem beitragen kann, wäre es eine mögliche Lösung, jeden Stack in eine eigene Pipeline zu integrieren.
Änderung erforderlich:
Erstellen Sie mehrere CDK-Pipelines, die nur für einen Stack zuständig sind. Also eine CDK-Pipeline für den Onboarding-Stack, der über alle AWS-Konten (DevTest/UAT/PRD) bereitgestellt wird, eine weitere für den Ingestion-Teil und so weiter...
Hindernisse:
Es werden zusätzliche Ressourcen zur Verfügung gestellt. Das kann zusätzliche Kosten bedeuten. Eine Standard-CDK-Pipeline verwendet KMS-Schlüssel, S3-Buckets, den CodePipeline-Dienst und den CodeBuild-Dienst. Außerdem bleibt das Problem der CDK-Synthese ungelöst. Das könnte bedeuten, dass das Problem in Zukunft wieder auftauchen könnte.
Option 4: Umschreiben der Codebasis in Typescript
Da wir nicht genau sagen können, warum dieses CDK Synth-Problem auftritt, wäre es vielleicht eine gute Idee, die native CDK-Implementierung mit Typescript anstelle von Python zu verwenden, so dass das JSII-Framework nicht mehr benötigt wird. Dies bedeutet eine Überarbeitung unseres CDK-Codes in einer anderen Sprache. Glücklicherweise haben wir den funktionierenden Python-Code bereits, so dass wir nicht untersuchen müssen, ob er auch in Typescript funktioniert. Es geht nur darum, den aktuellen Code in Typescript umzuschreiben.
Änderung erforderlich:
Umschreiben des gesamten Codes in Richtung der Typescript-Implementierung von CDK
Bei allen aufgelisteten Optionen war es Sache des Teams und des Produktverantwortlichen, eine Entscheidung zu treffen. Wobei Option 1 und 2 im Grunde gar keine Option waren. Die Entscheidung lag zwischen 3 und 4. Bei 4 war es schwierig, die für die Änderung benötigte Zeit zu berechnen. Also entschieden wir uns schließlich für Option 3.
Lösung
Die endgültige Lösung bestand darin, die Anwendung zu zerstückeln. Zu diesem Zweck mussten wir zwei weitere Konstrukte als wiederverwendbare Bausteine erstellen:
- sicheres Repository-Konstrukt
- sicheres Pipeline-Konstrukt
Mit diesen Konstrukten war es ein Leichtes, ein sicheres CDK-Projekt (App) zu erstellen, das den vom Sicherheitsteam festgelegten Richtlinien entsprach. Da der gesamte Code bereits vorhanden war, mussten wir lediglich die Systemmanager-Parameter (SSM) stärker nutzen, um bestimmte Arn zwischen CDK-Anwendungen weiterzuleiten.
Ich werde einen Folgeblog über beide Konstrukte schreiben, da es auch einige Herausforderungen gab. Vor allem, wie man die Konstrukte in allen CDK-Projekten gemeinsam nutzen kann. Kleiner Tipp, wir haben dafür Git-Submodule verwendet. Wenn Sie daran interessiert sind, bleiben Sie für den nächsten Blog dran.
Zusammenfassung
Ich habe versucht, einen Tag oder vielmehr einen Monat im Leben eines Cloud-Beraters aufzuschreiben. Auf welche Hindernisse wir gestoßen sind und dass es nicht immer ein glücklicher Fluss ist. Aber vor allem der Blick über das Problem hinaus und das Finden einer Lösung, die funktioniert, macht zufrieden.
Lernen Sie also weiter und fordern Sie sich jeden Tag aufs Neue heraus!
Verfasst von
Yvo van Zee
I'm an AWS Cloud Consultant working at Oblivion. I specialised myself in architecting and building high available environments using automation (Infrastructure as Code combined with Continuous Integration and Continuous Delivery (CI/CD)). Challenging problems and finding solutions which fit are my speciality.
Unsere Ideen
Weitere Blogs
Contact




