Course-এর সূচি

24.5

একটা মাত্র EC2 Instance, তবু Highly Available

Elastic IP দিয়ে failover, এক Instance-এর ASG, আর lifecycle hook দিয়ে EBS volume এক AZ থেকে আরেক AZ-এ নিয়ে যাওয়া।

18 মিনিট পড়া + Animation

টিপস: ডটেড-আন্ডারলাইন করা যেকোনো শব্দে ট্যাপ বা Hover করলে তার অর্থ দেখবে।

এই লেসন শেষে তুমি পারবে

  • High availability আসলে কী কথা দেয় (কম downtime, শূন্য না) সেটা বলতে, আর কেন একটা Availability Zone-এ একটা EC2 instance কখনো সেটা দিতে পারে না তা বোঝাতে।
  • EC2 automatic recovery কী সারায় (নষ্ট host) আর কী পারে না (হারিয়ে যাওয়া AZ, আটকে যাওয়া application, Auto Scaling group-এর instance), সেটা আলাদা করতে।
  • Pattern 1 বানাতে: একটা CloudWatch alarm বা EventBridge rule আর একটা Lambda function মিলে Elastic IP-কে standby instance-এ সরিয়ে দেয়; আর এর দুর্বল জায়গাগুলো চিনতে।
  • Pattern 2 বানাতে: দুটো AZ জুড়ে min 1, max 1, desired 1-এর একটা Auto Scaling group, যার user data instance role দিয়ে Elastic IP আবার লাগিয়ে নেয়।
  • Pattern 3 বানাতে: terminate আর launch lifecycle hook আর snapshot দিয়ে EBS volume অন্য AZ-এ নিয়ে যাওয়া, DLM snapshot-কে শেষ ভরসা রেখে; আর AZ হঠাৎ শেষ হলে কতটা data হারায় হিসাব করতে।
  • Application বদলানো গেলে আরও ভালো design বেছে নিতে: EFS Regional, RDS Multi-AZ, load balancer, বা Route 53 failover record।
  • সবগুলো উপায়কে failover-এর সময়, data হারানো, খরচ আর কীসে ভাঙে, এই চার দিক থেকে তুলনা করতে, আর প্রশ্নের শব্দ দেখে পরীক্ষার উত্তর বাছতে।

#একটা instance কেন সমস্যা

এই course-এর বেশিরভাগ জায়গায় আমরা application highly available করেছি সহজ রাস্তায়: কয়েকটা AZ-এ কয়েকটা instance, সামনে একটা load balancer (লেসন ৬.১)। এটা চলে তখনই, যখন application stateless, মানে যেকোনো কপি যেকোনো request সামলাতে পারে, আর যখন একসাথে কয়েকটা কপি চালানোর অনুমতি আছে।

কিছু server এর কোনোটাই না। একটা host-এ বাঁধা licence, পুরোনো আমলের এমন একটা program যার database file থাকে local disk-এ, এমন একটা vendor appliance যেটা দুবার চলতেই রাজি না। তোমাকে ঠিক একটা কপিই চালাতে হবে। এই লেসন সেই একটা কপিকে যতটা পারা যায় টিকিয়ে রাখা নিয়ে: slide-এর তিনটা design দিয়ে, আর তার আশেপাশের আরও ভালো বিকল্পগুলো দিয়ে।

#High availability মানে কম downtime, শূন্য না

Note-এ high availability-র সংজ্ঞা দেওয়া আছে এমন একটা system হিসেবে, যেটা “কখনোই ডাউন হবে না”। কথাটার মানে আসলে এটা না, আর AWS-এর কোনো design এমন কথা দেয়ও না। High availability মানে system downtime কম রাখে: এমনভাবে বানানো যে একটা কিছু নষ্ট হলে (একটা instance, একটা host, একটা AZ) বড়জোর অল্প সময়ের জন্য থামে। সাধারণত এটা মাপা হয় availability-র শতাংশে: 99.9% মানে বছরে প্রায় ৮.৮ ঘণ্টা বন্ধ থাকা চলে, 99.99% মানে প্রায় ৫৩ মিনিট। এই লেসনের প্রত্যেকটা pattern failover-এর সময় কয়েক মিনিট বন্ধ থাকে। যে design-এ বিপদের পরে একটুও বিরতি নেই আর পুরো capacity থেকে যায়, তাকে বলে fault tolerant, আর তার দাম বেশি (লেসন ৬.১-এ দুটোর পার্থক্য টানা আছে)।

Note যেটা ঠিক বলেছে: AWS-এ highly available হতে হলে system-কে একাধিক AZ-এ চলতে পারতে হবে।

#একটা instance থাকে একটাই Availability Zone-এ

একটা EC2 instance চলে একটা AZ-এর একটা data centre-এর একটা host-এ। তার EBS volume-ও ওই AZ-এ আটকানো (লেসন ৫.১)। AZ-টার বিদ্যুৎ, cooling বা network গেলে instance আর তার data দুটোই বিপদের ভেতরে পড়ে, আর এক-instance-এর ছবিতে এর বাইরে কিছুই নেই।

একটা instance থাকে একটাই AZ-এ

একটা clinic-এর appointment server: একটা EC2 instance, একটা EBS volume, একটা Elastic IP। নষ্ট host আর হারিয়ে যাওয়া Availability Zone পাশাপাশি দেখো: প্রথমটা AWS নিজেই সারিয়ে দিতে পারে, দ্বিতীয়টা থেকে এই ছবির কিছুই বাঁচতে পারে না।

পরিস্থিতি

প্রত্যেকটা request যায় AZ a-র একমাত্র instance-এ, সেটা পড়ে AZ a-র একমাত্র volume।

AZ a
AZ b
Clinic-এর staffbrowser
Elastic IP203.0.113.10
EC2 instanceappointment
EBS volumeরোগীর data
HTTPS
ধাপ 1 / 4
1

