Resilience, Disaster Recovery và Migration: shop-app sống qua một region "biến mất"

5 câu hỏi~45 phútTừ khóa: RTO, RPO, backup & restore, pilot light, warm standby, multi-site active-active, AWS Backup, S3 CRR, cross-region snapshot, Route 53 failover, Aurora Global, 7R, DMS, SCT, MGN, Migration Hub, Snowball, SAA: Domain 2 Resilient

Tiếp đi: disaster recovery. Sếp hỏi "nếu cả region Singapore sập thì shop-app bao lâu chạy lại và mất bao nhiêu đơn hàng?" Mình trả lời là RDS đã Multi-AZ rồi nên chắc không sao. Sếp bảo chưa đủ. Mình thiếu gì?

Sếp đúng, và câu hỏi của sếp chính là định nghĩa của hai con số bạn phải trả lời bằng số chứ không bằng "chắc không sao": RTO (bao lâu chạy lại) và RPO (mất dữ liệu bao nhiêu phút). Multi-AZ (22.7) bảo vệ khỏi mất một AZ; DR nói về mất cả region, hoặc mất dữ liệu do lỗi người/ransomware mà Multi-AZ sao chép lỗi đó sang standby tức thì. Bài này đi từ hai con số đó đến 4 chiến lược DR, dựng lab region thứ hai ở Tokyo, rồi nửa sau nói về migration vì đề SAA gom hai chủ đề này cùng domain.

1. Bài toán: điền hai con số

Hiện trạng shop-app, tất cả ở ap-southeast-1:
  Route 53 shop.example.com → CloudFront → shop-alb → shop-asg (2–4 EC2)
  RDS shop-db Multi-AZ (standby ở 1b), backup tự động 7 ngày, snapshot cùng region
  S3 shop-app-assets (ảnh), shop-app-logs
  DynamoDB shop-sessions, shop-carts; ElastiCache shop-cache; SQS shop-order-events

Kịch bản thảm họa      Multi-AZ cứu?   Backup cùng region cứu?
  Mất 1 AZ                 ✔ (1–2 phút)      ✔
  Mất cả region            ✘                 ✘ (snapshot nằm cùng region)
  DROP TABLE orders nhầm   ✘ (replicate lỗi) ✔ PITR, nhưng mất tới 5 phút dữ liệu
  Ransomware mã hóa S3     ✘                 ✔ nếu có versioning + object lock
  Tài khoản AWS bị chiếm   ✘                 ✘ (kẻ xấu xóa cả backup) → cần backup sang account khác

2. Vấn đề

3. Giải pháp: RTO/RPO → 4 chiến lược

            thảm họa xảy ra
                 │
  ◄── RPO ──────►│◄──────────── RTO ────────────►
  lần backup/    │ phát hiện  quyết định  restore  đổi DNS  ổn
  replicate cuối │
  "mất bao nhiêu dữ liệu"      "mất bao lâu dịch vụ"

Ví dụ shop-app: nghiệp vụ chấp nhận RPO 15 phút (mất tối đa 15 phút đơn hàng, có thể gọi khách xác nhận) và RTO 1 giờ. Đó là bài toán của pilot light.

Chiến lượcRTORPORegion 2 có gìChi phí tương đốiThuật ngữ đề
Backup & RestoreGiờ → ngàyGiờ (tần suất backup)Chỉ có backup (snapshot, S3 CRR). Dựng hạ tầng khi cần$ (chỉ phí lưu)"lowest cost", "RTO of 24 hours acceptable", AWS Backup cross-region copy
Pilot Light10 phút → 1 giờPhút (replicate liên tục)Dữ liệu sống (RDS read replica / Aurora Global, DynamoDB Global Table, S3 CRR), hạ tầng core nhưng compute tắt (ASG desired 0, AMI sẵn)$$"data replicated, core services, scale out when needed", "minimal running resources"
Warm StandbyPhútGiây → phútBản thu nhỏ đang chạy (ASG 1 instance, DB replica), có thể nhận traffic ngay rồi scale$$$"scaled-down but fully functional copy", "business-critical"
Multi-site Active-Active≈ 0 (giây)≈ 0Bản đầy đủ nhận traffic thật ở cả hai region; Route 53 latency/weighted; DB hai chiều (Aurora Global write forwarding, DynamoDB Global Tables)$$$$"zero downtime", "near-zero RPO/RTO", "serve users from both regions", "active-active"
Backup & Restore          Pilot Light               Warm Standby              Multi-site Active-Active
ap-se-1  │  ap-ne-1       ap-se-1  │  ap-ne-1       ap-se-1  │  ap-ne-1       ap-se-1  │  ap-ne-1
 ALB     │                 ALB     │  (ALB tạo sẵn   ALB     │   ALB           ALB     │   ALB
 ASG×2   │                 ASG×2   │   ASG desired=0) ASG×2   │   ASG×1          ASG×2   │   ASG×2
 RDS ────┼─► snapshot      RDS ────┼─► read replica  RDS ────┼─► read replica  Aurora Global / DDB Global
 S3  ────┼─► S3 (CRR)      S3  ────┼─► S3 (CRR)      S3  ────┼─► S3 (CRR)      S3 ◄───┼──► S3 (bi-dir)
         │  (không chạy)           │  (DB sống,              │  (chạy nhỏ)             │  (cả hai nhận traffic)
Route 53: đổi tay         Route 53 failover          Route 53 failover         Route 53 latency/weighted
RTO ngày  RPO giờ          RTO ~30 phút RPO phút      RTO phút   RPO giây        RTO ~0     RPO ~0
$          $$               $$$                       $$$$

Dịch vụ xây DR và thuật ngữ:

Nhu cầuDịch vụThuật ngữ
Backup tập trung nhiều dịch vụ, copy sang region/account khácAWS Backupbackup plan, backup rule, backup vault, vault lock (WORM), cross-region copy, cross-account copy (Organizations), resource assignment theo tag, PITR cho RDS/DynamoDB/S3, Backup Audit Manager
Dữ liệu DB sống ở region 2RDS cross-region read replica, Aurora Global DatabaseAurora Global: replication lag < 1 s, RTO < 1 phút, promote secondary; RDS replica promote; automated backup replication cross-region
Object ở region 2S3 Cross-Region Replication (CRR)Cần versioning cả 2 bucket, chỉ replicate object mới (Batch Replication cho cũ), RTC (Replication Time Control 15 phút SLA), replicate delete marker tùy chọn, không chain
NoSQL đa regionDynamoDB Global Tablesactive-active, last-writer-wins, cần Streams
Ảnh máy ở region 2AMI copy, EBS snapshot copycopy-image cross-region, encrypted với KMS key của region đích
Đổi hướng người dùngRoute 53 failover routing + health checkPRIMARY/SECONDARY record, health check endpoint, TTL ngắn, "evaluate target health"; 22.10
Replicate server EC2 liên tục sang region khácElastic Disaster Recovery (DRS)Block-level replication, staging area rẻ, point-in-time recovery, drill; kế thừa CloudEndure DR
Dữ liệu không thể xóaS3 Object Lock, Backup Vault Lock, EBS snapshot lockCompliance vs Governance mode, ransomware

4. Cấu hình từng bước (pilot light cho shop-app)

Bước 1: AWS Backup plan gom RDS + EBS + DynamoDB + EFS theo tag Project=shop-app, copy sang vault ở ap-northeast-1:

aws backup create-backup-vault --profile shop-lab --backup-vault-name shop-vault \
  --backup-vault-tags Project=shop-app,Env=lab
aws backup create-backup-vault --profile shop-lab --region ap-northeast-1 --backup-vault-name shop-vault-dr \
  --backup-vault-tags Project=shop-app,Env=lab
aws backup create-backup-plan --profile shop-lab --backup-plan '{
  "BackupPlanName": "shop-daily",
  "Rules": [{
    "RuleName": "daily-with-dr-copy",
    "TargetBackupVaultName": "shop-vault",
    "ScheduleExpression": "cron(0 18 * * ? *)",
    "StartWindowMinutes": 60, "CompletionWindowMinutes": 180,
    "Lifecycle": { "DeleteAfterDays": 35 },
    "CopyActions": [{
      "DestinationBackupVaultArn": "arn:aws:backup:ap-northeast-1:'$ACCOUNT_ID':backup-vault:shop-vault-dr",
      "Lifecycle": { "DeleteAfterDays": 35 }
    }],
    "EnableContinuousBackup": true
  }]
}'
aws backup create-backup-selection --profile shop-lab --backup-plan-id $PLAN_ID --backup-selection '{
  "SelectionName": "by-tag", "IamRoleArn": "arn:aws:iam::'$ACCOUNT_ID':role/service-role/AWSBackupDefaultServiceRole",
  "ListOfTags": [{ "ConditionType": "STRINGEQUALS", "ConditionKey": "Project", "ConditionValue": "shop-app" }]
}'

