Como posso usar o Step Functions para interromper uma instância do Amazon RDS por mais de 7 dias?

11 minuto de leitura
0

Quero usar o AWS Step Functions para interromper um Amazon Relational Database Service (Amazon RDS) por mais de 7 dias.

Breve descrição

Por padrão, você pode interromper uma instância de banco de dados do Amazon RDS por até sete dias por vez. Depois de sete dias, a instância é reiniciada para que não perca nenhuma atualização de manutenção.

Para interromper sua instância por mais de 7 dias, você pode usar o Step Functions para automatizar o fluxo de trabalho sem perder uma janela de manutenção.

Observação: para obter uma solução alternativa, consulte Como posso usar uma função do Lambda da AWS para interromper uma instância do Amazon RDS por mais de sete dias?

Resolução

Configurar permissões do IAM

Crie uma política do AWS Identity and Access Management (IAM) que permita que o Step Functions inicie e interrompa uma instância e recupere informações sobre a instância:

1.    Abra o console do IAM.

2.    No painel de navegação, selecione Policies (Políticas). Em seguia, escolha Create Policy (Criar política).

3.    Escolha a guia JSON. Em seguida, insira a seguinte política para conceder as permissões necessárias do IAM:

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

4.    Escolha Next (Avançar): Tags.

5.    (Opcional) Para adicionar uma tag, escolha Add tag (Adicionar tag) e insira os valores apropriados para os campos Key (Chave) e Value - optional (Valor - opcional).

6.    Escolha Next (Avançar): Revisar.

7.    Insira o nome da sua política. Por exemplo, insira step-functions-start-stop-rds-policy. Para revisar as permissões concedidas pela sua política, consulte a seção Resumo.

8.    Escolha Create policy (Criar política).

Para mais informações, consulte Creating policies using the JSON editor (Creating policies using the JSON editor).

Crie uma função do IAM e anexe as políticas necessárias

1.    Abra o console do IAM.

2.    No painel de navegação, selecione Roles (Perfis). Em seguida, escolha Create role (Criar perfil).

3.    Em Selecionar tipo de entidade confiável, escolha serviço da AWS.

4.    Na lista suspensa Casos de uso para outros serviços da AWS, escolha Step Functions. Em seguida, escolha a opção Step Functions.

5.    Escolha Next (Avançar).
Observação: não realize nenhuma ação na página Adicionar permissões. Crie a função primeiro e depois edite as permissões padrão.

6.    Escolha Next (Avançar).

7.    Em Nome da função, insira o nome da função. Por exemplo, insira step-functions-start-stop-rds-role.
(Opcional) Atualize a descrição da função.
(Opcional) Para adicionar uma tag, insira os valores apropriados para os campos Key (Chave) e Value (Valor).

8.    Escolha Create role (Criar perfil). Isso o leva de volta à lista de funções.

9.    Na caixa de pesquisa, digite o nome da função que você criou. Em seguida, selecione essa função para ver seus detalhes.

10.    Na guia Permissões, escolha a lista suspensa Adicionar permissões. Em seguida, escolha Anexar políticas.

11.    Insira o nome da política que você criou na seção Configurar permissões do IAM. Por exemplo, insira step-functions-start-stop-rds-policy. Quando você vê essa política como uma opção, selecione-a.

12.    Na guia Permissões, selecione a política gerenciada da AWS, AWS LambdaRole e escolha Remover.

Para mais informações, consulte Creating a role for an AWS service (console) (Criação de uma função para um serviço da AWS (console)).

Adicionar tags para instâncias de banco de dados

1.    Abra o console do Amazon RDS.

2.    No painel de navegação, escolha Painel.

3.    Selecione a instância de banco de dados que você deseja iniciar e interromper automaticamente.

4.    Escolha a guia Tags.

5.     Escolha Add (Adicionar). Em Tag key (chave tag), insira autostart. Em Value (Valor), insira yes.

6.    Escolha Add another Tag (Adicionar outra tag). Em Tag key (chave tag), insira autostop. Em Value (Valor), insira yes.

7.    Para salvar essas tags, escolha Add (Adicionar).

Para mais informações, consulte Adding, listing, and removing tags (Adicionar, listar e remover tags).

Crie uma máquina de estado para iniciar e interromper as instâncias de banco de dados marcadas

1.    Abra o console do Step Functions.

2.    No painel de navegação, escolha Máquinas de estado. Em seguida, escolha ** Criar máquina de estado**.

