Kapitel 4. Datenbanken

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

4.0 Einleitung

Du hast unzählige Möglichkeiten, Datenbanken mit AWS zu nutzen. Die Installation und der Betrieb einer Datenbank auf EC2 bietet dir die größte Auswahl an Datenbank-Engines und benutzerdefinierten Konfigurationen, bringt aber auch Herausforderungen wie Patches, Backups, Konfiguration der Hochverfügbarkeit, Replikation und Leistungsoptimierung mit sich. Wie auf der Produktseite von AWS beschrieben, bietet AWS verwaltete Datenbankservices an, die dabei helfen, diese Herausforderungen zu meistern und eine breite Palette von Datenbanktypen abzudecken (relational, Key-Value/NoSQL, In-Memory, Document, Wide Column, Graph, Time Series, Ledger). Bei der Wahl des Datenbanktyps und des Datenmodells musst du die Geschwindigkeit, das Volumen und die Zugriffsmuster im Auge behalten.

Die verwalteten Datenbankservices auf AWS sind mit vielen Diensten integriert und bieten dir zusätzliche Funktionen in den Bereichen Sicherheit, Betrieb und Entwicklung. In diesem Kapitel lernst du den Amazon Relational Database Service (RDS) und die NoSQL-Nutzung mit Amazon DynamoDB kennen und erfährst, wie du diese Datenbanktypen migrieren, sichern und in großem Umfang betreiben kannst. Du lernst zum Beispiel, wie du den Secrets Manager in eine RDS-Datenbank integrieren kannst, um die Passwörter der Datenbankbenutzer automatisch zu ändern. Du erfährst auch, wie du die IAM-Authentifizierung nutzen kannst, um die Abhängigkeit der Anwendung von Datenbankpasswörtern zu reduzieren und stattdessen den Zugriff auf RDS über IAM-Berechtigungen zu gewähren. Du lernst die Autoskalierung von DynamoDB kennen und erfährst, warum dies aus Kosten- und Leistungssicht wichtig ist.

Hinweis

Manche Leute denken, dass die Route 53 eine Datenbank ist, aber wir sind anderer Meinung :-)

Hinweis

Einige Datenbank-Engines haben in der Vergangenheit eine bestimmte Terminologie für Replikat-Konfigurationen, Standard-Root-Benutzernamen, primäre Tabellen usw. verwendet. Wir haben darauf geachtet, in diesem Kapitel (und im gesamten Buch) möglichst eine einheitliche Terminologie zu verwenden. Wir unterstützen die Bewegung zur Verwendung inklusiver Terminologie in diesen kommerziellen und Open-Source-Datenbank-Engines.

Konfiguration der Arbeitsstation

Befolge die "Allgemeinen Schritte zur Einrichtung der Workstation für CLI-Rezepte", um deine Konfiguration zu überprüfen und die erforderlichen Umgebungsvariablen einzurichten. Anschließend klonst du das Code-Repository des Kapitels:

git clone https://github.com/AWSCookbook/Databases
Warnung

Bei einigen Schritten in diesem Kapitel erstellst du Passwörter und speicherst sie vorübergehend als Umgebungsvariablen, um sie bei späteren Schritten zu verwenden. Vergewissere dich, dass du die Umgebungsvariablen nach Abschluss des Rezepts durch die Bereinigungsschritte zurücksetzt. Wir verwenden diesen Ansatz, weil er einfach zu verstehen ist. In Produktionsumgebungen sollte eine sicherere Methode (wie die in Rezept 1.8) verwendet werden.

4.1 Erstellen einer Amazon Aurora Serverless PostgreSQL Datenbank

Problem

Du hast eine Webanwendung, die unvorhersehbare Anfragen erhält, die eine Speicherung in einer relationalen Datenbank erfordern. Du brauchst eine Datenbanklösung, die mit der Nutzung skalieren kann und kostengünstig ist. Du möchtest eine Lösung entwickeln, die einen geringen Betriebsaufwand hat und mit deiner bestehenden PostgreSQL-basierten Anwendung kompatibel ist.

Lösung

Konfiguriere und erstelle einen Aurora Serverless Datenbank-Cluster mit einem komplexen Passwort. Wende dann eine angepasste Skalierungskonfiguration an und aktiviere die automatische Pause nach Inaktivität. Die Skalierungsaktivität als Reaktion auf die Richtlinie ist in Abbildung 4-1 dargestellt.

Aurora Serverless cluster scaling compute
Abbildung 4-1. Aurora Serverless-Cluster skaliert die Berechnungen

Voraussetzungen

  • VPC mit isolierten Subnetzen in zwei AZs und zugehörigen Routentabellen erstellt.

  • EC2-Instanz eingerichtet. Du brauchst die Möglichkeit, dich mit dieser Instanz zu verbinden, um zu testen.

