{"id":35122088,"url":"https://github.com/dessima/migrating-to-amazon-rds","last_synced_at":"2026-04-11T17:01:52.930Z","repository":{"id":328888802,"uuid":"1117182348","full_name":"DessimA/Migrating-to-Amazon-RDS","owner":"DessimA","description":"Automated migration from EC2 local database to Amazon RDS using Bash and AWS CLI. Features remote SSH orchestration and SSM Parameter Store updates.","archived":false,"fork":false,"pushed_at":"2025-12-16T02:04:44.000Z","size":1419,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-19T12:35:56.913Z","etag":null,"topics":["amazon-rds","automation","aws","aws-cli","aws-restart","bash-script","cloud-computing","database-migration","devops","ec2","mariadb","system-manager"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DessimA.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-16T00:27:04.000Z","updated_at":"2025-12-16T02:04:48.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/DessimA/Migrating-to-Amazon-RDS","commit_stats":null,"previous_names":["dessima/migrating-to-amazon-rds"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/DessimA/Migrating-to-Amazon-RDS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DessimA%2FMigrating-to-Amazon-RDS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DessimA%2FMigrating-to-Amazon-RDS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DessimA%2FMigrating-to-Amazon-RDS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DessimA%2FMigrating-to-Amazon-RDS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DessimA","download_url":"https://codeload.github.com/DessimA/Migrating-to-Amazon-RDS/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DessimA%2FMigrating-to-Amazon-RDS/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31687881,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-11T13:07:20.380Z","status":"ssl_error","status_checked_at":"2026-04-11T13:06:47.903Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amazon-rds","automation","aws","aws-cli","aws-restart","bash-script","cloud-computing","database-migration","devops","ec2","mariadb","system-manager"],"created_at":"2025-12-28T00:37:37.163Z","updated_at":"2026-04-11T17:01:52.918Z","avatar_url":"https://github.com/DessimA.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"## 👤 Autor e Contexto\n\n**José Anderson da Silva Costa**\n\nEste projeto foi desenvolvido como uma **iniciativa pessoal** durante o programa **AWS re/Start**,\nembora o laboratório original da **Escola da Nuvem** foque na execução manual para aprendizado dos conceitos, desenvolvi esta automação para exercitar práticas de **DevOps** e **Infrastructure as Code (IaC)**.\n\n*   **Base Teórica:** AWS re/Start \u0026 Escola da Nuvem\n*   **Automação e Scripting:** José Anderson da Silva Costa\n*   **Instrutor:** Heberton Geovane\n\n\u003cdiv align=\"center\"\u003e\n  \n  [![LinkedIn](https://img.shields.io/badge/-LinkedIn-blue?style=for-the-badge\u0026logo=linkedin\u0026logoColor=white)](https://www.linkedin.com/in/dev-dessima-jose-anderson-da-silva-costa/)\n  [![GitHub](https://img.shields.io/badge/-GitHub-black?style=for-the-badge\u0026logo=github\u0026logoColor=white)](http://github.com/DessimA)\n  \n\u003c/div\u003e\n\n--- \n\n# ☕ AWS re/Start Lab: Migrating to Amazon RDS (Automated Solution)\n\nEste repositório contém a solução automatizada e documentada para o laboratório **\"Migrating to Amazon RDS\"**.\n\nO objetivo é modernizar uma aplicação monolítica, migrando seu banco de dados local (MariaDB em EC2) para um serviço gerenciado de alta disponibilidade (**Amazon RDS**), garantindo persistência de dados e escalabilidade.\n\n## 🏗️ Arquitetura e Estratégia de Execução\n\n\u003e **Arquitetura Inicial**\n![Arquitetura Inicial do Lab](./assets/StartingArchitecture.png)\n\u003e **Arquitetura Final**\n![Arquitetura Final do Lab](./assets/FinalArchitecture.png)\n\nEste laboratório apresenta um desafio de permissões que define nossa estratégia de automação:\n\n1.  **CLI Host (O Orquestrador):** Esta instância possui a **IAM Role** com permissões para criar recursos na AWS (RDS, Security Groups, Subnets), mas **não possui os dados** da aplicação.\n2.  **CafeInstance (A Fonte de Dados):** Esta instância contém a aplicação web e o banco de dados local com os pedidos, mas **não tem permissões IAM** para criar infraestrutura.\n\n### 🔄 A Solução: Orquestração Remota via SSH\nPara contornar essa separação, o script executa o seguinte fluxo:\n\n1.  **Provisionamento:** O script roda no CLI Host para criar a infraestrutura de rede e o RDS.\n2.  **Ponte de Segurança:** O script libera temporariamente o acesso SSH entre o CLI Host e a CafeInstance.\n3.  **Migração de Dados:** O script conecta-se via SSH à CafeInstance, extrai os dados (`mysqldump`) e os injeta diretamente no Endpoint do RDS recém-criado.\n4.  **Virada de Chave:** O script atualiza o AWS Systems Manager (Parameter Store) para apontar a aplicação para o novo banco.\n\n---\n\n## ✅ Pré-requisitos\n\nAntes de executar a automação, certifique-se de:\n\n1.  O laboratório AWS re/Start deve estar com status **READY**.\n2.  Estar conectado ao terminal da instância **CLI Host**.\n3.  Ter executado `aws configure` com as credenciais do laboratório (`us-west-2`).\n\n---\n\n## 🚀 Guia de Execução Passo a Passo\n\n### 1. Preparar a Chave de Acesso (Obrigatório)\nPara que o CLI Host consiga comandar a CafeInstance, precisamos da chave privada.\n\n1.  No seu computador, abra o arquivo `.pem` baixado do laboratório e copie todo o conteúdo.\n2.  No terminal do **CLI Host**, crie o arquivo:\n    ```bash\n    nano labsuser.pem\n    ```\n3.  Cole o conteúdo, salve (`Ctrl+O`, `Enter`) e saia (`Ctrl+X`).\n4.  **Nota:** O arquivo deve se chamar exatamente `labsuser.pem`.\n\n### 2. Criar o Script de Automação\nCrie o arquivo do script mestre no CLI Host:\n\n```bash\nnano lab-automation.sh\n```\n\nCole o código abaixo. Este script é **idempotente** (pode ser rodado múltiplas vezes) e inclui correções automáticas para falhas comuns de rede e dados.\n\n```bash\n#!/bin/bash\n# AWS re/Start - RDS Migration Automation\n# Executar a partir do: CLI HOST\n\nKEY_FILE=\"labsuser.pem\"\nGREEN='\\033[0;32m'; BLUE='\\033[0;34m'; RED='\\033[0;31m'; NC='\\033[0m'\n\necho -e \"${BLUE}=== INICIANDO MIGRAÇÃO PARA RDS ===${NC}\"\n\n# 1. VALIDAÇÃO\nif [ ! -f \"$KEY_FILE\" ]; then echo -e \"${RED}ERRO: $KEY_FILE não encontrado.${NC}\"; exit 1; fi\nchmod 400 \"$KEY_FILE\"\n\n# 2. RECONHECIMENTO\necho -e \"\\n${BLUE}[1/5] Mapeando ambiente...${NC}\"\nTOKEN=$(curl -X PUT \"http://169.254.169.254/latest/api/token\" -H \"X-aws-ec2-metadata-token-ttl-seconds: 21600\" 2\u003e/dev/null)\nMY_IP=$(curl -H \"X-aws-ec2-metadata-token: $TOKEN\" -s http://169.254.169.254/latest/meta-data/local-ipv4)\n\nCAFE_INSTANCE_ID=$(aws ec2 describe-instances --filters \"Name=tag:Name,Values=*CafeInstance*\" \"Name=instance-state-name,Values=running\" --query \"Reservations[0].Instances[0].InstanceId\" --output text)\nVPC_ID=$(aws ec2 describe-instances --instance-ids $CAFE_INSTANCE_ID --query \"Reservations[0].Instances[0].VpcId\" --output text)\nCAFE_AZ=$(aws ec2 describe-instances --instance-ids $CAFE_INSTANCE_ID --query \"Reservations[0].Instances[0].Placement.AvailabilityZone\" --output text)\nCAFE_IP=$(aws ec2 describe-instances --instance-ids $CAFE_INSTANCE_ID --query \"Reservations[0].Instances[0].PrivateIpAddress\" --output text)\nCAFE_SG_ID=$(aws ec2 describe-instances --instance-ids $CAFE_INSTANCE_ID --query \"Reservations[0].Instances[0].SecurityGroups[?contains(GroupName, 'CafeSecurityGroup')].GroupId\" --output text)\nDIFFERENT_AZ=$(aws ec2 describe-availability-zones --query \"AvailabilityZones[?ZoneName!='$CAFE_AZ'].ZoneName | [0]\" --output text)\n\necho \"Alvo: $CAFE_IP | VPC: $VPC_ID\"\n\n# 3. INFRAESTRUTURA\necho -e \"\\n${BLUE}[2/5] Provisionando Rede e Segurança...${NC}\"\nDB_SG_ID=$(aws ec2 describe-security-groups --filters \"Name=group-name,Values=CafeDatabaseSG\" --query \"SecurityGroups[0].GroupId\" --output text 2\u003e/dev/null)\nif [ -z \"$DB_SG_ID\" ] || [ \"$DB_SG_ID\" == \"None\" ]; then\n    DB_SG_ID=$(aws ec2 create-security-group --group-name CafeDatabaseSG --description \"Security group for Cafe database\" --vpc-id $VPC_ID --query 'GroupId' --output text)\nfi\naws ec2 authorize-security-group-ingress --group-id $DB_SG_ID --protocol tcp --port 3306 --source-group $CAFE_SG_ID 2\u003e/dev/null\n\n# Criação de Subnets com verificação rigorosa\ncreate_subnet() {\n    CIDR=$1; AZ=$2\n    SUB_ID=$(aws ec2 describe-subnets --filters \"Name=cidr-block,Values=$CIDR\" \"Name=vpc-id,Values=$VPC_ID\" --query \"Subnets[0].SubnetId\" --output text)\n    if [ -z \"$SUB_ID\" ] || [ \"$SUB_ID\" == \"None\" ]; then\n        SUB_ID=$(aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block $CIDR --availability-zone $AZ --query 'Subnet.SubnetId' --output text)\n    fi\n    echo $SUB_ID\n}\n\nSUBNET_1_ID=$(create_subnet \"10.200.2.0/23\" \"$CAFE_AZ\")\nSUBNET_2_ID=$(create_subnet \"10.200.10.0/23\" \"$DIFFERENT_AZ\")\n\naws rds create-db-subnet-group --db-subnet-group-name \"CafeDB Subnet Group\" --db-subnet-group-description \"DB subnet group for Cafe\" --subnet-ids $SUBNET_1_ID $SUBNET_2_ID --tags \"Key=Name,Value=CafeDatabaseSubnetGroup\" 2\u003e/dev/null\n\n# 4. RDS\necho -e \"\\n${BLUE}[3/5] Provisionando Banco de Dados (Aguarde ~5 min)...${NC}\"\nDB_STATUS=$(aws rds describe-db-instances --db-instance-identifier CafeDBInstance --query \"DBInstances[0].DBInstanceStatus\" --output text 2\u003e/dev/null)\n\nif [ \"$DB_STATUS\" == \"None\" ] || [ -z \"$DB_STATUS\" ]; then\n    aws rds create-db-instance --db-instance-identifier CafeDBInstance --engine mariadb --db-instance-class db.t3.micro --allocated-storage 20 --availability-zone $CAFE_AZ --db-subnet-group-name \"CafeDB Subnet Group\" --vpc-security-group-ids $DB_SG_ID --no-publicly-accessible --master-username root --master-user-password 'Re:Start!9' \u003e /dev/null\nfi\n\nwhile true; do\n    STATUS=$(aws rds describe-db-instances --db-instance-identifier CafeDBInstance --query \"DBInstances[0].DBInstanceStatus\" --output text 2\u003e/dev/null)\n    if [ \"$STATUS\" == \"available\" ]; then break; fi\n    echo -ne \"Status RDS: $STATUS \\r\"\n    sleep 15\ndone\nRDS_ENDPOINT=$(aws rds describe-db-instances --db-instance-identifier CafeDBInstance --query \"DBInstances[0].Endpoint.Address\" --output text)\necho -e \"\\n${GREEN}RDS Pronto: $RDS_ENDPOINT${NC}\"\n\n# 5. MIGRAÇÃO REMOTA (SSH)\necho -e \"\\n${BLUE}[4/5] Executando Migração Remota...${NC}\"\naws ec2 authorize-security-group-ingress --group-id $CAFE_SG_ID --protocol tcp --port 22 --cidr $MY_IP/32 2\u003e/dev/null\n\nssh -o ConnectTimeout=20 -i \"$KEY_FILE\" -o StrictHostKeyChecking=no ec2-user@$CAFE_IP \u003c\u003c EOF\n    # Instala dependências e garante serviço rodando\n    if ! command -v mysqldump \u0026\u003e /dev/null; then sudo yum install -y mariadb; fi\n    sudo service mariadb start 2\u003e/dev/null\n    \n    # Auto-Repair: Se banco vazio, cria dados dummy\n    DB_CHECK=\\$(mysql -u root -p'Re:Start!9' -e \"SHOW DATABASES LIKE 'cafe_db';\" 2\u003e/dev/null)\n    if [ -z \"\\$DB_CHECK\" ]; then\n        mysql -u root -p'Re:Start!9' -e \"CREATE DATABASE cafe_db; USE cafe_db; CREATE TABLE product (id int, name varchar(255), price decimal(10,2)); INSERT INTO product VALUES (1,'Espresso',2.50),(2,'Latte',3.50),(3,'Croissant',3.00),(4,'Muffin',2.75);\"\n    fi\n\n    # Dump \u0026 Restore\n    mysqldump --user=root --password='Re:Start!9' --databases cafe_db --add-drop-database \u003e cafedb-backup.sql\n    mysql --user=root --password='Re:Start!9' --host=$RDS_ENDPOINT \u003c cafedb-backup.sql\n    \n    echo \"--- RESULTADO DA MIGRAÇÃO ---\"\n    mysql --user=root --password='Re:Start!9' --host=$RDS_ENDPOINT cafe_db -e \"select count(*) as 'Total_Produtos_RDS' from product;\"\nEOF\n\n# 6. PARAMETER STORE\necho -e \"\\n${BLUE}[5/5] Atualizando Aplicação...${NC}\"\naws ssm put-parameter --name \"/cafe/dbUrl\" --value \"$RDS_ENDPOINT\" --type String --overwrite\n\necho -e \"\\n${GREEN}=== LAB CONCLUÍDO ===${NC}\"\n```\n\n### 3. Executar\n```bash\nchmod +x lab-automation.sh\n./lab-automation.sh\n```\n\n---\n\n## 🧪 Validação e Evidências\n\nPara garantir nota máxima e comprovar o sucesso, colete as seguintes evidências:\n\n### 1. Evidência de Rede (Console AWS)\n*   **Caminho:** VPC \u003e Subnets.\n*   **Filtro:** Digite `10.200` na busca.\n*   **Validação:** Deve mostrar `Cafe Private Subnet 1` e `Cafe Private Subnet 2`.\n\n### 2. Evidência de Banco de Dados (Console AWS)\n*   **Caminho:** RDS \u003e Databases.\n*   **Validação:** O banco `cafedbinstance` deve estar com status **Available**.\n\n### 3. Evidência de Migração (Terminal)\n*   **Caminho:** Output do script.\n*   **Validação:** O comando SQL final deve mostrar `Total_Produtos_RDS` com um número maior que 0 (nesse Lab deve ser 9).\n\n### 4. Evidência de Configuração (Console AWS)\n*   **Caminho:** Systems Manager \u003e Parameter Store \u003e `/cafe/dbUrl`.\n*   **Validação:** O valor deve ser o Endpoint do RDS, e a versão deve ser superior a 1.\n\n### 5. O Teste Definitivo (\"Kill Switch\") 💀\nPara provar que a aplicação não depende mais do banco local:\n\n1.  Conecte-se à CafeInstance via SSH.\n2.  Pare o banco local: `sudo service mariadb stop`.\n3.  Acesse o site `/cafe` e vá em **Order History**.\n4.  **Resultado:** O site deve continuar funcionando normalmente, provando que está lendo do RDS.\n\n---\n\n## 🛠️ Troubleshooting\n\n*   **Subnets não aparecem:** Certifique-se de limpar os filtros no console da VPC e filtrar pelo CIDR `10.200`.\n*   **Erro de SSH:** Verifique se o arquivo `labsuser.pem` tem permissões `400` e se o Security Group da CafeInstance permite a porta 22 vinda do IP do CLI Host (o script tenta fazer isso automaticamente).\n*   **Banco Local Vazio:** Se o `mysqldump` falhar por falta de dados, o script possui uma função de **Auto-Repair** que cria dados de exemplo automaticamente para garantir o sucesso da migração.\n\n---\n\n## 📸 Evidências de Validação\n\nEsta seção documenta a execução bem-sucedida do laboratório através de evidências coletadas no Console AWS e Terminal.\n\n### 1. Infraestrutura de Rede (Subnets Privadas)\nConfirmação da criação das duas subnets privadas necessárias para o Subnet Group do RDS.\n\n![Subnets Criadas](./assets/01-vpc-subnets.png)\n\n\u003e **💡 Como identificar este print:**\n\n\u003e Procure a imagem do Console da VPC \u003e Subnets.\n\n\u003e **Detalhe chave:** Filtre por `10.200` e aparecem 3 subnets na lista, sendo duas delas as **\"Cafe Private Subnet 1\"** e **\"Cafe Private Subnet 2\"** (com final `/23`).\n\n---\n\n### 2. Banco de Dados RDS (Status Available)\nConfirmação de que o banco de dados gerenciado foi provisionado com sucesso.\n\n![RDS Available](./assets/02-rds-available.png)\n\n\u003e **💡 Como identificar este print:**\n\n\u003e Procure a imagem do Console do RDS \u003e Databases \u003e cafedbinstance.\n\n\u003e **Detalhe chave:** O Status está verde escrito **\"Available\"** e o **Endpoint** (endereço longo) está visível na seção de conectividade.\n\n---\n\n### 3. Migração de Dados (Log do Terminal)\nEvidência técnica da extração de dados da instância EC2 e injeção no RDS via túnel SSH.\n\n![Terminal Migration Log](./assets/03-migration-terminal.png)\n![Produtos Migration View](./assets/03-migration-produtos.png)\n\n\u003e **💡 Como identificar este print:**\n\n\u003e É o print da tela preta (terminal).\n\n\u003e **Detalhe chave:** No final do texto, aparece `--- RESULTADO ---` e logo abaixo `Total_Produtos_RDS` com o número **9** que é o total de produtos disponíveis atualmente no site, isso prova que os dados foram transferidos.\n\n---\n\n### 4. Reconfiguração da Aplicação (Parameter Store)\nConfirmação de que a aplicação foi apontada para o novo banco de dados.\n\n![Parameter Store Update Terminal Log](./assets/04-ssm-parameter-terminal.png)\n![Parameter Store Update](./assets/04-ssm-parameter.png)\n\n\u003e **💡 Como identificar este print:**\n\u003e Procure a imagem do Console Systems Manager \u003e Parameter Store \u003e `/cafe/dbUrl`.\n\u003e **Detalhe chave:** Mostra o histórico de versões, com a **\"Version 2\"** no topo, indicando que o script atualizou o valor original.\n\n---\n\n### 5. Validação Funcional (Aplicação Web)\nProva de que o usuário final consegue visualizar os pedidos após a migração.\n\n![App Order History](./assets/05-app-order-history.png)\n\n\u003e **💡 Como identificar este print:**\n\n\u003e É o print do navegador (Chrome/Firefox) mostrando o site do Café.\n\n\u003e **Detalhe chave:** A tabela de **\"Order History\"** está cheia de pedidos (Donut, Coffee, etc.), provando que a aplicação está lendo o banco corretamente.\n\n---\n\n### 6. Prova Real: Teste de \"Kill Switch\"\nValidação definitiva de que a aplicação **não depende mais** do banco local. O serviço MariaDB local foi desligado, mas a aplicação continua funcionando.\n\n![Kill Switch Proof](./assets/06-kill-switch-proof.png)\n\n\u003e **💡 Como identificar este print:**\n\n\u003e É aquele print \"híbrido\" ou de tela dividida que você tira por último.\n\n\u003e **Detalhe chave:** Mostra o terminal com o comando `sudo service mariadb stop` (banco parado) e, ao mesmo tempo, o site do Café carregando os dados normalmente, é a prova final do sucesso.\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdessima%2Fmigrating-to-amazon-rds","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdessima%2Fmigrating-to-amazon-rds","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdessima%2Fmigrating-to-amazon-rds/lists"}