Come posso utilizzare Step Functions per interrompere un'istanza Amazon RDS per più di 7 giorni?

10 minuti di lettura
0

Desidero utilizzare AWS Step Functions per interrompere un’istanza Amazon Relational Database Service (Amazon RDS) per un periodo superiore ai 7 giorni.

Breve descrizione

Per impostazione predefinita, è possibile interrompere un'istanza del database Amazon RDS per un massimo di sette giorni alla volta. Dopo sette giorni, l'istanza si riavvia in modo da non perdere eventuali aggiornamenti di manutenzione.

Per interrompere l'istanza per più di 7 giorni, puoi utilizzare Step Functions per automatizzare il flusso di lavoro senza perdere una finestra di manutenzione.

Nota: Per una risoluzione alternativa, vedi Come posso utilizzare una funzione AWS Lambda per interrompere un'istanza Amazon RDS per più di sette giorni?

Risoluzione

Configurazione delle autorizzazioni IAM

Crea una policy AWS IAM (Identity and Access Management) che consenta a Step Functions di avviare e arrestare un'istanza e di recuperare informazioni su di essa:

1.    Apri la console IAM.

2.    Nel pannello di navigazione, scegli Policy. Quindi, scegli Crea policy.

3.    Scegli la scheda JSON. Quindi, inserisci la seguente policy per concedere le autorizzazioni IAM necessarie:

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

4.    Scegli Successivo: Tag.

5.    (Facoltativo) Per aggiungere un tag, scegli Aggiungi tag, quindi inserisci i valori appropriati per i campi Chiave e Valore.

6.    Scegli Successivo: Revisione.

7.    Inserisci il nome della policy. Inserisci ad esempio step-functions-start-stop-rds-policy. Per esaminare le autorizzazioni concesse dalla policy, consulta la sezione Riepilogo.

8.    Scegli Crea policy.

Per ulteriori informazioni, consulta Creazione di policy utilizzando l'editor JSON.

Creazione di un ruolo IAM e collegamento delle policy necessarie

1.    Apri la console IAM.

2.    Nel pannello di navigazione, scegli Ruoli. Quindi, scegli Crea ruolo.

3.    Per Seleziona il tipo di entità attendibile, scegli Servizio AWS.

4.    Nell'elenco a discesa Casi d'uso per altri servizi AWS scegli Step Functions. Quindi, scegli l'opzione Step Functions.

5.    Scegli Avanti.
**Nota:**Non fare nulla nella pagina Aggiungi autorizzazioni. Crea prima il ruolo, quindi modifica le autorizzazioni predefinite.

6.    Scegli Avanti.

7.    In Nome ruolo, inserisci il nome del ruolo. Ad esempio, inserisci step-functions-start-stop-rds-role.
(Facoltativo) Aggiornare la descrizione del ruolo.
(Facoltativo) Per aggiungere un tag, inserisci i valori appropriati per i campi Chiave e Valore.

8.    Scegli Crea ruolo. Questa scelta ti riporta all'elenco Ruoli.

9.    Nella casella di ricerca, inserisci il nome del ruolo che hai creato. Quindi selezionalo per visualizzarne i dettagli.

10.    Nella scheda ** Autorizzazioni**, scegli l'elenco a discesa Aggiungi autorizzazioni. Quindi, scegli Collega policy.

11.    Inserisci il nome della policy che hai creato nella sezione Configura le autorizzazioni IAM. Inserisci ad esempio step-functions-start-stop-rds-policy. Quando questa policy viene visualizzata come un'opzione, selezionala.

12.    Nella scheda Autorizzazioni, seleziona la policy gestita da AWS AWSLambdaRole, quindi scegli Rimuovi.

Per ulteriori informazioni, consulta la paginaCreazione di un ruolo per un servizio AWS (console).

Aggiunta di tag per le istanze database

1.    Apri la console Amazon RDS.

2.    Nel riquadro di navigazione, scegli Database.

3.    Seleziona l'istanza database che desideri avviare e arrestare automaticamente.

4.    Scegli la scheda Tag .

5.     Scegli Aggiungi. Come Chiave tag inserisci ** autostart**. Come Valore inserisci .

6.    Scegli Aggiungi un altro tag. Come Chiave tag inserisci autostop. Come Valore, inserisci .

7.    Per salvare questi tag, scegli Aggiungi.

Per ulteriori informazioni, consulta Aggiunta, pubblicazione e rimozione di tag.

Creazione di una macchina a stati per avviare e arrestare le istanze DB con tag

1.    Apri la console Step Functions.

2.    Nel pannello di navigazione, scegli Macchina a stati. Quindi, scegli Crea una macchina a stati.