EnableContinuousBackup cho RDS/S3 là PITR (RPO xuống 5 phút trong cùng region); bản copy sang region khác vẫn là snapshot theo lịch (RPO 24 giờ) – muốn tốt hơn phải dùng replica.

Bước 2: S3 CRR cho bucket assets. Cần versioning hai bên và role cho S3:

aws s3api put-bucket-versioning --profile shop-lab --bucket shop-app-assets-$ACCOUNT_ID --versioning-configuration Status=Enabled
aws s3api create-bucket --profile shop-lab --bucket shop-app-assets-dr-$ACCOUNT_ID --region ap-northeast-1 \
  --create-bucket-configuration LocationConstraint=ap-northeast-1
aws s3api put-bucket-versioning --profile shop-lab --region ap-northeast-1 --bucket shop-app-assets-dr-$ACCOUNT_ID --versioning-configuration Status=Enabled
aws s3api put-bucket-replication --profile shop-lab --bucket shop-app-assets-$ACCOUNT_ID --replication-configuration '{
  "Role": "arn:aws:iam::'$ACCOUNT_ID':role/shop-s3-replication-role",
  "Rules": [{ "ID": "assets-to-tokyo", "Status": "Enabled", "Priority": 1, "Filter": {},
    "DeleteMarkerReplication": { "Status": "Disabled" },
    "Destination": { "Bucket": "arn:aws:s3:::shop-app-assets-dr-'$ACCOUNT_ID'", "StorageClass": "STANDARD_IA",
                     "ReplicationTime": { "Status": "Enabled", "Time": { "Minutes": 15 } },
                     "Metrics": { "Status": "Enabled", "EventThreshold": { "Minutes": 15 } } } }]
}'

DeleteMarkerReplication Disabled: xóa nhầm ở Singapore không lan sang Tokyo – đây là lớp bảo vệ, không chỉ là bản sao. STANDARD_IA ở đích vì DR ít đọc.

Bước 3: RDS sang region 2. Hai mức: rẻ là copy snapshot (RPO = tần suất copy), tốt hơn là cross-region read replica (RPO giây, nhưng trả tiền instance 24/7):

# Mức rẻ: copy snapshot thủ công / từ AWS Backup, mã hóa bằng KMS key ở Tokyo
aws rds copy-db-snapshot --profile shop-lab --region ap-northeast-1 \
  --source-db-snapshot-identifier arn:aws:rds:ap-southeast-1:$ACCOUNT_ID:snapshot:shop-db-manual-20261021 \
  --target-db-snapshot-identifier shop-db-dr-20261021 \
  --kms-key-id alias/shop-key-tokyo --source-region ap-southeast-1
# Hoặc bật replicate automated backup liên tục (PITR ở region 2, không cần instance)
aws rds start-db-instance-automated-backups-replication --profile shop-lab --region ap-northeast-1 \
  --source-db-instance-arn arn:aws:rds:ap-southeast-1:$ACCOUNT_ID:db:shop-db \
  --kms-key-id alias/shop-key-tokyo --backup-retention-period 7
# Mức pilot light "ấm": read replica
aws rds create-db-instance-read-replica --profile shop-lab --region ap-northeast-1 \
  --db-instance-identifier shop-db-tokyo --source-db-instance-identifier arn:aws:rds:ap-southeast-1:$ACCOUNT_ID:db:shop-db \
  --db-instance-class db.t3.micro --kms-key-id alias/shop-key-tokyo --tags Key=Project,Value=shop-app Key=Env,Value=lab

Khi failover: promote-read-replica biến replica thành DB độc lập (vài phút), app ở Tokyo trỏ vào endpoint mới – lưu endpoint trong Secrets Manager shop/db replicate sang Tokyo (Secrets Manager có multi-region replication của secret).

Bước 4: Hạ tầng Tokyo bằng Terraform, compute = 0. Cùng module đã viết cho Singapore, đổi region và asg_desired = 0. AMI copy sang:

aws ec2 copy-image --profile shop-lab --region ap-northeast-1 --source-region ap-southeast-1 \
  --source-image-id $SHOP_AMI --name shop-app-ami-dr --encrypted --kms-key-id alias/shop-key-tokyo

Bước 5: Route 53 failover.

HC_ID=$(aws route53 create-health-check --profile shop-lab --caller-reference shop-primary-$(date +%s) \
  --health-check-config "Type=HTTPS,FullyQualifiedDomainName=$ALB_SG_DNS,Port=443,ResourcePath=/actuator/health,RequestInterval=30,FailureThreshold=3" \
  --query HealthCheck.Id --output text)
aws route53 change-resource-record-sets --profile shop-lab --hosted-zone-id $ZONE_ID --change-batch '{
 "Changes": [
  { "Action": "UPSERT", "ResourceRecordSet": { "Name": "shop.example.com", "Type": "A", "SetIdentifier": "primary-sg",
    "Failover": "PRIMARY", "HealthCheckId": "'$HC_ID'",
    "AliasTarget": { "HostedZoneId": "'$ALB_SG_ZONE'", "DNSName": "'$ALB_SG_DNS'", "EvaluateTargetHealth": true } } },
  { "Action": "UPSERT", "ResourceRecordSet": { "Name": "shop.example.com", "Type": "A", "SetIdentifier": "secondary-tokyo",
    "Failover": "SECONDARY",
    "AliasTarget": { "HostedZoneId": "'$ALB_TOKYO_ZONE'", "DNSName": "'$ALB_TOKYO_DNS'", "EvaluateTargetHealth": true } } } ] }'

Health check của Route 53 đi từ ngoài Internet vào ALB (ALB SG đã mở 443). Với pilot light, record SECONDARY trỏ tới ALB Tokyo đang không có target; runbook failover gồm: promote replica → đổi secret → asg set-desired-capacity 2 → health check primary fail tự chuyển DNS. Có thể tự động hóa runbook bằng SSM Automation hoặc Step Functions kích hoạt từ alarm.

