Wie kann ich Step Functions verwenden, um eine Amazon RDS-Instance für mehr als 7 Tage zu stoppen?

Lesedauer: 10 Minute
0

Ich möchte AWS Step Functions verwenden, um einen Amazon Relational Database Service (Amazon RDS) für einen Zeitraum von mehr als 7 Tagen zu beenden.

Kurzbeschreibung

Standardmäßig können Sie eine Amazon RDS-Datenbank-Instanz ](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_StopInstance.html) für bis zu sieben Tage am Stück [anhalten. Nach sieben Tagen wird die Instanz neu gestartet, damit sie keine Wartungsupdates verpasst.

Um Ihre Instanz für mehr als 7 Tage zu stoppen, können Sie Step Functions verwenden, um den Arbeitsablauf zu automatisieren, ohne ein Wartungsfenster zu verpassen.

**Hinweis:**Eine alternative Lösung finden Sie unter Wie kann ich eine AWS Lambda-Funktion verwenden, um eine Amazon RDS-Instanz für mehr als sieben Tage zu stoppen?

Lösung

IAM-Berechtigungen konfigurieren

Erstellen Sie eine AWS-Richtlinie für Identity and Access Management (IAM), die es Step Functions ermöglicht, eine Instanz zu starten und zu stoppen und Informationen über die Instanz abzurufen:

1.    Öffnen Sie die IAM-Konsole.

2.    Wählen Sie im Navigationsbereich die Option Richtlinien aus. Wählen Sie dann Richtlinie erstellen aus.

3.Wählen Sie die Registerkarte JSON aus. Geben Sie dann die folgende Richtlinie ein, um die erforderlichen IAM-Berechtigungen zu gewähren:

{
    "Version": "2012-10-17",
    "Statement":
    [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "rds:DescribeDBInstances",
                "rds:StopDBInstance",
                "rds:StartDBInstance"
            ],
            "Resource": "*"
        }
    ]
}

4.    Wählen Sie Weiter: Tags.

  1. (Optional) Um ein Tag hinzuzufügen, wählen Sie Tag hinzufügen und geben Sie dann die entsprechenden Werte für die Felder Schlüssel und Wert ein.

6.    Wählen Sie Weiter: Überprüfung.

  1. Geben Sie den Namen für Ihre Richtlinie ein. Geben Sie beispielsweise step-functions-start-stop-rds-policy ein. Informationen zu den von Ihrer Richtlinie erteilten Berechtigungen finden Sie im Abschnitt Zusammenfassung.

8.Wählen Sie Richtlinie erstellen aus.

Weitere Informationen finden Sie unter Richtlinien mit dem JSON-Editor erstellen.

Erstellen Sie eine IAM-Rolle und fügen Sie die erforderlichen Richtlinien hinzu

1.    Öffnen Sie die IAM-Konsole.

2.    Wählen Sie im Navigationsbereich Rollen aus. Wählen Sie dann Rolle erstellen.

  1. Wählen Sie für Typ der vertrauenswürdigen Instanz die Option AWS-Service aus.

  2. Wählen Sie in der Dropdown-Liste Anwendungsfälle für anderen AWS-Service die Option Schrittfunktionen aus. Wählen Sie dann die Option Schrittfunktionen aus.

5.    Wählen Sie Weiter.
**Hinweis:**Ergreifen Sie auf der Seite Berechtigungen hinzufügen keine Aktionen. Erstellen Sie zuerst die Rolle und bearbeiten Sie dann die Standardberechtigungen.

6.    Wählen Sie Weiter.

  1. Geben Sie unter Rollenname den Namen für die Rolle ein. Geben Sie beispielsweise step-functions-start-stop-rds-role ein.
    (Optional) Aktualisieren Sie die Rollenbeschreibung.
    (Optional) Um ein Tag hinzuzufügen, geben Sie die entsprechenden Werte für die Felder Schlüssel und Wert ein.