3.    Scegli Scrivi il tuo flusso di lavoro in codice.

4.    Conserva il Tipo predefinito come Standard.

5.     Nell'editor Definizione definizioni, elimina la definizione JSON di esempio. Poi inserisci la seguente definizione di macchina a stati:

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

**Nota:**A scopo di test, è possibile modificare il campo Secondi nello stato Attendi 1 ora e 30 minuti . È inoltre possibile estendere questo valore per una finestra di manutenzione più o meno lunga.

6.    Scegli Avanti.

7.    Inserisci il nome della macchina a stati. Ad esempio, inserisci step-functions-start-stop-rds-state-machine.

8.    In Autorizzazioni seleziona Scegli un ruolo esistente. Quindi, seleziona il ruolo IAM che hai creato. Ad esempio, seleziona step-functions-start-stop-rds-role.

9.    (Facoltativo) Per aggiungere un tag, inserisci i valori appropriati per i campi Chiave e Valore.

10.  Scegli Crea macchina a stati.

Eseguire un test del flusso di lavoro

Per eseguire un test di funzionalità sulle istanze database con tag che si trovano nello stato Arrestato, completa i seguenti passaggi:

1.    Apri la console Step Functions.

2.    Nel pannello di navigazione, scegli Macchina a stati.

3.    Seleziona la macchina a stati che hai creato per avviare le tue istanze DB.

4.    Scegli Avvia esecuzione.
**Nota:**Questa risoluzione non richiede un payload dell’evento. Nella finestra di dialogo Avvia esecuzione puoi rimuovere il payload dell'evento o lasciare l'evento predefinito.

5.    Scegli Avvia esecuzione.

Creazione della Pianificazione

Per programmare una finestra di manutenzione settimanale per le istanze database con tag, crea una regola EventBridge. Questa regola avvia automaticamente l'istanza database 30 minuti prima della finestra di manutenzione.

Nel seguente caso d’uso, la finestra di manutenzione è fissata tra le 22:00 e le 22:30 di domenica. La regola di esempio avvia l'istanza database ogni domenica alle 21:30.

1.    Apri la console EventBridge.

2.    Seleziona la macchina a stati che hai creato in precedenza nella sezione Creazione di una macchina a stati per avviare e arrestare le istanze DB con tag.

3.    In Bus, seleziona Regole.

4.    Scegli il bus di eventi predefinito nell'elenco a discesa.

5.    Seleziona Crea regola.

6.    In Nome regola, inserisci il nome della regola che desideri creare. Inserisci ad esempio step-functions-start-stop-rds-rule.

7.    Per Tipo di regola, scegli Pianificazione. Per gli altri valori in questa pagina, mantieni le impostazioni predefinite.

8.    Scegli Continua nel pianificatore EventBridge.

9.    Per Pianificazione ricorrente, scegli Ricorrenza. Quindi per Tipo di programma, scegli Pianificazione basata su CRON.

10.    Aggiungi un'espressione cron per la pianificazione automatica. Ad esempio, inserisci cron(30 21 ? * SUN *).

11.    Per Finestra temporale flessibile scegli Disattivato.

12.    Scegli Avanti.

13.    Scegli API utilizzate di frequente e poi StartExecution.

14.    In StartExecution, seleziona la macchina a stati che hai creato. Ad esempio, seleziona step-functions-start-stop-rds-state-machine. Mantieni il valore dell'input predefinito di {}.

15.    Scegli Avanti.

16.    In Policy di ripetizione e coda DLQ (Dead-Letter Queue) deseleziona la Policy di ripetizione per disattivarla.

17.    In Autorizzazioni, conserva l'opzione predefinita: Crea un nuovo ruolo per questa pianificazione.

**Nota:**EventBridge crea un nuovo ruolo da assumere e predispone l'API StartExecution al tuo particolare flusso di lavoro.

18.    Scegli Avanti.

19.    In Dettagli della pianificazione, verifica che le prossime 10 date di chiamata corrispondano alle date previste dalla pianificazione.

20.    Scegli Crea pianificazione.

Quando EventBridge richiama la regola, avvia il flusso di lavoro Step Function. Le istanze database vengono avviate 30 minuti prima della finestra di manutenzione. Il flusso di lavoro interrompe quindi l'istanza database 30 minuti dopo la fine della finestra di manutenzione.  Ad esempio, il flusso di lavoro avvia l'istanza database alle 21:30. Il periodo di manutenzione è compreso tra le 22:00 e le 22:30. Quindi, il flusso di lavoro interrompe l'istanza alle 23:00.