Reception-এর মেয়েটা booking page খুলল। Browser যোগাযোগ করল 203.0.113.10-এ, মানে Elastic IP-তে। Elastic IP হলো তোমার নিজের একটা Regional ঠিকানা; সেটা কোনো AZ-এর সাথে বাঁধা না, এই মুহূর্তে যে instance-এর সাথে associate করা আছে, শুধু তার দিকে ইশারা করে।

#বিনা পয়সায় যা পাও: automatic recovery

কিছু বানানোর আগে জেনে নাও EC2 নিজে থেকেই কী করে। System status check ব্যর্থ হলে (host-এর hardware, বিদ্যুৎ বা network), simplified automatic recovery, যেটা সমর্থিত instance type-এ নিজে থেকেই চালু থাকে, instance-টাকে একই AZ-এর একটা সুস্থ host-এ সরিয়ে নেয়। StatusCheckFailed_System-এর ওপর recover action দেওয়া একটা CloudWatch alarm-ও একই কাজ করে, আরও দ্রুত, আর তোমার নিজের notification সহ। Instance-এর ID, private আর public IP, Elastic IP আর EBS volume সব একই থাকে; হারায় শুধু RAM-এর জিনিস। এগুলো সব শেখানো হয়েছে লেসন ১৯.৩-এ।

যা এটা পারে না:

  • এটা AZ ছেড়ে যেতে পারে না, তাই AZ নষ্ট হলে কিছুই করে না।
  • আটকে যাওয়া application বা ভেঙে পড়া operating system সারায় না (instance status check-এর জন্য দরকার reboot action)।
  • Auto Scaling group-এর instance-এ এটা চলে না (সেখানে group নিজেই instance বদলে দেয়); Elastic Fabric Adapter থাকলে, Dedicated Host-এ, বা অসমর্থিত type-এও না।

তাই যেকোনো একক instance-এর প্রথম স্তর হিসেবে automatic recovery ঠিক আছে, আর নিচের pattern-গুলো যোগ করে বাকি অংশটা: আরেকটা AZ।

#Pattern 1: Elastic IP আর একটা standby instance

প্রথম slide-এর design দ্বিতীয় একটা বন্ধ instance তৈরি রাখে, আর দরকারের সময় ঠিকানাটা তার কাছে সরিয়ে দেয়:

  1. একটা primary instance traffic সামলায় একটা Elastic IP দিয়ে (Region-এ তোমার নিজের একটা স্থির public IPv4 ঠিকানা, লেসন ৩.৬)।
  2. একই AMI থেকে বানানো একটা standby instance অন্য AZ-এ বন্ধ অবস্থায় বসে থাকে। বন্ধ instance-এর খরচ শুধু তার EBS storage।
  3. কেউ একজন গোলমাল টের পায়: status check-এর (বা application metric-এর) ওপর একটা CloudWatch alarm, অথবা instance-এর state change-এর মতো কোনো event-এর ওপর একটা EventBridge rule। Slide-এ লেখা “CloudWatch Event”, আজকের দিনে সেটাই EventBridge (লেসন ১৯.৫)।
  4. Trigger একটা Lambda function চালায়, যেটা standby-তে StartInstances call করে, তারপর AssociateAddress দিয়ে Elastic IP-কে তার কাছে সরিয়ে আনে।
  5. User-রা একই ঠিকানা ব্যবহার করতে থাকে, আর পৌঁছে যায় standby-তে।
# The failover function (boto3), invoked by the alarm or the EventBridge rule
import boto3
ec2 = boto3.client("ec2")

def handler(event, context):
    ec2.start_instances(InstanceIds=["i-0standby0example"])
    ec2.get_waiter("instance_running").wait(InstanceIds=["i-0standby0example"])
    ec2.associate_address(AllocationId="eipalloc-0clinic0example",
                          InstanceId="i-0standby0example")  # moves it off the dead primary

Pattern 1: Elastic IP সরিয়ে দাও standby instance-এ

AZ a-তে primary, AZ b-তে বন্ধ করে রাখা একটা standby, আর ছোট্ট একটু automation: একটা CloudWatch alarm বা EventBridge rule গোলমাল টের পায়, আর একটা Lambda function standby চালু করে ঠিকানাটা সরিয়ে দেয়।

পরিস্থিতি

Primary কাজ করে; standby বন্ধ, তাই তার খরচ শুধু EBS storage-এর।

AZ a
AZ b
Clinic-এর staff
Elastic IP203.0.113.10
Primary EC2
Standby EC2বন্ধ
Alarm বা ruleStatusCheckFailed
Lambdafailover code
ধাপ 1 / 2
1

203.0.113.10-এর traffic পৌঁছায় AZ a-র primary-তে। AZ b-র standby একই AMI থেকে বানানো, এখন বন্ধ: তার compute-এর টাকা লাগে না, শুধু EBS volume-এর।

#যে খুঁটিনাটি ঠিক করে দেয় এটা কাজ করবে কিনা

  • Standby রাখো অন্য AZ-এ। Primary-র পাশে রাখা standby একই AZ-এর বিপদে একসাথে মারা যায়।
  • শুধু ব্যর্থতা না, চুপ থাকাটাও ধরো। পুরো AZ বসে গেলে instance ব্যর্থ check-এর খবর পাঠায় না, metric পাঠানোই বন্ধ করে দেয়। Missing data-র default setting রাখা alarm তখন INSUFFICIENT_DATA-তে বসে থাকে। Treat missing data as breaching দাও, অথবা বাইরে থেকে Route 53 health check দিয়ে ধরো।
  • ঠিকানা সরানো এক call-এর কাজ। আজকের account-এ AssociateAddress অন্য কোথাও লাগানো ঠিকানাকে নিজে থেকেই reassociate করে; --allow-reassociation হলো পুরোনো, স্পষ্ট করে বলার flag, আর --no-allow-reassociation দিলে বরং call-টা ব্যর্থ হয়। Lambda function-এর role-এ লাগবে শুধু ec2:StartInstances আর ec2:AssociateAddress, এর বেশি না।
  • বন্ধ instance কোনো capacity ধরে রাখে না। বড় AZ বিপর্যয়ে অনেক customer একসাথে বাকি AZ-গুলোতে instance চালু করে, তখন StartInstances ব্যর্থ হতে পারে InsufficientInstanceCapacity দিয়ে। Standby-র AZ-এ একটা On-Demand Capacity Reservation এটা নিশ্চিত করে, কিন্তু সারাক্ষণই তার টাকা দিতে হয় (লেসন ৪.৪)।
  • Standby-র নিজের আলাদা disk। তুমি যে data কপি করে রেখেছ, শুধু সেটুকুই তার কাছে আছে। Replication না থাকলে standby চালু হবে গতকালের, বা গত মাসের, data নিয়ে। আর সে পিছিয়েও পড়ে: primary-তে যে patch আর configuration দিলে, standby-তেও সেগুলো দিতে হবে।
  • ফিরে আসাটা জেনেবুঝে করো। পুরোনো AZ ফিরলে কিছুই নিজে থেকে ফিরে যায় না। Data মিলিয়ে, ভিড় কম এমন সময়ে ঠিকানাটা ফিরিয়ে আনো।