Vorbereitung

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Steps

  1. Verwende AWS Secrets Manager, um ein komplexes Passwort zu erstellen:

    ADMIN_PASSWORD=$(aws secretsmanager get-random-password \
        --exclude-punctuation \
        --password-length 41 --require-each-included-type \
        --output text \
        --query RandomPassword)
    Hinweis

    Wir schließen Satzzeichen aus dem Passwort, das wir erstellen, aus, weil PostgreSQL sie nicht unterstützt. Siehe die Tabelle"Naming Constraints in Amazon RDS".

  2. Erstelle eine Datenbank-Subnetzgruppe, die die für den Cluster zu verwendenden VPC-Subnetze angibt. Datenbank-Subnetzgruppen vereinfachen die Platzierung von RDS Elastic Network Interfaces (ENIs):

    aws rds create-db-subnet-group \
        --db-subnet-group-name awscookbook401subnetgroup \
        --db-subnet-group-description "AWSCookbook401 subnet group" \
        --subnet-ids $SUBNET_ID_1 $SUBNET_ID_2

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "DBSubnetGroup": {
      "DBSubnetGroupName": "awscookbook402subnetgroup",
      "DBSubnetGroupDescription": "AWSCookbook401 subnet group",
      "VpcId": "vpc-<<VPCID>>",
      "SubnetGroupStatus": "Complete",
      "Subnets": [
        {
        "SubnetIdentifier": "subnet-<<SUBNETID>>",
        "SubnetAvailabilityZone": {
          "Name": "us-east-1b"
        },
        "SubnetOutpost": {},
        "SubnetStatus": "Active"
        },
    ...
  3. Erstelle eine VPC-Sicherheitsgruppe für die Datenbank:

    DB_SECURITY_GROUP_ID=$(aws ec2 create-security-group \
        --group-name AWSCookbook401sg \
        --description "Aurora Serverless Security Group" \
        --vpc-id $VPC_ID --output text --query GroupId)
  4. Erstelle einen Datenbank-Cluster, indem du und engine-mode von serverless angibst:

    aws rds create-db-cluster \
        --db-cluster-identifier awscookbook401dbcluster \
        --engine aurora-postgresql \
        --engine-mode serverless \
        --engine-version 10.14 \
        --master-username dbadmin \
        --master-user-password $ADMIN_PASSWORD \
        --db-subnet-group-name awscookbook401subnetgroup \
        --vpc-security-group-ids $DB_SECURITY_GROUP_ID

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "DBCluster": {
      "AllocatedStorage": 1,
      "AvailabilityZones": [
        "us-east-1f",
        "us-east-1b",
        "us-east-1a"
      ],
      "BackupRetentionPeriod": 1,
      "DBClusterIdentifier": "awscookbook401dbcluster",
      "DBClusterParameterGroup": "default.aurora-postgresql10",
      "DBSubnetGroup": "awscookbook401subnetgroup",
      "Status": "creating",
    ...
  5. Warte, bis der Status "verfügbar" angezeigt wird; das kann ein paar Augenblicke dauern:

    aws rds describe-db-clusters \
        --db-cluster-identifier awscookbook401dbcluster \
        --output text --query DBClusters[0].Status
  6. Ändere die Datenbank so, dass automatisch mit neuen Autoscaling-Kapazitätszielen (8 min, 16 max) skaliert und aktiviere AutoPause nach fünf Minuten Inaktivität:

    aws rds modify-db-cluster \
        --db-cluster-identifier awscookbook401dbcluster --scaling-configuration \
        MinCapacity=8,MaxCapacity=16,SecondsUntilAutoPause=300,TimeoutAction='ForceApplyCapacityChange',AutoPause=true

    Du solltest auf eine ähnliche Ausgabe sehen, wie in Schritt 4.

    Hinweis

    In der Praxis kann es sein, dass du einen anderen AutoPause Wert verwenden möchtest. Um herauszufinden, welcher Wert für dich geeignet ist, solltest du deinen Leistungsbedarf und die Preise von Aurora bewerten.

    Warte mindestens fünf Minuten und beobachte, ob die Kapazität der Datenbank auf 0 gesunken ist:

    aws rds describe-db-clusters \
        --db-cluster-identifier awscookbook401dbcluster \
        --output text --query DBClusters[0].Capacity
    Hinweis

    Die Funktion AutoPause setzt die Kapazität des Clusters nach Inaktivität automatisch auf 0. Wenn die Datenbankaktivität wieder aufgenommen wird (z. B. durch eine Abfrage oder eine Verbindung), wird der Kapazitätswert automatisch auf den von dir konfigurierten Mindestwert für die Skalierung der Kapazität gesetzt.

  7. Erteile der Sicherheitsgruppe deiner EC2-Instanz Zugriff auf den Standard-PostgreSQL-Port:

    aws ec2 authorize-security-group-ingress \
        --protocol tcp --port 5432 \
        --source-group $INSTANCE_SG \
        --group-id $DB_SECURITY_GROUP_ID

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "Return": true,
      "SecurityGroupRules": [
      {
        "SecurityGroupRuleId": "sgr-<<ID>>",
        "GroupId": "sg-<<ID>>",
        "GroupOwnerId": "111111111111",
        "IsEgress": false,
        "IpProtocol": "tcp",
        "FromPort": 5432,
        "ToPort": 5432,
        "ReferencedGroupInfo": {
        "GroupId": "sg-<<ID>>"
        }
        }
      ]
    }

Validierungsprüfungen

Liste den Endpunkt für den RDS-Cluster auf:

aws rds describe-db-clusters \
    --db-cluster-identifier awscookbook401dbcluster \
    --output text --query DBClusters[0].Endpoint

Du solltest etwas Ähnliches wie das hier sehen:

awscookbook401dbcluster.cluster-<<unique>>.us-east-1.rds.amazonaws.com

Erfahre das Passwort für deinen RDS-Cluster:

echo $ADMIN_PASSWORD

Verbinde dich mit der EC2-Instanz über den SSM Session Manager (siehe Rezept 1.6):

aws ssm start-session --target $INSTANCE_ID

Installiere das PostgreSQL-Paket, damit du den Befehl psql verwenden kannst, um dich mit der Datenbank zu verbinden:

sudo yum -y install postgresql

Verbinde dich mit der Datenbank. Das kann einen Moment dauern, da die Kapazität der Datenbank von 0 aufwärts skaliert wird. Du musst das Passwort (das zuvor ausgegeben wurde) kopieren und einfügen:

psql -h $HOST_NAME -U dbadmin -W -d postgres

Hier ist ein Beispiel für die Verbindung zu einer Datenbank mit dem Befehl psql:

sh-4.2$ psql -h awscookbook401dbcluster.cluster-<<unique>>.us-east-1.rds.amazonaws.com -U dbadmin -W -d postgres
Password for user dbadmin:(paste in the password)

Beende psql:

\q

Beende die Session Manager-Sitzung:

exit

Überprüfe die Kapazität des Clusters erneut , um zu sehen, ob die Datenbank auf den von dir konfigurierten Mindestwert hochskaliert wurde:

aws rds describe-db-clusters \
    --db-cluster-identifier awscookbook401dbcluster \
    --output text --query DBClusters[0].Capacity

Aufräumen

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Tipp

Standardmäßig wird beim Löschen eines RDS-Clusters ein letzter Snapshot als Sicherheitsmechanismus erstellt. Wir haben uns dafür entschieden, dieses Verhalten zu überspringen, indem wir die Option --skip-final-snapshot hinzugefügt haben, um sicherzustellen, dass dir keine Kosten für die Speicherung des Snapshots in deinem AWS-Konto entstehen. In einem realen Szenario würdest du den Snapshot wahrscheinlich für eine gewisse Zeit aufbewahren wollen, falls du die bestehende Datenbank anhand des Snapshots neu erstellen musst.

Diskussion

Der Cluster skaliert die Kapazität automatisch, um den Anforderungen deiner Nutzung gerecht zu werden. Wenn du MaxCapacity=16 einstellst, wird die Kapazität nach oben hin begrenzt, um ein Ausufern der Nutzung und unerwartete Kosten zu verhindern. Der Cluster setzt seine Kapazität auf 0, wenn keine Verbindung oder Aktivität festgestellt wird. Dies wird ausgelöst, wenn der Wert SecondsUntilAutoPause erreicht wird.

Wenn du AutoPause=true für deinen Cluster aktivierst, zahlst du nur für die zugrunde liegende Speicherung während der Inaktivitätszeiten. Die Standard- (und Mindest-) "Inaktivitätszeit" beträgt fünf Minuten. Wenn du dich mit einem angehaltenen Cluster verbindest, wird die Kapazität bis auf MinCapacity.

Warnung

Nicht alle Datenbank-Engines und Versionen sind mit der Serverless-Engine verfügbar. Zum Zeitpunkt der Erstellung dieses Artikels steht in den Aurora FAQ, dass Aurora Serverless derzeit für Aurora mit MySQL 5.6-Kompatibilität und für Aurora mit PostgreSQL 10.7+-Kompatibilität verfügbar ist.

Im Benutzerhandbuch heißt es, dass die Skalierung von Aurora Serverless in Kapazitätseinheiten (CUs) gemessen wird, die den für deinen Cluster reservierten Rechen- und Speicherressourcen entsprechen. Diese Fähigkeit eignet sich für viele Workloads und Anwendungsfälle, von der Entwicklung über Batch-basierte Workloads bis hin zu Produktions-Workloads, bei denen der Datenverkehr unvorhersehbar ist und die Kosten einer möglichen Überbelegung ein Problem darstellen. Da du keine Basisnutzungsmuster berechnen musst, kannst du schnell mit der Entwicklung beginnen, und der Cluster reagiert automatisch auf die Nachfrage, die deine Anwendung benötigt.

Wenn du derzeit einen Cluster mit "bereitgestellter" Kapazität auf Amazon RDS verwendest und Aurora Serverless nutzen möchtest, kannst du einen Snapshot deiner aktuellen Datenbank erstellen und ihn über die AWS-Konsole oder die Befehlszeile wiederherstellen, um eine Migration durchzuführen. Wenn sich deine aktuelle Datenbank nicht auf RDS befindet, kannst du die Dump- und Wiederherstellungsfunktionen deiner Datenbank-Engine nutzen oder den AWS Database Migration Service (AWS DMS) verwenden, um zu RDS zu migrieren.

Hinweis

Zum Zeitpunkt der Erstellung dieses Artikels befindet sich Amazon Aurora Serverless v2 in der Vorschau.

Im Benutzerhandbuch wird erwähnt, dass Aurora Serverless auf der bestehenden Aurora-Plattform aufbaut, die die zugrundeliegende Speicherung deiner Datenbank sechsfach über drei Availability Zones repliziert. Auch wenn diese Replikation ein Vorteil für die Ausfallsicherheit ist, solltest du dennoch automatische Backups für deine Datenbank verwenden, um dich vor Betriebsfehlern zu schützen. In Aurora Serverless sind automatische Backups standardmäßig aktiviert, und die Aufbewahrungszeit für Backups kann bei Bedarf auf bis zu 35 Tage erhöht werden.

Hinweis

Laut Dokumentation wird der Datenbank-Cluster mit einem Snapshot gesichert, wenn er länger als sieben Tage inaktiv war. In diesem Fall wird der Datenbank-Cluster wiederhergestellt, wenn eine Verbindung zu ihm hergestellt werden soll.

Herausforderung

Ändere die maximale Kapazität auf 64 und die Leerlaufzeit auf 10 Minuten für den Datenbankcluster.

Siehe auch

Rezept 4.2

Rezept 4.7

4.2 Verwendung der IAM-Authentifizierung mit einer RDS-Datenbank

Problem

Du hast einen Server, der sich mit einem Passwort mit einer Datenbank verbindet und möchtest stattdessen rotierende, temporäre Anmeldedaten verwenden.

Lösung

Zuerst aktivierst du die IAM-Authentifizierung für deine Datenbank. Dann konfigurierst du die IAM-Berechtigungen für die EC2-Instanz. Schließlich erstellst du einen neuen Benutzer für die Datenbank, rufst das IAM-Authentifizierungstoken ab und überprüfst die Verbindung (siehe Abbildung 4-2).

IAM authentication from an EC2 instance to an RDS database
Abbildung 4-2. IAM-Authentifizierung von einer EC2-Instanz zu einer RDS-Datenbank

Voraussetzungen

  • VPC mit isolierten Subnetzen in zwei AZs und zugehörigen Routentabellen erstellt.

  • Eine RDS-MySQL-Instanz.

  • EC2-Instanz eingerichtet. Du brauchst die Möglichkeit, dich mit dieser Instanz zu verbinden, um MySQL zu konfigurieren und zu testen.

Vorbereitung

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Steps

  1. Aktiviere die IAM-Datenbankauthentifizierung auf der RDS-Datenbankinstanz:

    aws rds modify-db-instance \
        --db-instance-identifier $RDS_DATABASE_ID \
        --enable-iam-database-authentication \
        --apply-immediately

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "DBInstance": {
      "DBInstanceIdentifier": "awscookbookrecipe402",
      "DBInstanceClass": "db.m5.large",
      "Engine": "mysql",
      "DBInstanceStatus": "available",
      "MasterUsername": "admin",
      "DBName": "AWSCookbookRecipe402",
      "Endpoint": {
        "Address": "awscookbookrecipe402.<<ID>>.us-east-1.rds.amazonaws.com",
        "Port": 3306,
        "HostedZoneId": "<<ID>>"
      },
    ...
    Warnung

    Die IAM-Datenbankauthentifizierung ist nur für die in diesem AWS-Artikel aufgeführten Datenbank-Engines verfügbar.

  2. Ruft die Ressourcen-ID der RDS-Datenbankinstanz ab:

    DB_RESOURCE_ID=$(aws rds describe-db-instances \
        --query \
        'DBInstances[?DBName==`AWSCookbookRecipe402`].DbiResourceId' \
        --output text)
  3. Erstelle eine Datei namens policy.json mit folgendem Inhalt (eine policy-template.json-Datei wird im Repository bereitgestellt):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "rds-db:connect"
          ],
          "Resource": [
            "arn:aws:rds-db:AWS_REGION:AWS_ACCOUNT_ID:dbuser:DBResourceId/db_user"
          ]
        }
      ]
    }
    Hinweis

    Im vorangegangenen Beispiel muss db_user mit dem Namen des Benutzers in der Datenbank übereinstimmen, dem wir die Verbindung erlauben möchten.

  4. Ersetze die Werte in der Vorlagendatei mit dem Befehl sed durch Umgebungsvariablen, die du gesetzt hast:

    sed -e "s/AWS_ACCOUNT_ID/${AWS_ACCOUNT_ID}/g" \
        -e "s|AWS_REGION|${AWS_REGION}|g" \
        -e "s|DBResourceId|${DB_RESOURCE_ID}|g" \
        policy-template.json > policy.json
  5. Erstelle eine IAM-Richtlinie unter Verwendung der soeben erstellten Datei:

    aws iam create-policy --policy-name AWSCookbook402EC2RDSPolicy \
        --policy-document file://policy.json

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "Policy": {
      "PolicyName": "AWSCookbook402EC2RDSPolicy",
      "PolicyId": "<<ID>>",
      "Arn": "arn:aws:iam::111111111111:policy/AWSCookbook402EC2RDSPolicy",
      "Path": "/",
      "DefaultVersionId": "v1",
      "AttachmentCount": 0,
      "PermissionsBoundaryUsageCount": 0,
      "IsAttachable": true,
      "CreateDate": "2021-09-21T21:18:54+00:00",
      "UpdateDate": "2021-09-21T21:18:54+00:00"
      }
    }
  6. Hänge die IAM-Richtlinie AWSCookbook402EC2RDSPolicy an die IAM-Rolle an, die der EC2 verwendet:

    aws iam attach-role-policy --role-name $INSTANCE_ROLE_NAME \
        --policy-arn arn:aws:iam::$AWS_ACCOUNT_ID:policy/AWSCookbook402EC2RDSPolicy
  7. Rufe das RDS-Administrator-Passwort aus dem Secrets Manager ab:

    RDS_ADMIN_PASSWORD=$(aws secretsmanager get-secret-value \
        --secret-id $RDS_SECRET_ARN \
        --query SecretString | jq -r | jq .password | tr -d '"')
  8. Text ausgeben, damit du ihn später verwenden kannst, wenn du dich mit der EC2-Instanz verbindest.

    Liste den Endpunkt für den RDS-Cluster auf:

    echo $RDS_ENDPOINT

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    awscookbookrecipe402.<<unique>>.us-east-1.rds.amazonaws.com

    Gib das Passwort für den RDS-Cluster an:

    echo $RDS_ADMIN_PASSWORD
  9. Verbinde dich mit der EC2-Instanz über den SSM Session Manager (siehe Rezept 1.6):

    aws ssm start-session --target $INSTANCE_ID
  10. Installiere MySQL:

    sudo yum -y install mysql
  11. Verbinde dich mit der Datenbank. Du musst das Passwort und den Hostnamen (die in Schritt 7 und 8 ausgegeben wurden) kopieren und einfügen:

    mysql -u admin -p$DB_ADMIN_PASSWORD -h $RDS_ENDPOINT

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    Welcome to the MariaDB monitor. Commands end with ; or \g.
    Your MySQL connection id is 18
    Server version: 8.0.23 Source distribution
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    MySQL [(none)]>
    Hinweis

    Im Befehl mysql in Schritt 11 gibt es kein Leerzeichen zwischen dem -p Flag und dem ersten Zeichen des Passworts.

  12. Erstelle einen neuen Datenbankbenutzer, der mit der IAM-Authentifizierung verknüpft wird:

    CREATE USER db_user@'%' IDENTIFIED WITH AWSAuthenticationPlugin as 'RDS';
    GRANT SELECT ON *.* TO 'db_user'@'%';

    Für beide Befehle in Schritt 12 solltest du eine ähnliche Ausgabe wie die folgende sehen:

    Query OK, 0 rows affected (0.01 sec)
  13. Beende jetzt die Eingabeaufforderung mysql:

    quit

