Ngân hàng đề — AWS Certified Developer Associate
Tìm thấy 1356 câu.
A Developer is creating a new web application that will be deployed using AWS Elastic Beanstalk from the AWS Management Console. The Developer is about to create a source bundle which will be uploaded using the console.
Which of the following are valid requirements for creating the source bundle? (Select TWO.)
-
A
Must not include a parent folder or top-level directory.
-
B
Must include the cron.yaml file.
-
C
Must not exceed 512 MB.
-
D
Must include a parent folder or top-level directory.
-
E
Must consist of one or more ZIP files.
Xem giải thích
Đáp án
A và C.
- A — Không được chứa thư mục cha hoặc thư mục cấp cao nhất.
- C — Không được vượt quá 512 MB.
Vì sao đúng
A — cấu trúc gói. Đây là lỗi đóng gói phổ biến nhất với Elastic Beanstalk. Các tệp phải nằm ngay ở gốc của tệp ZIP:
✅ ĐÚNG ❌ SAI
goi.zip goi.zip
├── index.html └── ung-dung/ ← thư mục cha thừa
├── app.js ├── index.html
└── .ebextensions/ ├── app.js
└── cau-hinh.config └── .ebextensions/
Cách đóng gói đúng — nén nội dung thư mục, không nén chính thư mục:
cd ung-dung/
zip -r ../goi.zip . -x "*.git*" # dấu chấm = nội dung thư mục hiện tại
Nếu có thư mục cha, Beanstalk sẽ tìm index.html hay application.py ở gốc và không thấy — ứng dụng triển khai xong nhưng trả về lỗi 404 hoặc 502 mà không có thông báo rõ ràng.
C — giới hạn kích thước. Source bundle không được vượt quá 512 MB. Vượt qua thì Console từ chối ngay lúc tải lên.
Vì sao các phương án khác sai
- D. Phải chứa thư mục cha — ngược hẳn với A. Đây là cặp phương án loại trừ nhau, và A mới đúng.
- E. Phải gồm một hoặc nhiều tệp ZIP — sai: source bundle là đúng MỘT tệp. Nó có thể là ZIP hoặc WAR (cho ứng dụng Java), nhưng không phải nhiều tệp ZIP. (Có một ngoại lệ hẹp: môi trường Java có thể nhận nhiều WAR trong một ZIP để triển khai nhiều ứng dụng — nhưng đó vẫn là một tệp bundle duy nhất.)
- B. Phải chứa tệp
cron.yaml—cron.yamlchỉ dùng cho worker environment để khai các tác vụ định kỳ. Đề nói đây là web application, và tệp này hoàn toàn không bắt buộc.
Ghi nhớ
Yêu cầu của source bundle: | Yêu cầu | Chi tiết | |---|---| | Một tệp duy nhất | ZIP hoặc WAR | | Không quá 512 MB | giới hạn cứng | | Không có thư mục cha | tệp nằm ở gốc của archive | | Không chứa symbolic link | không được hỗ trợ |
Các tệp cấu hình tuỳ chọn có thể đặt trong bundle: | Tệp/thư mục | Việc | |---|---| | .ebextensions/*.config | tuỳ chỉnh môi trường — cài gói, chạy lệnh, đặt option | | Procfile | khai cách khởi động tiến trình | | Buildfile | lệnh chạy lúc build | | .platform/hooks/ | script hook trên nền tảng Amazon Linux 2 trở lên | | cron.yaml | chỉ cho worker environment — tác vụ định kỳ |
Mẹo thực dụng: dùng EB CLI thì không phải lo chuyện đóng gói nữa — nó tự tạo bundle đúng cấu trúc từ nội dung thư mục (và tôn trọng .gitignore):
eb init
eb create moi-truong-production
eb deploy
A Development team wants to run their container workloads on Amazon ECS. Each application container needs to share data with another container to collect logs and metrics.
What should the Development team do to meet these requirements?
-
A
Create a single pod specification. Include both containers in the specification. Mount a persistent volume to both containers
-
B
Create one task definition. Specify both containers in the definition. Mount a shared volume between those two containers
-
C
Create two pod specifications. Make one to include the application container and the other to include the other container. Link the two pods together
-
D
Create two task definitions. Make one to include the application container and the other to include the other container. Mount a shared volume between the two tasks
Xem giải thích
Đáp án
B — Tạo một task definition, khai cả hai container trong đó, và mount một volume dùng chung giữa chúng.
Vì sao đúng
Yêu cầu: hai container chia sẻ dữ liệu với nhau (một thu log và metric từ cái kia).
Trong ECS, đơn vị chia sẻ tài nguyên là task: các container trong cùng một task được đặt trên cùng một instance, chia sẻ network namespace, và mount chung volume được.
{
"family": "ung-dung-co-sidecar",
"volumes": [{"name": "du-lieu-chung", "host": {}}],
"containerDefinitions": [
{
"name": "ung-dung",
"image": "...ecr.../app:v1",
"mountPoints": [{"sourceVolume": "du-lieu-chung", "containerPath": "/var/log/ung-dung"}]
},
{
"name": "thu-thap-log",
"image": "...ecr.../fluent-bit:v1",
"mountPoints": [{"sourceVolume": "du-lieu-chung", "containerPath": "/logs", "readOnly": true}]
}
]
}
Đây là mẫu sidecar — một trong những mẫu thiết kế container phổ biến nhất, dùng cho đúng các việc mà đề mô tả: thu log, thu metric, proxy service mesh.
Vì hai container chia sẻ network namespace, chúng còn gọi nhau qua localhost được:
requests.post('http://localhost:8125/metrics', json=du_lieu)
Vì sao các phương án khác sai
- D. Tạo HAI task definition và mount volume chung giữa hai task — không làm được: hai task là hai đơn vị triển khai độc lập, có thể nằm trên hai instance khác nhau, và không chia sẻ volume cục bộ. (Chia sẻ được nếu dùng EFS — nhưng đó là hệ thống tệp qua mạng, chậm hơn nhiều và là cách sai cho việc thu log của một ứng dụng.)
- A. Tạo "pod specification" chứa cả hai container và C. Tạo hai "pod specification" rồi liên kết — "pod" là khái niệm của Kubernetes, không phải của ECS. ECS dùng task definition. (Ý tưởng của A thực ra đúng — pod trong Kubernetes chính là tương đương với task trong ECS — nhưng thuật ngữ sai với dịch vụ đang hỏi. Nếu đề nói EKS thì A mới là đáp án.)
Ghi nhớ
Ánh xạ thuật ngữ giữa hai nền tảng — rất hay bị hỏi: | ECS | Kubernetes (EKS) | |---|---| | Task | Pod | | Task definition | Pod spec | | Service | Deployment / Service | | Cluster | Cluster | | Container instance | Node |
Các loại volume trong ECS: | Loại | Đặc điểm | |---|---| | host | thư mục trên instance — nhanh, mất khi task kết thúc nếu không khai đường dẫn | | bind mount rỗng | chia sẻ giữa các container trong cùng task — mặc định cho sidecar | | EFS | chia sẻ giữa nhiều task và nhiều instance, bền vững | | Docker volume | dùng driver, chỉ EC2 launch type |
Cách chọn: chia sẻ trong một task ⇒ bind mount. Chia sẻ giữa nhiều task ⇒ EFS.
Và với riêng nhu cầu thu log, ECS còn có cách gọn hơn cả sidecar tự dựng: FireLens (logDriver: awsfirelens) tự chạy Fluent Bit như một sidecar được quản lý, cho phép lọc và gửi log tới nhiều đích cùng lúc mà không phải tự khai volume.
A company is using an AWS Step Functions state machine. When testing the state machine errors were experienced in the Step Functions task state machine. To troubleshoot the issue a developer requires that the state input be included along with the error message in the state output.
Which coding practice can preserve both the original input and the error for the state?
-
A
Use ErrorEquals in a Retry statement to include the original input with the error.
-
B
Use OutputPath in a Retry statement to include the original input with the error.
-
C
Use InputPath in a Catch statement to include the original input with the error.
-
D
Use ResultPath in a Catch statement to include the original input with the error.
Xem giải thích
Đáp án
D — Dùng ResultPath trong câu lệnh Catch để giữ cả đầu vào gốc lẫn thông tin lỗi.
Vì sao đúng
Vấn đề: theo mặc định, khi một state bị lỗi và Catch bắt được, đầu ra của state bị THAY THẾ hoàn toàn bằng đối tượng lỗi — đầu vào gốc biến mất:
// Mặc định — mất hết đầu vào
{"Error": "States.TaskFailed", "Cause": "Không kết nối được CSDL"}
ResultPath quy định đặt kết quả vào ĐÂU trong đầu vào, thay vì thay thế nó:
{
"Type": "Task",
"Resource": "arn:aws:lambda:...:function:xu-ly",
"Catch": [{
"ErrorEquals": ["States.ALL"],
"ResultPath": "$.thongTinLoi",
"Next": "XuLyLoi"
}]
}
Kết quả giữ được cả hai:
{
"maDonHang": "DH-123", ← đầu vào gốc còn nguyên
"khachHang": "Nguyễn Văn A",
"thongTinLoi": { ← lỗi được ghép vào
"Error": "States.TaskFailed",
"Cause": "Không kết nối được CSDL"
}
}
Đúng yêu cầu của đề: "preserve both the original input and the error". Và với việc gỡ lỗi, đây là khác biệt rất lớn — biết lỗi gì mà không biết lỗi với dữ liệu nào thì gần như vô dụng.
Ba giá trị đặc biệt của ResultPath: | Giá trị | Kết quả | |---|---| | "$.tenTruong" | ghép kết quả vào đầu vào tại trường đó | | "$" (mặc định) | thay thế toàn bộ đầu vào | | null | bỏ kết quả, giữ nguyên đầu vào |
Vì sao các phương án khác sai
- C. Dùng
InputPathtrongCatch— sai vai trò:InputPathLỌC đầu vào TRƯỚC khi state chạy, chọn phần nào của đầu vào được đưa vào task. Nó không quyết định đầu ra khi có lỗi. VàCatchkhông có trườngInputPath. - B. Dùng
OutputPathtrongRetry— sai hai chỗ.Retrychỉ thử lại state, nó không sinh ra đầu ra và không có trườngOutputPath. Ngoài raOutputPathlà bộ lọc thu hẹp đầu ra — nó chỉ bỏ bớt, không ghép thêm được đầu vào gốc vào. - A. Dùng
ErrorEqualstrongRetry—ErrorEqualschỉ khai loại lỗi nào thì áp dụng quy tắc đó. Nó là bộ lọc chọn lỗi, hoàn toàn không liên quan tới việc giữ lại dữ liệu.
Ghi nhớ
Bốn bộ lọc dữ liệu của Step Functions, theo đúng thứ tự xử lý:
Đầu vào → InputPath → Parameters → [TASK CHẠY] → ResultSelector → ResultPath → OutputPath → Đầu ra
| Trường | Việc |
|---|---|
InputPath |
chọn phần nào của đầu vào đưa vào task |
Parameters |
dựng đối tượng đầu vào mới |
ResultSelector |
chọn phần nào của kết quả task |
ResultPath |
đặt kết quả vào đâu trong đầu vào |
OutputPath |
chọn phần nào được truyền sang state tiếp theo |
Khác biệt cốt lõi cần thuộc: ResultPath GHÉP THÊM, còn OutputPath THU HẸP. Muốn giữ dữ liệu thì dùng ResultPath.
Mẫu xử lý lỗi đầy đủ, kết hợp cả Retry và Catch:
"Retry": [{
"ErrorEquals": ["States.Timeout", "Lambda.ServiceException"],
"IntervalSeconds": 2, "MaxAttempts": 3, "BackoffRate": 2.0
}],
"Catch": [{
"ErrorEquals": ["States.ALL"],
"ResultPath": "$.thongTinLoi",
"Next": "XuLyLoi"
}]
Retry chạy trước Catch — chỉ khi đã hết số lần thử lại mà vẫn hỏng thì Catch mới kích hoạt.
An application uses an Amazon DynamoDB table that is 50 GB in size and provisioned with 10,000 read capacity units (RCUs) per second. The table must be scanned during non-peak hours when normal traffic consumes around 5,000 RCUs. The Developer must scan the whole table in the shortest possible time whilst ensuring the normal workload is not affected.
How would the Developer optimize this scan cost-effectively?
-
A
Use sequential scans and set the ConsistentRead parameter to false.
-
B
Use the Parallel Scan API operation and limit the rate.
-
C
Increase read capacity units during the scan operation.
-
D
Use sequential scans and apply a FilterExpression.
Xem giải thích
Đáp án
B — Dùng Parallel Scan API và giới hạn tốc độ.
Vì sao đúng
Đề đưa ra các con số cụ thể, và chúng định hình câu trả lời:
Bảng : 50 GB
Cấp phát : 10.000 RCU/giây
Tải thường: khoảng 5.000 RCU ← đang dùng
Còn rảnh : khoảng 5.000 RCU ← phần scan được phép dùng
Yêu cầu: quét nhanh nhất có thể nhưng không ảnh hưởng tải bình thường. Hai vế này tương ứng với hai nửa của đáp án.
Parallel scan cho tốc độ. Scan tuần tự chỉ dùng một luồng, không thể tiêu thụ hết 5.000 RCU rảnh. Parallel scan chia bảng thành các segment quét đồng thời:
import threading
TONG_SEGMENT = 10
def quet(segment):
kwargs = {'TableName': 'bang-lon', 'Segment': segment,
'TotalSegments': TONG_SEGMENT,
'ReturnConsumedCapacity': 'TOTAL'}
while True:
r = dynamodb.scan(**kwargs)
xu_ly(r['Items'])
dieu_tiet(r['ConsumedCapacity']['CapacityUnits']) # giới hạn tốc độ
if 'LastEvaluatedKey' not in r:
break
kwargs['ExclusiveStartKey'] = r['LastEvaluatedKey']
for i in range(TONG_SEGMENT):
threading.Thread(target=quet, args=(i,)).start()
Giới hạn tốc độ để bảo vệ production. Không có nó, parallel scan sẽ ngốn toàn bộ 10.000 RCU và làm workload thật bị throttle — đúng thứ đề cấm.
Cách điều tiết: đọc ConsumedCapacity trong mỗi phản hồi, cộng dồn theo giây, và chèn sleep khi vượt ngân sách 5.000 RCU tự đặt.
Vì sao các phương án khác sai
- A. Scan tuần tự với
ConsistentRead=false— giảm được một nửa chi phí RCU, nhưng không giải quyết vế tốc độ: một luồng vẫn là một luồng. Trái yêu cầu "shortest possible time". (Ghi chú:Scanmặc định đã là eventually consistent, nên đặtConsistentRead=falsethực chất không đổi gì.) - C. Tăng RCU trong lúc scan — chạy được nhưng tốn tiền, và không cần thiết: đề đã nói rõ có sẵn 5.000 RCU rảnh. Vấn đề là dùng cho hiệu quả, không phải mua thêm. Trái yêu cầu "cost-effectively".
- D. Scan tuần tự với
FilterExpression— hiểu sai cáchFilterExpressionhoạt động, và đây là hiểu nhầm rất phổ biến: bộ lọc được áp SAU KHI dữ liệu đã được đọc. Bạn vẫn trả đủ RCU cho toàn bộ dữ liệu quét qua — chỉ là kết quả trả về ít hơn. Nó không tiết kiệm RCU và không giảm thời gian chút nào.
Ghi nhớ
Điểm cần khắc sâu về FilterExpression:
Scan đọc 50 GB → tính tiền cho 50 GB → FilterExpression bỏ bớt → trả về 100 MB
↑ bạn trả tiền ở đây, không phải ở kết quả
Muốn thật sự giảm dữ liệu đọc thì phải dùng Query với khoá phù hợp, hoặc GSI, chứ không phải bộ lọc.
Các tham số của parallel scan: | Tham số | Việc | |---|---| | TotalSegments | chia thành bao nhiêu phần (1 – 1.000.000) | | Segment | phần nào (0 … N−1) | | Limit | số item mỗi lời gọi — công cụ điều tiết chính | | ProjectionExpression | chỉ lấy cột cần — giảm dữ liệu thật sự | | ReturnConsumedCapacity | để tự giám sát |
Chọn TotalSegments bao nhiêu: quy tắc thô là mỗi segment khoảng 1–2 GB, và số segment không nên vượt quá số luồng máy khách chạy được.
Và lời khuyên lớn hơn: nếu phải quét toàn bảng định kỳ, cân nhắc DynamoDB Export to S3 rồi phân tích bằng Athena — nó không tiêu thụ RCU nào cả, nên không thể ảnh hưởng tới production.
A developer is working on an application that must save hundreds of sensitive files. The application needs to encrypt each file using a unique key before storing it.
What should the developer do to implement this in the application?
-
A
Use a crypto library to generate a unique encryption key for the application, employ the encryption key to secure the data, and store the encrypted data.
-
B
Use the AWS KMS GenerateDataKey API to acquire a data key, use the data key to encrypt the data, and store both the encrypted data key and the data.
-
C
Utilize the AWS Key Management Service (KMS) Encrypt API to secure the data, storing both the encrypted data key and the actual data.
-
D
Upload the data to an Amazon S3 bucket employing server-side encryption with a key from AWS KMS.
Xem giải thích
Đáp án
B — Dùng kms:GenerateDataKey để lấy data key, mã hoá dữ liệu bằng data key đó, rồi lưu cả data key đã mã hoá lẫn dữ liệu đã mã hoá.
Vì sao đúng
Đề có hai yêu cầu, và cả hai đều trỏ về envelope encryption:
- Hàng trăm tệp
- Mỗi tệp một khoá riêng biệt
GenerateDataKey trả về hai dạng của cùng một khoá:
resp = kms.generate_data_key(KeyId='alias/khoa-cua-toi', KeySpec='AES_256')
khoa_ban_ro = resp['Plaintext'] # dùng để mã hoá NGAY TẠI CHỖ
khoa_ban_ma = resp['CiphertextBlob'] # lưu cùng dữ liệu
Quy trình đầy đủ cho mỗi tệp:
from cryptography.fernet import Fernet
import base64
def ma_hoa_tep(noi_dung):
r = kms.generate_data_key(KeyId='alias/khoa-cua-toi', KeySpec='AES_256')
f = Fernet(base64.urlsafe_b64encode(r['Plaintext']))
du_lieu_ma = f.encrypt(noi_dung)
del r['Plaintext'] # XOÁ khoá bản rõ khỏi bộ nhớ
return r['CiphertextBlob'], du_lieu_ma # lưu CẢ HAI
def giai_ma_tep(khoa_ban_ma, du_lieu_ma):
khoa = kms.decrypt(CiphertextBlob=khoa_ban_ma)['Plaintext']
return Fernet(base64.urlsafe_b64encode(khoa)).decrypt(du_lieu_ma)
Vì sao đây là cách đúng: | Lợi ích | Chi tiết | |---|---| | Mỗi tệp một khoá riêng | gọi GenerateDataKey cho từng tệp | | Không giới hạn kích thước | mã hoá tại chỗ, dữ liệu không đi qua mạng | | Nhanh | AES cục bộ, không phải chờ mạng cho từng khối dữ liệu | | CMK không bao giờ rời KMS | khoá gốc luôn an toàn | | Thu hồi được | vô hiệu hoá CMK là mọi data key thành vô dụng |
Vì sao các phương án khác sai
- C. Dùng
kms:Encryptđể mã hoá dữ liệu — giới hạn cứng 4 KB. Với "hàng trăm tệp nhạy cảm", hầu hết sẽ vượt quá và lời gọi bị từ chối. Ngoài ra mô tả trong phương án còn tự mâu thuẫn: nếu dùngEncrypttrực tiếp thì không có data key nào để lưu. - A. Dùng thư viện crypto tự sinh MỘT khoá cho cả ứng dụng — vi phạm yêu cầu "unique key" (một khoá cho tất cả), và tệ hơn: bạn phải tự bảo vệ khoá đó — lưu ở đâu, xoay vòng thế nào, ai được đọc. Đó chính là bài toán mà KMS sinh ra để giải.
- D. Tải lên S3 với server-side encryption bằng khoá KMS — hợp lý trong nhiều tình huống thật, nhưng lệch với đề: đề yêu cầu ứng dụng tự mã hoá từng tệp, còn phương án này giao việc mã hoá cho S3. (Về mặt kỹ thuật, SSE-KMS cũng dùng envelope encryption bên dưới và cũng sinh data key riêng cho mỗi object — nhưng nó chỉ áp dụng khi đích đến là S3, và đề không nói tệp được lưu ở đâu.)
Ghi nhớ
| API của KMS | Dùng khi | Giới hạn |
|---|---|---|
Encrypt |
dữ liệu nhỏ, khoá, mật khẩu | ≤ 4 KB |
GenerateDataKey |
dữ liệu lớn — envelope encryption | không giới hạn |
GenerateDataKeyWithoutPlaintext |
tạo sẵn khoá để dùng sau | — |
Decrypt |
giải mã ciphertext hoặc data key | ≤ 4 KB |
Ba nguyên tắc khi làm envelope encryption:
- Xoá khoá bản rõ khỏi bộ nhớ ngay sau khi dùng — đừng ghi nó ra đĩa, đừng ghi vào log
- Lưu khoá đã mã hoá cùng với dữ liệu — mất nó là mất dữ liệu vĩnh viễn
- Dùng encryption context để ràng buộc khoá với ngữ cảnh:
kms.generate_data_key(KeyId=..., KeySpec='AES_256',
EncryptionContext={'maTep': 'tep-123', 'chuSoHuu': 'phong-ke-toan'})
Encryption context được xác thực nhưng không mã hoá, và phải khớp chính xác khi giải mã — nên nó ngăn được việc dùng khoá của tệp này để giải mã tệp khác. Nó cũng xuất hiện trong CloudTrail, rất hữu ích cho kiểm toán.
Và nhớ: AWS Encryption SDK đã cài đặt sẵn toàn bộ mẫu này (kể cả caching data key, ký số, và định dạng thông điệp chuẩn) — trong thực tế nên dùng nó thay vì tự viết.
An application deployed on AWS Elastic Beanstalk experienced increased error rates during deployments of new application versions, resulting in service degradation for users. The Development team believes that this is because of the reduction in capacity during the deployment steps. The team would like to change the deployment policy configuration of the environment to an option that maintains full capacity during deployment while using the existing instances.
Which deployment policy will meet these requirements while using the existing instances?
-
A
All at once
-
B
Immutable
-
C
Rolling with additional batch
-
D
Rolling
Xem giải thích
Đáp án
C — Rolling with additional batch.
Vì sao đúng
Đề nêu hai ràng buộc, và chỉ một chính sách thoả cả hai:
- Giữ nguyên năng lực đầy đủ trong suốt quá trình triển khai
- Dùng các instance hiện có (không tạo hẳn một tập instance mới)
Rolling with additional batch giải quyết bằng cách thêm một lô instance TẠM THỜI trước khi bắt đầu:
Ban đầu: [A][A][A][A] 4 instance, phiên bản A
Thêm lô: [A][A][A][A] + [B][B] thêm 2 instance mới ← năng lực TĂNG
Cập nhật: [B][B][A][A] + [B][B] cập nhật lô 1
[B][B][B][B] + [B][B] cập nhật lô 2
Gỡ lô thêm: [B][B][B][B] xoá lô tạm
Năng lực không bao giờ xuống dưới 100% — đó chính là điều mà Rolling thường không làm được, và là nguyên nhân của tình trạng lỗi mà đội phát triển đang gặp.
Vì sao các phương án khác sai
- D. Rolling — đây chính là chính sách họ đang dùng và đang gây ra vấn đề. Nó cập nhật từng lô tại chỗ, nên trong lúc một lô đang được cập nhật thì năng lực giảm xuống dưới 100%:
Đúng nguyên nhân mà đề mô tả: "reduction in capacity during the deployment steps".[A][A][A][A] → [--][--][A][A] ← chỉ còn 50% năng lực - B. Immutable — giữ được năng lực đầy đủ (thoả điều kiện 1), nhưng trượt điều kiện 2: nó tạo ra một tập instance HOÀN TOÀN MỚI trong một Auto Scaling group tạm thời, rồi mới chuyển sang. Đề nói rõ "while using the existing instances". Immutable an toàn nhất và rollback nhanh nhất, nhưng tốn gấp đôi tài nguyên và chậm nhất.
- A. All at once — tệ nhất về mặt gián đoạn: cập nhật tất cả instance cùng lúc, gây downtime hoàn toàn trong vài phút. Nhanh nhất và rẻ nhất, nhưng chỉ hợp cho môi trường dev.
Ghi nhớ
Bảng so sánh chính sách triển khai của Elastic Beanstalk — đáng thuộc vì đề hay hỏi: | Chính sách | Downtime | Giữ đủ năng lực | Instance mới | Thời gian | Rollback | |---|---|---|---|---|---| | All at once | CÓ | ❌ | ❌ | nhanh nhất | phải triển khai lại | | Rolling | không | ❌ giảm | ❌ | trung bình | phải triển khai lại | | Rolling with additional batch | không | ✅ | tạm thời | chậm hơn | phải triển khai lại | | Immutable | không | ✅ | ✅ toàn bộ | chậm nhất | nhanh — huỷ ASG mới | | Traffic splitting | không | ✅ | ✅ toàn bộ | chậm nhất | nhanh |
Cách chọn theo yêu cầu trong đề:
- "Không downtime, dùng instance hiện có, giữ đủ năng lực" ⇒ Rolling with additional batch
- "An toàn nhất, rollback nhanh" ⇒ Immutable
- "Canary / thử với một phần người dùng" ⇒ Traffic splitting
- "Nhanh và rẻ, dev thôi" ⇒ All at once
Một điểm khác biệt quan trọng về rollback: với Rolling và Rolling with additional batch, nếu triển khai thất bại thì các instance đã cập nhật vẫn đang chạy phiên bản mới — muốn quay lại phải triển khai lại phiên bản cũ, mất thêm thời gian. Với Immutable, chỉ cần huỷ Auto Scaling group tạm là xong ngay lập tức, vì các instance cũ chưa bao giờ bị đụng tới.
A developer is responsible for a business critical application that uses Amazon DynamoDB as its main data repository. This DynamoDB table holds millions of records and handles high volumes of requests. The developer must implement near-real time processing on the records as soon as they are inserted or modified in the DynamoDB table.
What's the most efficient way to introduce this capability with MINIMUM modification to the existing application code?
-
A
Use Amazon SQS to queue incoming data and process it using Amazon EC2 instances.
-
B
Use AWS Lambda triggered by DynamoDB Streams to process the documents.
-
C
Set up an Amazon Kinesis Data Stream to process updates from the DynamoDB table.
-
D
Modify the application code to add processing logic after each DynamoDB write operation.
Xem giải thích
Đáp án
B — Dùng AWS Lambda được kích hoạt bởi DynamoDB Streams để xử lý các bản ghi.
Vì sao đúng
Hai yêu cầu của đề: xử lý gần thời gian thực ngay khi bản ghi được chèn hoặc sửa, với thay đổi tối thiểu cho mã hiện có.
DynamoDB Streams ghi lại mọi thay đổi ở mức item theo đúng thứ tự, và Lambda đọc stream đó tự động:
Ứng dụng ghi vào bảng (KHÔNG SỬA GÌ)
↓ DynamoDB tự phát sự kiện
DynamoDB Streams
↓ event source mapping
Lambda xử lý
Điểm mấu chốt cho vế "minimum modification": mã ứng dụng hiện có không đổi một dòng nào. Việc phát sự kiện do chính DynamoDB làm.
Bật rất gọn:
aws dynamodb update-table --table-name giao-dich \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
aws lambda create-event-source-mapping \
--function-name xu-ly-thay-doi \
--event-source-arn arn:aws:dynamodb:...:table/giao-dich/stream/2026-08-05T00:00:00.000 \
--starting-position LATEST \
--batch-size 100
Hàm nhận được cả ảnh cũ và ảnh mới:
def lambda_handler(event, context):
for ban_ghi in event['Records']:
if ban_ghi['eventName'] in ('INSERT', 'MODIFY'):
moi = ban_ghi['dynamodb']['NewImage']
cu = ban_ghi['dynamodb'].get('OldImage')
xu_ly(moi, cu)
Vì sao các phương án khác sai
- D. Sửa mã ứng dụng để thêm logic xử lý sau mỗi lần ghi — vi phạm thẳng yêu cầu "MINIMUM modification". Tệ hơn về mặt thiết kế: nó ghép chặt việc xử lý vào đường ghi chính, nên xử lý chậm hoặc hỏng sẽ làm chậm hoặc hỏng cả thao tác ghi. Và nếu ứng dụng crash giữa chừng thì thay đổi đã ghi nhưng chưa được xử lý — mất sự kiện.
- A. SQS + EC2 — đòi sửa mã ứng dụng để publish vào hàng đợi (vi phạm yêu cầu), cộng thêm việc vận hành EC2. Và nó không đảm bảo được mọi thay đổi đều vào hàng đợi — nếu có đường ghi nào khác vào bảng, đường đó bị bỏ sót.
- C. "Dựng Kinesis Data Stream để xử lý cập nhật từ bảng DynamoDB" — phương án này gần đúng nhưng thiếu chính xác. Có tồn tại tính năng Kinesis Data Streams for DynamoDB, cho phép đẩy thay đổi sang Kinesis. Nhưng nó là lựa chọn cho tình huống phức tạp hơn (nhiều consumer độc lập, giữ dữ liệu tới 365 ngày, tích hợp với hệ sinh thái Kinesis), và cần thêm hạ tầng consumer. Cho nhu cầu đơn giản trong đề, Streams + Lambda là con đường ngắn nhất.
Ghi nhớ
Bốn kiểu StreamViewType: | Kiểu | Nội dung | |---|---| | KEYS_ONLY | chỉ khoá chính | | NEW_IMAGE | item sau thay đổi | | OLD_IMAGE | item trước thay đổi | | NEW_AND_OLD_IMAGES | cả hai — linh hoạt nhất |
Đặc điểm của DynamoDB Streams: | Đặc điểm | Chi tiết | |---|---| | Thời gian giữ | 24 giờ | | Thứ tự | đảm bảo trong mỗi partition key | | Đảm bảo | exactly-once ghi vào stream, at-least-once khi Lambda đọc | | Chi phí | miễn phí phần stream; chỉ trả tiền lời gọi Lambda |
So sánh hai lựa chọn stream của DynamoDB: | | DynamoDB Streams | Kinesis Data Streams for DynamoDB | |---|---|---| | Giữ dữ liệu | 24 giờ | tới 365 ngày | | Consumer | tối đa 2 mỗi shard | nhiều, độc lập | | Thứ tự | đảm bảo | không đảm bảo tuyệt đối | | Quản lý | không có gì | phải quản shard |
Nhận dạng nhanh: "xử lý ngay khi dữ liệu thay đổi, ít sửa mã nhất" ⇒ DynamoDB Streams + Lambda.
Và nhớ viết hàm idempotent — Lambda đọc stream với đảm bảo at-least-once, nên cùng một bản ghi có thể được xử lý nhiều lần.
A Developer will be launching several Docker containers on a new Amazon ECS cluster using the EC2 Launch Type. The containers will all run a web service on port 80.
What is the EASIEST way the Developer can configure the task definition to ensure the web services run correctly and there are no port conflicts on the host instances?
-
A
Specify port 80 for the container port and port 0 for the host port
-
B
Leave both the container port and host port configuration blank
-
C
Specify port 80 for the container port and a unique port number for the host port
-
D
Specify a unique port number for the container port and port 80 for the host port
Xem giải thích
Đáp án
A — Khai container port 80 và host port 0.
Vì sao đúng
Vấn đề: nhiều container cùng chạy trên cổng 80, và nếu ánh xạ cứng ra cổng 80 của máy chủ thì chỉ một container khởi động được — các task còn lại thất bại vì cổng đã bị chiếm.
Đặt host port = 0 kích hoạt dynamic port mapping: ECS tự chọn một cổng còn trống trong dải ephemeral (thường 32768–60999) cho mỗi task:
"portMappings": [
{"containerPort": 80, "hostPort": 0, "protocol": "tcp"}
]
Kết quả:
Task 1: host:32768 → container:80
Task 2: host:32770 → container:80
Task 3: host:41234 → container:80
Không bao giờ xung đột, và chạy được nhiều task của cùng một service trên một instance — tận dụng máy tốt hơn hẳn.
Phần còn lại do ALB tự lo: khi đăng ký target, ECS báo cho ALB biết cổng động thực tế của từng task, nên load balancer luôn định tuyến đúng. Đây là lý do dynamic port mapping chỉ thực sự tiện khi có ALB (hoặc NLB) phía trước.
Điều kiện đi kèm: security group của instance phải mở dải ephemeral cho security group của ALB:
aws ec2 authorize-security-group-ingress --group-id sg-instance \
--protocol tcp --port 32768-60999 --source-group sg-alb
Quên bước này là mọi target đều unhealthy mà không rõ lý do — một trong những lỗi cấu hình ECS phổ biến nhất.
(Bỏ hẳn hostPort cũng cho kết quả tương đương với network mode bridge — nhưng khai 0 là cách nói rõ ý định.)
Vì sao các phương án khác sai
- C. Container port 80 và một cổng host duy nhất cho mỗi container — chạy được nhưng là cách khó nhất: bạn phải tự quản lý danh sách cổng, tạo một task definition riêng cho mỗi container, và tự đảm bảo không trùng. Trái hẳn yêu cầu "EASIEST way".
- D. Cổng container riêng biệt, host port 80 — sai chiều hoàn toàn: cổng 80 của máy chủ vẫn chỉ có một, nên vẫn xung đột. Và đổi cổng container nghĩa là phải sửa cấu hình ứng dụng bên trong image.
- B. Để trống cả hai — với network mode
bridge, thiếucontainerPortthì không có ánh xạ nào được tạo và container không nhận được traffic.containerPortlà trường bắt buộc khi khaiportMappings.
Ghi nhớ
Hành vi cổng theo network mode của ECS: | Network mode | hostPort | Ghi chú | |---|---|---| | bridge | 0 = động, hoặc cố định | mặc định trên EC2 | | awsvpc | phải bằng containerPort | mỗi task có ENI riêng và IP riêng | | host | phải bằng containerPort | dùng thẳng mạng của host, không tránh xung đột được | | none | — | không có mạng ngoài |
Với Fargate, network mode luôn là awsvpc — mỗi task có IP riêng nên không có xung đột cổng, và câu hỏi này chỉ phát sinh với EC2 launch type + bridge mode.
Xu hướng hiện nay là dùng awsvpc cả trên EC2: mỗi task có ENI và security group riêng, nên bảo mật rõ ràng hơn và không cần dynamic port mapping. Đổi lại, số ENI trên mỗi instance có giới hạn (dù ENI trunking nới rộng đáng kể), nên mật độ task thấp hơn so với bridge mode.
A serverless application uses an AWS Lambda function to process Amazon S3 events. The Lambda function executes 20 times per second and takes 20 seconds to complete each execution.
How many concurrent executions will the Lambda function require?
-
A
20
-
B
40
-
C
400
-
D
5
Xem giải thích
Đáp án
C — 400.
Vì sao đúng
Công thức concurrency của Lambda:
Concurrency = Số lần gọi mỗi giây × Thời gian chạy trung bình (giây)
Thay số từ đề:
20 lần/giây × 20 giây = 400
Trực giác đằng sau công thức: nếu mỗi lần gọi kéo dài 20 giây, thì tại một thời điểm bất kỳ, 20 giây gọi vừa qua đều đang còn chạy. Mỗi giây có 20 lần gọi mới, nên số hàm đang chạy đồng thời là 20 × 20 = 400.
Giây 0 : bắt đầu 20 hàm → đang chạy: 20
Giây 1 : bắt đầu 20 hàm → đang chạy: 40
...
Giây 19: bắt đầu 20 hàm → đang chạy: 400
Giây 20: 20 hàm đầu kết thúc, 20 hàm mới bắt đầu → ổn định ở 400
Con số này quan trọng vì nó phải nằm dưới hạn mức concurrency của tài khoản — mặc định 1.000 mỗi Region. 400 vẫn ổn, nhưng nó chiếm 40% hạn mức của cả tài khoản, nên nếu có hàm khác cùng chạy thì cần theo dõi kỹ hoặc xin tăng hạn mức.
Vì sao các phương án khác sai
- A. 20 — chỉ là số lần gọi mỗi giây, bỏ qua thời gian chạy. Nếu hàm chạy dưới 1 giây thì đáp án mới là 20.
- B. 40 — không tương ứng với phép tính nào; có thể do nhân đôi nhầm.
- D. 5 — có lẽ do chia thay vì nhân (20 ÷ 4?). Sai chiều phép tính.
Ghi nhớ
Công thức concurrency cần thuộc:
Concurrency = Requests/giây × Thời lượng (giây)
Vài ví dụ để kiểm tra trực giác: | Requests/giây | Thời lượng | Concurrency | |---|---|---| | 100 | 0,1 giây | 10 | | 100 | 1 giây | 100 | | 20 | 20 giây | 400 | | 10 | 60 giây | 600 |
Nhận xét quan trọng: hàm chạy càng lâu thì càng ngốn concurrency. Tối ưu thời gian chạy không chỉ giảm tiền mà còn giảm áp lực lên hạn mức.
Các hạn mức liên quan: | Hạn mức | Giá trị | |---|---| | Concurrency mặc định | 1.000 mỗi Region (tăng được) | | Burst concurrency | 500–3.000 tuỳ Region, sau đó tăng 500/phút | | Timeout tối đa | 15 phút |
Burst concurrency là chi tiết hay bị bỏ sót: khi tải tăng đột ngột, Lambda không nhảy thẳng lên 1.000 — 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.
Metric cần theo dõi: | Metric | Ý nghĩa | |---|---| | ConcurrentExecutions | số hàm đang chạy | | Throttles | số lần bị từ chối vì hết concurrency | | UnreservedConcurrentExecutions | phần còn lại của tài khoản |
An organization handles data that requires high availability in its relational database. The main headquarters for the organization is in Virginia with smaller offices located in California. The main headquarters uses the data more frequently than the smaller offices. How should the developer configure their databases to meet high availability standards?
-
A
Create an Aurora database with the primary database in Virginia and specify the failover to the Aurora replica in another AZ in Virginia.
-
B
Create a DynamoDB database with the primary database in Virginia and specify the failover to the DynamoDB replica in another AZ in Virginia.
-
C
Create an Athena database with the primary database in Virginia and specify the failover to the Athena replica in another AZ in Virginia.
-
D
Create an Aurora database with the primary database in Virginia and specify the failover to the Aurora replica in another AZ in California.
Xem giải thích
Đáp án
A — Tạo Aurora database với primary ở Virginia và failover sang Aurora replica ở một AZ KHÁC trong Virginia.
Vì sao đúng
Đề nêu ba dữ kiện: cần CSDL quan hệ, cần sẵn sàng cao, và trụ sở chính ở Virginia dùng dữ liệu nhiều hơn các văn phòng ở California.
Aurora là lựa chọn đúng cho CSDL quan hệ có sẵn sàng cao, và cơ chế của nó rất mạnh:
Region us-east-1 (Virginia)
├── AZ-a: Writer instance ← primary
├── AZ-b: Aurora Replica ← đích failover, ĐỌC ĐƯỢC
└── AZ-c: Aurora Replica
Lưu trữ: 6 bản sao trên 3 AZ (tự động, không cần cấu hình)
Khi writer hỏng, Aurora tự promote một replica lên làm writer trong khoảng 30 giây — và vì các instance dùng chung volume lưu trữ, không có việc sao chép dữ liệu nào phải chờ.
Vì sao replica phải ở cùng Region với primary: đó là cách Aurora hoạt động. Các instance trong một cluster cùng gắn vào một volume lưu trữ, và volume đó nằm trong một Region, trải trên ba AZ. Không có cách nào đặt một instance của cùng cluster sang Region khác.
Và điều này khớp với dữ kiện "trụ sở chính dùng dữ liệu nhiều hơn": giữ toàn bộ cluster ở Virginia cho độ trễ thấp nhất với người dùng chính.
Vì sao các phương án khác sai
- D. Aurora với failover sang replica ở AZ tại California — đây là bẫy chính. California là một Region khác (
us-west-1), không phải một AZ của Virginia. Aurora Replica trong cùng cluster phải nằm cùng Region. Muốn có bản sao ở Region khác thì phải dùng Aurora Global Database — cơ chế khác hẳn: nó nhân bản bất đồng bộ (độ trễ khoảng 1 giây) và failover sang Region là thao tác thủ công hoặc theo kịch bản, không tự động dưới 30 giây. - B. DynamoDB — không phải CSDL quan hệ. Đề nói rõ "relational database". (Về mặt sẵn sàng thì DynamoDB rất tốt — nó tự nhân bản trên 3 AZ — nhưng nó là NoSQL, và cũng không có khái niệm "chỉ định failover sang replica ở AZ khác" như phương án mô tả.)
- C. Athena — sai bản chất nghiêm trọng nhất: Athena không phải CSDL. Nó là dịch vụ truy vấn không máy chủ chạy SQL trên dữ liệu nằm sẵn trên S3. Nó không lưu trữ dữ liệu, không có instance, và không có khái niệm replica hay failover.
Ghi nhớ
Phạm vi của các cơ chế sẵn sàng cao: | Cơ chế | Phạm vi | Failover | |---|---|---| | Aurora Replica | AZ khác, CÙNG Region | tự động, ~30 giây | | Aurora Global Database | Region khác | thủ công, ~1 phút; RPO ~1 giây | | RDS Multi-AZ | AZ khác, cùng Region | tự động, 1–2 phút | | RDS cross-Region read replica | Region khác | thủ công (promote) |
Cách chọn theo đề bài:
- "High availability", "another AZ" ⇒ Aurora Replica (hoặc RDS Multi-AZ)
- "Disaster recovery", "another Region" ⇒ Aurora Global Database
- "Đọc từ nhiều châu lục" ⇒ Aurora Global Database (mỗi Region phụ có endpoint đọc riêng)
Nếu đề đổi một chút — ví dụ nói rằng văn phòng California cũng cần đọc nhiều — thì Aurora Global Database mới là câu trả lời, vì nó đặt được bản sao đọc ngay tại us-west-1. Nhưng đề này nói California dùng ít hơn, nên chấp nhận độ trễ xuyên lục địa cho vài truy vấn là hợp lý, và ưu tiên phải là failover tự động trong Region chính.