5. Cách hoạt động: failover pilot light

 Bình thường                                   Thảm họa ap-southeast-1
 user → Route 53 (PRIMARY healthy)             user → Route 53: health check fail 3×30s → trả SECONDARY (TTL 60s)
        → shop-alb SG → ASG×2 → RDS Multi-AZ          → shop-alb Tokyo → ASG 0→2 (AMI DR, user data lấy secret Tokyo)
 RDS ──async──► read replica Tokyo (lag ~1s)   runbook: promote-read-replica shop-db-tokyo (3–5 phút)
 S3 assets ──CRR (RTC 15 phút)──► assets-dr            update secret shop/db (replica Tokyo đã có)
 AWS Backup 18:00 daily ──copy──► vault Tokyo          set-desired-capacity shop-asg-tokyo 2 (~4 phút health)
 Secrets Manager shop/db ──replicate──► Tokyo   RTO ≈ 2 (phát hiện) + 5 (promote) + 5 (scale) + 1 (DNS) ≈ 15 phút
                                                RPO ≈ replica lag ≈ giây; đơn hàng trong SQS Singapore chờ region hồi

Hai bẫy thực tế: (1) failback khó hơn failover: khi Singapore hồi, dữ liệu mới ở Tokyo phải replicate ngược (tạo replica từ Tokyo về), và (2) dịch vụ global vs regional: IAM, Route 53, CloudFront là global nên không "sập theo region"; nhưng KMS key là regional nên mọi thứ ở Tokyo phải mã hóa bằng key Tokyo (đó là lý do mỗi lệnh ở trên đều có --kms-key-id alias/shop-key-tokyo).

6. So sánh: Multi-AZ vs Multi-Region, và các cặp đề thi

Tiêu chíMulti-AZ (HA)Multi-Region (DR)
Bảo vệ khỏiMất 1 AZ, hỏng hostMất cả region, sự kiện diện rộng
FailoverTự động, DNS endpoint giữ nguyên (RDS 1–2 phút, Aurora <30 s)Thường thủ công hoặc runbook; đổi endpoint/DNS
ReplicationĐồng bộ (RDS) / quorum (Aurora)Bất đồng bộ (lag)
Chi phí~2× instanceTừ phí lưu backup đến 2× cả stack
Chống lỗi logic (xóa nhầm)KhôngKhông, cần PITR/backup/object lock
CặpChọn khi
RDS Multi-AZ vs Read ReplicaMulti-AZ = HA, standby không đọc được. Replica = scale đọc, có thể cross-region và promote cho DR
Aurora Global vs RDS cross-region replicaAurora Global: lag <1 s, promote <1 phút, tới 5 secondary region, write forwarding. RDS replica: phút
S3 CRR vs SRRCRR = region khác (DR, latency, compliance). SRR = cùng region (gom log, prod→test, khác account)
AWS Backup vs DLM vs snapshot tayAWS Backup: nhiều dịch vụ, cross-region/account, vault lock, audit. DLM chỉ EBS/AMI. Snapshot tay: không
Backup vault lock vs S3 Object LockCùng ý "WORM", vault lock cho recovery point, Object Lock cho object
Route 53 failover vs Global AcceleratorFailover DNS phụ thuộc TTL/cache client. Global Accelerator: 2 anycast IP tĩnh, chuyển endpoint trong giây, không chờ DNS; cho TCP/UDP, game, API cần IP tĩnh
Elastic DR (DRS) vs AWS BackupDRS replicate server liên tục (RPO giây, RTO phút) cho EC2/on-prem → EC2; Backup cho snapshot theo lịch

7. Khi nào dùng chiến lược nào

Công ty mình còn một hệ thống kho cũ chạy Oracle + ứng dụng Java 8 trên máy vật lý ở văn phòng, muốn đưa lên AWS cùng shop-app. Đề thi hay nói "7R" và DMS, SCT, MGN, Migration Hub. Mình nên hiểu chúng theo bức tranh nào?

Bức tranh gồm ba lớp: chiến lược (7R: làm gì với từng ứng dụng), công cụ chuyển server và dữ liệu (MGN, DMS/SCT, DataSync/Snow), và công cụ quản lý chương trình (Migration Hub, Application Discovery Service, Migration Evaluator). Áp vào hệ thống kho của bạn sẽ thấy ngay.

1. 7R – chọn chiến lược cho từng ứng dụng

RNghĩaVí dụ với hệ khoTừ khóa đề
Rehost (lift & shift)Chuyển nguyên máy lên EC2Java 8 app → EC2 bằng MGN, Oracle → Oracle trên EC2"quickly", "no code change", "MGN"
Replatform (lift, tinker & shift)Đổi nền tảng nhỏ, không đổi kiến trúcOracle → RDS for Oracle (managed), app → Elastic Beanstalk / ECS"managed database", "reduce operational overhead without rewriting"
RepurchaseMua SaaS thay thếBỏ app kho tự viết, mua WMS SaaS trên Marketplace"replace with SaaS", "Marketplace"
Refactor / Re-architectViết lại tận dụng cloudTách microservice, Oracle → Aurora PostgreSQL (SCT + DMS), Lambda"cloud-native", "serverless", "highest long-term benefit, most effort"
RelocateChuyển VMware nguyên khốivSphere on-prem → VMware Cloud on AWS"VMware", "without purchasing new hardware or changing operations"
RetainGiữ lại on-premMáy in tem kho nối thiết bị PLC"not ready", "compliance requires on-prem"
RetireTắt bỏBáo cáo kho cũ không ai dùng"no longer needed"

2. Công cụ theo thứ gì cần chuyển

Chuyển gìDịch vụCách hoạt độngTừ khóa đề
Server (VM, vật lý)Application Migration Service (MGN)Cài agent → replicate block-level liên tục sang staging area (EC2 rẻ + EBS) → test launch → cutover với downtime phút. Thay SMS (đã ngừng)"lift-and-shift servers", "minimal downtime", "continuous replication", "test before cutover"
Database cùng engine (homogeneous)DMSReplication instance đọc nguồn, ghi đích: full load + CDC (change data capture) để đích đuổi kịp, cutover gần zero downtime. Nguồn/đích: on-prem, EC2, RDS, Aurora, S3, DynamoDB, Redshift, OpenSearch, Kinesis"migrate database with minimal downtime", "continuous replication", "ongoing replication", "Oracle to RDS Oracle"
Database khác engine (heterogeneous)SCT (Schema Conversion Tool) + DMSSCT chuyển schema, stored procedure, code (Oracle PL/SQL → PostgreSQL), báo cáo độ khó; DMS chuyển dữ liệu"Oracle/SQL Server to Aurora PostgreSQL/MySQL", "convert schema", "stored procedures"
DB Oracle/SQL Server → Aurora + app codeSCT + DMS + Babelfish (SQL Server → Aurora PostgreSQL hiểu T-SQL)Giảm sửa code app"minimal application changes from SQL Server"
File / dữ liệu lớnDataSync, Snowball, Storage Gateway, Transfer FamilyXem 22.16"petabytes offline" → Snowball; "NFS to EFS over network" → DataSync
MainframeAWS Mainframe ModernizationReplatform/refactor COBOLÍt ra
Container / KubernetesApp2Container, ECS/EKSĐóng gói Java/.NET app thành image"containerize existing Java application without code change"

3. Công cụ quản lý chương trình

Dịch vụLàm gìTừ khóa
Application Discovery ServiceThu thập inventory, cấu hình, hiệu năng, dependency server on-prem (agentless qua vCenter hoặc agent)"discover on-premises servers and dependencies", "plan migration"
Migration Evaluator (cũ TSO Logic)Business case, ước tính chi phí AWS từ dữ liệu discovery"TCO", "business case"
Migration HubMột bảng theo dõi tiến độ migration từ MGN, DMS, partner tool; Strategy Recommendations gợi ý R nào"single location to track migrations", "recommend migration strategy"
Cloud Adoption Framework (CAF), Migration Acceleration ProgramKhung tổ chức: Business, People, Governance, Platform, Security, Operations"framework for cloud adoption"