#Pattern 2: ঠিক একটা instance-এর Auto Scaling group

দ্বিতীয় slide হাতে বানানো standby-র জায়গায় বসায় একটা Auto Scaling group (লেসন ৬.৫):

Settingমানকেন
Minimum, maximum, desired1 / 1 / 1সবসময় ঠিক একটা instance। কখনো দুটো না, তাই licence-এর শর্ত মানা হয়
Subnetঅন্তত দুটো AZ-এএকটা AZ গেলে group-এর অন্য কোথাও launch করার জায়গা থাকে
Health check typeEC2 (default), সামনে load balancer থাকলে ELBকোনটাকে মৃত ধরা হবে, সেটা ঠিক করে (নিচে)
Launch templateAMI, instance type, instance profile, user dataনতুন instance-কে নিজেই নিজেকে সাজিয়ে নিতে হবে

Instance health check-এ ফেল করলে group সেটাকে terminate করে নতুন একটা চালায়, তার AZ-গুলোর মধ্যে যেটা সুস্থ সেখানে। Max 1 হওয়ায় সে আগে terminate করে, পরে launch করে: দুটো একসাথে চলার কোনো সময় নেই।

#নতুন instance-এর ঠিকানা নতুন

নতুন instance পায় নতুন private IP আর নতুন এলোমেলো একটা public IP। User, DNS record, partner সবাই চেনে শুধু 203.0.113.10। ASG instance বদলায়; ঠিকানা সরায় না। তাই boot-এর সময় কাজটা করে launch template-এর user data (লেসন ৪.৩):

#!/bin/bash
# User data: find the clinic's Elastic IP by tag and attach it to this instance
TOKEN=$(curl -sX PUT http://169.254.169.254/latest/api/token -H "X-aws-ec2-metadata-token-ttl-seconds: 300")
ID=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id)
ALLOC=$(aws ec2 describe-addresses --filters Name=tag:app,Values=clinic \
          --query 'Addresses[0].AllocationId' --output text)
aws ec2 associate-address --allocation-id "$ALLOC" --instance-id "$ID" --allow-reassociation

এটা কাজ করার জন্য launch template একটা instance profile লাগায়, যার role-এ call-গুলোর অনুমতি আছে:

{
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow", "Action": "ec2:DescribeAddresses", "Resource": "*" },
    {
      "Effect": "Allow",
      "Action": "ec2:AssociateAddress",
      "Resource": "*",
      "Condition": { "StringEquals": { "aws:ResourceTag/app": "clinic" } }
    }
  ]
}

(AssociateAddress-এর অনুমতি যাচাই হয় ঠিকানা আর instance দুটোর ওপরেই; ওপরের tag condition মেলে যখন ঠিকানায় app=clinic আছে আর instance-ও একই tag নিয়ে launch হয়। Instance-এ tag না দিলে condition-টা বাদ দাও, action রেখে দাও।) ঠিকানা code-এ লিখে না রেখে tag দিয়ে খুঁজলে একই template test আর production দুই জায়গায় চলে, প্রত্যেকের নিজের ঠিকানা নিয়ে।

Pattern 2: ঠিক একটা instance-এর Auto Scaling group

Min 1, max 1, desired 1, দুটো AZ জুড়ে। Group মরা instance-এর বদলে সুস্থ AZ-এ নতুন একটা চালায়; user data, একটা instance role নিয়ে, Elastic IP-টা নতুনটার গায়ে আবার লাগিয়ে দেয়।

পরিস্থিতি

Boot-এর সময় instance নিজেই tag দেখে Elastic IP খুঁজে নিজের গায়ে লাগায়।

Auto Scaling group 1/1/1
AZ a
AZ b
Clinic-এর staff
Elastic IP203.0.113.10
EC2 instance
Auto Scalinghealth check
Instance roleAssociateAddress
launch
ধাপ 1 / 3
1

Group তার একমাত্র instance চালু করল। সেটা AZ a বা AZ b যেকোনোটায় যেতে পারত; এখানে গেল AZ a-তে। নতুন সব instance-এর মতো এটাও পায় একটা এলোমেলো public IP, যেটা কেউ চেনে না।

#কোনটা ব্যর্থতা গোনা হবে: health check type

  • EC2 (default): instance চলছে না, বা কোনো status check ব্যর্থ। এটা মরা host বা মরা AZ দেখে, কিন্তু আটকে যাওয়া application দেখে না: web server error ফেরত দিলেও operating system তার check-এর উত্তর দিয়ে যায়। Group একটা zombie পুষে রাখে।
  • ELB: শুধু সামনে load balancer থাকলে পাওয়া যায়। এটা load balancer-এর application check-এর রায়ও যোগ করে।
  • Custom: load balancer না থাকলে একটা পাহারাদার (অন্য machine-এর cron script, application metric-এর ওপর CloudWatch alarm, Lambda function-কে খবর দেওয়া Route 53 health check) aws autoscaling set-instance-health --health-status Unhealthy call করে, আর group instance বদলে দেয়।