Validierungsprüfungen

Lade die von Amazon bereitgestellte RDS Root CA (Zertifizierungsstelle) aus dem S3-Bucket rds-downloads herunter, während du dich in der EC2-Instanz befindest:

sudo wget https://s3.amazonaws.com/rds-downloads/rds-ca-2019-root.pem

Lege die Region fest, indem du den Wert aus den Metadaten der Instanz nimmst:

export AWS_DEFAULT_REGION=$(curl --silent http://169.254.169.254/latest/dynamic/instance-identity/document \
| awk -F'"' ' /region/ {print $4}')

Erstelle das RDS-Authentifizierungstoken und speichere es als Variable. Du musst den Hostnamen (der in Schritt 8 ausgegeben wurde) kopieren und einfügen:

TOKEN="$(aws rds generate-db-auth-token --hostname $RDS_ENDPOINT --port 3306 --username db_user)"

Verbinde dich mit der Datenbank, indem du das RDS-Authentifizierungstoken mit dem neuen db_user verwendest. Du musst den Hostnamen (der in Schritt 8 ausgegeben wurde) kopieren und einfügen:

mysql --host=$RDS_ENDPOINT --port=3306 \
    --ssl-ca=rds-ca-2019-root.pem \
--user=db_user --password=$TOKEN

Führe eine SELECT-Abfrage in der Eingabeaufforderung mysql aus, um zu überprüfen, ob dieser Benutzer über die von dir angewendete Berechtigung SELECT *.* verfügt:

SELECT user FROM mysql.user;

Du solltest eine ähnliche Ausgabe wie die folgende sehen:

MySQL [(none)]> SELECT user FROM mysql.user;
+------------------+
| user             |
+------------------+
| admin            |
| db_user          |
| mysql.infoschema |
| mysql.session    |
| mysql.sys        |
| rdsadmin         |
+------------------+
6 rows in set (0.00 sec)

Beende die Eingabeaufforderung mysql:

quit

Beende die Session Manager-Sitzung:

exit

Aufräumen

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Diskussion

Anstelle eines Passworts in deinem MySQL-Verbindungsstring hast du ein Token abgerufen und verwendet, das mit der IAM-Rolle der EC2-Instanz verknüpft ist. In der Dokumentation für IAM steht, dass dieses Token 15 Minuten lang gültig ist. Wenn du eine Anwendung auf dieser EC2-Instanz installierst, kann der Code dieses Token mithilfe des AWS SDK regelmäßig aktualisieren. Es ist nicht nötig, die Passwörter für deinen Datenbankbenutzer zu ändern, da das alte Token nach 15 Minuten ungültig wird.

Du kannst mehrere Datenbankbenutzer erstellen, die mit bestimmten Berechtigungen verknüpft sind, damit deine Anwendung unterschiedliche Zugriffsebenen auf deine Datenbank hat. Die Berechtigungen werden in der Datenbank vergeben, nicht in den IAM-Berechtigungen. IAM steuert die Aktion db-connect für den jeweiligen Benutzer. Mit dieser IAM-Aktion kann das Authentifizierungs-Token abgerufen werden. Dieser Benutzername wird von IAM auf die GRANT(s) abgebildet, indem in der Datenbank derselbe Benutzername verwendet wird wie in der policy.json-Datei:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "rds-db:connect"
      ],
      "Resource": [
        "arn:aws:rds-db:AWS_REGION::dbuser:DBResourceId/db_user"
      ]
    }
  ]
}

In diesem Rezept hast du auch die Verschlüsselung bei der Übertragung aktiviert, indem du das SSL-Zertifikatspaket, das du auf die EC2-Instanz heruntergeladen hast, in deinem Datenbankverbindungsbefehl angegeben hast. Dadurch wird die Verbindung zwischen deiner Anwendung und deiner Datenbank verschlüsselt. Dies ist eine gute Sicherheitspraxis und wird oft für viele Compliance-Standards gefordert. In der Verbindungszeichenfolge, die du für die Verbindung mit dem IAM-Authentifizierungstoken verwendet hast, wurde ein SSL-Zertifikat als einer der Verbindungsparameter angegeben. Das Paket der Zertifizierungsstelle kannst du von AWS herunterladen und in deiner Anwendung verwenden.

Herausforderung

Versuche, dich von einer Lambda-Funktion mit IAM-Authentifizierung mit der Datenbank zu verbinden. Wir haben eine lambda_function.py-Datei im Repository bereitgestellt, die dir den Einstieg erleichtert.

4.3 Nutzung des RDS Proxy für Datenbankverbindungen von Lambda

Problem

Du hast eine serverlose Funktion, die auf eine relationale Datenbank zugreift und du musst Connection Pooling implementieren, um die Anzahl der Datenbankverbindungen zu minimieren und die Leistung zu verbessern.

Lösung

Erstelle einen RDS-Proxy, verknüpfe ihn mit deiner RDS-MySQL-Datenbank und konfiguriere deinen Lambda so, dass er sich mit dem Proxy verbindet, anstatt direkt auf die Datenbank zuzugreifen (siehe Abbildung 4-3).

Lambda connection path to database via RDS Proxy
Abbildung 4-3. Lambda-Verbindungspfad zur Datenbank über RDS-Proxy

Voraussetzungen

  • VPC mit isolierten Subnetzen in zwei AZs und zugehörigen Routentabellen erstellt

  • Eine RDS-MySQL-Instanz

  • Eine Lambda-Funktion, die du mit deiner RDS-Datenbank verbinden möchtest