8.Wählen Sie Rolle erstellen aus. Dadurch kehren Sie zur Liste Rollen zurück.

  1. Geben Sie in das Suchfeld den Namen der Rolle ein, die Sie erstellt haben. Wählen Sie dann diese Rolle aus, um ihre Details zu sehen.

  2. Wählen Sie auf der Registerkarte Berechtigungen die Dropdownliste Berechtigungen hinzufügen aus. Wählen Sie dann Richtlinie anhängen aus.

  3. Geben Sie den Namen der Richtlinie ein, die Sie im Abschnitt IAM-Berechtigungen konfigurieren erstellt haben. Geben Sie beispielsweise step-functions-start-stop-rds-policy ein. Wenn Sie diese Richtlinie als Option sehen, wählen Sie sie aus.

  4. Wählen Sie auf der Registerkarte Berechtigungen die von AWS verwaltete AWS-Richtlinie ** AWSLambdaRole** und dann Entfernen aus.

Weitere Informationen finden Sie unter Erstellen einer Rolle für einen AWS-Service (Konsole).

Fügen Sie Tags für DB-Instances hinzu

1.Öffnen Sie die Amazon RDS-Konsole.

2 Wählen Sie im Navigationsbereich Datenbanken aus.

  1. Wählen Sie die DB-Instance aus, die Sie automatisch starten und beenden möchten.

  2. Wählen Sie den ** Tab „**Schlagworte“.

5. Wählen Sie Hinzufügen aus. Geben Sie alsTag-Schlüssel Autostart ein. Geben Sie für Wert Ja ein.

  1. Wählen Sie Weiteres Tag hinzufügen. Geben Sie als ** Tag-Schlüssel** Autostop ein. Geben Sie für Wert Ja ein.

  2. Um diese Tags zu speichern, wählen Sie Hinzufügen.

Weitere Informationen finden Sie unter Hinzufügen, Auflisten und Entfernen von Tags.

Erstellen Sie eine Statusmaschine zum Starten und Stoppen der markierten DB-Instances

1.Öffnen Sie die Schrittfunktionen-Konsole.

2.Wählen Sie im linken Navigationsbereich Statusmaschinen aus. Wählen Sie dann Statusmaschine erstellen aus.

  1. Wählen Sie Ihren Workflow in Code schreiben aus.

  2. Behalten Sie den Typ als Standard bei.

5. Löschen Sie im Editor Definition die JSON-Beispieldefinition. Geben Sie dann die folgende Statusmaschinen-Definition ein:

{
  "Comment": "State Machine Definition to start and stop RDS DB instances",
  "StartAt": "Describe DBInstances to Start",
  "States": {
    "Describe DBInstances to Start": {
      "Type": "Task",
      "Parameters": {},
      "Resource": "arn:aws:states:::aws-sdk:rds:describeDBInstances",
      "Next": "Iterate on Instances to Start",
      "Retry": [
        {
          "ErrorEquals": [
            "Rds.InternalFailure",
            "Rds.ServiceUnavailable",
            "Rds.ThrottlingException",
            "Rds.SdkClientException"
          ],
          "BackoffRate": 2,
          "IntervalSeconds": 1,
          "MaxAttempts": 2
        }
      ]
    },
    "Iterate on Instances to Start": {
      "Type": "Map",
      "ItemProcessor": {
        "ProcessorConfig": {
          "Mode": "INLINE"
        },
        "StartAt": "Format Array before Start",
        "States": {
          "Format Array before Start": {
            "Type": "Pass",
            "Next": "Check If Instance stopped, if no Tags or if Tags contains 'autostart=yes'",
            "Parameters": {
              "DbInstanceStatus.$": "$.DBInstance.DbInstanceStatus",
              "DbInstanceIdentifier.$": "$.DBInstance.DbInstanceIdentifier",
              "TagList.$": "$.DBInstance.TagList",
              "TagsArrayLength.$": "States.ArrayLength($.DBInstance.TagList)",
              "TagContainsKey.$": "States.ArrayContains($.DBInstance.TagList,$.LookingFor)"
            }
          },
          "Check If Instance stopped, if no Tags or if Tags contains 'autostart=yes'": {
            "Type": "Choice",
            "Choices": [
              {
                "Not": {
                  "Variable": "$.DbInstanceStatus",
                  "StringEquals": "stopped"
                },
                "Next": "Instance is not in 'stopped' status"
              },
              {
                "Variable": "$.TagsArrayLength",
                "NumericEquals": 0,
                "Next": "No Tags found to Start"
              },
              {
                "Variable": "$.TagContainsKey",
                "BooleanEquals": true,
                "Next": "Tags found Start DBInstance"
              }
            ],
            "Default": "No Tags found to Start"
          },
          "Tags found Start DBInstance": {
            "Type": "Task",
            "Parameters": {
              "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
            },
            "Resource": "arn:aws:states:::aws-sdk:rds:startDBInstance",
            "Retry": [
              {
                "ErrorEquals": [
                  "Rds.InternalFailure",
                  "Rds.ServiceUnavailable",
                  "Rds.ThrottlingException",
                  "Rds.SdkClientException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 1,
                "MaxAttempts": 2
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "Failed to Start DBInstance"
              }
            ],
            "ResultSelector": {
              "message": "Instance Started",
              "DbInstanceIdentifier.$": "$.DbInstance.DbInstanceIdentifier"
            },
            "End": true
          },
          "Failed to Start DBInstance": {
            "Type": "Pass",
            "Parameters": {
              "message": "Failed to start instance",
              "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
            },
            "End": true
          },
          "No Tags found to Start": {
            "Type": "Pass",
            "End": true,
            "Parameters": {
              "message": "No Tags found to Start",
              "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
            }
          },
          "Instance is not in 'stopped' status": {
            "Type": "Pass",
            "End": true,
            "Parameters": {
              "message": "Instance is not in 'stopped' status",
              "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
            }
          }
        }
      },
      "InputPath": "$.DbInstances",
      "Next": "Wait for 1 hour and 30 minutes",
      "ItemSelector": {
        "LookingFor": {
          "Key": "autostart",
          "Value": "yes"
        },
        "DBInstance.$": "$$.Map.Item.Value"
      }
    },
    "Wait for 1 hour and 30 minutes": {
      "Type": "Wait",
      "Seconds": 5400,
      "Next": "Describe DBInstances to Stop"
    },
    "Describe DBInstances to Stop": {
      "Type": "Task",
      "Parameters": {},
      "Resource": "arn:aws:states:::aws-sdk:rds:describeDBInstances",
      "Retry": [
        {
          "ErrorEquals": [
            "Rds.InternalFailure",
            "Rds.ServiceUnavailable",
            "Rds.ThrottlingException",
            "Rds.SdkClientException"
          ],
          "BackoffRate": 2,
          "IntervalSeconds": 1,
          "MaxAttempts": 2
        }
      ],
      "Next": "Iterate on Instances to Stop"
    },
    "Iterate on Instances to Stop": {
      "Type": "Map",
      "ItemProcessor": {
        "ProcessorConfig": {
          "Mode": "INLINE"
        },
        "StartAt": "Format Array before Stop",
        "States": {
          "Format Array before Stop": {
            "Type": "Pass",
            "Next": "Check If Instance available, if no Tags or if Tags contains 'autostop=yes'",
            "Parameters": {
              "DbInstanceStatus.$": "$.DBInstance.DbInstanceStatus",
              "DbInstanceIdentifier.$": "$.DBInstance.DbInstanceIdentifier",
              "TagList.$": "$.DBInstance.TagList",
              "TagsArrayLength.$": "States.ArrayLength($.DBInstance.TagList)",
              "TagContainsKey.$": "States.ArrayContains($.DBInstance.TagList,$.LookingFor)"
            }
          },
          "Check If Instance available, if no Tags or if Tags contains 'autostop=yes'": {
            "Type": "Choice",
            "Choices": [
              {
                "Not": {
                  "Variable": "$.DbInstanceStatus",
                  "StringEquals": "available"
                },
                "Next": "Instance is not in 'available' status"
              },
              {
                "Variable": "$.TagsArrayLength",
                "NumericEquals": 0,
                "Next": "No Tags found to Stop"
              },
              {
                "Variable": "$.TagContainsKey",
                "BooleanEquals": true,
                "Next": "Tags found Stop DBInstance"
              }
            ],
            "Default": "No Tags found to Stop"
          },
          "Tags found Stop DBInstance": {
            "Type": "Task",
            "Parameters": {
              "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
            },
            "Resource": "arn:aws:states:::aws-sdk:rds:stopDBInstance",
            "Retry": [
              {
                "ErrorEquals": [
                  "Rds.InternalFailure",
                  "Rds.ServiceUnavailable",
                  "Rds.ThrottlingException",
                  "Rds.SdkClientException"
                ],
                "BackoffRate": 2,
                "IntervalSeconds": 1,
                "MaxAttempts": 2
              }
            ],
            "Catch": [
              {
                "ErrorEquals": [
                  "States.ALL"
                ],
                "Next": "Failed to Stop DBInstance"
              }
            ],
            "ResultSelector": {
              "message": "Instance Stopped",
              "DbInstanceIdentifier.$": "$.DbInstance.DbInstanceIdentifier"
            },
            "End": true
          },
          "Failed to Stop DBInstance": {
            "Type": "Pass",
            "Parameters": {
              "message": "Failed to stop instance",
              "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
            },
            "End": true
          },
          "No Tags found to Stop": {
            "Type": "Pass",
            "End": true,
            "Parameters": {
              "message": "No Tags found to Stop",
              "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
            }
          },
          "Instance is not in 'available' status": {
            "Type": "Pass",
            "End": true,
            "Parameters": {
              "message": "Instance is not in 'available' status",
              "DbInstanceIdentifier.$": "$.DbInstanceIdentifier"
            }
          }
        }
      },
      "InputPath": "$.DbInstances",
      "Next": "Workflow Finished",
      "ItemSelector": {
        "LookingFor": {
          "Key": "autostop",
          "Value": "yes"
        },
        "DBInstance.$": "$$.Map.Item.Value"
      }
    },
    "Workflow Finished": {
      "Type": "Succeed"
    }
  }
}

**Hinweis:**Zu Testzwecken können Sie das Feld Sekunden im Status 1 Stunde und 30 Minuten warten ändern. Sie können diesen Wert auch für ein längeres oder kürzeres Wartungsfenster verlängern.

6.    Wählen Sie Weiter.

  1. Geben Sie einen Statusmaschinen-Namen ein. Geben Sie beispielsweise step-functions-start-stop-rds-state-machine ein.

  2. Wählen Sie unter Berechtigungen Bestehende Rolle auswählen aus. Wählen Sie dann die IAM-Rolle aus, die Sie erstellt haben. Wählen Sie beispielsweise step-functions-start-stop-rds-role aus.

9.(Optional) Um ein Tag hinzuzufügen, geben Sie die entsprechenden Werte für die Felder Schlüssel und Wert ein.

  1. Wählen Sie Statusmaschine erstellen aus.

Führen Sie einen Workflow-Test durch

Gehen Sie wie folgt vor, um Funktionstests für markierte DB-Instances durchzuführen, die sich im Status Angehalten befinden:

1.Öffnen Sie die Schrittfunktionen-Konsole.

2.Wählen Sie im linken Navigationsbereich Statusmaschinen aus.

  1. Wählen Sie die Statusmaschine aus, die Sie erstellt haben, um Ihre DB-Instances zu starten.

  2. Wählen Sie Ausführung starten.
    **Hinweis:**Für diese Lösung ist keine Ereignis-Nutzlast erforderlich. Im Dialogfeld Ausführung starten können Sie die Ereignis-Nutzlast entfernen oder das Standardereignis beibehalten.

  3. Wählen Sie Ausführung starten.

Erstellen Sie den Zeitplan

Um ein wöchentliches Wartungsfenster für die markierten DB-Instances zu planen, erstellen Sie eine EventBridge-Regel. Diese Regel startet die DB-Instance automatisch 30 Minuten vor dem Wartungsfenster.

Im folgenden Beispielanwendungsfall findet das Wartungsfenster am Sonntag zwischen 22:00 und 22:30 Uhr statt. Die Beispielregel startet die DB-Instance jeden Sonntag um 21:30 Uhr.

1.Öffnen Sie die EventBridge-Konsole.

  1. Wählen Sie die Statusmaschine aus, die Sie vorher im Abschnitt Statusmaschine erstellen, um die markierten DB-Instances zu starten und zu stoppen, erstellt haben.

  2. Wählen Sie unter Busse die Option Regeln aus.

  3. Wählen Sie den Standard-Ereignisbus aus der Dropdown-Liste aus.

  4. Wählen Sie Regel erstellen aus.

  5. Geben Sie unter Regelname den Namen der Regel ein, die Sie erstellen möchten. Geben Sie beispielsweise step-functions-start-stop-rds-rule ein.

  6. Wählen Sie als Regeltyp Zeitplan aus. Behalten Sie für andere Werte auf dieser Seite die Standardeinstellungen bei.

  7. Wählen Sie Weiter mit EventBridge Scheduler.

  8. Wählen Sie für Wiederkehrender Zeitplan die Option Ereignis aus. Wählen Sie dann als Zeitplantyp die Option CRON-basierter Zeitplan aus.

  9. Fügen Sie einen Cron-Ausdruck für den automatisierten Zeitplan hinzu. Geben Sie beispielsweise cron(30 21 ? * SUN *) ein.

  10. Wählen Sie für das Flexible Zeitfenster die Option Aus.

12.    Wählen Sie Weiter.

  1. Wählen Sie Häufig verwendete APIs und dann StartExecution aus.

  2. Wählen Sie unter StartExecution die Statusmaschine aus, die Sie erstellt haben. Wählen Sie beispielsweise step-functions-start-stop-rds-state-machine aus. Behalten Sie den Standardwert der Eingabe von {} bei.

15.    Wählen Sie Weiter.

  1. Deaktivieren Sie unter Wiederholungsrichtlinie und Dead-Letter Queue (DLQ) die Wiederholungsrichtlinie, um sie zu deaktivieren.

  2. Behalten Sie unter Berechtigungen die Standardoption bei: Erstellen Sie eine neue Rolle für diesen Zeitplan.

**Hinweis:**EventBridge erstellt eine neue Rolle zur Übernahme und initiiert die StartExecution-API für Ihren speziellen Workflow.

18.Wählen Sie Weiter.

  1. Stellen Sie unter Zeitplandetails sicher, dass die nächsten 10 Aufrufdaten mit den Daten Ihres erwarteten Zeitplans übereinstimmen.

  2. Wählen Sie Zeitplan erstellen aus.

Wenn EventBridge die Regel aufruft, startet es den Schrittfunktions-Workflow. Dadurch werden die DB-Instances 30 Minuten vor dem Wartungsfenster gestartet. Der Workflow stoppt die DB-Instance dann 30 Minuten nach Abschluss des Wartungsfensters. Der Workflow startet Ihre DB-Instance beispielsweise um 21:30 Uhr. Das Wartungsfenster findet zwischen 22:00 und 22:30 Uhr statt. Dann stoppt der Workflow Ihre Instanz um 23:00 Uhr.