3.    Escolha Escrever seu fluxo de trabalho em código.

4.    Mantenha como padrão o Tipo Padrão.

5.     No editor de Definição, exclua a definição JSON de amostra. Em seguida, insira a seguinte definição de máquina de estado:

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

**Observação:**Para fins de teste, você pode modificar o campo Segundos no estado Esperar por 1 hora e 30 minutos. Além disso, você pode estender esse valor para uma janela de manutenção maior ou menor.

6.    Escolha Next (Avançar).

7.    Insira um nome de máquina de estado. Por exemplo, insira step-functions-start-stop-rds-state-machine.

8.    Em Permissões, escolha Escolher uma função existente. Em seguida, selecione a função do IAM que você criou. Por exemplo, selecione step-functions-start-stop-rds-role.

9.    (Opcional) Para adicionar uma tag, insira os valores apropriados para os campos Key (Chave) e Value (Valor).

10.    Escolha Criar máquina de estado.

Execute um teste de fluxo de trabalho

Para realizar testes de função para instâncias de banco de dados marcadas que estão no estado Parado, conclua as seguintes etapas:

1.    Abra o console do Step Functions.

2.    No painel de navegação, escolha Máquinas de estado.

3.    Selecione a máquina de estado que você criou para iniciar suas instâncias de banco de dados.

4.    Escolha Iniciar execução.
Observação: essa resolução não exige uma carga de eventos. Na caixa de diálogo Iniciar execução, você pode remover a carga do evento ou deixar o evento padrão.

5.    Escolha Iniciar execução.

Criar o cronograma

Para agendar uma janela de manutenção semanal para as instâncias de banco de dados marcadas, crie uma regra do EventBridge. Essa regra inicia automaticamente a instância de banco de dados 30 minutos antes da janela de manutenção.

No exemplo de caso de uso a seguir, a janela de manutenção ocorre das 22:00 às 22:30 no domingo. A regra de exemplo inicia a instância de banco de dados às 21:30 todos os domingos.

1.    Abra o console do EventBridge.

2.    Selecione a máquina de estado que você criou anteriormente na seção Criar uma máquina de estado para iniciar e interromper as instâncias de banco de dados marcadas.

3.    Em Barramentos, selecione Regras.

4.    Escolha o barramento de eventos padrão na lista suspensa.

5.    Selecione Criar regra.

6.    Em Rule name (Nome da regra), insira o nome da regra que você deseja criar. Por exemplo, insira step-functions-start-stop-rds-rule.

7.    Para Tipo de regra, escolha Cronograma. Para outros valores nesta página, mantenha suas configurações padrão.

8.    Escolha Continuar com o EventBridge Scheduler.

9.    Em Cronograma recorrente, escolha Ocorrência. Em seguida, em Tipo de agendamento, escolha Agendamento baseado em Cronograma.

10.    Adicione uma expressão de cronograma para o agendamento automatizado. Por exemplo, insira cron(30 21 ? * SUN *).

11.    Para a Janela de tempo flexível, escolha Desativado.

12.    Escolha Next (Avançar).

13.    Escolha APIs Usadas com frequência e, em seguida, escolha StartExecution.

14.    Em StartExecution, selecione a máquina de estado que você criou. Por exemplo, selecione step-functions-start-stop-rds-state-machine. Mantenha o valor padrão da entrada de {}.

15.    Escolha Next (Avançar).

16.    Em Política de repetição e fila de espera (DLQ), desmarque a Política de repetição para desativá-la.

17.    Em Permissões, mantenha a opção padrão: Crie uma nova função para esse cronograma.

**Observação:**O EventBridge cria uma nova função para assumir e iniciar a API StartExecution para seu fluxo de trabalho específico.

18.    Escolha Next (Avançar).

19.    Em Detalhes do cronograma, verifique se as próximas 10 datas de invocação correspondem às datas do seu cronograma esperado.

20.    Escolha Criar cronograma.

Quando o EventBridge invoca a regra, ele inicia o fluxo de trabalho do Step Function. Isso inicia as instâncias de banco de dados 30 minutos antes da janela de manutenção. Em seguida, o fluxo de trabalho interrompe a instância de banco de dados 30 minutos após a conclusão da janela de manutenção.  Por exemplo, o fluxo de trabalho inicia sua instância de banco de dados às 21:30. A janela de manutenção ocorre das 22:00 às 22:30. Em seguida, o fluxo de trabalho interrompe sua instância às 23:00.