1-Click Deployment
Description: Animals4Life base VPC Template + 3 Public Instances
Parameters:
  LatestAmiId:
    Description: AMI for EC2 (default is latest AmaLinux2023)
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.16.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: a4l-vpc1
  IPv6CidrBlock:
    Type: AWS::EC2::VPCCidrBlock
    Properties:
      VpcId: !Ref VPC
      AmazonProvidedIpv6CidrBlock: true
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: A4L-vpc1-igw
  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway
  RouteTableWeb:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: A4L-vpc1-rt-web
  RouteTableWebDefaultIPv4:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref RouteTableWeb
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
  RouteTableWebDefaultIPv6:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref RouteTableWeb
      DestinationIpv6CidrBlock: '::/0'
      GatewayId: !Ref InternetGateway
  RouteTableAssociationWebA:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref SubnetWEBA
      RouteTableId: !Ref RouteTableWeb
  RouteTableAssociationWebB:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref SubnetWEBB
      RouteTableId: !Ref RouteTableWeb
  RouteTableAssociationWebC:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref SubnetWEBC
      RouteTableId: !Ref RouteTableWeb
  SubnetReservedA:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 0
        - !GetAZs ''
      CidrBlock: 10.16.0.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 00::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-reserved-A
  SubnetReservedB:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 1
        - !GetAZs ''
      CidrBlock: 10.16.64.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 04::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-reserved-B
  SubnetReservedC:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 2
        - !GetAZs ''
      CidrBlock: 10.16.128.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 08::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-reserved-C
  SubnetDBA:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 0
        - !GetAZs ''
      CidrBlock: 10.16.16.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 01::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-db-A
  SubnetDBB:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 1
        - !GetAZs ''
      CidrBlock: 10.16.80.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 05::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-db-B
  SubnetDBC:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 2
        - !GetAZs ''
      CidrBlock: 10.16.144.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 09::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-db-C
  SubnetAPPA:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 0
        - !GetAZs ''
      CidrBlock: 10.16.32.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 02::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-app-A
  SubnetAPPB:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 1
        - !GetAZs ''
      CidrBlock: 10.16.96.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 06::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-app-B
  SubnetAPPC:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 2
        - !GetAZs ''
      CidrBlock: 10.16.160.0/20
      AssignIpv6AddressOnCreation: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 0A::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-app-C
  SubnetWEBA:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 0
        - !GetAZs ''
      CidrBlock: 10.16.48.0/20
      MapPublicIpOnLaunch: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 03::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-web-A
  SubnetWEBB:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 1
        - !GetAZs ''
      CidrBlock: 10.16.112.0/20
      MapPublicIpOnLaunch: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 07::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-web-B
  SubnetWEBC:
    Type: AWS::EC2::Subnet
    DependsOn: IPv6CidrBlock
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select
        - 2
        - !GetAZs ''
      CidrBlock: 10.16.176.0/20
      MapPublicIpOnLaunch: true
      Ipv6CidrBlock: !Sub
        - ${VpcPart}${SubnetPart}
        - SubnetPart: 0B::/64
          VpcPart: !Select
            - 0
            - !Split
              - 00::/56
              - !Select
                - 0
                - !GetAtt VPC.Ipv6CidrBlocks
      Tags:
        - Key: Name
          Value: sn-web-C
  IPv6WorkaroundSubnetWEBA:
    Type: Custom::SubnetModify
    Properties:
      ServiceToken: !GetAtt IPv6WorkaroundLambda.Arn
      SubnetId: !Ref SubnetWEBA
  IPv6WorkaroundSubnetWEBB:
    Type: Custom::SubnetModify
    Properties:
      ServiceToken: !GetAtt IPv6WorkaroundLambda.Arn
      SubnetId: !Ref SubnetWEBB
  IPv6WorkaroundSubnetWEBC:
    Type: Custom::SubnetModify
    Properties:
      ServiceToken: !GetAtt IPv6WorkaroundLambda.Arn
      SubnetId: !Ref SubnetWEBC
  IPv6WorkaroundRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: !Sub ipv6-fix-logs-${AWS::StackName}
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: arn:aws:logs:*:*:*
        - PolicyName: !Sub ipv6-fix-modify-${AWS::StackName}
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - ec2:ModifySubnetAttribute
                Resource: '*'
  IPv6WorkaroundLambda:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.lambda_handler
      Code:
        #import cfnresponse below required to send respose back to CFN
        ZipFile: !Sub |
          import cfnresponse
          import boto3
          def lambda_handler(event, context):
            if event['RequestType'] is 'Delete':
              cfnresponse.send(event, context, cfnresponse.SUCCESS)
              return
            responseValue = event['ResourceProperties']['SubnetId']
            ec2 = boto3.client('ec2', region_name='${AWS::Region}')
            ec2.modify_subnet_attribute(AssignIpv6AddressOnCreation={
                            'Value': True
                            },
                            SubnetId=responseValue)
            responseData = {}
            responseData['SubnetId'] = responseValue
            cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
      Runtime: python3.9
      Role: !GetAtt IPv6WorkaroundRole.Arn
      Timeout: 30
  Instance1:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: !Ref LatestAmiId
      IamInstanceProfile: !Ref SessionManagerInstanceProfile
      SubnetId: !Ref SubnetWEBA
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
      Tags:
        - Key: Name
          Value: A4L-EBS-INSTANCE1-AZA
  Instance2:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: !Ref LatestAmiId
      IamInstanceProfile: !Ref SessionManagerInstanceProfile
      SubnetId: !Ref SubnetWEBA
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
      Tags:
        - Key: Name
          Value: A4L-EBS-INSTANCE2-AZA
  Instance3:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: !Ref LatestAmiId
      IamInstanceProfile: !Ref SessionManagerInstanceProfile
      SubnetId: !Ref SubnetWEBB
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
      Tags:
        - Key: Name
          Value: A4L-EBS-INSTANCE1-AZB
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref VPC
      GroupDescription: Enable SSH access via port 22 IPv4 & v6
      SecurityGroupIngress:
        - Description: Allow SSH IPv4 IN
          IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIp: 0.0.0.0/0
        - Description: Allow HTTP IPv4 IN
          IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          CidrIp: 0.0.0.0/0
        - Description: Allow SSH IPv6 IN
          IpProtocol: tcp
          FromPort: '22'
          ToPort: '22'
          CidrIpv6: '::/0'
  SessionManagerRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - ssm:DescribeAssociation
                  - ssm:GetDeployablePatchSnapshotForInstance
                  - ssm:GetDocument
                  - ssm:DescribeDocument
                  - ssm:GetManifest
                  - ssm:GetParameter
                  - ssm:GetParameters
                  - ssm:ListAssociations
                  - ssm:ListInstanceAssociations
                  - ssm:PutInventory
                  - ssm:PutComplianceItems
                  - ssm:PutConfigurePackageResult
                  - ssm:UpdateAssociationStatus
                  - ssm:UpdateInstanceAssociationStatus
                  - ssm:UpdateInstanceInformation
                Resource: '*'
              - Effect: Allow
                Action:
                  - ssmmessages:CreateControlChannel
                  - ssmmessages:CreateDataChannel
                  - ssmmessages:OpenControlChannel
                  - ssmmessages:OpenDataChannel
                Resource: '*'
              - Effect: Allow
                Action:
                  - ec2messages:AcknowledgeMessage
                  - ec2messages:DeleteMessage
                  - ec2messages:FailMessage
                  - ec2messages:GetEndpoint
                  - ec2messages:GetMessages
                  - ec2messages:SendReply
                Resource: '*'
  SessionManagerInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref SessionManagerRole