#কত সময় লাগে, কত খরচ

বন্ধ থাকার সময় = টের পাওয়া + terminate + launch + boot + user data: কয়েক মিনিট ব্যর্থ status check, launch-এ প্রায় এক মিনিট, boot আর script চালাতে এক-দুই মিনিট। সাধারণত ৩ থেকে ১০ মিনিট। এটা recovery, নিরবচ্ছিন্ন high availability না; note-এর “crash করলে অন্য AZ-এ অটোমেটিক চালু হবে” কথাটা এভাবেই পড়ো।

পরীক্ষা এটা পছন্দ করে খরচের জন্য: Auto Scaling group বিনা পয়সায়; টাকা দাও শুধু একটা instance আর Elastic IP-এর (February 2024 থেকে প্রত্যেকটা public IPv4 ঠিকানা, Elastic হোক বা না হোক, ঘণ্টায় 0.005 USD, মাসে প্রায় 3.65 USD)।

যেটা এটা সমাধান করে না: নতুন instance boot করে AMI থেকে, নতুন root volume নিয়ে। পুরোনো instance নিজের disk-এ যা লিখেছিল, সব গেল। সেটা pattern 3-এর কাজ।

#Pattern 3: যে ASG তার EBS volume সাথে নিয়ে যায়

তৃতীয় slide কঠিন অংশটা যোগ করে: instance EBS volume-এ data রাখে, আর নতুন instance-এর সেটা লাগবেই।

#সমস্যা: volume তার AZ ছাড়তে পারে না

ap-southeast-1a-এর একটা EBS volume শুধু ap-southeast-1a-এর instance-এই attach করা যায়। সরানোর উপায় নেই, আর 1b-এর instance-এ attach করতে গেলে ব্যর্থ হয়। AZ থেকে AZ-এ যাওয়ার একমাত্র রাস্তা লেসন ৫.১-এরটাই: snapshot → target AZ-এ snapshot থেকে volume বানাও → attach। এটা চলে কারণ snapshot Regional: EBS এগুলো রাখে পুরো Region-এর জন্য (AWS-এর নিজের সামলানো S3-এ), কোনো একটা AZ-এর ভেতরে না।

#Terminate hook: যাওয়ার পথে snapshot

একটা terminating lifecycle hook পুরোনো instance-কে terminate হওয়ার আগে Terminating:Wait-এ থামিয়ে রাখে (লেসন ৬.৫-এ hook শেখানো আছে):

  1. Hook EventBridge-এ একটা event পাঠায়, EventBridge একটা Lambda function (বা একটা SSM Automation document) চালায়।
  2. Function, ভালো হয় আগে SSM Run Command দিয়ে application থামিয়ে বা file system freeze করে নিলে যাতে data consistent থাকে, data volume-এ CreateSnapshot call করে, আর snapshot-এ tag লাগায় (app=clinic, role=data)।
  3. Snapshot completed হলে complete-lifecycle-action call করে, তারপর terminate এগিয়ে যায়।

#Launch hook: নতুন AZ-এ volume

একটা launching lifecycle hook নতুন instance-কে Pending:Wait-এ আটকে রাখে, in service ধরা হওয়ার আগেই:

  1. EventBridge আবার function চালায়, এবার নতুন instance-এর ID দিয়ে।
  2. Default-এ group পুরোনো instance terminate হতে থাকার মধ্যেই নতুনটা চালু করে দেয়। তাই function আগে অপেক্ষা করে, যতক্ষণ না terminate hook-এর শেষ snapshot completed হয় (অথবা ওই hook হাল ছেড়ে দেয়)। তারপর tag মিলিয়ে সবচেয়ে নতুন completed snapshot খুঁজে বের করে, আর নতুন instance-এর AZ দিয়ে CreateVolume call করে।
  3. Volume available হওয়া পর্যন্ত অপেক্ষা করে, AttachVolume call করে, তারপর CONTINUE দিয়ে complete-lifecycle-action।
  4. User data (বা একটা systemd unit) device আসা পর্যন্ত অপেক্ষা করে, mount করে, application চালু করে, আর pattern 2-এর মতো Elastic IP লাগায়।

Note একই কাজ শুধু user data দিয়েই করে: সবচেয়ে নতুন snapshot খোঁজো, instance-এর নিজের AZ-এ volume বানাও, attach করো। এটাও চলে (তখন instance role-এ লাগবে ec2:DescribeSnapshots, ec2:CreateVolume, ec2:AttachVolume, আর volume-এ tag দিলে ec2:CreateTags), আর নিচের পরীক্ষার প্রশ্নে note এই উত্তরই দেয়। Hook-এর রাস্তাটা বেশি পরিচ্ছন্ন: data attach না হওয়া পর্যন্ত instance in service গোনা হয় না, আর terminate-এর সময়ের snapshot আরও টাটকা কপি দেয়।

#AZ হঠাৎ শেষ হলে: DLM-ই শেষ ভরসা

Terminate hook কাজে লাগে শুধু তখন, যখন পুরোনো AZ-এ তখনো পৌঁছানো যায়, যেমন শুধু instance-টা নষ্ট হলে। পুরো AZ চলে গেলে volume-এ পৌঁছানো যায় না, CreateSnapshot ব্যর্থ হয় বা শেষই হয় না, নতুন কিছু জমা হয় না। Launch hook তখন volume বানায় আগে থেকেই থাকা সবচেয়ে নতুন snapshot থেকে।

