Ngân hàng đề — AWS Certified Developer Associate

Tìm thấy 1356 câu.

Câu 721 AWS Compute

A media company uses Amazon EC2 instances managed by AWS Elastic Beanstalk to run its high-traffic website. The engineering team needs to introduce a new feature, which requires upgrading the underlying platform to a newer version of Node.js. The deployment of the new code and the platform upgrade need to happen without causing any downtime.

Which strategy should the team adopt to fulfill these requirements?

  1. A

    Create a duplicate EC2 instance manually with the new version of Node.js and the updated code. Test the new instance and replace one of the instances behind the ELB once the testing is successful.

  2. B

    Implement Blue/Green (CNAME Swap) deployment using Elastic Beanstalk. Prepare a separate environment with the new version of Node.js and the new code, and once testing is complete, swap the CNAMEs of the two environments.

  3. C

    Upgrade the platform version of the current Elastic Beanstalk environment, then deploy the new application code. Monitor the application and quickly roll back changes if any issues occur.

  4. D

    Use AWS CodeDeploy to deploy the new application code first, then manually update Node.js on the Elastic Beanstalk environment.

Xem giải thích

Đáp án

B — Triển khai Blue/Green (hoán đổi CNAME) với Elastic Beanstalk: chuẩn bị môi trường riêng có Node.js phiên bản mới và mã mới, kiểm thử xong thì hoán đổi CNAME.

Vì sao đúng

Đề có một chi tiết quyết định: cần nâng cấp NỀN TẢNG (platform version) — không chỉ triển khai mã mới.

Đây là điểm mà các chính sách triển khai thông thường không xử lý được tốt: nâng cấp platform version của một môi trường Beanstalk là thao tác thay thế toàn bộ instance, và nó có rủi ro gián đoạn.

Blue/green với hoán đổi CNAME giải quyết bằng cách dựng hẳn một môi trường thứ hai:

# 1. Tạo môi trường xanh với platform mới và mã mới
eb create moi-truong-xanh \
  --platform "64bit Amazon Linux 2023 v6.x.x running Node.js 20" \
  --version v2.0

# 2. Kiểm thử ĐẦY ĐỦ trên URL riêng của môi trường xanh
curl https://moi-truong-xanh.ap-southeast-1.elasticbeanstalk.com/health

# 3. Hoán đổi CNAME — traffic chuyển sang môi trường xanh
eb swap moi-truong-lam --destination-name moi-truong-xanh

Ba lợi ích khớp đúng với yêu cầu của đề: | Lợi ích | Chi tiết | |---|---| | Không downtime | môi trường cũ chạy nguyên vẹn cho tới khi hoán đổi | | Kiểm thử đầy đủ trước | URL riêng, không ai bị ảnh hưởng | | Rollback nhanh nhất | hoán đổi CNAME ngược lại — vài giây |

Và quan trọng nhất với đề bài: cả nâng cấp platform lẫn triển khai mã diễn ra trên môi trường mới, nên môi trường production không bị đụng tới chút nào.

Vì sao các phương án khác sai

  • C. Nâng cấp platform version của môi trường hiện tại rồi triển khai mã mới — có rủi ro gián đoạn: nâng cấp platform thay thế instance, và nếu phiên bản Node.js mới làm hỏng ứng dụng thì production đã bị ảnh hưởng rồi mới phát hiện. Rollback cũng chậm — phải nâng cấp ngược lại.
  • A. Tạo thủ công một EC2 với Node.js mới, kiểm thử rồi thay một instance sau ELB — thủ công và không nhất quán: bạn tạo một máy nằm ngoài quản lý của Beanstalk, và ASG của Beanstalk có thể huỷ nó bất cứ lúc nào. Ngoài ra "thay một instance" nghĩa là hai phiên bản chạy song song mà không có kiểm soát.
  • D. Dùng CodeDeploy triển khai mã rồi cập nhật Node.js thủ công — sai thứ tự và sai công cụ: mã mới cần Node.js mới, nên triển khai mã trước sẽ hỏng. Và cập nhật Node.js thủ công trên môi trường Beanstalk sẽ bị ghi đè ở lần thay thế instance tiếp theo — Beanstalk quản lý platform, không phải bạn.

Ghi nhớ

Hai loại thay đổi trong Beanstalk, và cách xử lý khác nhau: | Thay đổi | Cách xử lý | |---|---| | Chỉ mã ứng dụng | deployment policy (rolling, immutable…) | | Platform version, cấu hình lớn, hoặc cả hai | blue/green với hoán đổi CNAME |

Năm deployment policy của Beanstalk — dùng khi chỉ đổi mã: | Chính sách | Downtime | Đủ năng lực | Rollback | |---|---|---|---| | All at once | CÓ | ❌ | chậm | | Rolling | không | ❌ giảm | chậm | | Rolling + additional batch | không | ✅ | chậm | | Immutable | không | ✅ | nhanh | | Traffic splitting | không | ✅ | nhanh |

Blue/green không nằm trong bảng này vì nó không phải một deployment policy — nó là kỹ thuật vận hành dựa trên tính năng hoán đổi CNAME giữa hai môi trường.

Ba lưu ý khi hoán đổi CNAME:

  1. DNS có TTL — client đã cache kết quả cũ vẫn tới môi trường cũ trong khoảng đó. Đừng huỷ môi trường cũ ngay; chờ ít nhất vài lần TTL.
  2. CSDL phải nằm ngoài môi trường Beanstalk — nếu để Beanstalk tạo RDS như một phần của môi trường, hoán đổi sẽ khiến hai môi trường trỏ vào hai CSDL khác nhau.
  3. Chi phí gấp đôi trong thời gian hai môi trường cùng tồn tại.

Điểm thứ hai đáng nhấn mạnh: luôn tạo RDS độc lập rồi truyền endpoint vào Beanstalk qua biến môi trường — đây là thực hành bắt buộc cho production.

Câu 722 AWS Security, Identity, & Compliance

An application is running on a fleet of EC2 instances running behind an Elastic Load Balancer (ELB). The EC2 instances session data in a shared Amazon S3 bucket. Security policy mandates that data must be encrypted in transit.