Outputs:
  a4lvpc1:
    Description: Animals4Life VPC1_ID
    Value: !Ref VPC
    Export:
      Name: a4l-vpc1
  a4lvpc1subnetweba:
    Description: Animals4Life VPC1 SubnetWEBA
    Value: !Ref SubnetWEBA
    Export:
      Name: a4l-vpc1-subnet-weba
  a4lvpc1subnetwebb:
    Description: Animals4Life VPC1 SubnetWEBB
    Value: !Ref SubnetWEBB
    Export:
      Name: a4l-vpc1-subnet-webb
  a4lvpc1subnetwebc:
    Description: Animals4Life VPC1 SubnetWEBC
    Value: !Ref SubnetWEBC
    Export:
      Name: a4l-vpc1-subnet-webc
  a4lvpc1subnetappa:
    Description: Animals4Life VPC1 SubnetAPPA
    Value: !Ref SubnetAPPA
    Export:
      Name: a4l-vpc1-subnet-appa
  a4lvpc1subnetappb:
    Description: Animals4Life VPC1 SubnetAPPB
    Value: !Ref SubnetAPPB
    Export:
      Name: a4l-vpc1-subnet-appb
  a4lvpc1subnetappc:
    Description: Animals4Life VPC1 SubnetAPPC
    Value: !Ref SubnetAPPC
    Export:
      Name: a4l-vpc1-subnet-appc
  a4lvpc1subnetdba:
    Description: Animals4Life VPC1 SubnetDBA
    Value: !Ref SubnetDBA
    Export:
      Name: a4l-vpc1-subnet-dba
  a4lvpc1subnetdbb:
    Description: Animals4Life VPC1 SubnetDBB
    Value: !Ref SubnetDBB
    Export:
      Name: a4l-vpc1-subnet-dbb
  a4lvpc1subnetdbc:
    Description: Animals4Life VPC1 SubnetDBC
    Value: !Ref SubnetDBC
    Export:
      Name: a4l-vpc1-subnet-dbc
  a4lvpc1subnetreserveda:
    Description: Animals4Life VPC1 SubnetReservedA
    Value: !Ref SubnetReservedA
    Export:
      Name: a4l-vpc1-subnet-reserveda
  a4lvpc1subnetreservedb:
    Description: Animals4Life VPC1 SubnetReservedB
    Value: !Ref SubnetReservedB
    Export:
      Name: a4l-vpc1-subnet-reservedb
  a4lvpc1subnetreservedc:
    Description: Animals4Life VPC1 SubnetReservedC
    Value: !Ref SubnetReservedC
    Export:
      Name: a4l-vpc1-subnet-reservedc