4. Áp vào hệ kho của bạn

Giai đoạn 1 (tuần 1–2): Discovery Agent trên 6 máy → Migration Hub thấy dependency: app Java ↔ Oracle ↔ máy in
Giai đoạn 2 (tuần 3–6): Rehost app Java 8 bằng MGN → EC2 (test launch ở shop-vpc private subnet, cutover cuối tuần)
                       Replatform Oracle → RDS for Oracle bằng DMS full load + CDC (cutover khi lag = 0), hoặc
                       Refactor dần: SCT đánh giá Oracle → Aurora PostgreSQL, nếu < 20% PL/SQL phải sửa tay thì làm
Giai đoạn 3:           Retain máy in tem tại kho, nối về AWS qua Site-to-Site VPN; Retire báo cáo cũ
Theo dõi:              Migration Hub; chi phí: Migration Evaluator; dữ liệu lịch sử 8 TB → DataSync (có mạng)

Lưu ý Java: MGN giữ nguyên Java 8 là "rehost", nhưng cơ hội vàng là nâng lên Java 21 + Spring Boot 3 ngay sau khi lên EC2 (replatform), vì License Oracle JDK 8 trên cloud là chi phí ẩn – đổi sang Amazon Corretto miễn phí.

Cho mình hiểu kỹ DMS một chút: full load và CDC chạy thế nào, cần chuẩn bị gì ở PostgreSQL/Oracle nguồn, và cutover lúc nào? Mình lo nhất là mất giao dịch trong lúc chuyển.

Lo đúng chỗ. DMS giải quyết đúng nỗi lo đó bằng hai pha nối tiếp, và cutover chỉ xảy ra khi pha hai báo "đã đuổi kịp".

1. Kiến trúc

Nguồn on-prem (Oracle / PostgreSQL)        DMS replication instance (EC2 managed, trong shop-vpc)        Đích (RDS / Aurora)
  ──VPN/Direct Connect──►  source endpoint ──► task: full load + CDC ──► target endpoint ──►
                                                  │
                                                  ├─ Pha 1 Full load: SELECT từng bảng, ghi song song (8 bảng cùng lúc)
                                                  │   trong lúc đó mọi thay đổi ở nguồn được cache
                                                  └─ Pha 2 CDC: đọc transaction log (Oracle redo/LogMiner hoặc Binary Reader,
                                                      PostgreSQL logical replication slot/WAL) → áp lên đích theo thứ tự
                                                      → metric CDCLatencySource / CDCLatencyTarget → về ~0 giây = "đuổi kịp"

DMS Serverless (mới) tự chọn capacity; task truyền thống phải chọn instance class (dms.t3.medium cho lab, dms.r5 cho prod) và đủ dung lượng disk cho cache CDC.

2. Chuẩn bị nguồn

3. Cấu hình task (CLI rút gọn)

aws dms create-replication-task --profile shop-lab --replication-task-identifier wms-oracle-to-rds \
  --source-endpoint-arn $SRC --target-endpoint-arn $TGT --replication-instance-arn $RI \
  --migration-type full-load-and-cdc \
  --table-mappings '{"rules":[{"rule-type":"selection","rule-id":"1","rule-name":"wms","object-locator":{"schema-name":"WMS","table-name":"%"},"rule-action":"include"}]}' \
  --replication-task-settings '{"TargetMetadata":{"ParallelLoadThreads":8},"FullLoadSettings":{"TargetTablePrepMode":"TRUNCATE_BEFORE_LOAD","MaxFullLoadSubTasks":8},"ValidationSettings":{"EnableValidation":true},"Logging":{"EnableLogging":true}}' \
  --tags Key=Project,Value=shop-app Key=Env,Value=lab
aws dms start-replication-task --replication-task-arn $TASK --start-replication-task-type start-replication

EnableValidation làm DMS so dòng nguồn–đích liên tục (tốn thêm đọc nguồn nhưng là bảo hiểm cho nỗi lo của bạn).

4. Cutover không mất giao dịch

1. Full load xong (FullLoadProgressPercent 100), CDC đang chạy, CDCLatencyTarget < 5 s, validation = Validated
2. Tạo index phụ, FK, sequence trên đích; chạy ANALYZE
3. Tối cuối tuần: đặt app on-prem vào read-only / tắt ghi (maintenance page) → 2–10 phút downtime
4. Chờ CDCLatencySource = 0 và CDCLatencyTarget = 0 → đích đã có mọi giao dịch cuối
5. Đặt sequence đích = max(id)+1; đổi connection string app (secret) sang RDS; bật app mới trên EC2
6. Giữ task CDC chạy ngược (đích → nguồn) nếu cần kế hoạch rollback vài ngày, rồi stop task, xóa instance

Vậy "zero downtime" thực ra là "downtime vài phút, không mất dữ liệu". Thuật ngữ đề: "minimal downtime" + "continuous replication" + "ongoing changes" = DMS CDC; "different database engine" thêm SCT. DMS cũng dùng để replicate liên tục không cutover, ví dụ RDS → S3 Parquet làm nguồn cho data lake của 22.17, hoặc RDS → Kinesis/OpenSearch.

Cho mình bài lab để tự tay làm phần này nhé.

Lab 22.18: Backup plan, S3 CRR, snapshot RDS sang Tokyo và Route 53 failover

Mục tiêu

Chi phí & thời gian

Chuẩn bị

export AWS_REGION=ap-southeast-1; export DR_REGION=ap-northeast-1
export ACCOUNT_ID=$(aws sts get-caller-identity --profile shop-lab --query Account --output text)
export TAGS="Key=Project,Value=shop-app Key=Env,Value=lab"

Các bước

Bước 1: KMS key ở Tokyo (key là regional; mọi bản sao ở Tokyo mã hóa bằng key này).

DR_KEY=$(aws kms create-key --profile shop-lab --region $DR_REGION --description "shop-app DR key" \
  --tags TagKey=Project,TagValue=shop-app TagKey=Env,TagValue=lab --query KeyMetadata.KeyId --output text)
aws kms create-alias --profile shop-lab --region $DR_REGION --alias-name alias/shop-key-tokyo --target-key-id $DR_KEY

Console: đổi region sang Tokyo → KMS → Customer managed keys → Create key.

Bước 2: AWS Backup – 2 vault, plan, selection theo tag, chạy on-demand.

aws backup create-backup-vault --profile shop-lab --backup-vault-name shop-vault --backup-vault-tags Project=shop-app,Env=lab
aws backup create-backup-vault --profile shop-lab --region $DR_REGION --backup-vault-name shop-vault-dr \
  --encryption-key-arn arn:aws:kms:$DR_REGION:$ACCOUNT_ID:key/$DR_KEY --backup-vault-tags Project=shop-app,Env=lab
# role mặc định của AWS Backup (tạo nếu chưa có)
aws iam create-role --profile shop-lab --role-name AWSBackupDefaultServiceRole --path /service-role/ \
  --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"backup.amazonaws.com"},"Action":"sts:AssumeRole"}]}' 2>/dev/null
aws iam attach-role-policy --profile shop-lab --role-name AWSBackupDefaultServiceRole --policy-arn arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup
aws iam attach-role-policy --profile shop-lab --role-name AWSBackupDefaultServiceRole --policy-arn arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores
BACKUP_ROLE=arn:aws:iam::$ACCOUNT_ID:role/service-role/AWSBackupDefaultServiceRole

