Blog
So aktualisieren Sie CDK von CDKv1 auf CDKv2 in einem bestehenden Projekt

Hintergrund
Am 2. Dezember hat AWS die allgemeine Verfügbarkeit von CDK Version 2 angekündigt. Der Hauptgrund dafür, dass das CDK-Team die zweite Version veröffentlicht hat, war das Problem der so genannten Abhängigkeitshölle. Nach dem Upgrade sind CDK und alle stabilen Konstrukte jetzt in 1 Paket/Modul zusammengefasst. Experimentelle Module müssen immer noch einzeln installiert werden.
Da ich als Cloud-Berater für ein Unternehmen im Finanzsektor arbeite, sind Sicherheit und Patches für Ihre Software - ja, auch CDK kann als Software angesehen werden - ein Muss. Ein Upgrade von CDK auf Version 2 ist also unumgänglich. Vor allem, da CDK Version 1 am 1. Juni 2023 aus dem Verkehr gezogen wird, siehe Instandhaltungspolitik AWS
Es ist also an der Zeit, auch unsere Codebasis zu aktualisieren. Es gibt zahlreiche Anleitungen im Internet, darunter auch die offizielle von AWSDieser Blog wird nicht im Detail darauf eingehen, wie eine Migration auf CDK Version 2 ablaufen sollte. Er beschreibt den Weg, den ich gegangen bin, um von CDK Version 1 auf Version 2 zu wechseln.
Voraussetzungen für das Upgrade von CDK
Da dieser Blog das Patchen von und das Upgrade auf CDK beschreibt, sind Kenntnisse über CDK erforderlich. Glücklicherweise hat AWS Workshops zu diesem Thema eingerichtet. Bitte schauen Sie sich diese an, wenn Sie CDK und CDK-Pipelines ausprobieren möchten.
Sie benötigen Zugriff auf ein AWS-Konto mit den entsprechenden Rechten für die Bereitstellung von Ressourcen.
Installation
Nehmen Sie einfach eine Tasse Kaffee und lesen Sie weiter...
Szenario der realen Welt
Bei dem aktuellen Auftrag wird eine Datenplattform in AWS erstellt. Die Plattform wird Daten aus verschiedenen Quellen aufnehmen, die Daten verarbeiten und sie für Endbenutzer verfügbar machen. Die verwendeten Dienste sind DataSync, S3, Glue, EMR, Athena und Managed Workflow Apache Airflow(MWAA). Neben diesen Diensten werden auch eine Menge anderer sogenannter unterstützender Dienste verwendet.
Zu Beginn des Projekts war CDK Version 1 die einzige verfügbare Hauptversion. Wenn Sie mit CDK Version 1 arbeiten, muss jedes Paket/Modul, das für die CDK App benötigt wird, installiert werden. Für diese Anwendung, die eine Python CDK App ist, wird eine requirements.txt verwendet.
Die Datenplattform selbst wird in einer sogenannten eingeschränkten AWS-Umgebung erstellt, was bedeutet, dass keine öffentliche Internetverbindung verfügbar ist. Jede Verbindung zum Internet wird über Direct Connects zu Firewalls vor Ort geleitet, wo der Datenverkehr gescannt und geprüft wird.
Da es keine Internetverbindung zur Außenwelt gibt, um die in einer requirements.txt-Datei konfigurierten Build-Pakete abzurufen, muss ein Paketmanager vor Ort konfiguriert werden. Und aufgrund der restriktiven Richtlinien kann jedes Paket, das in der Datei requirements.txt und den Abhängigkeiten benötigt wird, vom Paketmanager blockiert werden. Da diese Datenplattform für ein Unternehmen erstellt wird, dauert die Freigabe eines solchen Pakets einige Zeit. Ein Ticket muss erstellt werden, die Kommunikation mit dem Sicherheitsteam, die Freigabe des Pakets - all das braucht Zeit.
Mit CDK Version 2 ist das Herunterladen von Paketen auf ein einziges Paket beschränkt, das aws-cdk-lib-Paket. Ok, eigentlich brauchen Sie auch das constructs-Paket. Das macht die Datei requirements.txt und das mögliche Whitelisting des aws-cdk-lib-Pakets einfacher.
Bauen gehen
Alte CDK Version 1
Als die Datenplattformanwendung erstellt wurde, verwendete sie die Version cdk 1.136.0. Die requirements.txt-Dateien sahen wie folgt aus:
aws-cdk.aws-athena==1.136.0 aws-cdk.aws-certificatemanager==1.136.0 aws-cdk.aws-codecommit==1.136.0 aws-cdk.aws-codebuild==1.136.0 aws-cdk.aws-codepipeline==1.136.0 aws-cdk.aws-codepipeline-actions==1.136.0 aws-cdk.custom-resources==1.136.0 aws-cdk.aws-datasync==1.136.0 aws-cdk.aws-dynamodb==1.136.0 aws-cdk.aws-ec2==1.136.0 aws-cdk.aws-elasticloadbalancingv2==1.136.0 aws-cdk.aws-elasticloadbalancingv2-targets==1.136.0 aws-cdk.aws-emr==1.136.0 aws-cdk.aws-glue==1.136.0 aws-cdk.aws-iam==1.136.0 aws-cdk.aws-lambda-event-sources==1.136.0 aws-cdk.aws-lambda-python==1.136.0 aws-cdk.aws-lambda==1.136.0 aws-cdk.aws-logs==1.136.0 aws-cdk.aws-mwaa==1.136.0 aws-cdk.aws-route53==1.136.0 aws-cdk.aws-route53-targets==1.136.0 aws-cdk.aws-s3==1.136.0 aws-cdk.aws-s3-deployment==1.136.0 aws-cdk.aws-s3-notifications==1.136.0 aws-cdk.aws-secretsmanager==1.136.0 aws-cdk.aws-ssm==1.136.0 aws-cdk.pipelines==1.136.0 jsonschema<=3.2.0 Boto3 pytest -e .
Wie Sie oben sehen können, wird jedes Paket separat installiert und könnte möglicherweise von der Paketverwaltung blockiert werden.
Unsere cdk.json Datei, die Informationen über CDK enthält, sah wie folgt aus:
{ "app": "python app.py", "Kontext": { "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, "@aws-cdk/core:enableStackNameDuplicates": "true", "aws-cdk:enableDiffNoFail": "true", "@aws-cdk/core:stackRelativeExports": "true", "@aws-cdk/aws-ecr-assets:dockerIgnoreSupport": true, "@aws-cdk/aws-secretsmanager:parseOwnedSecretName": true, "@aws-cdk/aws-kms:defaultKeyPolicies": true, "@aws-cdk/aws-s3:grantWriteWithoutAcl": true, "@aws-cdk/aws-ecs-patterns:removeDefaultDesiredCount": true, "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, "@aws-cdk/aws-efs:defaultEncryptionAtRest": true, "@aws-cdk/aws-lambda:recognizeVersionProps": true, "@aws-cdk/core:newStyleStackSynthesis": true, } }
Zum Schluss unsere setup.py Datei:
importieren Sie setuptools mit open("README.md") as fp: long_description = fp.read() setuptools.setup( name="hashnode", version="0.0.1", description="Datenplattform-Anwendung", long_description=long_description, long_description_content_type="text/markdown", author="Yvo van Zee", author_email="yvo@yvovanzee.nl", package_dir={"": "hashnode"}, packages=setuptools.find_packages(where="hashnode"), install_requires=[ "aws-cdk.core==1.136.0", ], python_requires=">=3.6", Klassifikatoren=[ "Entwicklungsstatus :: 4 - Beta", "Zielpublikum :: Entwickler", "Programmiersprache :: JavaScript", "Programmiersprache :: Python :: 3 :: Nur", "Programmiersprache :: Python :: 3.6", "Programmiersprache :: Python :: 3.7", "Programmiersprache :: Python :: 3.8", "Thema :: Software-Entwicklung :: Code-Generatoren", "Thema :: Dienstprogramme", "Tippen :: Getippt", ], )
Wechsel zu CDK Version 2
Da es sich um ein pythonbasiertes CDK-Projekt handelt, können die Pakete in einer virtuellen Umgebung installiert werden. Eine virtuelle Umgebung ist die Standardeinrichtung, wenn Sie ein CDK-Projekt zum ersten Mal installieren. Für die Migration auf CDK Version 2 wurde eine zusätzliche virtuelle Umgebung erstellt, in der unsere CDK Version 2 Pakete installiert werden.
➜ hashnode git:(main) python3 -m venv .cdkv2 ➜ hashnode git:(main) source .cdkv2/bin/activate (.cdkv2) ➜ hashnode git:(main)
Um Änderungen zu vereinfachen, wurde ein separater Zweig erstellt, um alle Änderungen zu verfolgen.
(.cdkv2) ➜ hashnode git:(main) git checkout -b feature/cdk_version_2 Zu einem neuen Zweig 'feature/cdk_version_2' gewechselt (.cdkv2) ➜ hashnode git:(feature/cdk_version_2)
Da nun alles eingestellt ist, beginnt der Spaß. Die CDK Version 2 Pakete müssen konfiguriert werden. Ich habe mich dafür entschieden, diese Pakete in die setup.py zu verschieben, die mit der Option -e . in der requirements.txt installiert wird. So kann die Datei requirements.txt bereinigt werden. Die neue Version sieht wie folgt aus:
Boto3 pytest -e .
In der Datei setup.py werden die Pakete aws-cdk-lib und construct hinzugefügt, und das Paket aws-cdk.core==1.136.0 wird entfernt. Die Version des aws-cdk-lib-Pakets wird auf Version 2.2.0 festgesetzt. Der Grund dafür war, dass das lib-Paket zunächst in den Quarantänemodus versetzt wurde. Das lag daran, dass das PyYaml-Paket eine Sicherheitslücke aufwies. Als das PyYaml-Paket vom Sicherheitsteam geprüft wurde, kam es auf die Whitelist.
importieren Sie setuptools mit open("README.md") as fp: long_description = fp.read() setuptools.setup( name="hashnode", version="0.0.1", description="Datenplattform-Anwendung", long_description=long_description, long_description_content_type="text/markdown", author="Yvo van Zee", author_email="yvo@yvovanzee.nl", package_dir={"": "hashnode"}, packages=setuptools.find_packages(where="hashnode"), install_requires=[ "aws-cdk-lib==2.2.0", "constructs>=10.0.0,<11.0.0", ], python_requires=">=3.6", Klassifikatoren=[ "Entwicklungsstatus :: 4 - Beta", "Zielpublikum :: Entwickler", "Programmiersprache :: JavaScript", "Programmiersprache :: Python :: 3 :: Nur", "Programmiersprache :: Python :: 3.6", "Programmiersprache :: Python :: 3.7", "Programmiersprache :: Python :: 3.8", "Thema :: Software-Entwicklung :: Code-Generatoren", "Thema :: Dienstprogramme", "Tippen :: Getippt", ], )
Wie in dem offiziellen Migrationshandbuch von AWSmuss auch die cdk.json angepasst werden. Viele der in CDK Version 1 verwendeten Optionen sind jetzt veraltet. Das vereinfacht unsere cdk.json auf:
{ "app": "python app.py", "Kontext": { "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": false, "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": false, "@aws-cdk/aws-rds:lowercaseDbIdentifier": false, "@aws-cdk/core:stackRelativeExports": false, } }
Da es sich hier um die Konfiguration des Installationsteils handelt, ist es an der Zeit, die requirements.txt in unserer virtuellen Umgebung zu installieren:
(.cdkv2) ➜ hashnode git:(main) pip install -r requirements.txt Abrufen von file:///Users/yvthepief/Code/hashnode (aus -r requirements.txt (Zeile 3)) Vorbereiten der Metadaten (setup.py) ... erledigt Sammeln von boto3 Herunterladen von boto3-1.20.35-py3-none-any.whl (131 kB) |████████████████████████████████| 131 kB 3.8 MB/s Sammeln von pytest Zwischengespeicherte pytest-6.2.5-py3-none-any.whl verwenden (280 kB) Sammeln von botocore<1.24.0,>=1.23.35 Herunterladen von botocore-1.23.35-py3-none-any.whl (8,5 MB) |████████████████████████████████| 8.5 MB 6.9 MB/s Sammeln von jmespath<1.0.0,>=0.7.1 Zwischengespeicherte jmespath-0.10.0-py2.py3-none-any.whl verwenden (24 kB) Sammeln von s3transfer<0.6.0,>=0.5.0 Zwischengespeicherte s3transfer-0.5.0-py3-none-any.whl verwenden (79 kB) Sammeln von Pluggy<2.0,>=0.12 Zwischengespeicherte pluggy-1.0.0-py2.py3-none-any.whl verwenden (13 kB) Sammeln von Toml Zwischengespeicherte toml-0.10.2-py2.py3-none-any.whl verwenden (16 kB) Sammeln von py>=1.8.2 Zwischengespeicherte py-1.11.0-py2.py3-none-any.whl verwenden (98 kB) Sammeln von Verpackungen Zwischengespeicherte Verpackung-21.3-py3-none-any.whl verwenden (40 kB) Sammeln von Attributen>=19.2.0 Herunterladen von attrs-21.4.0-py2.py3-none-any.whl (60 kB) |████████████████████████████████| 60 kB 9.9 MB/s Sammeln von iniconfig Zwischengespeicherte iniconfig-1.1.1-py2.py3-none-any.whl verwenden (5.0 kB) Sammeln von aws-cdk-lib==2.2.0 Zwischengespeicherte aws_cdk_lib-2.2.0-py3-none-any.whl verwenden (57,6 MB) Sammeln von Konstrukten<11.0.0,>=10.0.0 Herunterladen von constructs-10.0.33-py3-none-any.whl (50 kB) |████████████████████████████████| 50 kB 10.1 MB/s Sammeln von Veröffentlichungen>=0.0.3 Zwischengespeicherte Veröffentlichung verwenden-0.0.3-py2.py3-none-any.whl (7.7 kB) Sammeln von jsii<2.0.0,>=1.47.0 Herunterladen von jsii-1.52.1-py3-none-any.whl (382 kB) |████████████████████████████████| 382 kB 11.6 MB/s Sammeln von python-dateutil<3.0.0,>=2.1 Zwischengespeicherte python_dateutil-2.8.2-py2.py3-none-any.whl verwenden (247 kB) Sammeln von urllib3<1.27,>=1.25.4 Herunterladen von urllib3-1.26.8-py2.py3-none-any.whl (138 kB) |████████████████████████████████| 138 kB 8.9 MB/s Sammeln von pyparsing!=3.0.5,>=2.0.2 Zwischengespeicherte pyparsing-3.0.6-py3-none-any.whl verwenden (97 kB) Sammeln von Typisierungserweiterungen<5.0,>=3.7 Zwischengespeicherte typing_extensions-4.0.1-py3-none-any.whl verwenden (22 kB) Sammeln von Cattrs<1.11,>=1.8 Zwischengespeicherte cattrs-1.10.0-py3-none-any.whl verwenden (29 kB) Sammeln von sechs>=1.5 Zwischengespeicherte six-1.16.0-py2.py3-none-any.whl verwenden (11 kB) Installation der gesammelten Pakete: six, attrs, typing-extensions, python-dateutil, cattrs, urllib3, publication, jsii, jmespath, pyparsing, constructs, botocore, toml, s3transfer, py, pluggy, packaging, iniconfig, aws-cdk-lib, pytest, boto3, aac-cdp Ausführen von setup.py develop für aac-cdp Erfolgreich installiert aac-cdp-0.0.1 attrs-21.4.0 aws-cdk-lib-2.2.0 boto3-1.20.35 botocore-1.23.35 cattrs-1.10.0 constructs-10.0.33 iniconfig-1.1.1 jmespath-0.10.0 jsii-1.52.1 packaging-21.3 pluggy-1.0.0 publication-0.0.3 py-1.11.0 pyparsing-3.0.6 pytest-6.2.5 python-dateutil-2.8.2 s3transfer-0.5.0 six-1.16.0 toml-0.10.2 typing-extensions-4.0.1 urllib3-1.26.8
Konfigurieren des Codes zur Verwendung der neuen aktualisierten CDK Version 2 Bibliotheken
Da wir nun unsere Umgebung eingerichtet haben, ist es an der Zeit, auch unsere Importe zu ändern. Diese verweisen jetzt immer noch auf die aws_cdk.core Bibliotheken. Die Datei app.py zum Beispiel verwendete die folgenden Importe (CDKv1):
#!/usr/bin/env python3 importieren os from aws_cdk import core as cdk from pipeline_resources.cdkpipeline import CdkPipelineStack from pipeline_resources.repository import RepositoryStack from utilities.permission_boundary import PermissionBoundaryAspect from utilities.tagging import add_tags
Um CDK Version 2 zu verwenden, ändern Sie die Importe in:
#!/usr/bin/env python3 importieren os from aws_cdk importieren ( App, Aspekte, Aws, Umwelt, ) from pipeline_resources.cdkpipeline import CdkPipelineStack from pipeline_resources.repository import RepositoryStack from utilities.permission_boundary import PermissionBoundaryAspect from utilities.tagging import add_tags
Das sieht nach mehr Codezeilen aus, warum? Nun, das liegt daran, dass früher in CDK Version 1 das Core-Modul als vollständiges Modul importiert wurde. Das bedeutete, dass Sie auf alles innerhalb des Kernmoduls zugreifen konnten, wie z.B. App, Stack, Construct. Mit CDK Version 2 wurde auch der Code ein wenig bereinigt. Wo wir früher mit cdk.App() auf das App-Modul verwiesen haben, heißt es jetzt nur noch App().
Für den Pipeline-Stapel sehen die aktualisierten Importe wie folgt aus:
from aws_cdk importieren ( Aspekte, Stapel, aws_codecommit als codecommit, aws_codebuild als codebuild, aws_ec2 als ec2, aws_iam als iam, aws_kms als kms, aws_secretsmanager als secretsmanager, Pipelines, ) from constructs importieren ( Konstruieren Sie, ) class CdkPipelineStack(Stack): def __init__(self, scope: Construct, construct_id: str, named_environments: dict, **kwargs) -> Keine: super().__init__(scope, construct_id, **kwargs) <SNIPPIT>
Wie Sie oben sehen können, importieren wir im Grunde zwei Module (Aspects und Stack), die zuvor im Kernmodul enthalten waren. Außerdem wird auch das Modul Construct von constructs verwendet. Es befindet sich in der Klassendefinition des Stacks (scope). Im Grunde genommen wird alles, was cdk.xxx oder core.xxx war, je nach Art des Imports, durch den direkten Import aus dem Modul aws_cdk ersetzt. Alle anderen Importe wie aws_ec2 und ec2 bleiben unangetastet.
Eine praktische Dokumentation, um zu prüfen, was wo landen sollte, ist der RFC 0192 von CDK.
Testen des CDK Version 2, Synthese von
Der erste Versuch, die Vorlagen zu synthetisieren, schlug fehl. Das lag daran, dass mit allen SecureBucket-Ressourcen (eine Demo zur Erstellung eines sicheren Bucket-Konstrukts finden Sie in dieses Blog), wurde auch ein KMS-Schlüssel erstellt. Für diesen KMS-Schlüssel haben wir den Wert trust_account_identities auf True gesetzt. Aber dies ist nicht mehr unterstützt für den KMS Schlüssel in CDKv2 nicht mehr unterstützt.
Also zweiter Versuch, wieder ein Fehlschlag. Diesmal bei der VPC-Auswahl des isolierten Subnetzes. Im Glue Stack ist eine der Sicherheitsanforderungen, dass wir eine CfnConnection für Glue erstellen, damit es die VPC verwendet. Wir wählen die erste private Subnetz-ID:
subnet_id=vpc.select_subnets( subnet_type=ec2.SubnetType.ISOLATED ).subnet_ids[0]
Dies schlägt mit einem AttributeError fehl
Datei "/Users/yvthepief/Code/Hashnode/devtest/repository/application_resources/Ingestion/glue.py", Zeile 262, in __init__ private_subnets = vpc.vpc.select_subnets(subnet_type=ec2.SubnetType.ISOLATED, one_per_az=True) Datei "/usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/enum.py", Zeile 429, in __getattr__ raise AttributeError(name) von None AttributFehler: ISOLIERT Unterprozess wurde mit Fehler 1 beendet
Das bedeutet eigentlich, dass ISOLATED nicht mehr verwendet wird. Dies ist umbenannt in CDK Version 2 auf PRIVATE_ISOLATED. Andere Optionen sind PUBLIC oder PRIVATE_WITH_NAT.
Endlich, das dritte Mal ist ein Glücksfall! CDK synthetisiert korrekt, d.h. alle Vorlagen im Ordner cdk.out werden jetzt mit CDK Version 2 gerendert.
Als Letztes müssen Sie den Code in der neu erstellten Verzweigung einchecken. Erstellen Sie eine ordentliche Commit-Nachricht, die einer Pull-Anfrage folgt. Dieser Pull Request wurde von einem Kollegen überprüft, die so genannte 4-Augen-Methode, und mit dem Hauptzweig zusammengeführt, damit die CDK-Pipelines ihre Arbeit tun konnten.
Versuchen Sie es selbst
Da der Code aus einem Unternehmens-Repository stammt, ist es mir nicht gestattet, ihn hier zu veröffentlichen.
Wenn Sie es selbst ausprobieren möchten, können Sie mein cdkpipeline_with_cfn_nag Repository auf GitHub. Dies ist eine CDK Version 1 Anwendung mit CDK Pipelines; einen Blog dazu finden Sie hier hier. Klonen oder forken Sie es und versuchen Sie, CDK auf Version 2 zu aktualisieren, indem Sie den Schritten in diesem Blog folgen.
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