এজন্যই design-এর note-এর অংশটা অপরিহার্য থেকে যায়: Amazon Data Lifecycle Manager (DLM)-এর নিয়মিত snapshot, একটা সময়সূচি ধরে (প্রতি 1, 2, 3, 4, 6, 8, 12 বা 24 ঘণ্টায়, অথবা একটা cron expression, কিন্তু কখনোই ঘণ্টায় একবারের বেশি না), tag দেখে volume ধরে, সংখ্যা বা বয়স দিয়ে কতগুলো রাখবে ঠিক করে। AZ হঠাৎ শেষ হলে হারাবে শেষ নির্ধারিত snapshot-এর পরে লেখা সবকিছু। প্রতি ঘণ্টায় snapshot মানে বড়জোর এক ঘণ্টার booking। DLM প্রত্যেকটা run নির্ধারিত সময়ের এক ঘণ্টার মধ্যে শুরু করে, তাই একটু ঢিলেঢালা হিসাব রাখো। এই ফাঁকটাই এই design-এর recovery point; disaster recovery-র অধ্যায়ে লেসন ২৩.১ এই সংখ্যাগুলোর সংজ্ঞা আর তুলনা দেয়। আরও কম হারাতে চাও? আরও ঘন ঘন snapshot নাও (এক ঘণ্টার নিচে DLM পারে না; একটা EventBridge Scheduler schedule বা rule EBS-এর CreateSnapshot action call করতে পারে, ধরো প্রতি ১৫ মিনিটে, পুরোনোগুলো মোছার ব্যবস্থা নিজে করে), অথবা data instance-এর বাইরে সরিয়ে ফেলো (পরের অংশ)।

এই অবস্থায় hook function-কে দিয়ে দুটো কাজ করাও: দ্রুত হাল ছাড়া (volume-এর snapshot নেওয়া না গেলে অপেক্ষা না করে তখনই complete-lifecycle-action call করা), আর hook-এর heartbeat timeout যুক্তিসংগত রাখা। এটা default ১ ঘণ্টা; কেউ action complete না করলে hook ততক্ষণ অপেক্ষা করে, তারপর default result খাটে; আর launch hook যেহেতু ওই শেষ snapshot-এর জন্য বসে থাকে, সে-ও ততক্ষণ আটকে থাকে। বড় প্রথম snapshot-এর জন্য বেশি সময় লাগতে পারে, সেটা script record-lifecycle-action-heartbeat দিয়ে কিনে নিতে পারে (৪৮ ঘণ্টা বা ১০০টা heartbeat পর্যন্ত, যেটা আগে আসে)।

Pattern 3: EBS-এর data অন্য AZ-এ নিয়ে যাওয়া

Volume নিজের AZ ছেড়ে যেতে পারে না, কিন্তু snapshot Regional। Terminate lifecycle hook যাওয়ার পথে volume-এর snapshot নেয়; launch lifecycle hook নতুন AZ-এ সর্বশেষ snapshot থেকে নতুন volume বানায়। পুরোনো AZ-এ একদমই পৌঁছানো না গেলে ভরসা DLM-এর snapshot।

পরিস্থিতি

সব ঠিক থাকা অবস্থায় একটা Data Lifecycle Manager policy নির্দিষ্ট সময় পরপর volume-এর snapshot নেয়।

AZ a
AZ b
EC2 instance
EBS volumeAZ a-তে আটকা
Hook LambdaEventBridge দিয়ে
SnapshotRegional, tag দেওয়া
লেখা
ধাপ 1 / 3
1

AZ a-র instance appointment আর scan করা report লেখে তার EBS data volume-এ।

#যে খুঁটিনাটিগুলো কামড়ায়

  • Restore করা volume শুরুতে ধীর। Snapshot থেকে বানানো volume প্রথমবার ছোঁয়ার সময় block-গুলো S3 থেকে আনে, তাই failover-এর পরের প্রথম read-গুলো ধীর। Snapshot-এ Fast Snapshot Restore (প্রতি AZ প্রতি ঘণ্টা টাকা লাগে) এই ঝামেলা সরায় (লেসন ৫.১)।
  • Crash-consistent আর application-consistent এক না। চলন্ত database file-এর snapshot mount করার পর recovery লাগতে পারে। Terminate hook-এ application থামাও বা flush করো; নির্ধারিত snapshot-এর জন্য DLM-এর pre আর post script ব্যবহার করো।
  • Tag-ই আঠা। Launch hook-কে ঠিক snapshot খুঁজে পেতে হবে। Tag একরকম রাখো, StartTime দিয়ে সাজাও, আর শুধু completed snapshot নাও।
  • একই AZ-ও হতে পারে। শুধু instance নষ্ট হলে group নতুনটা একই AZ-এ চালাতে পারে। পুরোনো volume রেখে দেওয়া থাকলে (DeleteOnTermination false) সেটা আবার attach করা snapshot restore-এর চেয়ে দ্রুত; ভালো function আগে AZ দেখে নেয়।
  • পরিষ্কার রাখো। প্রত্যেকটা failover একটা পুরোনো বা নতুন volume ফেলে রাখে; DLM-এর retention পুরোনো snapshot মোছে, কিন্তু ছড়িয়ে থাকা volume তুমি না মোছা পর্যন্ত টাকা খায়।

#আরও ভালো উত্তর: data instance-এর বাইরে রাখো

Pattern 2 আর 3 অনেক খেটে এমন state বয়ে নিয়ে যায়, যেটা প্রথম থেকেই instance-এ থাকার কথা না। Data কোথায় থাকবে সেটা বদলানো গেলে সমস্যার বেশিরভাগটাই উধাও হয়ে যায় (লেসন ৯.২ web app-এর জন্য একই ভাবনা দেখায়):

  • File রাখো Amazon EFS-এ, Regional file system type দিয়ে: data জমা থাকে অন্তত তিনটা AZ জুড়ে, প্রত্যেক AZ-এ একটা mount target, আর নতুন instance একই file system mount করে নেয় (লেসন ৫.৪)। Note বলে EFS “জন্মগতভাবেই Multi-AZ”: কথাটা সত্যি শুধু Regional-এর বেলায়। EFS One Zone data রাখে একটা AZ-এ, আর ঠিক EBS volume-এর মতোই সেই AZ-এর সাথে যায়।
  • Database রাখো RDS Multi-AZ-এ: অন্য AZ-এ একটা synchronous standby, প্রায় এক থেকে দুই মিনিটে স্বয়ংক্রিয় failover, endpoint-এর নাম একই (লেসন ৭.১)।
  • Object (scan, PDF) রাখো S3-এ, যেটা Regional।