PLAN_ID=$(aws backup create-backup-plan --profile shop-lab --backup-plan "{
  \"BackupPlanName\": \"shop-daily\",
  \"Rules\": [{ \"RuleName\": \"daily-dr-copy\", \"TargetBackupVaultName\": \"shop-vault\",
    \"ScheduleExpression\": \"cron(0 18 * * ? *)\", \"StartWindowMinutes\": 60, \"CompletionWindowMinutes\": 180,
    \"Lifecycle\": { \"DeleteAfterDays\": 7 },
    \"CopyActions\": [{ \"DestinationBackupVaultArn\": \"arn:aws:backup:$DR_REGION:$ACCOUNT_ID:backup-vault:shop-vault-dr\",
                        \"Lifecycle\": { \"DeleteAfterDays\": 7 } }] }] }" \
  --backup-plan-tags Project=shop-app,Env=lab --query BackupPlanId --output text)
aws backup create-backup-selection --profile shop-lab --backup-plan-id $PLAN_ID --backup-selection "{
  \"SelectionName\": \"shop-by-tag\", \"IamRoleArn\": \"$BACKUP_ROLE\",
  \"ListOfTags\": [{ \"ConditionType\": \"STRINGEQUALS\", \"ConditionKey\": \"Project\", \"ConditionValue\": \"shop-app\" }] }"

# Không chờ 18:00: chạy on-demand cho RDS
RDS_ARN=arn:aws:rds:$AWS_REGION:$ACCOUNT_ID:db:shop-db
JOB=$(aws backup start-backup-job --profile shop-lab --backup-vault-name shop-vault --resource-arn $RDS_ARN \
  --iam-role-arn $BACKUP_ROLE --lifecycle DeleteAfterDays=7 --query BackupJobId --output text)
aws backup describe-backup-job --profile shop-lab --backup-job-id $JOB --query '[State,PercentDone]'   # CREATED → RUNNING → COMPLETED (~10 phút)

Console: AWS Backup → Backup plans → Create plan → Build new plan → Add rule (copy to destination region) → Assign resources (tag). Protected resources → Create on-demand backup.

Khi job COMPLETED, chạy copy sang Tokyo (plan chỉ copy bản theo lịch; on-demand copy bằng tay):

RP=$(aws backup list-recovery-points-by-backup-vault --profile shop-lab --backup-vault-name shop-vault \
  --query 'RecoveryPoints[0].RecoveryPointArn' --output text)
COPY=$(aws backup start-copy-job --profile shop-lab --recovery-point-arn $RP --source-backup-vault-name shop-vault \
  --destination-backup-vault-arn arn:aws:backup:$DR_REGION:$ACCOUNT_ID:backup-vault:shop-vault-dr \
  --iam-role-arn $BACKUP_ROLE --query CopyJobId --output text)
aws backup describe-copy-job --profile shop-lab --copy-job-id $COPY --query 'CopyJob.State'

Bước 3: S3 CRR sang Tokyo.

SRC=shop-app-assets-$ACCOUNT_ID; DST=shop-app-assets-dr-$ACCOUNT_ID
aws s3api put-bucket-versioning --profile shop-lab --bucket $SRC --versioning-configuration Status=Enabled
aws s3api create-bucket --profile shop-lab --region $DR_REGION --bucket $DST --create-bucket-configuration LocationConstraint=$DR_REGION
aws s3api put-bucket-versioning --profile shop-lab --region $DR_REGION --bucket $DST --versioning-configuration Status=Enabled
aws s3api put-bucket-tagging --profile shop-lab --region $DR_REGION --bucket $DST --tagging 'TagSet=[{Key=Project,Value=shop-app},{Key=Env,Value=lab}]'
aws s3api put-public-access-block --profile shop-lab --region $DR_REGION --bucket $DST \
  --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

aws iam create-role --profile shop-lab --role-name shop-s3-replication-role --tags $TAGS \
  --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"s3.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