How can the Developer ensure that all data that is sent to the S3 bucket is encrypted in transit?

  1. A

    Create an S3 bucket policy that denies traffic where SecureTransport is true

  2. B

    Create an S3 bucket policy that denies any S3 Put request that does not include the x-amz-server-side-encryption

  3. C

    Create an S3 bucket policy that denies traffic where SecureTransport is false

  4. D

    Configure HTTP to HTTPS redirection on the Elastic Load Balancer

Xem giải thích

Đáp án

C — Tạo bucket policy từ chối traffic khi aws:SecureTransport là false.

Vì sao đúng

Yêu cầu là mã hoá khi truyền (in transit), và aws:SecureTransport là khoá điều kiện toàn cục cho biết request có đi qua HTTPS hay không.

Cách viết đúng là Deny khi giá trị là false:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "BatBuocHTTPS",
    "Effect": "Deny",
    "Principal": "*",
    "Action": "s3:*",
    "Resource": [
      "arn:aws:s3:::kho-session",
      "arn:aws:s3:::kho-session/*"
    ],
    "Condition": {"Bool": {"aws:SecureTransport": "false"}}
  }]
}

Hai chi tiết quan trọng trong policy này:

1. Dùng Deny, không dùng Allow. Vì Deny tường minh thắng mọi Allow, không IAM policy nào ở bất kỳ đâu có thể lách qua. Viết dạng Allow khi SecureTransport = true thì một Allow khác vẫn có thể cho HTTP đi qua.