তখন instance-এ থাকে শুধু operating system আর application, যেগুলো AMI-তে আগে থেকেই আছে। এক-instance-এর ASG কয়েক মিনিটে সেটা বদলে দেয়, আর কোনো data হারায় না। বন্ধ থাকার সময় এখনো একটা বদলের সেই কয়েক মিনিট, কারণ একটা instance তো একটাই; লাভটা হলো recovery-র দাম আর data দিয়ে দিতে হয় না।

আরও ভালো: data instance-এর বাইরে রাখো

File থাকে EFS Regional-এ, database থাকে RDS Multi-AZ-এ, আর instance-এ এমন কিছু নেই যেটা আবার বানানো যায় না। এক-instance-এর ASG তখনো সেটা বদলায়, কিন্তু বয়ে নেওয়ার মতো volume নেই, হারানোর মতো কিছুও নেই।

পরিস্থিতি

Instance row লেখে RDS-এ আর file লেখে EFS-এ; নিজের disk-এ থাকে শুধু OS আর app।

AZ a
AZ b
EC2 instance
RDS Multi-AZ
EFS Regional৩+ AZ
row লেখা
ধাপ 1 / 2
1

একটা booking মানে database-এর একটা row: সেটা যায় RDS-এ, যার অন্য AZ-এর Multi-AZ standby প্রত্যেকটা লেখা synchronously পায়।

#একই ঠিকানা রাখার অন্য উপায়

“User নতুন instance-কে কীভাবে খুঁজে পাবে” প্রশ্নে slide-এর উত্তর Elastic IP। এটাই একমাত্র উত্তর না, আর AWS নিজেও Elastic IP কম ব্যবহার করতে বলে (লেসন ৩.৬)।

#সামনে একটা load balancer, একটা instance হলেও

1/1/1-এর ASG-কে একটা Application Load Balancer-এর পেছনে বসাও, target group হিসেবে register করো:

  • User-রা ব্যবহার করে ALB-এর DNS নাম (বা তার দিকে তোমার alias record)। কোনো ঠিকানা কখনো সরাতে হয় না, তাই user data লাগে না, role লাগে না, Elastic IP লাগে না।
  • ELB health check type application পরীক্ষা করে, তাই আটকে যাওয়া app-ও বদলে যায়। Health check একটু টিউন করলে (ধরো ১০ সেকেন্ড পরপর, ৩ বার ব্যর্থ হলে) কয়েক মিনিটের জায়গায় আধা মিনিটের মতো সময়ে টের পাওয়া যায়।
  • Instance বসতে পারে private subnet-এ, আর ALB যোগ করে TLS termination আর WAF।
  • খরচ: একটা ALB মাসে মোটামুটি ১৬ USD, সাথে capacity unit। ছোট একটা clinic-এর জন্য সবচেয়ে পরিচ্ছন্ন design-এর আসল দাম এটাই।

Partner-দের যদি স্থির IP allow-list করতে হয়, Network Load Balancer প্রতি AZ-এ একটা করে Elastic IP নিতে পারে; Global Accelerator দেয় দুটো স্থির anycast IP (লেসন ৬.৩)।

#একটা Route 53 failover record

IP না সরিয়ে নামটাকে অন্য জায়গায় ঘুরিয়ে দাও: failover routing-এর একটা record, যাতে একটা primary (চালু instance, সাথে health check) আর একটা secondary (লেসন ৮.৩, লেসন ৮.৪)। Health check ব্যর্থ হলে (default-এ ৩০ সেকেন্ড পরপর ৩ বার ব্যর্থ হলে) Route 53 উত্তর দেয় secondary দিয়ে। ঝামেলা DNS caching: client পুরোনো উত্তর record-এর TTL পর্যন্ত রেখে দেয়, তাই TTL ছোট রাখো (ধরো ৬০ সেকেন্ড), আর মনে রেখো কিছু client আরও বেশি সময় রাখে। এর জন্য চালু একটা secondary লাগে, অথবা ASG নতুন instance আনার পর record আপডেট করার একটা script।

#Pattern-গুলোর তুলনা

DesignFailover-এর সময় (সাধারণত)AZ নষ্ট হলে হারানো dataবাড়তি খরচকীসে ভাঙে
এক instance + automatic recoveryHost-এর দোষে কয়েক মিনিট; AZ-এর দোষে কয়েক ঘণ্টা (AZ না ফেরা পর্যন্ত)AZ ফিরলে কিছু না; না ফিরলে ঝুঁকিতেনেইযেকোনো AZ বিপর্যয়; আটকে যাওয়া app
P1 Elastic IP + বন্ধ standby৩–৫ মিনিটStandby-তে যা কপি করা হয়নি, সবStandby-র EBS; Lambda (কয়েক সেন্ট)Standby চালু করার capacity নেই; পুরোনো standby; missing data-য় অন্ধ alarm
P2 ASG 1/1/1 + user data দিয়ে Elastic IP৩–১০ মিনিটInstance-এর disk-এ যা ছিল, সবনেই (ASG বিনা পয়সায়)EIP-এর ধাপ বা role-এর অনুমতি ভুলে যাওয়া; EC2 check দিয়ে আটকে যাওয়া app
P3 ASG + lifecycle hook দিয়ে EBS + DLM৫–১২ মিনিট (শেষ snapshot সময় বাড়ায়)Instance নষ্ট হলে কিছু না; AZ হঠাৎ শেষ হলে শেষ DLM snapshot-এর পর থেকেSnapshot storage; LambdaTimeout পর্যন্ত বসে থাকা hook; ভুল AZ-এ attach; ধীর প্রথম read
ASG 1/1/1 + EFS Regional + RDS Multi-AZ৩–১০ মিনিটকিছু নাEFS আর Multi-AZ-এর দামEFS One Zone বেছে নেওয়া
ALB-এর পেছনে ASG 1/1/1 (data বাইরে)২–৫ মিনিটকিছু নাALBনতুন কিছু না; ঠিকানা DNS নাম হতে পারলে সবচেয়ে পরিচ্ছন্ন