Vorbereitung

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Steps

  1. Erstelle eine Datei namens assume-role-policy.json mit folgendem Inhalt (die Datei wird im Repository bereitgestellt):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "rds.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
  2. Erstelle eine IAM-Rolle für den RDS-Proxy mit der Datei assume-role-policy.json:

    aws iam create-role --assume-role-policy-document \
        file://assume-role-policy.json --role-name AWSCookbook403RDSProxy

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "Role": {
      "Path": "/",
      "RoleName": "AWSCookbook403RDSProxy",
      "RoleId": "<<ID>>",
      "Arn": "arn:aws:iam::111111111111:role/AWSCookbook403RDSProxy",
      "CreateDate": "2021-09-21T22:33:57+00:00",
      "AssumeRolePolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "rds.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
        ]
      }
      }
    }
  3. Erstelle eine Sicherheitsgruppe für , die vom RDS-Proxy verwendet wird:

    RDS_PROXY_SG_ID=$(aws ec2 create-security-group \
        --group-name AWSCookbook403RDSProxySG \
        --description "Lambda Security Group" --vpc-id $VPC_ID \
        --output text --query GroupId)
  4. Erstelle den RDS-Proxy. Dies wird ein paar Augenblicke dauern:

    RDS_PROXY_ENDPOINT_ARN=$(aws rds create-db-proxy \
        --db-proxy-name $DB_NAME \
        --engine-family MYSQL \
        --auth '{
                "AuthScheme": "SECRETS",
                "SecretArn": "'"$RDS_SECRET_ARN"'",
                "IAMAuth": "REQUIRED"
              }' \
        --role-arn arn:aws:iam::$AWS_ACCOUNT_ID:role/AWSCookbook403RDSProxy \
        --vpc-subnet-ids $ISOLATED_SUBNETS \
        --vpc-security-group-ids $RDS_PROXY_SG_ID \
        --require-tls --output text \
        --query DBProxy.DBProxyArn)

    Warte darauf, dass der RDS-Proxy verfügbar wird:

    aws rds describe-db-proxies \
        --db-proxy-name $DB_NAME \
        --query DBProxies[0].Status \
        --output text
  5. Rufe die RDS_PROXY_ENDPOINT ab:

    RDS_PROXY_ENDPOINT=$(aws rds describe-db-proxies \
        --db-proxy-name $DB_NAME \
        --query DBProxies[0].Endpoint \
        --output text)
  6. Als Nächstes brauchst du eine IAM-Richtlinie, die es der Lambda-Funktion erlaubt, IAM-Authentifizierungstoken zu erzeugen. Erstelle eine Datei namens template-policy.json mit folgendem Inhalt (die Datei wird im Repository bereitgestellt):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "rds-db:connect"
          ],
          "Resource": [
            "arn:aws:rds-db:AWS_REGION:AWS_ACCOUNT_ID:dbuser:RDSProxyID/admin"
          ]
        }
      ]
    }
  7. Trenne die Proxy-ID von der ARN des RDS-Proxy-Endpunkts. Die Proxy-ID wird für die Konfiguration der IAM-Richtlinien in den folgenden Schritten benötigt:

    RDS_PROXY_ID=$(echo $RDS_PROXY_ENDPOINT_ARN | awk -F: '{ print $7} ')
  8. Ersetze die Werte in der Vorlagendatei mit dem Befehl sed durch Umgebungsvariablen, die du gesetzt hast:

    sed -e "s/AWS_ACCOUNT_ID/${AWS_ACCOUNT_ID}/g" \
        -e "s|AWS_REGION|${AWS_REGION}|g" \
        -e "s|RDSProxyID|${RDS_PROXY_ID}|g" \
    policy-template.json > policy.json
  9. Erstelle eine IAM-Richtlinie unter Verwendung der soeben erstellten Datei:

    aws iam create-policy --policy-name AWSCookbook403RdsIamPolicy \
        --policy-document file://policy.json

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "Policy": {
      "PolicyName": "AWSCookbook403RdsIamPolicy",
      "PolicyId": "<<Id>>",
      "Arn": "arn:aws:iam::111111111111:policy/AWSCookbook403RdsIamPolicy",
      "Path": "/",
      "DefaultVersionId": "v1",
      "AttachmentCount": 0,
      "PermissionsBoundaryUsageCount": 0,
      "IsAttachable": true,
      "CreateDate": "2021-09-21T22:50:24+00:00",
      "UpdateDate": "2021-09-21T22:50:24+00:00"
      }
    }
  10. Hänge die Richtlinie an die Rolle der DBAppFunction Lambda-Funktion an:

    aws iam attach-role-policy --role-name $DB_APP_FUNCTION_ROLE_NAME \
        --policy-arn arn:aws:iam::$AWS_ACCOUNT_ID:policy/AWSCookbook403RdsIamPolicy

    Mit diesem Befehl kannst du prüfen, wann der Proxy in den Status "verfügbar" wechselt und dann fortfahren:

    aws rds describe-db-proxies --db-proxy-name $DB_NAME \
        --query DBProxies[0].Status \
        --output text
  11. Verbinde die Richtlinie SecretsManagerReadWrite mit der Rolle des RDS-Proxys:

    aws iam attach-role-policy --role-name AWSCookbook403RDSProxy \
        --policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite
    Tipp

    In einem Produktionsszenario solltest du diese Berechtigung auf die minimalen geheimen Ressourcen einschränken, auf die deine Anwendung zugreifen muss, anstatt SecretsManagerReadWrite zu gewähren, die Lese- und Schreibzugriff auf alle Geheimnisse erlaubt.

  12. Füge der Sicherheitsgruppe der RDS-Instanz eine Ingress-Regel hinzu, die den Zugriff auf den TCP-Port 3306 (den Standard-TCP-Port der MySQL-Engine) von der RDS-Proxy-Sicherheitsgruppe aus erlaubt:

    aws ec2 authorize-security-group-ingress \
        --protocol tcp --port 3306 \
        --source-group $RDS_PROXY_SG_ID \
        --group-id $RDS_SECURITY_GROUP

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "Return": true,
      "SecurityGroupRules": [
      {
        "SecurityGroupRuleId": "sgr-<<ID>>",
        "GroupId": "sg-<<ID>>",
        "GroupOwnerId": "111111111111",
        "IsEgress": false,
        "IpProtocol": "tcp",
        "FromPort": 3306,
        "ToPort": 3306,
        "ReferencedGroupInfo": {
        "GroupId": "sg-<<ID>>"
        }
      }
      ]
    }
    Hinweis

    Sicherheitsgruppen können auf andere Sicherheitsgruppen verweisen. Aufgrund der dynamischen IP-Adressen innerhalb von VPCs gilt dies als die beste Möglichkeit, Zugang zu gewähren, ohne die Sicherheitsgruppe zu weit zu öffnen. Weitere Informationen findest du in Rezept 2.5.

  13. Registriere die Ziele beim RDS-Proxy:

    aws rds register-db-proxy-targets \
        --db-proxy-name $DB_NAME \
        --db-instance-identifiers $RDS_DATABASE_ID

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "DBProxyTargets": [
      {
        "Endpoint": "awscookbook403db.<<ID>>.us-east-1.rds.amazonaws.com",
        "RdsResourceId": "awscookbook403db",
        "Port": 3306,
        "Type": "RDS_INSTANCE",
        "TargetHealth": {
        "State": "REGISTERING"
        }
      }
      ]
    }

    Überprüfe den Status der Zielregistrierung mit diesem Befehl. Warte, bis der Status AVAILABLE erreicht:

    aws rds describe-db-proxy-targets \
        --db-proxy-name awscookbookrecipe403 \
        --query Targets[0].TargetHealth.State \
        --output text
  14. Füge eine Ingress Regel zur RDS Proxy Sicherheitsgruppe hinzu, die den Zugriff auf TCP Port 3306 von der Sicherheitsgruppe der Lambda App Funktion erlaubt:

    aws ec2 authorize-security-group-ingress \
        --protocol tcp --port 3306 \
        --source-group $DB_APP_FUNCTION_SG_ID \
        --group-id $RDS_PROXY_SG_ID

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "Return": true,
      "SecurityGroupRules": [
      {
        "SecurityGroupRuleId": "sgr-<<ID>>",
        "GroupId": "sg-<<ID>>",
        "GroupOwnerId": "111111111111",
        "IsEgress": false,
        "IpProtocol": "tcp",
        "FromPort": 3306,
        "ToPort": 3306,
        "ReferencedGroupInfo": {
        "GroupId": "sg-<<ID>>"
        }
      }
      ]
    }
  15. Ändere die Lambda-Funktion so, dass sie jetzt den RDS-Proxy-Endpunkt als DB_HOST verwendet, anstatt sich direkt mit der Datenbank zu verbinden:

    aws lambda update-function-configuration \
        --function-name $DB_APP_FUNCTION_NAME \
        --environment Variables={DB_HOST=$RDS_PROXY_ENDPOINT}

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "FunctionName": "cdk-aws-cookbook-403-LambdaApp<<ID>>",
      "FunctionArn": "arn:aws:lambda:us-east-1:111111111111:function:cdk-aws-cookbook-403-LambdaApp<<ID>>",
      "Runtime": "python3.8",
      "Role": "arn:aws:iam::111111111111:role/cdk-aws-cookbook-403-LambdaAppServiceRole<<ID>>",
      "Handler": "lambda_function.lambda_handler",
      "CodeSize": 665,
      "Description": "",
      "Timeout": 600,
      "MemorySize": 1024,
    ...

Validierungsprüfungen

Führe die Lambda-Funktion mit diesem Befehl aus, um zu überprüfen, ob sich die Funktion über deinen RDS-Proxy mit RDS verbinden kann:

aws lambda invoke \
    --function-name $DB_APP_FUNCTION_NAME \
    response.json && cat response.json

Du solltest eine ähnliche Ausgabe wie die folgende sehen:

{
  "StatusCode": 200,
  "ExecutedVersion": "$LATEST"
}
"Successfully connected to RDS via RDS Proxy!"

Aufräumen

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Diskussion

Das Pooling von Verbindungen ist wichtig, wenn du Lambdas mit RDS verwendest. Da die Funktion je nach Anwendung mit hoher Gleichzeitigkeit und Häufigkeit ausgeführt werden kann, kann die Anzahl der Rohverbindungen zu deiner Datenbank steigen und die Leistung beeinträchtigen. Durch die Verwendung von RDS Proxy zur Verwaltung der Verbindungen zur Datenbank werden weniger Verbindungen zur eigentlichen Datenbank benötigt. Diese Einrichtung erhöht die Leistung und Effizienz.

Ohne RDS Proxy baut eine Lambda-Funktion möglicherweise bei jedem Funktionsaufruf eine neue Verbindung zur Datenbank auf. Dieses Verhalten hängt von der Ausführungsumgebung, den Laufzeiten (Python, NodeJS, Go usw.) und der Art und Weise ab, wie du Verbindungen zur Datenbank aus dem Funktionscode instanziierst. In Fällen mit hoher Funktionsgleichzeitigkeit kann dies zu einer großen Anzahl von TCP-Verbindungen zu deiner Datenbank führen, was die Datenbankleistung verringert und die Latenzzeit erhöht. Laut Dokumentation hilft RDS Proxy bei der Verwaltung der Lambda-Verbindungen, indem er sie als "Pool" verwaltet, so dass RDS Proxy die tatsächlichen Verbindungen zur Datenbank nur bei Bedarf erhöht und den TCP-Overhead an RDS Proxy auslagert, wenn die Gleichzeitigkeit zunimmt.

Die SSL-Verschlüsselung bei der Übertragung wird von RDS Proxy unterstützt, wenn du das von AWS bereitgestellte Zertifikatsbündel in deinen Datenbankverbindungsstring einfügst. RDS Proxy unterstützt MySQL und PostgreSQL RDS-Datenbanken. Eine vollständige Liste aller unterstützten Datenbank-Engines und Versionen findest du in diesem Support-Dokument.

Tipp

Du kannst auch architekten, um mit kurzlebigen Datenbankverbindungen effizient zu arbeiten, indem du die RDS-Daten-API in deiner Anwendung verwendest, die eine von Amazon RDS bereitgestellte REST-API nutzt. Ein Beispiel für die RDS-Daten-API findest du in Rezept 4.8.

Herausforderung

Aktiviere erweiterte Protokollierung für den RDS-Proxy. Dies ist nützlich für die Fehlersuche.

4.4 Verschlüsselung der Speicherung einer bestehenden Amazon RDS for MySQL-Datenbank

Problem

Du musst die Speicherung einer bestehenden Datenbank verschlüsseln.

Lösung

Erstelle ein Replikat von deiner bestehenden Datenbank, mache einen Snapshot des Replikats, kopiere den Snapshot in einen verschlüsselten Snapshot und stelle den verschlüsselten Snapshot in einer neuen verschlüsselten Datenbank wieder her, wie in Abbildung 4-4 gezeigt.

Process of encrypting a RDS database using a snapshot
Abbildung 4-4. Prozess der Verschlüsselung einer RDS-Datenbank mit einem Snapshot

Voraussetzungen

  • VPC mit isolierten Subnetzen in zwei AZs und zugehörigen Routentabellen erstellt

  • Eine RDS-MySQL-Instanz mit einer RDS-Subnetzgruppe

