Comment puis-je utiliser Step Functions pour arrêter une instance Amazon RDS pendant plus de 7 jours ?

Lecture de 10 minute(s)
0

Je souhaite utiliser AWS Step Functions pour arrêter un Amazon Relational Database Service (Amazon RDS) pendant une durée supérieure à 7 jours.

Brève description

Par défaut, vous pouvez arrêter une instance de base de données Amazon RDS pendant sept jours maximum à la fois. Au bout de sept jours, l'instance redémarre afin de ne manquer aucune mise à jour de maintenance.

Pour arrêter votre instance pendant plus de 7 jours, vous pouvez utiliser Step Functions pour automatiser le flux de travail sans manquer de fenêtre de maintenance.

**Remarque :**Pour une autre solution, consultez Comment utiliser une fonction AWS Lambda pour arrêter une instance Amazon RDS pendant plus de sept jours ?

Résolution

Configurer les autorisations IAM

Créez une politique AWS Identity and Access Management (IAM) qui permet à Step Functions de démarrer et d'arrêter une instance et de récupérer des informations sur l'instance :

1.    Ouvrez la console IAM.

2.     Dans le volet de navigation, choisissez Politiques.      Choisissez ensuite Créer une politique.

3.    Choisissez l'onglet JSON. Entrez ensuite la politique suivante pour accorder les autorisations IAM requises :

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

4.    Choisissez Suivant : Balises.

5.     (Facultatif) Pour ajouter une balise, choisissez Ajouter une balise, puis entrez les valeurs appropriées pour les champs Clé et Valeur.

6.    Choisissez Suivant : Révision.

7.     Entrez le nom de votre politique. Par exemple, entrez step-functions-start-stop-rds-policy. Pour consulter les autorisations accordées dans le cadre de votre politique, consultez la section Résumé.

8.     Choisissez Créer une politique.

Pour plus d'informations, consultez la section Création de politiques à l'aide de l'éditeur JSON.

Créez un rôle IAM et associez les politiques requises

1.     Ouvrez la console IAM.

2.     Dans le volet de navigation, choisissez Rôles. Choisissez Créer Rôle.

3.     Pour Sélectionner le type d'entité de confiance, choisissez le service AWS.

4.     Dans la liste déroulanteCas d'utilisation pour d'autres services AWS, choisissez Step Functions. Choisissez ensuite l'option Step Functions.

5.    Choisissez Suivant.
**Remarque :**N'effectuez aucune action sur la page Ajouter des autorisations . Créez d'abord le rôle, puis modifiez les autorisations par défaut.

6.    Choisissez Suivant.

7.     Dans Nom du rôle, entrez le nom du rôle. Par exemple, entrez step-functions-start-stop-rds-role.
(Facultatif) Mettez à jour la description du rôle.
(Facultatif) Pour ajouter une balise, entrez les valeurs appropriées pour les champs Clé et Valeur.

8.    Choisissez Créer Rôle. Cela vous ramène à la liste des Rôles .

9.     Dans le champ de recherche, entrez le nom du rôle que vous avez créé. Sélectionnez ensuite ce rôle pour en voir les détails.

10.     Dans l'onglet Autorisations, choisissez la liste déroulante Ajouter des autorisations. Choisissez ensuite Attacher des politiques.

11.     Entrez le nom de la politique que vous avez créée dans la section Configurer les autorisations IAM. Par exemple, entrez step-functions-start-stop-rds-policy. Lorsque vous voyez cette politique comme une option, sélectionnez-la.

12.     Dans l'onglet Autorisations, sélectionnez la politique gérée par AWS AWSLambdaRole, puis choisissez Supprimer.

Pour plus d'informations, consultez Création d'un rôle pour un service AWS (console).

Ajouter des balises pour les instances de base de données

1.     Ouvrez la console Amazon RDS.

2     Dans le volet de navigation, choisissez Bases de données.

3.     Sélectionnez l'instance de base de données que vous souhaitez démarrer et arrêter automatiquement.

4.     Choisissez l'onglet Balises.

5.      Choisissez Ajouter. Pour Clé de balise, entrez autostart. Dans le champ Valeur, saisissez oui.

6.     Choisissez Ajouter une autre balise. Pour Clé de balise, saisissez autostop. Dans le champ Valeur, saisissez oui.

7.     Pour enregistrer ces balises, choisissez Ajouter.

Pour plus d'informations, consultez la section Ajouter, répertorier et supprimer des balises.

Créez une machine d'état pour démarrer et arrêter les instances de base de données balisées

1.     Ouvrez la console Step Functions.

2.     Dans le volet de navigation, choisissez État machines. Choisissez ensuite Create state machine.

3.     Choisissez Écrire votre flux de travail sous forme de code.