2. Phải khai CẢ HAI ARN. arn:aws:s3:::bucket áp cho thao tác mức bucket (ListBucket), còn arn:aws:s3:::bucket/* áp cho thao tác mức object (GetObject, PutObject). Thiếu một trong hai là có lỗ hổng.

Vì sao các phương án khác sai

  • A. Từ chối traffic khi SecureTransport là true — đảo ngược điều kiện: nó chặn đúng những request đang dùng HTTPS và cho phép HTTP đi qua. Sai hoàn toàn về ý định.
  • B. Từ chối PutObject không kèm x-amz-server-side-encryption — nhầm hai loại mã hoá: điều kiện này bắt buộc mã hoá KHI LƯU (at rest), còn đề hỏi về mã hoá KHI TRUYỀN (in transit). Hai thứ hoàn toàn khác nhau.
  • D. Cấu hình chuyển hướng HTTP sang HTTPS trên load balancer — sai đối tượng: ELB kiểm soát traffic giữa client và EC2, còn đề hỏi về traffic giữa EC2 và S3. Cấu hình này không chạm tới đường đi đó.

Ghi nhớ

Hai loại mã hoá — đừng bao giờ lẫn: | | Khi truyền (in transit) | Khi lưu (at rest) | |---|---|---| | Bảo vệ khỏi | nghe lén trên đường mạng | đọc trộm dữ liệu trên đĩa | | Cơ chế S3 | HTTPS/TLS | SSE-S3, SSE-KMS, SSE-C | | Bắt buộc bằng | aws:SecureTransport | s3:x-amz-server-side-encryption |

Bộ đôi policy thường đi cùng nhau cho yêu cầu tuân thủ đầy đủ:

// 1. Bắt buộc HTTPS (in transit)
{"Effect":"Deny","Principal":"*","Action":"s3:*","Resource":["arn:aws:s3:::kho","arn:aws:s3:::kho/*"],
 "Condition":{"Bool":{"aws:SecureTransport":"false"}}}

// 2. Bắt buộc mã hoá at rest
{"Effect":"Deny","Principal":"*","Action":"s3:PutObject","Resource":"arn:aws:s3:::kho/*",
 "Condition":{"Null":{"s3:x-amz-server-side-encryption":"true"}}}

Vài khoá điều kiện toàn cục hữu ích khác: | Khoá | Kiểm tra | |---|---| | aws:SecureTransport | request có dùng HTTPS không | | aws:SourceIp | IP nguồn | | aws:SourceVpce | đến từ VPC endpoint nào | | aws:PrincipalOrgID | thuộc tổ chức nào | | aws:MultiFactorAuthPresent | có dùng MFA không |

Khoá aws:SourceVpce đáng nhớ cho kiến trúc trong đề: nếu EC2 truy cập S3 qua VPC Gateway Endpoint, bạn thắt chặt được thêm một bậc — chỉ cho phép truy cập từ đúng endpoint đó, chặn hoàn toàn mọi đường khác.

Và nguyên tắc thiết kế: dùng Deny cho guardrail bảo mật, Allow cho việc cấp quyền. Deny không thể bị lách bởi bất kỳ policy nào khác — đó là điều làm nó phù hợp cho các yêu cầu tuân thủ.

Câu 723 AWS Networking & Content Delivery

An AWS Lambda function must be connected to an Amazon VPC private subnet that does not have Internet access. The function also connects to an Amazon DynamoDB table. What MUST a Developer do to enable access to the DynamoDB table?

  1. A

    Attach an ENI to the DynamoDB table

  2. B

    Attach an Internet Gateway

  3. C

    Create a route table

  4. D

    Configure a VPC endpoint

Xem giải thích

Đáp án

D — Cấu hình một VPC endpoint.

Vì sao đúng

Bối cảnh: Lambda nằm trong private subnet không có Internet, và cần gọi DynamoDB.

Điểm mấu chốt: DynamoDB là dịch vụ công khai, không nằm trong VPC của bạn. Bình thường, lời gọi tới nó đi qua Internet — mà private subnet thì không có đường ra.

VPC endpoint tạo một đường riêng từ VPC tới dịch vụ AWS, không qua Internet:

aws ec2 create-vpc-endpoint \
  --vpc-id vpc-abc123 \
  --service-name com.amazonaws.ap-southeast-1.dynamodb \
  --vpc-endpoint-type Gateway \
  --route-table-ids rtb-private-a rtb-private-b

Với DynamoDB, loại endpoint là Gateway endpoint — và nó có hai ưu điểm lớn: | Ưu điểm | Chi tiết | |---|---| | MIỄN PHÍ | không tính phí endpoint, không tính phí dữ liệu | | Không cần NAT | tiết kiệm hẳn chi phí NAT Gateway |

Cách nó hoạt động: endpoint thêm một route vào route table của subnet, trỏ dải IP của DynamoDB tới endpoint thay vì ra Internet Gateway.

Sau khi tạo, hàm Lambda gọi DynamoDB bình thường — không đổi một dòng mã nào:

import boto3
table = boto3.resource('dynamodb').Table('don-hang')
table.get_item(Key={'id': 'DH-001'})    # đi qua VPC endpoint

Vì sao các phương án khác sai

  • B. Gắn Internet Gateway — hai vấn đề. Thứ nhất, IGW gắn vào VPC, và subnet có route tới IGW thì trở thành public subnet — trái yêu cầu "private". Thứ hai, kể cả muốn ra Internet từ private subnet thì phải dùng NAT Gateway, không phải IGW.
  • C. Tạo route table — thiếu bước quan trọng: route table cần một đích (target) để trỏ tới. Không có VPC endpoint hay NAT Gateway thì không có gì để khai vào route. (Việc thêm route là một phần của quy trình tạo Gateway endpoint, nhưng bản thân nó không đủ.)
  • A. Gắn ENI vào bảng DynamoDB — không làm được: DynamoDB là dịch vụ được quản lý, bạn không có quyền truy cập vào hạ tầng của nó và không gắn network interface vào bảng.

Ghi nhớ

Hai loại VPC endpoint — khác biệt rất quan trọng: | | Gateway endpoint | Interface endpoint (PrivateLink) | |---|---|---| | Dịch vụ hỗ trợ | CHỈ S3 và DynamoDB | hầu hết dịch vụ AWS | | Cơ chế | route trong route table | ENI có IP riêng trong subnet | | Chi phí | MIỄN PHÍ | có phí giờ + phí dữ liệu | | DNS | dùng tên miền công khai | tên miền riêng (bật private DNS thì dùng được tên công khai) | | Từ on-premises | ❌ | ✅ qua Direct Connect/VPN |

Dòng đầu tiên đáng thuộc: chỉ S3 và DynamoDB có Gateway endpoint — mọi dịch vụ khác (Secrets Manager, KMS, SQS, SNS…) phải dùng Interface endpoint có phí.

Ba cách để tài nguyên trong private subnet gọi được dịch vụ AWS: | Cách | Chi phí | Bảo mật | |---|---|---| | NAT Gateway | có phí giờ + phí GB | traffic ra Internet | | Gateway endpoint (S3, DynamoDB) | miễn phí | không ra Internet | | Interface endpoint | có phí | không ra Internet |

Với Lambda trong VPC, đây là điều cần lưu ý nhất: gắn hàm vào VPC là nó mất truy cập Internet, nên mọi dịch vụ AWS nó cần gọi đều phải có đường riêng.

Và một lợi ích bảo mật của endpoint: bạn thắt chặt được policy theo aws:SourceVpce:

"Condition": {"StringNotEquals": {"aws:SourceVpce": "vpce-0abc123"}}

Kết hợp với Deny, cách này đảm bảo bảng DynamoDB chỉ truy cập được từ đúng VPC của bạn — kể cả credential bị lộ cũng không dùng được từ ngoài.

Câu 724 AWS Application Integration

A Developer is writing an AWS Lambda function that processes records from an Amazon Kinesis Data Stream. The Developer must write the function so that it sends a notice to Administrators if it fails to process a batch of records.

How should the Developer write the function?

  1. A

    Separate the Lambda handler from the core logic

  2. B

    Push the failed records to an Amazon SQS queue

  3. C

    Use Amazon CloudWatch Events to send the processed data

  4. D

    Configure an Amazon SNS topic as an on-failure destination

Xem giải thích

Đáp án

D — Cấu hình một SNS topic làm on-failure destination.

Vì sao đúng

Yêu cầu: gửi thông báo cho quản trị viên khi hàm xử lý một lô bản ghi thất bại.

Lambda destination là tính năng dựng sẵn cho việc đó — và với nguồn kiểu stream như Kinesis, nó khai trong event source mapping:

aws lambda update-event-source-mapping --uuid <id> \
  --maximum-retry-attempts 3 \
  --bisect-batch-on-function-error \
  --destination-config '{
    "OnFailure": {"Destination": "arn:aws:sns:ap-southeast-1:123456789012:canh-bao-quan-tri"}
  }'

Khi một lô thất bại hết số lần thử, Lambda tự gửi bản ghi mô tả sự cố tới SNS:

{
  "requestContext": {"functionArn": "...", "condition": "RetryAttemptsExhausted"},
  "responseContext": {"statusCode": 200, "functionError": "Unhandled"},
  "version": "1.0",
  "timestamp": "2026-08-05T10:30:00.000Z",
  "KinesisBatchInfo": {
    "shardId": "shardId-000000000001",
    "startSequenceNumber": "49590338271490256608559692538361571095921575989136588898",
    "endSequenceNumber": "...",
    "batchSize": 100
  }
}

SNS là lựa chọn đúng vì đề nói "gửi thông báo" — nó gửi thẳng email, SMS, hoặc đẩy sang Slack qua AWS Chatbot. Và mô hình pub/sub cho phép nhiều người cùng nhận mà không cần sửa cấu hình Lambda.

Đáng chú ý: bản ghi gửi đi chỉ chứa metadata về lô (shard, khoảng sequence number), không chứa dữ liệu. Quản trị viên dùng thông tin đó để đọc lại đúng đoạn stream nếu cần điều tra.

Vì sao các phương án khác sai

  • B. Đẩy các bản ghi lỗi vào SQS queue — cách hợp lệ để LƯU LẠI bản ghi hỏng, nhưng nó không gửi thông báo cho ai cả. Đề yêu cầu rõ là "sends a notice to Administrators". (SQS cũng là destination hợp lệ — nhưng nó phục vụ mục đích khác: xử lý lại về sau.)
  • A. Tách Lambda handler khỏi phần logic cốt lõi — thực hành tốt về cấu trúc mã (dễ kiểm thử đơn vị hơn), nhưng hoàn toàn không liên quan tới việc thông báo khi thất bại.
  • C. Dùng CloudWatch Events để gửi dữ liệu đã xử lý — sai hai chỗ: EventBridge không phát sự kiện khi một lô Lambda thất bại, và phương án nói về "dữ liệu đã xử lý" — tức là trường hợp thành công, ngược với điều đề hỏi.

Ghi nhớ

Lambda destination — các đích hợp lệ và khi nào chọn cái nào: | Đích | Dùng khi | |---|---| | SNS | gửi thông báo cho người — email, SMS, Slack | | SQS | lưu lại để xử lý lại về sau | | Lambda | chạy logic xử lý lỗi phức tạp | | EventBridge | định tuyến theo mẫu tới nhiều nơi |

Hai loại destination: | | On success | On failure | |---|---|---| | Kích hoạt khi | hàm chạy xong không lỗi | hết số lần thử mà vẫn lỗi | | Có với nguồn stream? | ❌ | ✅ |

Ba tham số quan trọng của event source mapping cho Kinesis — nên cấu hình đủ cả ba: | Tham số | Việc | |---|---| | MaximumRetryAttempts | giới hạn số lần thử (mặc định: tới khi hết hạn giữ dữ liệu) | | BisectBatchOnFunctionError | chia đôi lô khi lỗi để CÔ LẬP bản ghi hỏng | | DestinationConfig | gửi thông tin lô hỏng đi đâu | | MaximumRecordAgeInSeconds | bỏ qua bản ghi quá cũ |

Thiếu ba tham số đầu là một bản ghi hỏng sẽ chặn toàn bộ shard trong 24 giờ — Lambda cứ thử lại mãi cùng một lô, và mọi bản ghi phía sau nằm chờ. Đây là sự cố khó chịu và khá phổ biến với Kinesis.

BisectBatchOnFunctionError đặc biệt hữu ích: thay vì bỏ cả lô 100 bản ghi vì một cái hỏng, nó chia đôi liên tục cho tới khi tìm ra đúng bản ghi gây lỗi — 99 bản ghi còn lại vẫn được xử lý.

Câu 725 AWS Compute

A Developer is deploying an Amazon ECS update using AWS CodeDeploy. In the appspec.yaml file, which of the following is a valid structure for the order of hooks that should be specified?

  1. A

    BeforeBlockTraffic > AfterBlockTraffic > BeforeAllowTraffic > AfterAllowTraffic

  2. B

    BeforeAllowTraffic > AfterAllowTraffic

  3. C


    BeforeInstall > AfterInstall > ApplicationStart > ValidateService

  4. D

    BeforeInstall > AfterInstall > AfterAllowTestTraffic > BeforeAllowTraffic > AfterAllowTraffic

Xem giải thích

Đáp án

D — BeforeInstall → AfterInstall → AfterAllowTestTraffic → BeforeAllowTraffic → AfterAllowTraffic.

Vì sao đúng

Amazon ECS có đúng năm hook, và thứ tự trên phản ánh các giai đoạn của một lần triển khai blue/green:

1. BeforeInstall        ← trước khi tạo task set mới
2. AfterInstall         ← task set mới đã tạo, chưa nhận traffic
3. AfterAllowTestTraffic ← TEST listener đã trỏ vào task set mới
4. BeforeAllowTraffic   ← ngay trước khi chuyển traffic PRODUCTION
5. AfterAllowTraffic    ← traffic production đã chuyển xong
version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: "arn:aws:ecs:...:task-definition/ung-dung:5"
        LoadBalancerInfo: {ContainerName: "web", ContainerPort: 80}
Hooks:
  - BeforeInstall: "arn:aws:lambda:...:function:chuan-bi"
  - AfterInstall: "arn:aws:lambda:...:function:kiem-tra-cau-hinh"
  - AfterAllowTestTraffic: "arn:aws:lambda:...:function:kiem-thu-sau"
  - BeforeAllowTraffic: "arn:aws:lambda:...:function:chot-cuoi"
  - AfterAllowTraffic: "arn:aws:lambda:...:function:kiem-tra-sau-trien-khai"

Hook đặc trưng nhất của ECS là AfterAllowTestTraffic: nó chạy khi test listener đã trỏ vào task set mới, cho phép kiểm thử sâu bằng traffic thật mà người dùng production chưa hề bị ảnh hưởng.

Đây là lý do blue/green trên ECS cần hai listener — một cho production, một cho test.

Vì sao các phương án khác sai

  • B. BeforeAllowTraffic → AfterAllowTraffic — đây là bộ hook của AWS Lambda, chỉ có hai. Lambda không có bước cài đặt (version đã tồn tại sẵn) và không có test listener.
  • C. BeforeInstall → AfterInstall → ApplicationStart → ValidateService — bộ hook của EC2/On-premises kiểu in-place. Nó có ý nghĩa ở đó vì thật sự có bước dừng, cài đặt và khởi động ứng dụng trên máy.
  • A. BeforeBlockTraffic → AfterBlockTraffic → BeforeAllowTraffic → AfterAllowTraffic — bộ hook của EC2/On-premises có load balancer: rút instance khỏi LB, cập nhật, rồi đưa lại vào. ECS không có khái niệm "block traffic" vì task set mới và cũ tồn tại song song.

Ghi nhớ

Bảng hook theo nền tảng — đáng thuộc vì đề hay hỏi: | Nền tảng | Hook | |---|---| | Lambda | BeforeAllowTraffic, AfterAllowTraffic (chỉ hai) | | ECS | BeforeInstall, AfterInstall, AfterAllowTestTraffic, BeforeAllowTraffic, AfterAllowTraffic | | EC2 in-place | ApplicationStop, BeforeInstall, AfterInstall, ApplicationStart, ValidateService | | EC2 blue/green | thêm BeforeBlockTraffic, AfterBlockTraffic |

Ba mẹo nhận dạng nhanh: | Thấy hook | Nền tảng | |---|---| | AfterAllowTestTraffic | chỉ có ở ECS | | ApplicationStop / ApplicationStart | chỉ có ở EC2/on-premises | | Chỉ hai hook *AllowTraffic | Lambda |

Hai hook dùng để kiểm thử trong ECS, và chúng khác nhau về phạm vi: | Hook | Kiểm thử qua | |---|---| | AfterAllowTestTraffic | test listener — kiểm thử sâu, chưa ai bị ảnh hưởng | | BeforeAllowTraffic | chốt cuối cùng trước khi mở cho người dùng |

Nguyên tắc chung: mọi việc kiểm tra có thể chặn được triển khai đều phải nằm TRƯỚC khi traffic production chuyển. Hook sau khi chuyển chỉ dùng để phát hiện và rollback — tức là đã có người dùng gặp lỗi.

Và điều bắt buộc với mọi hook function: phải gọi put_lifecycle_event_hook_execution_status để báo kết quả về CodeDeploy:

cd.put_lifecycle_event_hook_execution_status(
    deploymentId=event['DeploymentId'],
    lifecycleEventHookExecutionId=event['LifecycleEventHookExecutionId'],
    status='Succeeded' if kiem_thu_ok() else 'Failed')

Quên gọi là triển khai treo cho tới khi hết timeout.

Câu 726 AWS Application Integration

A monitoring application that keeps track of a large eCommerce website uses Amazon Kinesis for data ingestion. During periods of peak data rates, the Kinesis stream cannot keep up with the incoming data.
What step will allow Kinesis data streams to accommodate the traffic during peak hours?

  1. A

    1. Ingest multiple records into the stream in a single call using PutRecords

  2. B

    Install the Kinesis Producer Library (KPL) for ingesting data into the stream

  3. C

    Create an SQS queue and decouple the producers from the Kinesis data stream

  4. D

    Increase the shard count of the stream using UpdateShardCount

Xem giải thích

Đáp án

D — Tăng số shard của stream bằng UpdateShardCount.

Vì sao đúng

Vấn đề trong đề rất rõ: stream không theo kịp lượng dữ liệu vào lúc cao điểm. Đó là giới hạn ở năng lực nạp, và năng lực nạp của Kinesis được quyết định bởi số shard.

Giới hạn của mỗi shard: | Chiều | Giới hạn mỗi shard | |---|---| | Ghi | 1 MB/giây hoặc 1.000 bản ghi/giây | | Đọc (shared fan-out) | 2 MB/giây |

Nên nếu đỉnh tải vượt quá số_shard × 1 MB/giây, producer sẽ nhận ProvisionedThroughputExceededException và dữ liệu bị từ chối.

Thêm shard là cách duy nhất tăng năng lực nạp:

aws kinesis update-shard-count \
  --stream-name du-lieu-giam-sat \
  --target-shard-count 20 \
  --scaling-type UNIFORM_SCALING

UpdateShardCount tiện hơn SplitShard thủ công vì AWS tự tính toán cách chia — bạn chỉ nêu số shard mong muốn.

(Vài giới hạn của lệnh này: mỗi lần gọi tăng tối đa gấp đôi hoặc giảm tối đa một nửa, và có giới hạn số lần thực hiện trong 24 giờ.)

Và với tải biến động mạnh theo giờ như đề mô tả, đáng cân nhắc chế độ on-demand — nó tự co giãn tới 200 MB/giây mà không phải quản shard:

aws kinesis update-stream-mode --stream-arn <arn> \
  --stream-mode-details StreamMode=ON_DEMAND

Vì sao các phương án khác sai

  • B. Cài Kinesis Producer Library (KPL) — đây là phương án đáng cân nhắc nhất, vì KPL thật sự cải thiện hiệu quả: nó gom nhiều bản ghi nhỏ vào một (aggregation) nên tận dụng tốt hơn giới hạn 1.000 bản ghi/giây. Nhưng nó không nới được giới hạn 1 MB/giây mỗi shard — nếu nút thắt là băng thông thì KPL không giúp gì.
  • A. Dùng PutRecords để gửi nhiều bản ghi trong một lời gọi — cũng chỉ giảm số lời gọi API, không tăng năng lực của shard. Vẫn cùng giới hạn 1 MB/giây.
  • C. Tạo SQS queue để tách producer khỏi Kinesis — chỉ trì hoãn vấn đề: hàng đợi hấp thụ được đỉnh ngắn, nhưng nếu tốc độ trung bình vượt năng lực stream thì hàng đợi dài ra vô hạn và độ trễ tăng mãi. Ngoài ra nó thêm một dịch vụ và một tầng xử lý.

Ghi nhớ

Ba cách xử lý khi Kinesis không theo kịp: | Nút thắt | Giải pháp | |---|---| | Vượt 1 MB/giây mỗi shard | thêm shard ← câu này | | Vượt 1.000 bản ghi/giây mỗi shard | KPL aggregation hoặc thêm shard | | Một shard nóng hơn hẳn | sửa partition key để rải đều | | Tải biến động mạnh | chế độ on-demand |

Dòng thứ ba đáng kiểm tra trước tiên: nếu partition key có ít giá trị (ví dụ chỉ 3 mã vùng), mọi dữ liệu dồn vào vài shard trong khi các shard khác nằm không. Khi đó thêm shard không giúp gì — phải sửa cách chọn partition key.

Các metric cần theo dõi: | Metric | Ý nghĩa | |---|---| | WriteProvisionedThroughputExceeded | thiếu shard cho ghi ← triệu chứng của đề | | ReadProvisionedThroughputExceeded | thiếu băng thông đọc | | GetRecords.IteratorAgeMilliseconds | consumer đang tụt lại bao xa | | IncomingBytes, IncomingRecords | lượng dữ liệu vào |

Hai chế độ năng lực của Kinesis Data Streams: | | Provisioned | On-demand | |---|---|---| | Quản shard | bạn tự tính | tự động | | Năng lực | shard × 1 MB/giây | tới 200 MB/giây | | Chi phí | rẻ hơn khi tải đều | cao hơn mỗi GB, rẻ hơn khi tải thất thường |

Với hệ thống thương mại điện tử có đỉnh tải rõ rệt như đề mô tả, on-demand thường là lựa chọn thực dụng hơn — nó loại bỏ hẳn việc phải đoán trước số shard và phản ứng kịp thời với đỉnh bất ngờ.

Câu 727 Chọn nhiều đáp án AWS Networking & Content Delivery

An online multiplayer game employs Amazon API Gateway WebSocket APIs with an HTTP backend. The game developer needs to add a feature that identifies players with unstable connections who repeatedly join and leave the game. The developer also wants the ability to disconnect such players from the game.

What two modifications should the developer implement in the game to fulfill these requirements? (Select TWO.)

  1. A

    Add logic to track the player's connection status using Amazon DynamoDB in the backend service.

  2. B

    Switch to AWS App Runner for the backend service.

  3. C

    Switch to REST APIs in the backend service.

  4. D

    Implement AWS Cognito for player authentication in the backend service.

  5. E

    Implement $connect and $disconnect routes in the backend service.

Xem giải thích

Đáp án

A và E.

  • E — Cài đặt các route $connect và $disconnect trong backend
  • A — Thêm logic theo dõi trạng thái kết nối bằng DynamoDB trong backend

Vì sao đúng

Đề nêu hai nhu cầu, và mỗi đáp án giải quyết một nhu cầu:

  1. Phát hiện người chơi liên tục vào ra (kết nối không ổn định)
  2. Ngắt kết nối những người chơi đó

E — hai route đặc biệt của WebSocket API là nơi bắt sự kiện vào và ra:

# Route $connect
def xu_ly_ket_noi(event, context):
    conn_id = event['requestContext']['connectionId']
    nguoi_choi = event['queryStringParameters']['playerId']
    bang.put_item(Item={
        'connection_id': conn_id,
        'nguoi_choi': nguoi_choi,
        'ket_noi_luc': int(time.time()),
        'het_han': int(time.time()) + 86400        # TTL dọn bản ghi mồ côi
    })
    return {'statusCode': 200}

# Route $disconnect
def xu_ly_ngat(event, context):
    conn_id = event['requestContext']['connectionId']
    item = bang.delete_item(Key={'connection_id': conn_id}, ReturnValues='ALL_OLD')
    ghi_nhan_lan_ngat(item['Attributes']['nguoi_choi'])

A — DynamoDB lưu trạng thái, vì WebSocket API không tự nhớ ai đang kết nối. Bảng này phục vụ hai việc: | Việc | Cách dùng bảng | |---|---| | Đếm số lần vào/ra | ghi một bản ghi mỗi lần $disconnect | | Ngắt kết nối người chơi | tra connectionId hiện tại của họ để gọi API ngắt |

Và ngắt kết nối dùng Management API:

apigw = boto3.client('apigatewaymanagementapi',
                     endpoint_url='https://abc123.execute-api.ap-southeast-1.amazonaws.com/prod')
apigw.delete_connection(ConnectionId=conn_id)

Hai đáp án bổ sung cho nhau: E bắt sự kiện, A lưu và phân tích chúng.

Vì sao các phương án khác sai

  • C. Chuyển sang REST API — REST không giữ kết nối bền: mỗi request là một kết nối riêng, không có khái niệm "connect" và "disconnect". Chuyển sang REST là mất hẳn khả năng phát hiện điều đề yêu cầu.
  • D. Dùng Cognito để xác thực người chơi — xác thực CHO BIẾT AI, nhưng không theo dõi trạng thái kết nối. Hữu ích để định danh người chơi (và thường dùng ở $connect), nhưng một mình nó không đáp ứng được yêu cầu nào trong hai yêu cầu.
  • B. Chuyển backend sang AWS App Runner — đổi nơi chạy mã, không thêm khả năng nào. Vấn đề nằm ở logic theo dõi kết nối, không phải ở nền tảng tính toán.

Ghi nhớ

Ba route đặc biệt của WebSocket API — luôn có sẵn, không do bạn đặt tên: | Route | Kích hoạt khi | |---|---| | $connect | client mở kết nối — nơi xác thực và lưu connectionId | | $disconnect | client ngắt kết nối — nơi dọn dẹp | | $default | message không khớp route nào |

Các API của Management API để tương tác với kết nối: | API | Việc | |---|---| | PostToConnection | gửi message tới một client | | DeleteConnection | ngắt kết nối một client | | GetConnection | xem thông tin kết nối |

Ba lưu ý quan trọng khi làm việc với WebSocket API:

  1. $disconnect là best-effort — nếu client mất mạng đột ngột, sự kiện này có thể không tới. Vì vậy luôn đặt TTL trên bảng DynamoDB để dọn các bản ghi mồ côi.
  2. PostToConnection trả về GoneException nếu kết nối đã đóng — dùng nó làm tín hiệu dọn bản ghi:
    try:
        apigw.post_to_connection(ConnectionId=cid, Data=du_lieu)
    except apigw.exceptions.GoneException:
        bang.delete_item(Key={'connection_id': cid})
    
  3. Giới hạn thời gian: kết nối WebSocket của API Gateway tối đa 2 giờ, và idle timeout 10 phút — client phải gửi ping định kỳ để giữ kết nối.

Điểm thứ ba đáng chú ý với game: hãy đảm bảo client có cơ chế tự kết nối lại, nếu không người chơi sẽ bị rơi sau 2 giờ chơi liên tục.

Câu 728 AWS Compute

A software organization has developed a new feature in its serverless application hosted on AWS. This feature involves an AWS Lambda function that gets invoked by an Amazon API Gateway API. Currently, the API uses a specific Lambda alias to invoke the Lambda function. The organization wants to roll out this new feature to a select group of users for beta testing without affecting the application's existing users.

What would be the most efficient approach to meet these requirements?

  1. A

    Use the AWS CLI to manually switch between the old and new versions of the Lambda function during testing periods.

  2. B

    Implement Amazon S3 bucket versioning on the Lambda function code. For testing purposes, link the API Gateway to the new version of the code stored in the S3 bucket.

  3. C

    Use AWS CodeDeploy to deploy the updated Lambda function. Split traffic between the new and old versions of the function for testing purposes.

  4. D

    Create a new version of the Lambda function. Build a new stage on API Gateway integrated with this new Lambda version. Utilize this new API Gateway stage for beta testing.

Xem giải thích

Đáp án

D — Tạo một version mới của hàm Lambda, dựng một stage mới trên API Gateway tích hợp với version đó, và dùng stage mới cho beta test.

Vì sao đúng

Chi tiết quyết định nằm ở yêu cầu: phát hành cho một NHÓM NGƯỜI DÙNG XÁC ĐỊNH để beta test, không ảnh hưởng người dùng hiện tại.

Đó là nhóm xác định, không phải "một tỷ lệ phần trăm ngẫu nhiên" — nên cần một endpoint riêng mà chỉ nhóm đó biết:

https://abc123.execute-api.ap-southeast-1.amazonaws.com/prod  → alias "prod"  → version 4
https://abc123.execute-api.ap-southeast-1.amazonaws.com/beta  → version 5     ← chỉ beta tester

Quy trình:

# 1. Publish version mới
version=$(aws lambda publish-version --function-name xu-ly --query Version --output text)

# 2. Tạo alias cho beta rồi trỏ vào version đó
aws lambda create-alias --function-name xu-ly --name beta --function-version $version

# 3. Tạo stage beta trên API Gateway, dùng stage variable trỏ tới alias
aws apigateway create-deployment --rest-api-id abc123 --stage-name beta \
  --variables alias=beta

Với integration URI dạng ...function:xu-ly:${stageVariables.alias}, stage prod và stage beta tự trỏ vào hai version khác nhau mà không phải sửa gì trong định nghĩa API.

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Cô lập hoàn toàn | người dùng production không bao giờ chạm vào bản beta | | Kiểm soát ai được thử | chỉ người biết URL beta | | Cấu hình riêng | log chi tiết hơn ở stage beta, throttling riêng |

Vì sao các phương án khác sai

  • C. Dùng CodeDeploy chia traffic giữa version cũ và mới — đây là phương án đáng cân nhắc nhất, và cần phân biệt kỹ. Traffic splitting chia theo TỶ LỆ NGẪU NHIÊN — nghĩa là một phần người dùng hiện tại sẽ nhận bản beta mà không hề hay biết. Trái yêu cầu "without affecting the application's existing users". (Canary là công cụ đúng khi bạn muốn thử với % người dùng thật; ở đây đề muốn nhóm xác định.)
  • A. Dùng AWS CLI chuyển đổi thủ công giữa hai version trong lúc kiểm thử — không cô lập gì cả: khi chuyển sang version mới thì mọi người dùng đều nhận bản beta. Và đó là thao tác thủ công, dễ quên chuyển lại.
  • B. Bật S3 bucket versioning cho mã Lambda rồi trỏ API Gateway vào version trong S3 — hiểu sai cơ chế: API Gateway trỏ tới hàm Lambda qua ARN, không trỏ tới tệp mã trên S3. S3 versioning chỉ quản lý các phiên bản của gói ZIP, không tạo ra endpoint nào.

Ghi nhớ

Ba cách phát hành từng phần với Lambda và API Gateway — chọn theo ai được thử: | Cách | Ai nhận bản mới | |---|---| | Stage riêng | nhóm xác định biết URL ← câu này | | Lambda alias weighted routing | % ngẫu nhiên trong tổng traffic | | API Gateway canary | % ngẫu nhiên, cùng một URL | | Header hoặc cookie routing | nhóm xác định, cùng URL |

Nhận dạng nhanh trong đề:

  • "select group of users", "beta testers", "without affecting existing users" ⇒ stage riêng
  • "gradually roll out", "X% of traffic" ⇒ canary hoặc weighted routing

Mô hình version và alias của Lambda: | Khái niệm | Là gì | Đổi được? | |---|---|---| | $LATEST | bản đang sửa | ✅ (đừng dùng cho production) | | Version | bản chụp BẤT BIẾN | ❌ | | Alias | con trỏ có tên | ✅ |

Và cảnh báo quan trọng khi dùng stage variable trỏ tới alias: API Gateway không tự thêm quyền vào resource-based policy của Lambda cho alias động. Phải tự cấp quyền cho MỌI alias:

aws lambda add-permission --function-name xu-ly --qualifier beta \
  --statement-id ApiGatewayInvokeBeta --action lambda:InvokeFunction \
  --principal apigateway.amazonaws.com

Thiếu bước này, stage beta trả về 500 mà không có thông báo gì hữu ích — lỗi rất khó chẩn đoán.

Câu 729 AWS Security, Identity, & Compliance

A developer has a user account in the Development AWS account. He has been asked to modify resources in a Production AWS account. What is the MOST secure way to provide temporary access to the developer?

  1. A

    Generate an access key on the second account using the root account and share the access keys with the developer for API access

  2. B

    Use AWS KMS to generate cross-account customer master keys and use those get short-lived credentials

  3. C

    Add the user to a group in the second account that has a role attached granting the necessary permissions

  4. D

    Create a cross-account access role, and use sts:AssumeRole API to get short-lived credentials

Xem giải thích

Đáp án

D — Tạo một cross-account access role, và dùng API sts:AssumeRole để lấy credential ngắn hạn.

Vì sao đúng

Đây là mẫu cross-account access chuẩn của AWS, và là cách duy nhất trong bốn phương án vừa an toàn vừa hoạt động.

Cơ chế gồm hai phía:

Phía tài khoản Production — tạo role với trust policy chấp nhận tài khoản Development:

{
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::<ID-Development>:user/lap-trinh-vien"},
  "Action": "sts:AssumeRole",
  "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
}

Phía tài khoản Development — cấp quyền được assume:

{"Effect": "Allow", "Action": "sts:AssumeRole",
 "Resource": "arn:aws:iam::<ID-Production>:role/RoleSuaTaiNguyen"}

Rồi chuyển đổi bằng một dòng trong ~/.aws/config:

[profile production]
role_arn = arn:aws:iam::<ID-Production>:role/RoleSuaTaiNguyen
source_profile = development
mfa_serial = arn:aws:iam::<ID-Development>:mfa/lap-trinh-vien
aws ec2 describe-instances --profile production

Vì sao đây là cách an toàn nhất: | Lợi ích | Chi tiết | |---|---| | Credential TẠM THỜI | hết hạn sau 1–12 giờ, giảm hẳn thiệt hại nếu bị lộ | | Một danh tính duy nhất | chỉ một bộ credential dài hạn phải bảo vệ | | Vết kiểm toán rõ | CloudTrail ghi cả người assume lẫn hành động sau đó | | Thu hồi tức thì | sửa trust policy là mất quyền ngay | | Ép được MFA | qua condition key |

Và đề nói "temporary access" — đúng bản chất của credential từ STS.

Vì sao các phương án khác sai

  • A. Tạo access key trên tài khoản thứ hai bằng root account rồi chia sẻ — sai lầm bảo mật nghiêm trọng nhất, và sai ở nhiều tầng: dùng root account (AWS khuyến nghị không dùng cho việc hằng ngày), tạo credential DÀI HẠN (không "temporary" chút nào), và chia sẻ credential giữa người với người (mất hoàn toàn khả năng truy vết).
  • C. Thêm user vào một group ở tài khoản thứ hai, group có role gắn vào — không làm được về mặt kỹ thuật: IAM group chỉ chứa user của CHÍNH tài khoản đó, không thêm được user chéo tài khoản. Và group không "gắn role" — group chỉ chứa policy.
  • B. Dùng KMS tạo cross-account CMK để lấy credential ngắn hạn — sai chức năng hoàn toàn: KMS quản lý khoá mã hoá, nó không cấp credential nào. Khoá KMS có chia sẻ chéo tài khoản được, nhưng đó là để giải mã dữ liệu, không phải để truy cập tài nguyên.

Ghi nhớ

Các API của STS: | API | Dùng khi | |---|---| | AssumeRole | danh tính IAM assume role, kể cả CHÉO TÀI KHOẢN | | AssumeRoleWithSAML | liên kết SAML từ IdP doanh nghiệp | | AssumeRoleWithWebIdentity | liên kết OIDC (Cognito, Google) | | GetSessionToken | credential tạm thời cho chính user đó, thường kèm MFA | | GetCallerIdentity | "tôi đang là ai?" — lệnh gỡ lỗi hữu ích nhất |

Hai loại policy và khả năng chéo tài khoản: | | Identity-based | Resource-based | |---|---|---| | Gắn vào | user, group, role | S3, SQS, SNS, KMS, trust policy của role | | Khai Principal | ❌ | ✅ |

Hai thực hành nên áp dụng:

  1. Ép MFA trong trust policy — với tài khoản production thì gần như bắt buộc.
  2. Dùng ExternalId khi cấp quyền cho bên thứ ba (đối tác, nhà cung cấp dịch vụ), để chống confused deputy problem.

Và với tổ chức nhiều tài khoản, AWS IAM Identity Center (SSO) là bước tiến tiếp theo: nó bỏ hẳn IAM user, cho phép đăng nhập một lần rồi chọn tài khoản và permission set — cùng nguyên lý assume role nhưng không còn credential dài hạn nào cả.

Câu 730 AWS Compute

A Developer has created an AWS Lambda function in a new AWS account. The function is expected to be invoked 40 times per second and the execution duration will be around 100 seconds. What MUST the Developer do to ensure there are no errors?

  1. A

    Contact AWS Support to increase the concurrent execution limits

  2. B

    Implement tracing with X-Ray

  3. C

    Implement error handling within the function code

  4. D

    Implement a Dead Letter Queue to capture invocation errors

Xem giải thích

Đáp án

A — Liên hệ AWS Support để tăng hạn mức concurrent executions.

Vì sao đúng

Bắt đầu bằng phép tính concurrency:

Concurrency = số lần gọi mỗi giây × thời lượng mỗi lần (giây)
            = 40 × 100
            = 4.000

So với hạn mức mặc định:

Cần        : 4.000
Mặc định   : 1.000 mỗi Region
             ─────
Thiếu      : 3.000

Nhu cầu vượt xa hạn mức của cả tài khoản, nên không có cách nào khác ngoài việc xin tăng. Đây là hạn mức mềm (soft limit), tăng được qua Service Quotas hoặc AWS Support:

aws service-quotas request-service-quota-increase \
  --service-code lambda \
  --quota-code L-B99A9384 \
  --desired-value 5000

Điểm cần nhấn mạnh: hạn mức 1.000 là của TOÀN TÀI KHOẢN trong một Region, chia sẻ cho mọi hàm Lambda. Nên kể cả khi đây là hàm duy nhất, nó vẫn không thể vượt 1.000.

Và chi tiết "tài khoản AWS mới" trong đề càng củng cố: tài khoản mới thường có hạn mức mặc định, chưa từng được nâng.

Vì sao các phương án khác sai

  • C. Cài đặt xử lý lỗi trong mã hàm — sai chỗ: throttle xảy ra TRƯỚC KHI hàm được gọi — Lambda từ chối lời gọi ở tầng dịch vụ, nên mã bên trong hàm không bao giờ chạy để mà bắt lỗi.
  • D. Cài đặt Dead Letter Queue để bắt lỗi gọi hàm — chỉ lưu lại sự kiện thất bại, không ngăn được thất bại. Với 3.000 lời gọi bị từ chối mỗi lúc cao điểm, DLQ sẽ đầy ắp mà vấn đề vẫn nguyên. (Và DLQ chỉ áp cho gọi bất đồng bộ.)
  • B. Cài đặt theo dấu bằng X-Ray — công cụ quan sát, giúp bạn thấy vấn đề nhưng không giải quyết nó.

Ghi nhớ

Công thức cần thuộc:

Concurrency = Requests/giây × Thời lượng (giây)
Requests/giây Thời lượng Concurrency
100 0,1 giây 10
100 1 giây 100
40 100 giây 4.000
50 100 giây 5.000

Nhận xét quan trọng: thời lượng chạy ảnh hưởng tới concurrency mạnh ngang số request. Trong bài này, tối ưu hàm từ 100 giây xuống 20 giây sẽ giảm concurrency cần thiết từ 4.000 xuống 800 — vừa khít hạn mức mặc định, và không cần xin tăng gì. Đó thường là hướng đáng cân nhắc trước.

Các hạn mức của Lambda: | Hạn mức | Giá trị | Loại | |---|---|---| | Concurrent executions | 1.000 mỗi Region | mềm — tăng được | | Burst concurrency | 500–3.000 tuỳ Region | mềm | | Timeout | 15 phút | cứng | | Bộ nhớ | 128 MB – 10.240 MB | cứng | | Kích thước gói (giải nén) | 250 MB | cứng |

Phân biệt hai khái niệm hay bị lẫn: | | Reserved concurrency | Hạn mức tài khoản | |---|---|---| | Là gì | phần DÀNH RIÊNG cho một hàm | tổng của cả Region | | Tăng được | chỉ trong phạm vi tổng | xin AWS tăng | | Đặt = 0 | tắt hàm | — |

Đây là lý do "tăng concurrency limit cho hàm" không phải giải pháp: reserved concurrency chỉ chia phần trong tổng đang có, không tạo thêm năng lực.

Và nhớ burst concurrency: khi tải tăng đột ngột, Lambda không nhảy thẳng lên hạn mức tối đa — nó khởi động một lượng burst ban đầu rồi tăng dần 500 mỗi phút. Nên với đỉnh rất dốc, bạn vẫn có thể bị throttle dù chưa chạm hạn mức tổng.