aws iam put-role-policy --profile shop-lab --role-name shop-s3-replication-role --policy-name crr --policy-document "{
 \"Version\":\"2012-10-17\",\"Statement\":[
  {\"Effect\":\"Allow\",\"Action\":[\"s3:GetReplicationConfiguration\",\"s3:ListBucket\"],\"Resource\":\"arn:aws:s3:::$SRC\"},
  {\"Effect\":\"Allow\",\"Action\":[\"s3:GetObjectVersionForReplication\",\"s3:GetObjectVersionAcl\",\"s3:GetObjectVersionTagging\"],\"Resource\":\"arn:aws:s3:::$SRC/*\"},
  {\"Effect\":\"Allow\",\"Action\":[\"s3:ReplicateObject\",\"s3:ReplicateDelete\",\"s3:ReplicateTags\"],\"Resource\":\"arn:aws:s3:::$DST/*\"}]}"
sleep 10
aws s3api put-bucket-replication --profile shop-lab --bucket $SRC --replication-configuration "{
  \"Role\": \"arn:aws:iam::$ACCOUNT_ID:role/shop-s3-replication-role\",
  \"Rules\": [{ \"ID\": \"to-tokyo\", \"Status\": \"Enabled\", \"Priority\": 1, \"Filter\": {},
    \"DeleteMarkerReplication\": { \"Status\": \"Disabled\" },
    \"Destination\": { \"Bucket\": \"arn:aws:s3:::$DST\", \"StorageClass\": \"STANDARD_IA\",
      \"ReplicationTime\": { \"Status\": \"Enabled\", \"Time\": { \"Minutes\": 15 } },
      \"Metrics\": { \"Status\": \"Enabled\", \"EventThreshold\": { \"Minutes\": 15 } } } }] }"
echo "dr-test $(date)" > dr-test.txt
aws s3 cp dr-test.txt s3://$SRC/products/dr-test.txt --profile shop-lab

Console: S3 → bucket → Management → Replication rules → Create. (Nếu bucket nguồn mã hóa SSE-KMS, role cần thêm kms:Decrypt key nguồn và kms:Encrypt key đích, và rule thêm SourceSelectionCriteria.SseKmsEncryptedObjects.)

Bước 4: Snapshot RDS → copy sang Tokyo → restore thử.

aws rds create-db-snapshot --profile shop-lab --db-instance-identifier shop-db --db-snapshot-identifier shop-db-manual-dr --tags $TAGS
aws rds wait db-snapshot-available --profile shop-lab --db-snapshot-identifier shop-db-manual-dr
aws rds copy-db-snapshot --profile shop-lab --region $DR_REGION \
  --source-db-snapshot-identifier arn:aws:rds:$AWS_REGION:$ACCOUNT_ID:snapshot:shop-db-manual-dr \
  --target-db-snapshot-identifier shop-db-dr-copy --kms-key-id alias/shop-key-tokyo --source-region $AWS_REGION --copy-tags
aws rds wait db-snapshot-available --profile shop-lab --region $DR_REGION --db-snapshot-identifier shop-db-dr-copy   # 10–20 phút
# Restore ở Tokyo vào VPC default (lab) để kiểm tra dữ liệu còn nguyên
aws rds restore-db-instance-from-db-snapshot --profile shop-lab --region $DR_REGION \
  --db-instance-identifier shop-db-dr-test --db-snapshot-identifier shop-db-dr-copy \
  --db-instance-class db.t3.micro --no-multi-az --no-publicly-accessible --tags $TAGS
aws rds wait db-instance-available --profile shop-lab --region $DR_REGION --db-instance-identifier shop-db-dr-test

Console: RDS → Snapshots → Actions → Copy snapshot (Destination region Tokyo, KMS key) → sang Tokyo → Restore snapshot.

Kết nối: dùng một EC2 nhỏ ở Tokyo trong cùng VPC, hoặc bật tạm --publicly-accessible với SG chỉ cho IP của bạn, chạy psql -h <endpoint> -U shop -d shop -c "select count(*) from orders"; password lấy từ secret shop/db (Singapore) – restore giữ nguyên password của snapshot.

Bước 5: Endpoint "secondary" tối giản ở Tokyo. Trang bảo trì tĩnh trên S3 website (hoặc EC2 nếu bạn đã có AMI):

MAINT=shop-maintenance-$ACCOUNT_ID
aws s3api create-bucket --profile shop-lab --region $DR_REGION --bucket $MAINT --create-bucket-configuration LocationConstraint=$DR_REGION
aws s3api put-public-access-block --profile shop-lab --region $DR_REGION --bucket $MAINT --public-access-block-configuration BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false
aws s3api put-bucket-policy --profile shop-lab --region $DR_REGION --bucket $MAINT --policy "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:GetObject\",\"Resource\":\"arn:aws:s3:::$MAINT/*\"}]}"
echo '<h1>shop-app dang bao tri (DR site Tokyo)</h1>' > index.html
aws s3 cp index.html s3://$MAINT/ --content-type text/html --profile shop-lab --region $DR_REGION
aws s3 website s3://$MAINT/ --index-document index.html --profile shop-lab --region $DR_REGION
# endpoint: $MAINT.s3-website-ap-northeast-1.amazonaws.com (Route 53 alias hosted zone ID của S3 website Tokyo: Z2M4EHUR26P7ZW)

Bước 6: Route 53 health check + failover record.

ZONE_ID=$(aws route53 list-hosted-zones-by-name --profile shop-lab --dns-name example.com --query 'HostedZones[0].Id' --output text | cut -d/ -f3)
ALB_DNS=$(aws elbv2 describe-load-balancers --profile shop-lab --names shop-alb --query 'LoadBalancers[0].DNSName' --output text)
ALB_ZONE=$(aws elbv2 describe-load-balancers --profile shop-lab --names shop-alb --query 'LoadBalancers[0].CanonicalHostedZoneId' --output text)
HC_ID=$(aws route53 create-health-check --profile shop-lab --caller-reference shop-hc-$(date +%s) \
  --health-check-config "Type=HTTP,FullyQualifiedDomainName=$ALB_DNS,Port=80,ResourcePath=/actuator/health,RequestInterval=10,FailureThreshold=3" \
  --query HealthCheck.Id --output text)
aws route53 change-tags-for-resource --profile shop-lab --resource-type healthcheck --resource-id $HC_ID --add-tags Key=Name,Value=shop-primary $TAGS
aws route53 change-resource-record-sets --profile shop-lab --hosted-zone-id $ZONE_ID --change-batch "{
 \"Changes\": [
  { \"Action\": \"UPSERT\", \"ResourceRecordSet\": { \"Name\": \"dr.shop.example.com\", \"Type\": \"A\", \"SetIdentifier\": \"primary-sg\",
    \"Failover\": \"PRIMARY\", \"HealthCheckId\": \"$HC_ID\",
    \"AliasTarget\": { \"HostedZoneId\": \"$ALB_ZONE\", \"DNSName\": \"$ALB_DNS\", \"EvaluateTargetHealth\": true } } },
  { \"Action\": \"UPSERT\", \"ResourceRecordSet\": { \"Name\": \"dr.shop.example.com\", \"Type\": \"A\", \"SetIdentifier\": \"secondary-tokyo\",
    \"Failover\": \"SECONDARY\",
    \"AliasTarget\": { \"HostedZoneId\": \"Z2M4EHUR26P7ZW\", \"DNSName\": \"s3-website-ap-northeast-1.amazonaws.com\", \"EvaluateTargetHealth\": false } } } ] }"

Lưu ý: alias tới S3 website đòi tên bucket = tên record (dr.shop.example.com); nếu dùng tên bucket $MAINT ở trên, thay record SECONDARY bằng CNAME tới $MAINT.s3-website-ap-northeast-1.amazonaws.com với TTL 60. Console: Route 53 → Health checks → Create; Hosted zones → Create record → Routing policy: Failover.

Kiểm tra kết quả

# AWS Backup: recovery point ở cả 2 vault
aws backup list-recovery-points-by-backup-vault --profile shop-lab --backup-vault-name shop-vault --query 'RecoveryPoints[].[ResourceType,Status]' --output text
aws backup list-recovery-points-by-backup-vault --profile shop-lab --region $DR_REGION --backup-vault-name shop-vault-dr --query 'RecoveryPoints[].[ResourceType,Status]' --output text
# RDS  COMPLETED (cả hai)

# S3 CRR: object sang Tokyo (ReplicationStatus COMPLETED ở nguồn), delete không lan
aws s3api head-object --profile shop-lab --bucket $SRC --key products/dr-test.txt --query ReplicationStatus     # "COMPLETED" sau vài phút
aws s3 ls s3://$DST/products/ --profile shop-lab --region $DR_REGION
aws s3 rm s3://$SRC/products/dr-test.txt --profile shop-lab          # tạo delete marker ở Singapore
sleep 60; aws s3 ls s3://$DST/products/ --profile shop-lab --region $DR_REGION   # vẫn còn dr-test.txt ở Tokyo

# RDS ở Tokyo
aws rds describe-db-instances --profile shop-lab --region $DR_REGION --db-instance-identifier shop-db-dr-test --query 'DBInstances[0].[DBInstanceStatus,KmsKeyId,Endpoint.Address]'

# Route 53: health check Success; tắt primary → chuyển
aws route53 get-health-check-status --profile shop-lab --health-check-id $HC_ID --query 'HealthCheckObservations[].StatusReport.Status' | head -3
dig +short dr.shop.example.com      # IP của ALB Singapore
# Gây lỗi: đổi ASG về 0 (ALB trả 503) hoặc chặn SG ALB port 80
aws autoscaling set-desired-capacity --profile shop-lab --auto-scaling-group-name shop-asg --desired-capacity 0 --no-honor-cooldown
sleep 120; aws route53 get-health-check-status --profile shop-lab --health-check-id $HC_ID --query 'HealthCheckObservations[0].StatusReport.Status'   # Failure
dig +short dr.shop.example.com      # giờ là IP của S3 website Tokyo
curl -s http://dr.shop.example.com | head -1     # <h1>shop-app dang bao tri (DR site Tokyo)</h1>
# Phục hồi
aws autoscaling set-desired-capacity --profile shop-lab --auto-scaling-group-name shop-asg --desired-capacity 2

Ghi lại thời gian từ lúc đặt desired 0 đến lúc dig đổi: đó là RTO phần DNS (thường 60–120 giây với interval 10 s × 3 lần + TTL 60).

Thử thêm

Dọn tài nguyên

# 1. RDS ở Tokyo (tốn theo giờ)
aws rds delete-db-instance --profile shop-lab --region $DR_REGION --db-instance-identifier shop-db-dr-test --skip-final-snapshot
aws rds delete-db-snapshot --profile shop-lab --region $DR_REGION --db-snapshot-identifier shop-db-dr-copy
aws rds delete-db-snapshot --profile shop-lab --db-snapshot-identifier shop-db-manual-dr
# 2. Route 53 record + health check (record failover phải xóa cả 2 bằng Action DELETE với đúng nội dung; dễ nhất qua Console)
aws route53 delete-health-check --profile shop-lab --health-check-id $HC_ID
# 3. S3: tắt replication, xóa bucket DR và maintenance (versioned: phải xóa mọi version)
aws s3api delete-bucket-replication --profile shop-lab --bucket $SRC
for B in $DST $MAINT; do
  aws s3api list-object-versions --profile shop-lab --region $DR_REGION --bucket $B --query '{Objects: [Versions[].{Key:Key,VersionId:VersionId}, DeleteMarkers[].{Key:Key,VersionId:VersionId}][] }' --output json > /tmp/v.json
  grep -q VersionId /tmp/v.json && aws s3api delete-objects --profile shop-lab --region $DR_REGION --bucket $B --delete file:///tmp/v.json >/dev/null
  aws s3 rb s3://$B --profile shop-lab --region $DR_REGION
done
aws iam delete-role-policy --profile shop-lab --role-name shop-s3-replication-role --policy-name crr
aws iam delete-role --profile shop-lab --role-name shop-s3-replication-role
# 4. AWS Backup: recovery point → selection → plan → vault (vault chỉ xóa được khi trống; vault đã lock thì phải chờ hết retention)
for R in $AWS_REGION $DR_REGION; do V=$([ $R = $AWS_REGION ] && echo shop-vault || echo shop-vault-dr)
  for RP in $(aws backup list-recovery-points-by-backup-vault --profile shop-lab --region $R --backup-vault-name $V --query 'RecoveryPoints[].RecoveryPointArn' --output text); do
    aws backup delete-recovery-point --profile shop-lab --region $R --backup-vault-name $V --recovery-point-arn $RP; done; done
SEL=$(aws backup list-backup-selections --profile shop-lab --backup-plan-id $PLAN_ID --query 'BackupSelectionsList[0].SelectionId' --output text)
aws backup delete-backup-selection --profile shop-lab --backup-plan-id $PLAN_ID --selection-id $SEL
aws backup delete-backup-plan --profile shop-lab --backup-plan-id $PLAN_ID
sleep 60
aws backup delete-backup-vault --profile shop-lab --backup-vault-name shop-vault
aws backup delete-backup-vault --profile shop-lab --region $DR_REGION --backup-vault-name shop-vault-dr
# 5. KMS key Tokyo (chờ 7 ngày mới xóa hẳn, nhưng ngừng tính tiền khi pending deletion)
aws kms schedule-key-deletion --profile shop-lab --region $DR_REGION --key-id $DR_KEY --pending-window-in-days 7

Nhắc: RDS instance ở Tokyo, recovery point trong vault (GB-tháng), health check Route 53 và KMS key là các thứ nằm ở region khác nên dễ quên khi nhìn Console ở Singapore – luôn kiểm tra Cost Explorer theo tag Env=lab ở mọi region (bài 22.19).

Phỏng vấn và đề thi SAA hỏi về DR, RTO/RPO và migration thì sao?

Q1. RTO và RPO là gì? Bạn thiết kế DR cho một ứng dụng Spring Boot + PostgreSQL thế nào với RTO 1 giờ, RPO 15 phút?

🇻🇳 Tiếng Việt:

RPO là lượng dữ liệu tối đa chấp nhận mất, đo bằng thời gian từ bản sao cuối đến lúc sự cố; RTO là thời gian tối đa để dịch vụ chạy lại. RTO 1 giờ và RPO 15 phút là bài pilot light: em replicate dữ liệu liên tục sang region hai bằng RDS cross-region read replica hoặc Aurora Global, S3 Cross-Region Replication cho file, Secrets Manager replicate secret; hạ tầng VPC, ALB, launch template dựng sẵn bằng Terraform nhưng ASG desired 0 và AMI đã copy; Route 53 failover record với health check. Khi sự cố, runbook promote replica, scale ASG lên, DNS tự chuyển; tổng khoảng 15 đến 30 phút. AWS Backup copy cross-region và cross-account là lớp cuối cho lỗi logic và tài khoản bị chiếm. Và phải có game day định kỳ để con số RTO là số đo, không phải ước đoán.

🇬🇧 English:

RPO is the maximum acceptable data loss, measured as the time between the last copy and the incident; RTO is the maximum time to restore service. One hour RTO and 15 minute RPO points to pilot light: I replicate data continuously to a second region with an RDS cross-region read replica or Aurora Global Database, S3 Cross-Region Replication for files, and Secrets Manager replication; the VPC, ALB and launch template are pre-built with Terraform but the ASG sits at zero with a copied AMI; Route 53 failover records use a health check. On disaster a runbook promotes the replica, scales the ASG and DNS switches, around 15 to 30 minutes in total. AWS Backup with cross-region and cross-account copies is the last layer against logical errors and account compromise. And regular game days make the RTO a measurement rather than a guess.

Q2. Bốn chiến lược DR khác nhau thế nào về chi phí và RTO/RPO?

🇻🇳 Tiếng Việt:

Backup and restore rẻ nhất, chỉ trả tiền lưu backup, RTO nhiều giờ đến ngày, RPO bằng tần suất backup. Pilot light giữ dữ liệu sống ở region hai nhưng compute tắt, RTO vài chục phút, RPO phút. Warm standby chạy bản thu nhỏ đang hoạt động, RTO phút, RPO giây, trả tiền compute liên tục. Multi-site active-active chạy đủ ở cả hai region và nhận traffic cả hai, RTO và RPO gần không, đắt nhất và phức tạp vì phải xử lý ghi hai chiều với Aurora Global hoặc DynamoDB Global Tables. Chọn theo chi phí của một giờ downtime so với chi phí chạy region hai.

🇬🇧 English:

Backup and restore is the cheapest, paying only for stored backups, with RTO of hours to days and RPO equal to the backup frequency. Pilot light keeps live data in the second region with compute off, RTO in tens of minutes and RPO in minutes. Warm standby runs a scaled-down working copy, RTO in minutes and RPO in seconds, paying for compute continuously. Multi-site active-active runs fully in both regions and serves traffic from both, with near-zero RTO and RPO, the most expensive and complex because of two-way writes with Aurora Global or DynamoDB Global Tables. The choice compares the cost of an hour of downtime with the cost of running the second region.

Q3. Migrate một database Oracle on-prem lên AWS với downtime tối thiểu, có thể đổi sang PostgreSQL. Bạn dùng gì?

🇻🇳 Tiếng Việt:

Em dùng Schema Conversion Tool để đánh giá và chuyển schema, stored procedure từ Oracle sang Aurora PostgreSQL, xem báo cáo phần nào phải sửa tay. Sau đó dùng Database Migration Service với task full load cộng CDC: full load copy dữ liệu hiện có trong khi CDC đọc redo log và cache thay đổi, rồi áp liên tục lên đích cho đến khi latency về không. Cutover chỉ cần dừng ghi vài phút, chờ lag bằng không, đổi connection string trong Secrets Manager. Nếu không đổi engine thì bỏ SCT, DMS chuyển thẳng sang RDS for Oracle. Dữ liệu lịch sử rất lớn thì seed bằng Snowball rồi DMS CDC đuổi phần còn lại.

🇬🇧 English:

I use the Schema Conversion Tool to assess and convert the schema and stored procedures from Oracle to Aurora PostgreSQL, reviewing its report for what needs manual work. Then I run Database Migration Service with a full-load-plus-CDC task: full load copies existing data while CDC reads the redo logs and caches changes, then applies them continuously until latency reaches zero. Cutover only needs a few minutes of write freeze, waiting for zero lag and switching the connection string in Secrets Manager. If the engine stays the same I skip SCT and DMS migrates straight to RDS for Oracle. For very large history I seed with Snowball and let DMS CDC catch up the rest.

Q4. 7R là gì và MGN, Migration Hub dùng lúc nào?

🇻🇳 Tiếng Việt:

7R là bảy chiến lược cho từng ứng dụng khi migrate: rehost chuyển nguyên máy lên EC2, replatform đổi nền tảng nhỏ như sang RDS hay container, repurchase mua SaaS, refactor viết lại cloud-native, relocate chuyển VMware nguyên khối lên VMware Cloud on AWS, retain giữ lại, retire tắt bỏ. MGN là công cụ rehost: agent replicate block-level liên tục sang staging, cho test launch rồi cutover với downtime phút. Application Discovery Service thu thập inventory và dependency trước đó, Migration Hub là nơi theo dõi tiến độ mọi công cụ và gợi ý chiến lược.

🇬🇧 English:

The 7Rs are seven per-application migration strategies: rehost moves servers as-is to EC2, replatform makes small platform changes such as moving to RDS or containers, repurchase buys SaaS, refactor rewrites cloud-native, relocate moves VMware workloads wholesale to VMware Cloud on AWS, retain keeps on-prem, retire shuts down. MGN is the rehost tool: an agent replicates block-level continuously to a staging area, allows test launches and then cutover with minutes of downtime. Application Discovery Service collects inventory and dependencies beforehand, and Migration Hub tracks progress across all tools and recommends strategies.

Góc thi SAA-C03

Câu 1: Một công ty chạy ứng dụng web ở một region với RDS MySQL. Yêu cầu DR: RTO 30 phút, RPO 5 phút, chi phí thấp nhất có thể. Giải pháp nào phù hợp?
A. Snapshot RDS hàng ngày copy sang region khác; dựng lại hạ tầng khi cần.
B. Cross-region read replica RDS, hạ tầng dựng sẵn bằng CloudFormation với Auto Scaling group min 0, Route 53 failover; promote replica khi sự cố.
C. Chạy bản sao đầy đủ ở region hai với Route 53 weighted 50/50 và Aurora Global Database.
D. Bật RDS Multi-AZ và dùng AWS Backup hàng giờ.

Đáp án: B. RPO 5 phút loại A (snapshot hàng ngày = RPO 24 giờ). RTO 30 phút cho phép pilot light (compute tắt, promote replica) rẻ hơn C (active-active, "lowest cost" loại). D: Multi-AZ không chống mất region, backup hàng giờ RPO 60 phút.

Câu 2: Một công ty phải migrate database Microsoft SQL Server 8 TB on-prem lên Amazon Aurora PostgreSQL với downtime tối thiểu. Kết nối Direct Connect 1 Gbps đã có. Giải pháp nào?
A. Dùng AWS Snowball để chuyển backup, restore vào Aurora.
B. Dùng AWS SCT để chuyển schema, rồi AWS DMS với full load và CDC để migrate dữ liệu và thay đổi liên tục; cutover khi lag bằng 0.
C. Dùng AWS DataSync để copy file database sang S3 rồi import vào Aurora.
D. Dùng native backup/restore của SQL Server vào RDS for SQL Server.

Đáp án: B. Khác engine (heterogeneous) → SCT; "minimal downtime" + "ongoing changes" → DMS CDC. 8 TB qua 1 Gbps ≈ 1 ngày, mạng đủ nên không cần Snowball (A, và Snowball không "restore vào Aurora" từ backup SQL Server). C: DataSync copy file, Aurora không import file .bak. D: đích sai (yêu cầu Aurora PostgreSQL).

Câu 3: Một công ty lo ngại ransomware và tài khoản AWS bị chiếm có thể xóa backup EBS và RDS. Họ cần backup không thể xóa trong 90 ngày và được lưu ở tài khoản khác. Giải pháp nào với LEAST operational overhead?
A. Script Lambda copy snapshot sang tài khoản khác hàng ngày và xóa quyền IAM delete.
B. AWS Backup với backup plan copy cross-account vào vault ở tài khoản backup, bật Backup Vault Lock chế độ compliance, min retention 90 ngày.
C. Bật EBS snapshot và RDS automated backup với retention 90 ngày.
D. Lưu snapshot vào S3 Glacier Deep Archive với Object Lock.

Đáp án: B. "Cross-account", "immutable", "least overhead" = AWS Backup + vault lock (compliance mode không ai gỡ được). A: tự vận hành, quyền IAM vẫn có thể bị kẻ chiếm account sửa. C: backup cùng account, kẻ chiếm xóa được, retention RDS tối đa 35 ngày. D: EBS/RDS snapshot không phải object bạn đặt vào S3 bucket của mình.

Cách nhớ ngắn gọn

Từ khóa trong đềDịch vụ / chiến lược
lowest cost DR, RTO hours/daysBackup & Restore (AWS Backup cross-region)
data replicated, core infra ready, scale when needed, RTO tens of minutesPilot Light
scaled-down running copy, RTO minutesWarm Standby
near-zero RTO/RPO, serve from multiple regionsMulti-site Active-Active (Aurora Global, DynamoDB Global Tables, Route 53 latency)
centralized backup, multiple services, cross-region/cross-account, immutableAWS Backup (+ Vault Lock)
replicate objects to another region, 15-minute SLAS3 CRR (+ RTC)
global DB, <1 s lag, promote <1 minAurora Global Database
automatic DNS failover to standby regionRoute 53 failover routing + health check
static anycast IPs, fast regional failover without DNS cachingGlobal Accelerator
continuous block replication of servers for DR, RPO secondsElastic Disaster Recovery
lift-and-shift servers, minimal downtime cutoverApplication Migration Service (MGN)
database migration, minimal downtime, ongoing replicationDMS (full load + CDC)
different database engine, convert stored proceduresSCT (+ DMS)
T-SQL compatibility on Aurora PostgreSQLBabelfish
discover on-prem servers and dependenciesApplication Discovery Service
track all migrations in one place, strategy recommendationMigration Hub
VMware wholesale moveRelocate → VMware Cloud on AWS
containerize Java/.NET app without code changeApp2Container

Tự kiểm tra

RTO và RPO khác nhau thế nào? Cái nào quyết định tần suất replicate?

RPO là lượng dữ liệu tối đa chấp nhận mất (thời gian từ bản sao cuối), quyết định tần suất backup/replicate. RTO là thời gian tối đa để dịch vụ chạy lại, quyết định hạ tầng chuẩn bị sẵn bao nhiêu.

Pilot light và warm standby khác nhau ở điểm gì?

Pilot light: dữ liệu replicate sống nhưng compute ở region hai tắt (ASG 0), phải scale lên khi sự cố. Warm standby: bản thu nhỏ đang chạy, nhận traffic được ngay rồi scale; RTO ngắn hơn, tiền nhiều hơn.

Vì sao Multi-AZ không phải DR, và backup cùng region không đủ?

Multi-AZ chỉ chống mất một AZ và replicate cả lỗi logic sang standby. Backup cùng region mất theo khi region sập; cần copy cross-region và cross-account (AWS Backup, S3 CRR), thêm vault lock chống xóa.

DMS full load + CDC hoạt động thế nào để downtime tối thiểu?

Full load copy dữ liệu hiện có; song song CDC đọc transaction log nguồn và cache thay đổi, sau full load áp liên tục lên đích. Khi latency về 0, dừng ghi vài phút, đổi connection string, xong. Khác engine thì SCT chuyển schema trước.

MGN, DMS, DataSync, Snowball mỗi cái chuyển thứ gì?

MGN: server (block-level, rehost). DMS: database (dữ liệu + CDC). DataSync: file/object qua mạng. Snowball: dữ liệu lớn offline khi mạng không đủ.

🧪 Thực hành bài này: Challenge: Kiến trúc tham chiếu + DR + cost (chưa triển khai) · lab labs/aws