Lesson Commands
Commands User¶
Instance 1¶
lsblk sudo file -s /dev/xvdf sudo mkfs -t xfs /dev/xvdf sudo file -s /dev/xvdf sudo mkdir /ebstest sudo mount /dev/xvdf /ebstest cd /ebstest sudo nano amazingtestfile.txt add a message save and exit ls -la
Reboot Instance 1¶
sudo reboot
Instance 1 After Reboot¶
df -k sudo blkid sudo nano /etc/fstab ADD LINE UUID=YOURUUIDHEREREPLACEME /ebstest xfs defaults,nofail sudo mount -a cd /ebstest ls -la
Instance 2¶
lsblk sudo file -s /dev/xvdf sudo mkdir /ebstest sudo mount /dev/xvdf /ebstest cd /ebstest ls -la
Instance 3¶
lsblk sudo file -s /dev/xvdf sudo mkdir /ebstest sudo mount /dev/xvdf /ebstest cd /ebstest ls -la
InstanceStoreTest¶
lsblk sudo file -s /dev/nvme1n1 sudo mkfs -t xfs /dev/nvme1n1 sudo file -s /dev/nvme1n1 sudo mkdir /instancestore sudo mount /dev/nvme1n1 /instancestore cd /instancestore sudo touch instancestore.txt
InstancStoreTest - After Restart¶
df -k its not there but we can mount it sudo mount /dev/nvme1n1 /instancestore cd /instancestore ls -la
InstanceStoreTest - After Stop/Start¶
sudo file -s /dev/nvme1n1
🛠️ Demo thực tế EBS & Snapshot – Phần 2 (script đầy đủ, thực chiến & mẹo đi làm, đi thi)¶
1. Kiểm tra persistence & auto-mount sau reboot¶
a. Sau reboot instance¶
- Đợi EC2 khởi động lại, connect lại bằng EC2 Instance Connect.
- 
Kiểm tra mount: → Không thấy volume mount vì mount thủ công chưa auto-mount sau reboot.
- 
Tìm UUID của volume: 
- Tìm dòng tương ứng với /dev/xvdf(hoặc device bạn mount, tùy instance nhận).
- 
Copy UUID (giá trị trong dấu “”). 
- 
Edit file /etc/fstabđể auto-mount:
- Thêm dòng:
- (Thay UUID và mount point cho đúng)
- 
defaults,nofailgiúp instance boot ngay cả khi volume chưa attach.
- 
Mount lại toàn bộ từ fstab: 
- 
Kiểm tra lại: → File vẫn còn, chứng minh EBS persistent & auto-mount.
2. Detach EBS & attach sang instance khác (trong cùng AZ)¶
a. Dừng (stop) instance 1a (nơi đang attach volume)¶
- EC2 Console > Instances > instance 1a > Stop
b. Detach volume¶
- EC2 Console > Volumes > chọn volume vừa test > Actions > Detach Volume
c. Attach volume sang instance 2a (cùng AZ)¶
- Chọn volume > Actions > Attach Volume > chọn instance 2a > Device: /dev/xvdf
- EC2 Console > Instances > instance 2a > Connect (EC2 Instance Connect)
d. Kiểm tra trên instance mới¶
lsblk
sudo file -s /dev/xvdf
# Thấy đã có file system xfs
sudo mkdir /EBS-test
sudo mount /dev/xvdf /EBS-test
ls /EBS-test
cat /EBS-test/amazing-test-file.txt
3. Di chuyển volume sang AZ khác bằng snapshot¶
a. Dừng instance 2a, detach volume như trên¶
b. Tạo snapshot từ volume¶
- EC2 Console > Volumes > chọn volume > Actions > Create Snapshot > mô tả EBS test snap
c. Tạo volume từ snapshot, chọn AZ khác (ví dụ: us-east-1b)¶
- Snapshots > chọn snapshot vừa tạo > Actions > Create Volume
- AZ: us-east-1b, size/type giữ nguyên, tag: EBS test volume - AZB
d. Attach volume sang instance ở AZ mới (instance-1ab)¶
- Volumes > chọn volume mới > Attach Volume > chọn instance-1ab > Device: /dev/xvdf
- EC2 Console > Instances > instance-1ab > Connect
e. Kiểm tra trên instance mới ở AZ khác¶
lsblk
sudo file -s /dev/xvdf
sudo mkdir /EBS-test
sudo mount /dev/xvdf /EBS-test
ls /EBS-test
cat /EBS-test/amazing-test-file.txt
4. Copy snapshot sang region khác (DR/migration)¶
- Snapshots > chọn snapshot > Actions > Copy Snapshot
- Chọn region đích (ví dụ: ap-southeast-2), đặt tên, bấm Copy
- Ở region đích, có thể tạo volume mới từ snapshot này.
5. Clean up resources (dọn dẹp tránh tốn phí)¶
- Snapshots > chọn snapshot > Delete
- Volumes > từng volume > Delete
- EC2 Console > Instances > dừng (stop) hoặc terminate các instance không còn dùng
6. Mẹo thực tế & đi thi cần nhớ¶
- EBS persistent, detach/attach linh hoạt trong cùng AZ
- Muốn di chuyển AZ/region → dùng snapshot
- Snapshot chỉ chứa data thực dùng, incremental
- Volume tạo từ snapshot phải mount lại, file system vẫn giữ nguyên
- fstab + UUID để auto-mount khi reboot
- Không thể attach EBS volume cross-AZ, chỉ cross-AZ bằng snapshot
- Always cleanup sau thực hành tránh phát sinh phí
7. Lệnh tổng hợp thực tế¶
# Mount auto sau reboot
sudo blkid                   # Lấy UUID
sudo nano /etc/fstab         # Thêm cấu hình mount
sudo mount -a                # Mount lại toàn bộ
df -h
ls /EBS-test
# Kiểm tra, mount, đọc file sau khi attach sang instance khác
lsblk
sudo file -s /dev/xvdf
sudo mkdir /EBS-test
sudo mount /dev/xvdf /EBS-test
ls /EBS-test
cat /EBS-test/amazing-test-file.txt
8. Giá (tham khảo us-east-1, 2024)¶
- EBS gp3: ~$0.08/GB/tháng
- Snapshot: ~$0.05/GB/tháng (data thực dùng)
- Instance lớn (cho demo instance store): ~$0.13$/giờ (không Free Tier)
- Instance store: Đã tính trong giá instance
Tóm tắt:
- EBS persistent, detach/attach linh hoạt trong AZ, snapshot để move AZ/region, dùng fstab để auto-mount, luôn cleanup để tránh phí, nhớ các step thực tế và lệnh Linux cơ bản.