Failover-এর সময়রেখা

একটা design আর একটা বিপদ বেছে নিয়ে চালাও। Bar দেখাবে মিনিটগুলো কোথায় যায়: বিপদ টের পেতে, automation-এ, boot হতে, নাকি শুধু বসে থাকতে। সময়গুলো ছোট একটা Linux instance-এর সাধারণ আন্দাজ।

১. Design

২. কী নষ্ট হয়

৩. Application health check

এখনো কিছু নষ্ট হয়নি। বিপদ শুরু করতে বোতাম চাপো।

#কী ভুল হয়

লক্ষণকারণসমাধান
Failover-এর পর নতুন instance healthy, তবু site বন্ধনতুন instance-এর নতুন public IP, কেউ Elastic IP আবার লাগায়নিUser data বা launch hook দিয়ে AssociateAddress; অথবা সামনে ALB
User data চলল, কিন্তু ঠিকানা লাগানো হলো নাInstance role-এ ec2:AssociateAddress / ec2:DescribeAddresses নেই; error শুধু /var/log/cloud-init-output.log-এRole ঠিক করো; ঠিকানা লাগানোর পরেই launch hook complete করো, যাতে ব্যর্থতা চোখে পড়ে
ASG একই নষ্ট AZ-এ launch করতে থাকে, বা launch-ই করতে পারে নাGroup-এর subnet একটাই AZ-এঅন্তত দুটো AZ-এ subnet দাও
App এক ঘণ্টা আটকে থাকে, কিছুই হয় নাEC2 health check পাস করছে; load balancer নেইset-instance-health দিয়ে custom health, application alarm, অথবা ELB check type-সহ ALB
AZ বিপর্যয়ের সময় standby চালুই হয় নাবাকি AZ-এ InsufficientInstanceCapacityCapacity Reservation, কয়েকটা instance type, বা ASG
AZ মরে গেলেও failover alarm বাজে নাকোনো data আসে না, আর missing data-কে missing হিসেবেই ধরা হয়Missing data-কে breaching ধরো, অথবা Route 53 health check
AttachVolume zone mismatch দিয়ে ব্যর্থVolume পুরোনো AZ-এSnapshot → instance-এর AZ-এ CreateVolume → attach
নতুন instance চালু হওয়ার আগে এক ঘণ্টা অপেক্ষাTerminate hook মরা AZ-এর snapshot নিতে না পেরে ১ ঘণ্টার timeout পর্যন্ত বসে ছিল, আর launch hook ওই শেষ snapshot-এর অপেক্ষায় ছিলব্যর্থ হলে function তখনই action complete করুক; heartbeat timeout ছোট করো
Failover-এর পর এক ঘণ্টার data নেইAZ হঠাৎ শেষ; শেষ DLM snapshot এক ঘণ্টা পুরোনো ছিলআরও ঘন ঘন snapshot, অথবা data EFS Regional / RDS Multi-AZ-এ
Failover-এর পর প্রথম কয়েক মিনিট database ধীরSnapshot থেকে restore করা volume block আনে ধীরে ধীরেSnapshot-এ Fast Snapshot Restore, অথবা volume আগে থেকে পড়ে নাও
“EFS তো Multi-AZ”, তবু data হারালFile system-টা EFS One ZoneAZ হারিয়েও যে data টিকতে হবে, তার জন্য Regional type

#System design-এ এটা কীভাবে লাগে

Clinic-এর শেষ design, বাজেট যেমন যেমন এল তেমন তেমন ধাপে ধাপে বানানো:

  1. প্রথম দিন (বিনা পয়সায়): simplified automatic recovery আগে থেকেই চালু; সাথে StatusCheckFailed_System-এর ওপর recover action আর SNS email দেওয়া একটা alarm, আর StatusCheckFailed_Instance-এর ওপর reboot।
  2. প্রথম আসল সমাধান: ap-southeast-1a আর 1b জুড়ে 1/1/1-এর একটা ASG, tag দেওয়া Elastic IP লাগানোর user data, আর তার জন্য একটা instance role। বাড়তি খরচ: কিছু না।
  3. Data: vendor-এর database file EBS volume-এই থাকে (licence-এর দরকার local path)। Lifecycle hook সেটা AZ পার করে নিয়ে যায়; একটা DLM policy প্রতি ঘণ্টায় snapshot নেয়, শেষ ৪৮টা রাখে; clinic খোলা থাকার সময় সর্বশেষ snapshot-এ দুই AZ-এই FSR চালু থাকে।
  4. পরের বছর: scan করা report যাবে EFS Regional-এ, আর vendor সমর্থন দিলে database যাবে RDS Multi-AZ-এ। তখন hook আর DLM-এর দরকার ফুরাবে, আর Elastic IP-র জায়গা নেবে একটা ALB।

ভাবনাটা অন্য জায়গাতেও খাটে: engineering software-এর একক license server, পুরোনো একটা reporting box, ছোট একটা game server, cache-ওয়ালা self-hosted CI runner। যেটা fleet হতে পারে না, সেটাকে বানাও নিজে নিজে সেরে ওঠা একক server: AZ জুড়ে এক-instance-এর ASG, state instance-এর বাইরে বা snapshot-এ বয়ে নেওয়া, আর এমন একটা ঠিকানা যেটা তার পেছন পেছন যায়।

#নিজে করে দেখো

# 1. Allocate and tag the Elastic IP the instance will look for
aws ec2 allocate-address --domain vpc \
  --tag-specifications 'ResourceType=elastic-ip,Tags=[{Key=app,Value=clinic}]'