Vorbereitung

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Steps

  1. Vergewissere dich, dass die Speicherung der Datenbank nicht verschlüsselt ist:

    aws rds describe-db-instances \
        --db-instance-identifier $RDS_DATABASE_ID \
        --query DBInstances[0].StorageEncrypted

    Du solltest sehen, dass false ausgegeben wird.

  2. Erstelle einen KMS-Schlüssel, mit dem du später deinen Datenbank-Snapshot verschlüsseln kannst. Speichere die Schlüssel-ID in einer Umgebungsvariablen:

    KEY_ID=$(aws kms create-key \
        --tags TagKey=Name,TagValue=AWSCookbook404RDS \
        --description "AWSCookbook RDS Key" \
        --query KeyMetadata.KeyId \
        --output text)
  3. Erstelle einen Alias, um den Schlüssel, den du erstellt hast, einfach zu referenzieren:

    aws kms create-alias \
        --alias-name alias/awscookbook404 \
        --target-key-id $KEY_ID
  4. Erstelle ein lesendes Replikat deiner bestehenden unverschlüsselten Datenbank:

    aws rds create-db-instance-read-replica \
        --db-instance-identifier awscookbook404db-rep \
        --source-db-instance-identifier $RDS_DATABASE_ID \
        --max-allocated-storage 10

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "DBInstance": {
      "DBInstanceIdentifier": "awscookbook404db-rep",
      "DBInstanceClass": "db.m5.large",
      "Engine": "mysql",
      "DBInstanceStatus": "creating",
      "MasterUsername": "admin",
      "DBName": "AWSCookbookRecipe404",
      "AllocatedStorage": 8,
      "PreferredBackupWindow": "05:51-06:21",
      "BackupRetentionPeriod": 0,
      "DBSecurityGroups": [],
    ...
    Hinweis

    Indem du ein lesendes Replikat erstellst, erlaubst du, dass der Snapshot von diesem erstellt wird und somit die Leistung der primären Datenbank nicht beeinträchtigt.

    Warte darauf, dass die DBInstanceStatus auf "verfügbar" wird:

    aws rds describe-db-instances \
        --db-instance-identifier awscookbook404db-rep \
        --output text --query DBInstances[0].DBInstanceStatus
  5. Mache einen unverschlüsselten Snapshot deines Replikats:

    aws rds create-db-snapshot \
        --db-instance-identifier awscookbook404db-rep \
        --db-snapshot-identifier awscookbook404-snapshot

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "DBSnapshot": {
      "DBSnapshotIdentifier": "awscookbook404-snapshot",
      "DBInstanceIdentifier": "awscookbook404db-rep",
      "Engine": "mysql",
      "AllocatedStorage": 8,
      "Status": "creating",
      "Port": 3306,
      "AvailabilityZone": "us-east-1b",
      "VpcId": "vpc-<<ID>>",
      "InstanceCreateTime": "2021-09-21T22:46:07.785000+00:00",

    Warte darauf, dass die Status des Schnappschusses verfügbar wird:

    aws rds describe-db-snapshots \
        --db-snapshot-identifier awscookbook404-snapshot \
        --output text --query DBSnapshots[0].Status
  6. Kopiere den unverschlüsselten Snapshot in einen neuen Snapshot und verschlüssele dabei deinen KMS-Schlüssel mit :

    aws rds copy-db-snapshot \
    --copy-tags \
    --source-db-snapshot-identifier awscookbook404-snapshot \
    --target-db-snapshot-identifier awscookbook404-snapshot-enc \
    --kms-key-id alias/awscookbook404

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "DBSnapshot": {
      "DBSnapshotIdentifier": "awscookbook404-snapshot-enc",
      "DBInstanceIdentifier": "awscookbook404db-rep",
      "Engine": "mysql",
      "AllocatedStorage": 8,
      "Status": "creating",
      "Port": 3306,
      "AvailabilityZone": "us-east-1b",
      "VpcId": "vpc-<<ID>>",
      "InstanceCreateTime": "2021-09-21T22:46:07.785000+00:00",
      "MasterUsername": "admin",
    ...
    Tipp

    Durch die Angabe eines KMS-Schlüssels mit dem Befehl copy-snapshot wird der kopierte Snapshot verschlüsselt. Die Wiederherstellung eines verschlüsselten Snapshots in einer neuen Datenbank führt zu einer verschlüsselten Datenbank.

    Warte darauf, dass die Status des verschlüsselten Snapshots verfügbar wird:

    aws rds describe-db-snapshots \
        --db-snapshot-identifier awscookbook404-snapshot-enc \
        --output text --query DBSnapshots[0].Status
  7. Stelle den verschlüsselten Snapshot in einer neuen RDS-Instanz wieder her:

    aws rds restore-db-instance-from-db-snapshot \
        --db-subnet-group-name $RDS_SUBNET_GROUP \
        --db-instance-identifier awscookbook404db-enc \
        --db-snapshot-identifier awscookbook404-snapshot-enc

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "DBInstance": {
      "DBInstanceIdentifier": "awscookbook404db-enc",
      "DBInstanceClass": "db.m5.large",
      "Engine": "mysql",
      "DBInstanceStatus": "creating",
      "MasterUsername": "admin",
      "DBName": "AWSCookbookRecipe404",
      "AllocatedStorage": 8,
    ...

Validierungsprüfungen

Warte darauf, dass DBInstanceStatus verfügbar wird:

aws rds describe-db-instances \
    --db-instance-identifier awscookbook404db-enc \
    --output text --query DBInstances[0].DBInstanceStatus

Überprüfe, ob die Speicherung jetzt verschlüsselt ist:

aws rds describe-db-instances \
    --db-instance-identifier awscookbook404db-enc \
    --query DBInstances[0].StorageEncrypted

Du solltest sehen, dass true ausgegeben wird.

Aufräumen

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Diskussion

Wenn du die Schritte abgeschlossen hast, musst du deine Anwendung neu konfigurieren, damit sie auf einen neuen Datenbank-Endpunkt verweist. Um dies mit minimaler Ausfallzeit zu tun, kannst du einen Route 53 DNS-Eintrag konfigurieren, der auf deinen Datenbankendpunkt verweist. Deine Anwendung wird so konfiguriert, dass sie den DNS-Eintrag verwendet. Dann stellst du deinen Datenbankverkehr auf die neue verschlüsselte Datenbank um, indem du den DNS-Eintrag mit dem neuen Datenbank-Endpunkt-DNS aktualisierst.

Die Verschlüsselung im Ruhezustand ist ein Sicherheitsansatz, der im AWS-Modell der geteilten Verantwortung den Endnutzern überlassen wird und oft erforderlich ist, um die Einhaltung gesetzlicher Vorschriften zu erreichen oder aufrechtzuerhalten. Der verschlüsselte Snapshot, den du erstellt hast, kann auch automatisch in eine andere Region kopiert und zu Archivierungs-/Backupzwecken in S3 exportiert werden.

Herausforderung

Erstelle eine neue RDS-Datenbank mit verschlüsselter Speicherung und migriere deine Daten aus deiner bestehenden Datenbank in die neue Datenbank mit AWS DMS, wie in Rezept 4.7 gezeigt.

4.5 Automatisieren der Passwortrotation für RDS-Datenbanken

Problem

Du möchtest automatische Passwortrotation für einen Datenbankbenutzer einführen.

Lösung

Erstelle ein Passwort und platziere es im AWS Secrets Manager. Konfiguriere ein Rotationsintervall für das Geheimnis, das das Passwort enthält. Schließlich erstellst du eine Lambda-Funktion mit dem von AWS bereitgestellten Code und konfigurierst die Funktion so, dass sie die Passwortrotation durchführt. Mit dieser Konfiguration kann die Automatisierung der Kennwortrotation wie in Abbildung 4-5 dargestellt durchgeführt werden.

Secrets Manager Lambda function integration
Abbildung 4-5. Integration der Secrets Manager Lambda-Funktion

Voraussetzungen

  • VPC mit isolierten Subnetzen in zwei AZs und zugehörigen Routentabellen erstellt.

  • MySQL RDS-Instanz und EC2-Instanz sind eingerichtet. Du brauchst die Möglichkeit, dich mit diesen Instanzen zu verbinden, um sie zu testen.

Vorbereitung

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Steps

  1. Verwende den AWS Secrets Manager, um ein Passwort zu erstellen, das den RDS-Anforderungen entspricht:

    RDS_ADMIN_PASSWORD=$(aws secretsmanager get-random-password \
        --exclude-punctuation \
        --password-length 41 --require-each-included-type \
        --output text --query RandomPassword)
    Tipp

    Du kannst die API-Methode GetRandomPassword von Secrets Manager aufrufen, um zufällige Zeichenketten für verschiedene Zwecke zu erzeugen, die über die Passwortgenerierung hinausgehen.

  2. Ändere das Admin-Passwort für deine RDS-Datenbank in das, das du gerade erstellt hast:

    aws rds modify-db-instance \
        --db-instance-identifier $RDS_DATABASE_ID \
        --master-user-password $RDS_ADMIN_PASSWORD \
        --apply-immediately

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "DBInstance": {
      "DBInstanceIdentifier": "awscookbook405db",
      "DBInstanceClass": "db.m5.large",
      "Engine": "mysql",
      "DBInstanceStatus": "available",
      "MasterUsername": "admin",
      "DBName": "AWSCookbookRecipe405",
    ...
  3. Erstelle eine Datei mit folgendem Inhalt: rdscreds-template.json (die Datei wird im Repository bereitgestellt):

    {
      "username": "admin",
      "password": "PASSWORD",
      "engine": "mysql",
      "host": "HOST",
      "port": 3306,
      "dbname": "DBNAME",
      "dbInstanceIdentifier": "DBIDENTIFIER"
    }
  4. Verwende sed, um die Werte in rdscreds-template.json zu ändern und rdscreds.json zu erstellen:

    sed -e "s/AWS_ACCOUNT_ID/${AWS_ACCOUNT_ID}/g" \
        -e "s|PASSWORD|${RDS_ADMIN_PASSWORD}|g" \
        -e "s|HOST|${RdsEndpoint}|g" \
        -e "s|DBNAME|${DbName}|g" \
        -e "s|DBIDENTIFIER|${RdsDatabaseId}|g" \
        rdscreds-template.json > rdscreds.json
  5. Lade den Code für die Lambda-Funktion Rotation aus dem AWS Samples GitHub-Repository herunter:

    wget https://raw.githubusercontent.com/aws-samples/aws-secrets-manager-rotation-
    lambdas/master/SecretsManagerRDSMySQLRotationSingleUser/lambda_function.py
    Hinweis

    AWS stellt in diesem Artikel Informationen und Templates für verschiedene Szenarien der Datenbankrotation bereit.

  6. Komprimiere die Datei, die den Code enthält:

    zip lambda_function.zip lambda_function.py

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

      adding: lambda_function.py (deflated 76%)
  7. Erstelle eine neue Sicherheitsgruppe, die die Lambda-Funktion verwenden soll:

    LAMBDA_SG_ID=$(aws ec2 create-security-group \
        --group-name AWSCookbook405LambdaSG \
        --description "Lambda Security Group" --vpc-id $VPC_ID \
        --output text --query GroupId)
  8. Füge der Sicherheitsgruppe der RDS-Instanzen eine Ingress-Regel hinzu, die den Zugriff auf den TCP-Port 3306 von der Lambda-Sicherheitsgruppe aus erlaubt:

    aws ec2 authorize-security-group-ingress \
        --protocol tcp --port 3306 \
        --source-group $LAMBDA_SG_ID \
        --group-id $RDS_SECURITY_GROUP

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "Return": true,
      "SecurityGroupRules": [
      {
        "SecurityGroupRuleId": "sgr-<<ID>>",
        "GroupId": "sg-<<ID>>",
        "GroupOwnerId": "111111111111",
        "IsEgress": false,
        "IpProtocol": "tcp",
        "FromPort": 3306,
        "ToPort": 3306,
        "ReferencedGroupInfo": {
        "GroupId": "sg-<<ID>>"
        }
      }
      ]
    }
  9. Erstelle eine Datei namens assume-role-policy.json mit folgendem Inhalt (die Datei wird im Repository bereitgestellt):

    {
      "Version": "2012-10-17",
      "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
        "Service": "lambda.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
      }
      ]
    }
  10. Erstelle mit diesem Befehl eine IAM-Rolle mit der Anweisung in der mitgelieferten Datei assume-role-policy.json:

    aws iam create-role --role-name AWSCookbook405Lambda \
        --assume-role-policy-document file://assume-role-policy.json

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "Role": {
      "Path": "/",
      "RoleName": "AWSCookbook405Lambda",
      "RoleId": "<<ID>>",
      "Arn": "arn:aws:iam::111111111111:role/AWSCookbook405Lambda",
      "CreateDate": "2021-09-21T23:01:57+00:00",
      "AssumeRolePolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
    ...
  11. Füge die von IAM verwaltete Richtlinie für AWSLambdaVPCAccess der IAM-Rolle hinzu:

    aws iam attach-role-policy --role-name AWSCookbook405Lambda \
        --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole
  12. Füge die IAM-verwaltete Richtlinie für SecretsManagerReadWrite der IAM-Rolle hinzu:

    aws iam attach-role-policy --role-name AWSCookbook405Lambda \
        --policy-arn arn:aws:iam::aws:policy/SecretsManagerReadWrite
    Tipp

    Die IAM-Rolle, die du mit der Lambda-Funktion verknüpft hast, um das Passwort zu drehen, verwendet die verwaltete Richtlinie SecretsManagerReadWrite. In einem produktiven Szenario solltest du dies einschränken, um die Geheimnisse einzuschränken, mit denen die Lambda-Funktion interagieren kann.

  13. Erstelle die Lambda-Funktion, um die geheime Drehung mithilfe des Codes durchzuführen:

    LAMBDA_ROTATE_ARN=$(aws lambda create-function \
        --function-name AWSCookbook405Lambda \
        --runtime python3.8 \
        --package-type "Zip" \
        --zip-file fileb://lambda_function.zip \
        --handler lambda_function.lambda_handler --publish \
        --environment Variables={SECRETS_MANAGER_ENDPOINT=https://secretsmanager.$AWS_REGION.amazonaws.com} \
        --layers $PyMysqlLambdaLayerArn \
        --role \
        arn:aws:iam::$AWS_ACCOUNT_ID:role/AWSCookbook405Lambda \
        --output text --query FunctionArn \
        --vpc-config SubnetIds=${ISOLATED_SUBNETS},SecurityGroupIds=$LAMBDA_SG_ID)

    Benutze diesen Befehl, um festzustellen, wann die Lambda-Funktion in den aktiven Zustand übergegangen ist:

    aws lambda get-function --function-name $LAMBDA_ROTATE_ARN \
        --output text --query Configuration.State
  14. Füge der Lambda-Funktion eine Berechtigung hinzu, damit sie von Secrets Manager aufgerufen werden kann:

    aws lambda add-permission --function-name $LAMBDA_ROTATE_ARN \
        --action lambda:InvokeFunction --statement-id secretsmanager \
        --principal secretsmanager.amazonaws.com

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "Statement": "{\"Sid\":\"secretsmanager\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"secretsmanager.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:us-east-1:111111111111:function:AWSCookbook405Lambda\"}"
    }
  15. Lege ein eindeutiges Suffix für den geheimen Namen fest, um sicherzustellen, dass du dieses Muster bei Bedarf für weitere automatische Passwortrotationen wiederverwenden kannst:

    AWSCookbook405SecretName=AWSCookbook405Secret-$(aws secretsmanager \
        get-random-password \
        --exclude-punctuation \
        --password-length 6 --require-each-included-type \
        --output text \
        --query RandomPassword)
  16. Erstelle ein Geheimnis im Secrets Manager, um dein Admin-Passwort zu speichern:

    aws secretsmanager create-secret --name $AWSCookbook405SecretName \
        --description "My database secret created with the CLI" \
        --secret-string file://rdscreds.json

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "ARN": "arn:aws:secretsmanager:us-east-1:1111111111111:secret:AWSCookbook405Secret-T4tErs-AlJcLn",
      "Name": "AWSCookbook405Secret-<<Random>>",
      "VersionId": "<<ID>>"
    }
  17. Richte eine automatische Rotation alle 30 Tage ein und gib die Lambda-Funktion an, um die Rotation für das gerade erstellte Geheimnis durchzuführen:

    aws secretsmanager rotate-secret \
        --secret-id $AWSCookbook405SecretName \
        --rotation-rules AutomaticallyAfterDays=30 \
        --rotation-lambda-arn $LAMBDA_ROTATE_ARN

    Du solltest eine ähnliche Ausgabe wie die folgende sehen:

    {
      "ARN": "arn:aws:secretsmanager:us-east-1:1111111111111:secret:AWSCookbook405Secret-<<unique>>",
      "Name": "AWSCookbook405Secret-<<unique>>",
      "VersionId": "<<ID>>"
    }
    Hinweis

    Der Befehl rotate-secret löst eine erste Drehung des Kennworts aus. Im nächsten Schritt wirst du eine weitere Rotation des Passworts auslösen, um zu zeigen, wie du Rotationen bei Bedarf durchführen kannst.

  18. Führe eine weitere Drehung des Geheimnisses durch:

    aws secretsmanager rotate-secret --secret-id $AWSCookbook405SecretName

    Du solltest eine ähnliche Ausgabe wie in Schritt 17 sehen. Beachte, dass V⁠e⁠r⁠s⁠i⁠o⁠n​I⁠d anders aussieht als beim letzten Befehl, was bedeutet, dass das Geheimnis gedreht wurde.

Validierungsprüfungen

Rufe das RDS-Administrator-Passwort aus dem Secrets Manager ab:

RDS_ADMIN_PASSWORD=$(aws secretsmanager get-secret-value --secret-id $AWSCookbook405SecretName --query SecretString | jq -r | jq .password | tr -d '"')

Liste den Endpunkt für den RDS-Cluster auf:

echo $RDS_ENDPOINT

Erfahre das Passwort für deinen RDS-Cluster:

echo $RDS_ADMIN_PASSWORD

Verbinde dich mit der EC2-Instanz über den SSM Session Manager (siehe Rezept 1.6):

aws ssm start-session --target $INSTANCE_ID

Installiere den MySQL-Client:

sudo yum -y install mysql

Verbinde dich mit der Datenbank, um zu überprüfen, ob das zuletzt gedrehte Passwort funktioniert. Du musst das Passwort (das zuvor ausgegeben wurde) kopieren und einfügen:

mysql -u admin -p$password -h $hostname

Führe eine SELECT-Anweisung für die Tabelle mysql.user aus, um die Administratorrechte zu überprüfen:

SELECT user FROM mysql.user;

Du solltest eine ähnliche Ausgabe wie die folgende sehen:

+------------------+
| user             |
+------------------+
| admin            |
| mysql.infoschema |
| mysql.session    |
| mysql.sys        |
| rdsadmin         |
+------------------+
5 rows in set (0.00 sec)

Beende die Eingabeaufforderung mysql:

quit

Beende die Session Manager-Sitzung:

exit

Aufräumen

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Diskussion

Die von AWS bereitgestellte Lambda-Funktion speichert das rotierte Passwort im Secrets Manager. Du kannst deine Anwendung dann so konfigurieren, dass sie Geheimnisse direkt aus dem Secrets Manager abruft; oder die Lambda-Funktion, die du zur Aktualisierung der Secrets Manager-Werte konfiguriert hast, könnte das Passwort auch an einem sicheren Ort deiner Wahl speichern. Du müsstest der Lambda-Funktion zusätzliche Rechte erteilen, um mit dem von dir gewählten sicheren Speicherort zu interagieren, und einen Code hinzufügen, um den neuen Wert dort zu speichern. Mit dieser Methode könntest du auch die Passwörter für die Benutzerkonten von Nicht-Administratoren in der Datenbank ändern, indem du die gleichen Schritte durchführst, nachdem du den/die Benutzer in deiner Datenbank angelegt hast.

Die Lambda-Funktion, die du eingesetzt hast, ist Python-basiert und verbindet sich mit einer MySQL-Engine-kompatiblen Datenbank. In der Lambda-Laufzeitumgebung ist diese Bibliothek nicht standardmäßig enthalten. Deshalb hast du mit dem Befehl aws lambda create-function einen Lambda-Layer angegeben. Diese Schicht ist erforderlich, damit die PyMySQL-Bibliothek für die Funktion in der Lambda-Laufzeitumgebung zur Verfügung steht. Sie wurde als Teil des Vorbereitungsschritts für dich bereitgestellt, als du cdk deploy ausgeführt hast.

Herausforderung

Erstelle eine weitere Lambda-Funktion und eine separate IAM-Rolle. Gewähre dieser neuen Funktion Zugriff auf das gleiche Geheimnis.

Siehe auch

Rezept 5.2

4.6 Automatische Skalierung der bereitgestellten DynamoDB-Tabellenkapazität

Problem

Du hast eine DynamoDB Datenbanktabelle mit einem niedrigen bereitgestellten Durchsatz. Du stellst fest, dass die Last deiner Anwendung variabel ist und du den bereitgestellten Durchsatz je nach Schwankungen der eingehenden Anwendungslast erhöhen oder verringern musst.

Lösung

Konfiguriere die Lese- und Schreibskalierung, indem du ein Skalierungsziel und eine Skalierungsrichtlinie für die Lese- und Schreibkapazität der DynamoDB-Tabelle mithilfe von AWS Application Autoscaling festlegst, wie in Abbildung 4-6 dargestellt.

DynamoDB auto scaling configuration
Abbildung 4-6. Konfiguration der automatischen DynamoDB-Skalierung

Voraussetzung

  • Eine DynamoDB-Tabelle

Vorbereitung

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Steps

  1. Navigiere zum Verzeichnis dieses Rezepts im Chapter Repository:

    cd 406-Auto-Scaling-DynamoDB
  2. Registriere ein ReadCapacityUnits Skalierungsziel für die DynamoDB-Tabelle:

    aws application-autoscaling register-scalable-target \
        --service-namespace dynamodb \
        --resource-id "table/AWSCookbook406" \
        --scalable-dimension "dynamodb:table:ReadCapacityUnits" \
        --min-capacity 5 \
        --max-capacity 10
  3. Registriere ein WriteCapacityUnits Skalierungsziel für die DynamoDB-Tabelle:

    aws application-autoscaling register-scalable-target \
        --service-namespace dynamodb \
        --resource-id "table/AWSCookbook406" \
        --scalable-dimension "dynamodb:table:WriteCapacityUnits" \
        --min-capacity 5 \
        --max-capacity 10
  4. Erstelle eine JSON-Datei mit Skalierungsrichtlinien für die Skalierung der Lesekapazität(read-policy.json im Repository):

    {
      "PredefinedMetricSpecification": {
        "PredefinedMetricType": "DynamoDBReadCapacityUtilization"
      },
      "ScaleOutCooldown": 60,
      "ScaleInCooldown": 60,
      "TargetValue": 50.0
    }
  5. Erstelle eine JSON-Datei mit Skalierungsrichtlinien für die Skalierung der Schreibkapazität(write-policy.json-Datei im Repository):

    {
      "PredefinedMetricSpecification": {
        "PredefinedMetricType": "DynamoDBWriteCapacityUtilization"
      },
      "ScaleOutCooldown": 60,
      "ScaleInCooldown": 60,
      "TargetValue": 50.0
    }
    Hinweis

    Dievon DynamoDB bereitgestellte Kapazität verwendet Kapazitätseinheiten, um die Lese- und Schreibkapazität deiner Tabellen zu definieren. Der Zielwert, den du festlegst, bestimmt, wann die Skalierung auf der Grundlage der aktuellen Nutzung erfolgen soll. Skalierungs-Cooldown-Parameter legen in Sekunden fest, wie lange nach einem Skalierungsvorgang gewartet werden soll, bis die Skalierung erneut durchgeführt wird. Weitere Informationen findest du in der API-Referenz für die automatische Skalierung TargetTrackingScalingPolicyConfiguration.

  6. Wende die Richtlinie zur Leseskalierung auf die Tabelle an, indem du die Datei read-policy.json verwendest:

    aws application-autoscaling put-scaling-policy \
        --service-namespace dynamodb \
        --resource-id "table/AWSCookbook406" \
        --scalable-dimension "dynamodb:table:ReadCapacityUnits" \
        --policy-name "AWSCookbookReadScaling" \
        --policy-type "TargetTrackingScaling" \
        --target-tracking-scaling-policy-configuration \
        file://read-policy.json
  7. Wende die Richtlinie zur Schreibskalierung mithilfe der Datei write-policy.json auf die Tabelle an:

    aws application-autoscaling put-scaling-policy \
        --service-namespace dynamodb \
        --resource-id "table/AWSCookbook406" \
        --scalable-dimension "dynamodb:table:WriteCapacityUnits" \
        --policy-name "AWSCookbookWriteScaling" \
        --policy-type "TargetTrackingScaling" \
        --target-tracking-scaling-policy-configuration \
        file://write-policy.json

Validierungsprüfungen

Du kannst die Autoscaling-Konfiguration für deine Tabelle beobachten, indem du sie in der DynamoDB-Konsole auswählst und unter dem Reiter "Zusätzliche Einstellungen" nachschaust.

Aufräumen

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Diskussion

Tipp

Mit diesen Schritten werden die Lese- und Schreibkapazitäten für deine DynamoDB-Tabelle unabhängig voneinander skaliert, was dir hilft, das Modell mit den niedrigsten Betriebskosten für die spezifischen Anforderungen deiner Anwendung zu finden.

DynamoDB bietet zwei Kapazitätsmodi: bereitgestellt und auf Abruf. Im Modus "Bereitgestellte Kapazität" kannst du die Anzahl der Lese- und Schreibvorgänge pro Sekunde festlegen. Im Leitfaden zur Preisgestaltung steht, dass du nach den von dir angegebenen Kapazitätseinheiten abgerechnet wirst. Im Gegensatz dazu zahlst du im On-Demand-Modus pro Anfrage für die Lese- und Schreibvorgänge, die deine Anwendung auf deinen Tabellen durchführt. Im Allgemeinen kann die Nutzung des On-Demand-Modus bei besonders transaktionsintensiven Anwendungen zu höheren Kosten führen als der Provisioned-Modus.

Du musst deine Anwendung und dein Nutzungsverhalten kennen, wenn du eine bereitgestellte Kapazität für deine Tabellen auswählst. Wenn du die Kapazität zu niedrig einstellst, wird die Datenbankleistung langsam und deine Anwendung könnte in Fehler- und Wartezustände geraten, da die DynamoDB-API ThrottlingException und ProvisionedThroughputExceededException Antworten an deine Anwendung zurückgibt, wenn diese Grenzen erreicht sind. Wenn du die Kapazität zu hoch ansetzt, zahlst du für nicht benötigte Kapazität. Wenn du die automatische Skalierung aktivierst, kannst du Mindest- und Höchstwerte festlegen, indem du ein Skalierungsziel festlegst. Außerdem kannst du definieren, wann der Auslöser für die automatische Skalierung in Kraft treten soll, um die Kapazität zu erhöhen, und wann er beginnen soll, sie zu verringern. So kannst du sowohl die Kosten als auch die Leistung optimieren und gleichzeitig die Vorteile des DynamoDB-Dienstes nutzen. Um eine Liste der skalierbaren Ziele zu sehen, die du für deine Tabelle konfiguriert hast, kannst du den folgenden Befehl verwenden:

aws application-autoscaling describe-scalable-targets \
    --service-namespace dynamodb \
    --resource-id "table/AWSCookbook406"

Weitere Informationen zu DynamoDB-Kapazitäten und wie sie gemessen werden, findest du in diesem Support-Dokument.

Herausforderung

Erstelle eine Lambda-Funktion, die die Leistung deiner DynamoDB-Tabelle überwacht, und ändere dann die Autoskalierung Zielwerte Minimalwerte und Maximalwerte entsprechend.

4.7 Migrieren von Datenbanken zu Amazon RDS mit AWS DMS

Problem

Du musst Daten von einer Quelldatenbank in eine Zieldatenbank verschieben.

Lösung

Konfiguriere die VPC-Sicherheitsgruppen und IAM-Berechtigungen so, dass AWS Database Migration Service (DMS) eine Verbindung zu den Datenbanken herstellen kann. Konfiguriere dann die DMS-Endpunkte für die Quell- und Zieldatenbanken. Als nächstes konfigurierst du eine DMS-Replikationsaufgabe. Schließlich startest du die Replikationsaufgabe. Ein Architekturdiagramm der Lösung ist in Abbildung 4-7 dargestellt.

DMS network diagram
Abbildung 4-7. DMS-Netzwerkdiagramm

Vorbereitung

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Steps

  1. Erstelle eine Sicherheitsgruppe für die Replikationsinstanz:

    DMS_SG_ID=$(aws ec2 create-security-group \
        --group-name AWSCookbook407DMSSG \
        --description "DMS Security Group" --vpc-id $VPC_ID \
        --output text --query GroupId)
  2. Gewähre der DMS-Sicherheitsgruppe Zugriff auf die Quell- und Zieldatenbank auf TCP-Port 3306:

    aws ec2 authorize-security-group-ingress \
        --protocol tcp --port 3306 \
        --source-group $DMS_SG_ID \
        --group-id $SOURCE_RDS_SECURITY_GROUP
    aws ec2 authorize-security-group-ingress \
        --protocol tcp --port 3306 \
        --source-group $DMS_SG_ID \
        --group-id $TARGET_RDS_SECURITY_GROUP
  3. Erstelle eine Rolle für DMS, indem du die mitgelieferte assume-role-policy.json verwendest:

    aws iam create-role --role-name dms-vpc-role \
        --assume-role-policy-document file://assume-role-policy.json
    Warnung

    Der DMS-Dienst erfordert eine IAM-Rolle mit einem bestimmten Namen und einer bestimmten Richtlinie. Der Befehl, den du zuvor ausgeführt hast, erfüllt diese Anforderung. Es kann auch sein, dass du diese Rolle bereits in deinem Konto hast, wenn du DMS schon einmal benutzt hast. In diesem Fall würde der Befehl zu einem Fehler führen und du kannst ohne Bedenken mit den nächsten Schritten fortfahren.

  4. Verbinde die verwaltete DMS-Richtlinie mit der Rolle:

    aws iam attach-role-policy --role-name dms-vpc-role --policy-arn \
    arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole
  5. Erstelle eine Replikations-Subnetzgruppe für die Replikationsinstanz:

    REP_SUBNET_GROUP=$(aws dms create-replication-subnet-group \
        --replication-subnet-group-identifier awscookbook407 \
        --replication-subnet-group-description "AWSCookbook407" \
        --subnet-ids $ISOLATED_SUBNETS \
        --query ReplicationSubnetGroup.ReplicationSubnetGroupIdentifier \
        --output text)
  6. Erstelle eine Replikationsinstanz und speichere den ARN in einer Variablen:

    REP_INSTANCE_ARN=$(aws dms create-replication-instance \
        --replication-instance-identifier awscookbook407 \
        --no-publicly-accessible \
        --replication-instance-class dms.t2.medium \
        --vpc-security-group-ids $DMS_SG_ID \
        --replication-subnet-group-identifier $REP_SUBNET_GROUP \
        --allocated-storage 8 \
        --query ReplicationInstance.ReplicationInstanceArn \
        --output text)

    Warte, bis die ReplicationInstanceStatus verfügbar ist; überprüfe den Status mit diesem Befehl:

    aws dms describe-replication-instances \
        --filter=Name=replication-instance-id,Values=awscookbook407 \
        --query ReplicationInstances[0].ReplicationInstanceStatus
    Warnung

    Für dieses Beispiel hast du die Replikationsinstanzgröße dms.t2.medium verwendet. Du solltest eine Instanzgröße wählen, die der Datenmenge entspricht, die du migrieren willst. DMS überträgt Tabellen parallel, daher brauchst du für größere Datenmengen eine größere Instanzgröße. Weitere Informationen findest du in diesem Benutzerhandbuch über bewährte Methoden für DMS.

  7. Rufe die Quell- und Ziel-DB-Admin-Passwörter aus dem Secrets Manager ab und speichere sie in Umgebungsvariablen:

    RDS_SOURCE_PASSWORD=$(aws secretsmanager get-secret-value --secret-id $RDS_SOURCE_SECRET_NAME --query
    SecretString --output text | jq .password | tr -d '"')
    
    RDS_TARGET_PASSWORD=$(aws secretsmanager get-secret-value --secret-id $RDS_TARGET_SECRET_NAME --query
    SecretString --output text | jq .password | tr -d '"')
  8. Erstelle einen Quell-Endpunkt für DMS und speichere den ARN in einer Variablen:

    SOURCE_ENDPOINT_ARN=$(aws dms create-endpoint \
        --endpoint-identifier awscookbook407source \
        --endpoint-type source --engine-name mysql \
        --username admin --password $RDS_SOURCE_PASSWORD \
        --server-name $SOURCE_RDS_ENDPOINT --port 3306 \
        --query Endpoint.EndpointArn --output text)
  9. Erstelle einen Zielendpunkt für DMS und speichere den ARN in einer Variablen:

    TARGET_ENDPOINT_ARN=$(aws dms create-endpoint \
        --endpoint-identifier awscookbook407target \
        --endpoint-type target --engine-name mysql \
        --username admin --password $RDS_TARGET_PASSWORD \
        --server-name $TARGET_RDS_ENDPOINT --port 3306 \
        --query Endpoint.EndpointArn --output text)
  10. Erstelle deine Replikationsaufgabe:

    REPLICATION_TASK_ARN=$(aws dms create-replication-task \
        --replication-task-identifier awscookbook-task \
        --source-endpoint-arn $SOURCE_ENDPOINT_ARN \
        --target-endpoint-arn $TARGET_ENDPOINT_ARN \
        --replication-instance-arn $REP_INSTANCE_ARN \
        --migration-type full-load \
        --table-mappings file://table-mapping-all.json \
        --query ReplicationTask.ReplicationTaskArn --output text)

    Warte, bis der Status "bereit" erreicht ist. Um den Status der Replikationsaufgabe zu überprüfen, gehst du wie folgt vor:

    aws dms describe-replication-tasks \
        --filters "Name=replication-task-arn,Values=$REPLICATION_TASK_ARN" \
        --query "ReplicationTasks[0].Status"
  11. Starte die Replikationsaufgabe:

    aws dms start-replication-task \
        --replication-task-arn $REPLICATION_TASK_ARN \
        --start-replication-task-type start-replication

Validierungsprüfungen

Überwache den Fortschritt der Replikationsaufgabe:

aws dms describe-replication-tasks

Verwende die AWS-Konsole oder den Vorgang aws dms describe-replication-tasks, um zu überprüfen, ob deine Tabellen migriert wurden:

aws dms describe-replication-tasks \
    --query ReplicationTasks[0].ReplicationTaskStats

Du kannst den Status der Replikationsaufgabe auch in der DMS-Konsole einsehen.

Aufräumen

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Diskussion

Tipp

full-load-and-cdc Du könntest auch verwenden, um Änderungen in der Quelle kontinuierlich auf das Ziel zu replizieren und so die Ausfallzeiten deiner Anwendung zu minimieren, wenn du auf die neue Datenbank umstellst.

DMS verfügt über eine Funktion zum Testen der Quell- und Zielendpunkte der Replikationsinstanz. Dies ist eine praktische Funktion, mit der du bei der Arbeit mit DMS überprüfen kannst, ob die Konfiguration korrekt ist, bevor du mit der Ausführung von Replikationsaufgaben beginnst. Das Testen der Verbindung von der Replikationsinstanz zu den beiden konfigurierten Endpunkten kann über die DMS-Konsole oder die Befehlszeile mit den folgenden Befehlen durchgeführt werden:

aws dms test-connection \
    --replication-instance-arn $rep_instance_arn \
    --endpoint-arn $source_endpoint_arn

aws dms test-connection \
    --replication-instance-arn $rep_instance_arn \
    --endpoint-arn $target_endpoint_arn

Der Vorgang test-connection dauert ein paar Augenblicke, bis er abgeschlossen ist. Du kannst den Status und die Ergebnisse des Vorgangs mit diesem Befehl überprüfen:

aws dms describe-connections --filter \
"Name=endpoint-arn,Values=$source_endpoint_arn,$target_endpoint_arn"

Der DMS-Service unterstützt viele Arten von Quell- und Zieldatenbanken in deiner VPC, in einem anderen AWS-Konto oder in Datenbanken, die in einer Nicht-AWS-Umgebung gehostet werden. Der Service kann auch Daten für dich umwandeln, wenn deine Quelle und dein Ziel unterschiedliche Datenbanktypen sind, indem du zusätzliche Konfigurationen in der table-mappings.json-Datei verwendest. Zum Beispiel kann der Datentyp einer Spalte in einer Oracle-Datenbank ein anderes Format haben als der entsprechende Typ in einer PostgreSQL-Datenbank. Das AWS Schema Conversion Tool (SCT) kann dabei helfen, die notwendigen Transformationen zu identifizieren und Konfigurationsdateien für die Verwendung mit DMS zu erstellen.

Herausforderung

Aktiviere die Volllast- und laufende Replikation, um kontinuierlich von einer Datenbank zur anderen zu replizieren.

4.8 Aktivieren des REST-Zugriffs auf Aurora Serverless mit der RDS-Daten-API

Problem

Du hast eine PostgreSQL-Datenbank und möchtest dich mit ihr verbinden, ohne dass deine Anwendung persistente Datenbankverbindungen verwalten muss.

Lösung

Aktiviere zunächst die Daten-API für deine Datenbank und konfiguriere die IAM-Berechtigungen für deine EC2-Instanz. Teste dann sowohl über die CLI als auch über die RDS-Konsole. So kann sich deine Anwendung mit deiner Aurora Serverless-Datenbank verbinden, wie in Abbildung 4-8 gezeigt.

An Application using the RDS Data API
Abbildung 4-8. Eine Anwendung, die die RDS-Daten-API nutzt

Voraussetzungen

  • VPC mit isolierten Subnetzen in zwei AZs und zugehörigen Routentabellen erstellt.

  • PostgreSQL RDS-Instanz und EC2-Instanz eingerichtet. Du brauchst die Möglichkeit, dich zu Testzwecken mit diesen Instanzen zu verbinden.

Vorbereitung

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Steps

  1. Aktiviere die Daten-API auf deinem Aurora Serverless-Cluster:

    aws rds modify-db-cluster \
        --db-cluster-identifier $CLUSTER_IDENTIFIER \
        --enable-http-endpoint \
        --apply-immediately
  2. Stelle sicher, dass HttpEndpointEnabled auf true eingestellt ist:

    aws rds describe-db-clusters \
        --db-cluster-identifier $CLUSTER_IDENTIFIER \
        --query DBClusters[0].HttpEndpointEnabled
  3. Teste einen Befehl aus deinem CLI:

    aws rds-data execute-statement \
        --secret-arn "$SECRET_ARN" \
        --resource-arn "$CLUSTER_ARN" \
        --database "$DATABASE_NAME" \
        --sql "select * from pg_user" \
        --output json

    (Optional) Du kannst den Zugriff auch über die AWS-Konsole mit dem Amazon RDS Query Editor testen. Führe zuerst diese beiden Befehle in deinem Terminal aus, damit du die Werte kopieren und einfügen kannst:

    echo $SECRET_ARN
    echo $DATABASE_NAME
  4. Melde dich in der AWS-Konsole mit Admin-Rechten an und gehe zur RDS-Konsole. Klicke im Menü der linken Seitenleiste auf Abfrage-Editor. Fülle die Werte aus und wähle "Mit der Datenbank verbinden", wie in Abbildung 4-9 gezeigt.

    Connect to database settings
    Abbildung 4-9. Einstellungen für die Verbindung zur Datenbank
  5. Führe die gleiche Abfrage aus und sieh dir die Ergebnisse unter dem Abfrage-Editor an (siehe Abbildung 4-10):

    SELECT * from pg_user;
    RDS Query Editor
    Abbildung 4-10. RDS-Abfrage-Editor
  6. Konfiguriere deine EC2-Instanz für die Nutzung der Daten-API mit deinem Datenbank-Cluster. Erstelle eine Datei mit dem Namen policy-template.json mit folgendem Inhalt (die Datei wird im Repository bereitgestellt):

    {
      "Version": "2012-10-17",
      "Statement": [
      {
        "Action": [
        "rds-data:BatchExecuteStatement",
        "rds-data:BeginTransaction",
        "rds-data:CommitTransaction",
        "rds-data:ExecuteStatement",
        "rds-data:RollbackTransaction"
        ],
        "Resource": "*",
        "Effect": "Allow"
      },
      {
        "Action": [
        "secretsmanager:GetSecretValue",
        "secretsmanager:DescribeSecret"
        ],
        "Resource": "SecretArn",
        "Effect": "Allow"
      }
      ]
    }
  7. Ersetze die Werte in der Vorlagendatei mit dem Befehl sed durch Umgebungsvariablen, die du gesetzt hast:

    sed -e "s/SecretArn/${SECRET_ARN}/g" \
        policy-template.json > policy.json
  8. Erstelle eine IAM-Richtlinie mit der Datei, die du gerade erstellt hast:

    aws iam create-policy --policy-name AWSCookbook408RDSDataPolicy \
        --policy-document file://policy.json
  9. Füge die IAM-Richtlinie für AWSCookbook408RDSDataPolicy der IAM-Rolle deiner EC2-Instanz hinzu:

    aws iam attach-role-policy --role-name $INSTANCE_ROLE_NAME \
        --policy-arn arn:aws:iam::$AWS_ACCOUNT_ID:policy/AWSCookbook408RDSDataPolicy

Validierungsprüfungen

Erstelle und fülle einige SSM-Parameter, um Werte zu speichern, damit du sie von deiner EC2-Instanz abrufen kannst:

aws ssm put-parameter \
    --name "Cookbook408DatabaseName" \
    --type "String" \
    --value $DATABASE_NAME 

aws ssm put-parameter \
    --name "Cookbook408ClusterArn" \
    --type "String" \
    --value $CLUSTER_ARN

aws ssm put-parameter \
    --name "Cookbook408SecretArn" \
    --type "String" \
    --value $SECRET_ARN

Verbinde dich mit der EC2-Instanz über den SSM Session Manager (siehe Rezept 1.6):

aws ssm start-session --target $INSTANCE_ID

Lege die Region fest:

export AWS_DEFAULT_REGION=us-east-1

Rufe die SSM-Parameterwerte ab und setze sie auf Umgebungswerte:

DatabaseName=$(aws ssm get-parameters \
    --names "Cookbook408DatabaseName" \
       --query "Parameters[*].Value" --output text)

SecretArn=$(aws ssm get-parameters \
    --names "Cookbook408SecretArn" \
       --query "Parameters[*].Value" --output text)

ClusterArn=$(aws ssm get-parameters \
    --names "Cookbook408ClusterArn" \
       --query "Parameters[*].Value" --output text)

Führe eine Abfrage in der Datenbank durch:

aws rds-data execute-statement \
    --secret-arn "$SecretArn" \
    --resource-arn "$ClusterArn" \
    --database "$DatabaseName" \
    --sql "select * from pg_user" \
    --output json

Beende die Session Manager-Sitzung:

exit

Aufräumen

Folge den Schritten im Ordner dieses Rezepts im Kapitel Code Repository.

Diskussion

Die Daten-API stellt einen HTTPS-Endpunkt für die Verwendung mit Aurora zur Verfügung und nutzt die IAM-Authentifizierung, damit deine Anwendung SQL-Anweisungen für deine Datenbank über HTTPS ausführen kann, anstatt die klassische TCP-Datenbankverbindung zu nutzen.

Tipp

Laut Aurora-Benutzerhandbuch sind alle Aufrufe der Daten-API synchron, und die Standardzeitüberschreitung für eine Abfrage beträgt 45 Sekunden. Wenn deine Abfragen länger als 45 Sekunden dauern, kannst du den Parameter continueAfterTimeout verwenden, um langwierige Abfragen zu erleichtern.

Wie bei anderen AWS-Service-APIs, die IAM-Authentifizierung verwenden, werden alle Aktivitäten, die mit der Daten-API durchgeführt werden, in CloudTrail aufgezeichnet, um sicherzustellen, dass ein Prüfpfad vorhanden ist, der dazu beitragen kann, deine Sicherheits- und Prüfanforderungen zu erfüllen. Du kannst den Zugriff auf den Daten-API-Endpunkt kontrollieren und delegieren, indem du IAM-Richtlinien verwendest, die mit Rollen für deine Anwendung verknüpft sind. Wenn du deiner Anwendung zum Beispiel nur die Möglichkeit geben möchtest, über die Daten-API von deiner Datenbank zu lesen, könntest du eine Richtlinie schreiben, die die Berechtigungen rds-data:CommitTransaction und rds-data:RollbackTransaction auslässt.

Der Query Editor in der RDS-Konsole bietet einen webbasierten Zugang zur Ausführung von SQL-Abfragen für deine Datenbank. Dies ist ein bequemer Mechanismus für Entwickler und DBAs, um maßgeschneiderte Aufgaben schnell zu erledigen. Die gleichen Rechte, die du deiner EC2-Instanz in diesem Rezept zugewiesen hast, musst du auch deinen Entwicklern und DBAs über IAM-Rollen gewähren.

Herausforderung

Erstelle eine Lambda-Funktion, die Zugriffsrechte auf die von dir bereitgestellte RDS-Daten-API hat, und setze sie ein.

Get AWS-Kochbuch now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.