4.     Conservez le Type par défaut en tant que Standard.

5.      Dans l'éditeur de Définition, supprimez l'exemple de définition JSON. Entrez ensuite la définition de machine d'état suivante :

{
  "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"
    }
  }
}

**Remarque :**À des fins de test, vous pouvez modifier le champ Secondes dans l'état Attendre 1 heure et 30 minutes. Vous pouvez également étendre cette valeur pour une fenêtre de maintenance plus ou moins longue.

6.    Choisissez Suivant.

7.     Entrez un nom de machine d'état. Par exemple, entrez step-functions-start-stop-rds-state-machine.

8.     Sous Autorisations, choisissez Choisir un rôle existant. Sélectionnez ensuite le rôle IAM que vous avez créé. Par exemple, sélectionnez step-functions-start-stop-rds-role.

9.     (Facultatif) Pour ajouter une balise, entrez les valeurs appropriées pour les champs Clé et Valeur.

10.     Choisissez Create state machine.

Réaliser un test de flux de travail

Pour effectuer des tests de fonctionnement pour les instances de base de données balisées qui sont dans l'état Arrêté, procédez comme suit :

1.     Ouvrez la console Step Functions.

2.     Dans le volet de navigation, choisissez État machines.

3.     Sélectionnez la machine d'état que vous avez créée pour démarrer vos instances de base de données.

4.     Choisissez Lancer l'exécution.
**Remarque :**Cette résolution ne nécessite pas de charge utile d'événement. Dans la boîte de dialogue Démarrer l'exécution, vous pouvez supprimer la charge utile de l'événement ou conserver l'événement par défaut.

5.     Choisissez Lancer l'exécution.

Création du calendrier

Pour planifier une fenêtre de maintenance hebdomadaire pour les instances de base de données balisées, créez une règle EventBridge. Cette règle démarre automatiquement l'instance de base de données 30 minutes avant la fenêtre de maintenance.

Dans l'exemple d'utilisation suivant, la fenêtre de maintenance se déroule entre 22h00 et 22h30 le dimanche. L'exemple de règle démarre l'instance de base de données à 21h30 tous les dimanches.

1.     Ouvrez la console EventBridge.

2.     Sélectionnez la machine d'état que vous avez précédemment créée dans la section Créer une machine d'état pour démarrer et arrêter les instances de base de données balisées.

3.     Sous Bus, sélectionnez Règles.

4.     Choisissez le **bus événements ** par défaut dans la liste déroulante.

5.     Sélectionnez Créer une règle.

6.     Dans Nom de la règle, entrez le nom de la règle que vous souhaitez créer. Par exemple, entrez step-functions-start-stop-rds-rule.

7.     Pour Type de règle, choisissez Planification. Pour les autres valeurs de cette page, conservez leurs paramètres par défaut.

8.     Choisissez ** Continuer avec EventBridge Scheduler**.

9.     Pour Calendrier récurrent, choisissez Occurrence. Ensuite, pour Type de planification, choisissez Planification basée sur CRON.

10.     Ajoutez une expression cron pour le calendrier automatique. Par exemple, entrez cron(30 21 ? * DIM*).

11.     Pour la fenêtre horaire flexible, choisissez Désactivé.

12.    Choisissez Suivant.

13.     Choisissez API fréquemment utilisées, puis choisissez StartExecution.

14.     Sous StartExecution, sélectionnez la machine d'état que vous avez créée. Par exemple, sélectionnez step-functions-start-stop-rds-state-machine . Conservez la valeur par défaut de l'entrée, {}.

15.    Choisissez Suivant.

16.     Sous ** Politique de nouvelle tentative et file d'attente de lettres mortes (DLQ)**, désactivez la politique de nouvelle tentative pour la désactiver.

17.     Sous Autorisations, conservez l'option par défaut : Créez un nouveau rôle pour ce calendrier.

**Remarque :**EventBridge crée un nouveau rôle à assumer et lance l'API StartExecution pour votre flux de travail particulier.

18.     Choisissez Suivant.

19.     Sous ** Détails du calendrier**, vérifiez que les 10 prochaines dates d'invocation correspondent aux dates de votre calendrier prévu.

20.     Choisissez Créer un calendrier.

Lorsque EventBridge appelle la règle, il lance le flux de travail Step Function. Cela démarre les instances de base de données 30 minutes avant la fenêtre de maintenance. Le flux de travail arrête ensuite l'instance de base de données 30 minutes après la fin de la fenêtre de maintenance.     Par exemple, le flux de travail démarre votre instance de base de données à 21h30. La fenêtre de maintenance se déroule entre 22h00 et 22h30. Le flux de travail arrête ensuite votre instance à 23h00.