# {"AllocationId": "eipalloc-0a1b2c3d4e5f6a7b8", "PublicIp": "203.0.113.10", "Domain": "vpc"}

# 2. Move it by hand to another instance (what pattern 1's Lambda function does)
aws ec2 associate-address --allocation-id eipalloc-0a1b2c3d4e5f6a7b8 \
  --instance-id i-0standby0example --allow-reassociation
# {"AssociationId": "eipassoc-0f1e2d3c4b5a69788"}

# 3. Pattern 2: a group of exactly one across two AZs
aws autoscaling create-auto-scaling-group --auto-scaling-group-name clinic-asg \
  --launch-template LaunchTemplateName=clinic-lt,Version='$Latest' \
  --min-size 1 --max-size 1 --desired-capacity 1 \
  --vpc-zone-identifier "subnet-0aaa1111example,subnet-0bbb2222example" \
  --health-check-type EC2 --health-check-grace-period 300

# 4. Pattern 3: the two lifecycle hooks (EventBridge rules on these hook events invoke the function)
aws autoscaling put-lifecycle-hook --auto-scaling-group-name clinic-asg \
  --lifecycle-hook-name snapshot-on-terminate \
  --lifecycle-transition autoscaling:EC2_INSTANCE_TERMINATING \
  --heartbeat-timeout 900 --default-result CONTINUE
aws autoscaling put-lifecycle-hook --auto-scaling-group-name clinic-asg \
  --lifecycle-hook-name volume-on-launch \
  --lifecycle-transition autoscaling:EC2_INSTANCE_LAUNCHING \
  --heartbeat-timeout 600 --default-result ABANDON

# 5. What the launch hook function does: newest tagged snapshot -> volume in the new AZ -> attach
aws ec2 describe-snapshots --owner-ids self \
  --filters Name=tag:app,Values=clinic Name=status,Values=completed \
  --query 'sort_by(Snapshots,&StartTime)[-1].[SnapshotId,StartTime]' --output text
# snap-0123456789abcdef0	2026-11-01T09:00:12.000Z
aws ec2 create-volume --snapshot-id snap-0123456789abcdef0 \
  --availability-zone ap-southeast-1b --volume-type gp3 \
  --tag-specifications 'ResourceType=volume,Tags=[{Key=app,Value=clinic}]'
# {"VolumeId": "vol-0fedcba9876543210", "AvailabilityZone": "ap-southeast-1b", "State": "creating", ...}
aws ec2 attach-volume --volume-id vol-0fedcba9876543210 \
  --instance-id i-0replacement0example --device /dev/sdf
aws autoscaling complete-lifecycle-action --auto-scaling-group-name clinic-asg \
  --lifecycle-hook-name volume-on-launch --instance-id i-0replacement0example \
  --lifecycle-action-result CONTINUE

# 6. The safety net: an hourly DLM policy for volumes tagged app=clinic, keeping 48
aws dlm create-lifecycle-policy --description "clinic hourly" --state ENABLED \
  --execution-role-arn arn:aws:iam::111122223333:role/AWSDataLifecycleManagerDefaultRole \
  --policy-details '{"PolicyType":"EBS_SNAPSHOT_MANAGEMENT","ResourceTypes":["VOLUME"],
    "TargetTags":[{"Key":"app","Value":"clinic"}],
    "Schedules":[{"Name":"hourly","CopyTags":true,
      "CreateRule":{"Interval":1,"IntervalUnit":"HOURS","Times":["00:00"]},"RetainRule":{"Count":48}}]}'
# {"PolicyId": "policy-0a1b2c3d4e5f6a7b8"}

# 7. Test it: kill the instance on purpose and time the gap
aws autoscaling set-instance-health --instance-id i-0abc123example --health-status Unhealthy
aws autoscaling describe-scaling-activities --auto-scaling-group-name clinic-asg --max-items 2

Design-এর ওপর ভরসা করার আগে ৭ নম্বর ধাপটা চালাও: কেউ পরীক্ষা করেনি এমন failover একটা আশা মাত্র, পরিকল্পনা না।

#সারসংক্ষেপ

মূল কথা

  • High availability মানে অল্প downtime, শূন্য না, আর এর জন্য লাগে একাধিক AZ। এক AZ-এ এক instance কখনোই HA-এর উত্তর না।
  • Automatic recovery একই AZ-এ নষ্ট host সারায় (একই IP, একই volume); AZ বিপর্যয় সামলাতে পারে না, আটকে যাওয়া app সারায় না, আর ASG-এর ভেতরে খাটে না।
  • Pattern 1: অন্য AZ-এ একটা বন্ধ standby; CloudWatch alarm বা EventBridge rule Lambda চালায়, Lambda সেটা চালু করে Elastic IP সরিয়ে দেয়। নজর রাখো missing-data alarm, capacity আর পুরোনো হয়ে যাওয়া standby-র দিকে।
  • Pattern 2: অন্তত দুটো AZ জুড়ে 1/1/1-এর ASG, সবচেয়ে সস্তা স্বয়ংক্রিয় উত্তর। নতুন instance-এর IP নতুন, তাই user data tag দেখে Elastic IP লাগায়, এমন একটা instance role দিয়ে যার ec2:AssociateAddress-এর অনুমতি আছে। কয়েক মিনিট বন্ধ থাকবে ধরে নাও।
  • Pattern 3: EBS তার AZ-এ আটকা, কিন্তু snapshot Regional। Terminate hook যাওয়ার পথে snapshot নেয়; launch hook নতুন AZ-এ সর্বশেষ snapshot থেকে volume বানিয়ে attach করে। AZ হঠাৎ শেষ হলে terminate hook চলতে পারে না, তখন DLM snapshot ঠিক করে কতটা data হারাল।
  • আরও ভালো: data instance-এর বাইরে রাখো: EFS Regional (One Zone না), RDS Multi-AZ, S3। ঠিকানার জন্য আরও ভালো: সামনে একটা ALB, অথবা Route 53 failover record।