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

Tìm thấy 1356 câu.

Câu 711 AWS Security, Identity, & Compliance

A Developer is creating a banking application that will be used to view financial transactions and statistics. The application requires multi-factor authentication to be added to the login protocol.

Which service should be used to meet this requirement?

  1. A

    Amazon Cognito User Pool with MFA

  2. B

    Amazon Cognito Identity Pool with MFA

  3. C

    AWS Directory Service

  4. D

    AWS IAM with MFA

Xem giải thích

Đáp án

A — Amazon Cognito User Pool với MFA.

Vì sao đúng

Đề nêu hai yêu cầu: đây là ứng dụng cho người dùng cuối (khách hàng ngân hàng), và cần xác thực đa yếu tố khi đăng nhập.

User pool là thư mục người dùng, và nó có MFA tích hợp sẵn:

aws cognito-idp set-user-pool-mfa-config \
  --user-pool-id ap-southeast-1_xxx \
  --mfa-configuration ON \
  --software-token-mfa-configuration Enabled=true \
  --sms-mfa-configuration '{"SmsConfiguration":{"SnsCallerArn":"arn:aws:iam::...:role/SnsRole"}}'

Ba chế độ MFA: | Chế độ | Hành vi | |---|---| | OFF | tắt | | ON | bắt buộc cho MỌI người dùng | | OPTIONAL | người dùng tự bật |

Với ứng dụng ngân hàng, ON là lựa chọn phù hợp.

Hai phương thức MFA được hỗ trợ: | Phương thức | Đặc điểm | |---|---| | TOTP (software token) | Google Authenticator, Authy — an toàn hơn | | SMS | tiện nhưng dễ bị tấn công SIM swap |

Và với ngành tài chính, nên bật thêm advanced security — cụ thể là adaptive authentication (chấm điểm rủi ro theo thiết bị, vị trí, danh tiếng IP rồi tự động chặn hoặc đòi MFA) và compromised credentials (chặn mật khẩu đã xuất hiện trong các vụ rò rỉ).

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

  • B. Cognito Identity Pool với MFA — identity pool không có cơ chế xác thực riêng: nó chỉ đổi danh tính đã được xác thực ở nơi khác lấy credential AWS tạm thời. Nó không có thư mục người dùng, không có luồng đăng nhập, và không có MFA.
  • D. AWS IAM với MFA — IAM dành cho danh tính trong AWS (nhân sự, ứng dụng), không dành cho người dùng cuối của ứng dụng. Ngoài ra có giới hạn 5.000 IAM user mỗi tài khoản — không dùng được cho ứng dụng ngân hàng có hàng nghìn tới hàng triệu khách hàng.
  • C. AWS Directory Service — thư mục doanh nghiệp (Microsoft Active Directory được quản lý), dùng cho nhân viên nội bộ và các ứng dụng doanh nghiệp. Không dành cho người dùng công khai.

Ghi nhớ

User Pool Identity Pool
Là gì thư mục người dùng bộ đổi danh tính
MFA ✅ ❌
Đăng ký, đăng nhập, quên mật khẩu ✅ ❌
Phát ra JWT credential AWS tạm thời
Gọi thẳng S3/DynamoDB ❌ ✅

Cách chọn:

  • "đăng nhập, MFA, quản lý người dùng" ⇒ user pool ← câu này
  • "truy cập trực tiếp dịch vụ AWS" ⇒ identity pool
  • cả hai nhu cầu ⇒ dùng cả hai

Nhóm tính năng advanced security của user pool — rất đáng bật cho ứng dụng tài chính: | Tính năng | Việc | |---|---| | Adaptive authentication | chấm điểm rủi ro rồi Allow / đòi MFA / Block | | Compromised credentials | chặn mật khẩu đã bị lộ trong các vụ rò rỉ | | Advanced security metrics | số liệu và log sự kiện bảo mật |

Nên bật ở chế độ AUDIT trước vài tuần để xem thực tế có bao nhiêu người dùng thật bị chấm điểm rủi ro cao, rồi mới chuyển sang ENFORCED — chặn nhầm người dùng hợp lệ là sự cố rất khó phát hiện.

Và cân nhắc chuyển sang passkey (WebAuthn) — Cognito đã hỗ trợ, và nó an toàn hơn cả TOTP lẫn SMS vì chống được tấn công lừa đảo.

Câu 712 AWS Developer Tools

A company needs a fully-managed source control service that will work in AWS. The service must ensure that revision control synchronizes multiple distributed repositories by exchanging sets of changes peer-to-peer. All users need to work productively even when not connected to a network.

Which source control service should be used?

  1. A

    Subversion

  2. B

    AWS CodeBuild

  3. C

    AWS CodeCommit

  4. D

    AWS CodeStar

Xem giải thích

Đáp án

C — AWS CodeCommit.

Vì sao đúng

Đề mô tả bằng ngôn ngữ kỹ thuật, và mỗi mô tả là một đặc điểm của Git: | Mô tả trong đề | Đặc điểm | |---|---| | "revision control synchronizes multiple distributed repositories" | hệ thống phân tán (DVCS) | | "exchanging sets of changes peer-to-peer" | commit — tập thay đổi, trao đổi giữa các bản sao | | "work productively even when not connected" | mỗi bản clone là một kho đầy đủ, làm việc offline được | | "fully-managed" | dịch vụ được quản lý |

Ba đặc điểm đầu là định nghĩa của một hệ thống quản lý phiên bản phân tán, và CodeCommit lưu trữ kho Git chuẩn:

git clone https://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/du-an
# Từ giờ làm việc offline hoàn toàn được:
git add . && git commit -m "Thêm tính năng"    # commit cục bộ, không cần mạng
git log                                         # xem toàn bộ lịch sử, offline
git checkout -b thu-nghiem                      # tạo nhánh, offline
# Khi có mạng:
git push origin thu-nghiem

Điểm mấu chốt: mỗi bản clone chứa TOÀN BỘ lịch sử kho — đó là lý do làm việc offline được, và cũng là lý do gọi là "phân tán".

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

  • A. Subversion (SVN) — đây là bẫy hay nhất, và nó sai ở chính đặc điểm mà đề nhấn mạnh: SVN là hệ thống TẬP TRUNG, không phải phân tán. Mỗi thao tác commit, xem lịch sử, tạo nhánh đều cần kết nối tới máy chủ trung tâm — trái hẳn yêu cầu "work productively even when not connected". (Và AWS không có dịch vụ SVN được quản lý.)
  • B. AWS CodeBuild — biên dịch mã và chạy test. Nó lấy mã từ nơi khác; không lưu trữ và không có lịch sử phiên bản.
  • D. AWS CodeStar — dịch vụ quản lý dự án, tạo sẵn bộ khung gồm kho mã, pipeline và dashboard. Bản thân nó không lưu trữ mã — nó dùng CodeCommit cho việc đó. (Và AWS đã ngừng hoạt động CodeStar từ 31/7/2024.)

Ghi nhớ

So sánh hai mô hình quản lý phiên bản: | | Tập trung (SVN, CVS) | Phân tán (Git, Mercurial) | |---|---|---| | Lịch sử | chỉ trên máy chủ | có đủ trên mọi bản clone | | Commit offline | ❌ | ✅ | | Xem lịch sử offline | ❌ | ✅ | | Tạo nhánh | chậm, tốn tài nguyên máy chủ | rất nhanh, cục bộ | | Trao đổi | client ↔ server | peer-to-peer |

Nhận dạng nhanh trong đề: "distributed", "peer-to-peer", "work offline" ⇒ Git ⇒ CodeCommit.

Vai trò từng dịch vụ trong bộ công cụ phát triển: | Dịch vụ | Việc | |---|---| | CodeCommit | lưu trữ mã nguồn (Git) | | CodeBuild | biên dịch, test, đóng gói | | CodeDeploy | triển khai | | CodePipeline | điều phối | | CodeArtifact | kho package |

Và các đặc điểm "fully-managed" của CodeCommit: | Đặc điểm | Chi tiết | |---|---| | Riêng tư mặc định | không có khái niệm kho công khai | | Mã hoá | at-rest (KMS) và in-transit, tự động | | Bền, sẵn sàng cao | lưu trữ dư thừa đa AZ | | Dung lượng | không giới hạn |

(Ghi chú thời sự: từ 25/7/2024, AWS ngừng cho khách hàng mới tạo repository trên CodeCommit; tài khoản đã dùng vẫn hoạt động bình thường. Với dự án mới, dùng GitHub, GitLab hoặc Bitbucket — nối vào CodePipeline qua CodeStar Connections.)

Câu 713 AWS Database

A Developer needs to return a list of items in a global secondary index from an Amazon DynamoDB table.

Which DynamoDB API call can the Developer use in order to consume the LEAST number of read capacity units?

  1. A

    Query operation using strongly-consistent reads

  2. B

    Scan operation using strongly-consistent reads

  3. C

    Scan operation using eventually-consistent reads

  4. D

    Query operation using eventually-consistent reads

Xem giải thích

Đáp án

D — Query với eventually consistent read.

Vì sao đúng

Hai quyết định, mỗi quyết định tiết kiệm một phần chi phí.

Quyết định 1 — Query thay vì Scan. Đây là khác biệt lớn nhất:

Query: đọc CHỈ các item khớp partition key → tính tiền theo lượng dữ liệu khớp
Scan:  đọc TOÀN BỘ index                   → tính tiền theo toàn bộ dữ liệu quét qua

Với index có hàng triệu item mà bạn chỉ cần vài chục, Query rẻ hơn hàng nghìn lần.

Quyết định 2 — eventually consistent:

Eventually consistent: 0,5 RCU cho mỗi 4 KB
Strongly consistent  : 1   RCU cho mỗi 4 KB   ← gấp đôi
table.query(
    IndexName='ChiMucTheoLoai',
    KeyConditionExpression=Key('loai').eq('dien-tu'),
    ConsistentRead=False        # mặc định — rẻ một nửa
)

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

  • A. Query với strongly consistent read — KHÔNG THỰC HIỆN ĐƯỢC, và đây là điểm quan trọng nhất: GSI KHÔNG BAO GIỜ hỗ trợ strongly consistent read. Truyền ConsistentRead=True khi truy vấn GSI sẽ nhận ValidationException. Lý do: GSI được cập nhật bất đồng bộ sau khi ghi vào bảng gốc, nên DynamoDB không thể đảm bảo nhất quán mạnh.
  • C. Scan với eventually consistent read — loại đọc rẻ, nhưng Scan đọc toàn bộ index nên tốn hơn Query rất nhiều.
  • B. Scan với strongly consistent read — tệ nhất về mọi mặt, và cũng không làm được trên GSI vì lý do trên.

Ghi nhớ

Bảng so sánh GSI và LSI — điểm khác biệt về tính nhất quán là chỗ hay bị hỏi nhất: | | GSI | LSI | |---|---|---| | Strongly consistent read | ❌ KHÔNG BAO GIỜ | ✅ | | Partition key | tự do chọn | phải giống bảng gốc | | Capacity | RIÊNG, phải cấp riêng | dùng chung với bảng | | Tạo lúc nào | bất cứ lúc nào | chỉ khi tạo bảng | | Xoá được | ✅ | ❌ | | Số lượng | 20 | 5 | | Giới hạn kích thước | không | 10 GB mỗi partition key |

Dòng "capacity riêng" của GSI còn gây một hệ quả đáng nhớ: nếu GSI thiếu WCU, thao tác ghi vào BẢNG GỐC sẽ bị throttle — dù bảng gốc còn dư năng lực. DynamoDB làm vậy để index không bị lệch với dữ liệu.

Bốn cách đọc dữ liệu, theo hiệu quả giảm dần: | Thao tác | Dùng khi | Chi phí | |---|---|---| | GetItem | biết chính xác khoá của một item | thấp nhất | | BatchGetItem | biết khoá của nhiều item | thấp | | Query | nhiều item cùng partition key | trung bình | | Scan | không có lựa chọn nào khác | cao nhất |

Và hiểu nhầm phổ biến nhất về chi phí: FilterExpression KHÔNG giảm RCU. Bộ lọc được áp sau khi dữ liệu đã được đọc và tính tiền:

Scan đọc 50 GB → tính tiền 50 GB → FilterExpression bỏ bớt → trả về 100 MB
                       ↑ bạn trả tiền ở đây

Muốn thật sự giảm dữ liệu đọc thì phải thiết kế khoá cho Query hoặc thêm GSI phù hợp với mẫu truy vấn.

Câu 714 AWS Compute

Based on the following AWS CLI command the resulting output, what has happened here?

$ aws lambda invoke --function-name MyFunction --payload ewogICJrZXkxIjogInZhbHVlMSIsCiAgImtleTIiOiAidmFsdWUyIiwKICAia2V5MyI6ICJ2YWx1ZTMiCn0= response.json
{
"StatusCode": 200
}
  1. A

    An AWS Lambda function has been invoked asynchronously and has completed successfully

  2. B

    An AWS Lambda function has been invoked asynchronously and has not completed successfully

  3. C

    An AWS Lambda function has been invoked synchronously and has completed successfully

  4. D

    An AWS Lambda function has been invoked synchronously and has not completed successfully

Xem giải thích

Đáp án

C — Hàm Lambda đã được gọi đồng bộ và hoàn tất thành công.

Vì sao đúng

Đọc lệnh và kết quả theo hai manh mối:

Manh mối 1 — KHÔNG có --invocation-type nghĩa là dùng giá trị mặc định, và mặc định của Lambda là RequestResponse — tức là gọi ĐỒNG BỘ:

aws lambda invoke --function-name MyFunction --payload ... response.json
#                 ↑ không khai invocation-type → mặc định RequestResponse

Manh mối 2 — StatusCode: 200 là mã của gọi đồng bộ thành công: | Mã | Nghĩa | |---|---| | 200 OK | gọi ĐỒNG BỘ thành công, kèm kết quả | | 202 Accepted | gọi bất đồng bộ được tiếp nhận | | 204 No Content | DryRun thành công |

Hai manh mối khớp nhau: gọi đồng bộ, và hàm chạy xong không lỗi.

Với gọi đồng bộ, kết quả trả về nằm trong tệp response.json — khác với gọi bất đồng bộ (tệp rỗng).

(Phần --payload là chuỗi base64, giải mã ra là:

{"key1": "value1", "key2": "value2", "key3": "value3"}

— payload mẫu chuẩn mà AWS hay dùng trong tài liệu.)

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

  • D. Đồng bộ nhưng "chưa hoàn tất thành công" — đúng nửa đầu, sai nửa sau. (Nhưng đây là chỗ cần cẩn thận — xem phần ghi nhớ bên dưới.)
  • A và B. "Bất đồng bộ" — mâu thuẫn với việc không khai --invocation-type Event. Và với gọi bất đồng bộ thành công thì mã là 202, không phải 200.

Ghi nhớ

Bảng đối chiếu kiểu gọi và mã trả về: | Invocation type | Mã thành công | Có kết quả trong response? | |---|---|---| | RequestResponse (mặc định) | 200 | ✅ có | | Event | 202 | ❌ rỗng | | DryRun | 204 | ❌ |

Một chi tiết rất quan trọng khi gọi đồng bộ: hàm LỖI vẫn trả về StatusCode: 200. Lỗi nằm ở chỗ khác:

aws lambda invoke --function-name xu-ly response.json
# {"StatusCode": 200, "FunctionError": "Unhandled", "ExecutedVersion": "$LATEST"}

Trường FunctionError mới là dấu hiệu hàm chạy lỗi, và nội dung lỗi nằm trong response.json.

Nên nghiêm ngặt mà nói, mã 200 một mình chưa chứng minh hàm chạy đúng — phải kiểm tra thêm FunctionError. Trong đề bài, kết quả chỉ có {"StatusCode": 200} không kèm FunctionError, nên kết luận "hoàn tất thành công" là hợp lý.

Bài học thực dụng: đừng chỉ kiểm tra StatusCode khi gọi Lambda bằng script — luôn kiểm tra cả FunctionError:

ket_qua=$(aws lambda invoke --function-name xu-ly out.json)
if echo "$ket_qua" | grep -q FunctionError; then
  echo "Hàm chạy lỗi:"; cat out.json; exit 1
fi

Các mã lỗi thường gặp khi gọi Lambda: | Mã | Nghĩa | |---|---| | 400 | payload không hợp lệ | | 403 | thiếu quyền lambda:InvokeFunction | | 404 | không tìm thấy hàm hoặc alias | | 429 | bị throttle — hết concurrency | | 500 | lỗi nội bộ của dịch vụ Lambda |

Câu 715 AWS Application Integration

A Developer has setup an Amazon Kinesis Data Stream with 6 shards to ingest a maximum of 2000 records per second. An AWS Lambda function has been configured to process these records. In which order will these records be processed?

  1. A

    Lambda will receive each record in the exact order it was placed into the shard. There is no guarantee of order across shards

  2. B

    The Developer can select exact order or reverse order using the GetRecords API

  3. C

    Lambda will receive each record in the reverse order it was placed into the stream

  4. D

    Lambda will receive each record in the exact order it was placed into the stream

Xem giải thích

Đáp án

A — Lambda nhận mỗi bản ghi theo đúng thứ tự nó được đưa vào SHARD. Không có đảm bảo thứ tự giữa các shard.

Vì sao đúng

Kinesis đảm bảo thứ tự trong phạm vi một shard, không phải trên toàn stream.

Cách bản ghi được phân phối:

PutRecord(partitionKey="KH-001") → hash → shard 3
PutRecord(partitionKey="KH-002") → hash → shard 1
PutRecord(partitionKey="KH-001") → hash → shard 3   ← cùng khoá, CÙNG shard

Partition key quyết định shard, và Kinesis băm nó để chọn. Nên: | Phạm vi | Thứ tự | |---|---| | Trong một shard | ✅ đảm bảo tuyệt đối | | Giữa các shard | ❌ không có đảm bảo |

Lý do rất tự nhiên: với 6 shard, Lambda chạy 6 consumer song song — mỗi consumer đọc một shard độc lập. Không có cơ chế nào đồng bộ thứ tự giữa chúng, và nếu có thì sẽ mất hết lợi ích của việc song song hoá.

Hệ quả thực tế cho thiết kế: muốn các bản ghi liên quan được xử lý theo thứ tự, hãy cho chúng CÙNG partition key:

kinesis.put_record(
    StreamName='giao-dich',
    Data=json.dumps(giao_dich),
    PartitionKey=giao_dich['khach_hang_id']    # mọi giao dịch của một khách → cùng shard
)

Cách này đảm bảo mọi giao dịch của cùng một khách hàng được xử lý đúng trình tự, trong khi các khách hàng khác nhau vẫn xử lý song song.

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

  • D. Lambda nhận theo đúng thứ tự bản ghi được đưa vào STREAM — quá mạnh: đảm bảo thứ tự chỉ áp cho shard, không cho toàn stream. Đây là bẫy chính, và nó chỉ khác đáp án đúng ở một từ.
  • C. Lambda nhận theo thứ tự ngược — không có cơ chế nào như vậy. Kinesis luôn phân phối theo thứ tự tăng dần của sequence number trong shard.
  • B. Lập trình viên chọn thứ tự xuôi hoặc ngược bằng GetRecords — GetRecords không có tham số thứ tự. Bạn chọn được điểm bắt đầu bằng ShardIteratorType (TRIM_HORIZON, LATEST, AT_SEQUENCE_NUMBER…), nhưng chiều đọc luôn là xuôi.

Ghi nhớ

Đảm bảo thứ tự của các dịch vụ luồng và hàng đợi: | Dịch vụ | Phạm vi đảm bảo thứ tự | |---|---| | Kinesis Data Streams | trong một shard | | DynamoDB Streams | trong một partition key | | SQS FIFO | trong một message group | | SQS Standard | không đảm bảo | | SNS Standard | không đảm bảo | | SNS FIFO | trong một message group |

Mẫu chung của cả bảng: thứ tự luôn được đảm bảo trong một "phân vùng logic", không bao giờ trên toàn hệ thống — đó là cái giá của khả năng mở rộng ngang.

Vài điểm khác về Kinesis và Lambda: | Điểm | Chi tiết | |---|---| | Một shard ↔ một consumer | tối đa một Lambda xử lý một shard tại một thời điểm | | ParallelizationFactor | tới 10 batch song song trên MỘT shard — vẫn giữ thứ tự theo partition key | | Bản ghi lỗi chặn shard | Lambda thử lại cả lô cho tới khi thành công hoặc hết hạn |

Điểm cuối rất quan trọng: một "poison pill" có thể chặn toàn bộ shard trong 24 giờ. Luôn cấu hình:

aws lambda update-event-source-mapping --uuid <id> \
  --bisect-batch-on-function-error \
  --maximum-retry-attempts 3 \
  --destination-config '{"OnFailure":{"Destination":"arn:aws:sqs:...:ban-ghi-loi"}}'

BisectBatchOnFunctionError chia đôi lô khi lỗi để cô lập đúng bản ghi hỏng thay vì chặn cả lô.

Và mẹo chọn partition key: dùng giá trị có nhiều biến thể và phân bố đều (như customer_id), tránh giá trị ít biến thể (như region chỉ có 3 giá trị) — nếu không sẽ tạo ra hot shard.

Câu 716 AWS Compute

A Developer must run a shell script on Amazon EC2 Linux instances each time they are launched by an Amazon EC2 Auto Scaling group. What is the SIMPLEST way to run the script?

  1. A

    Add the script to the user data when creating the launch configuration

  2. B

    Configure Amazon CloudWatch Events to trigger the AWS CLI when an instance is launched and run the script

  3. C

    Run the script using the AWS Systems Manager Run Command

  4. D

    Package the script in a zip file with some AWS Lambda source code. Upload to Lambda and run the function when instances are launched

Xem giải thích

Đáp án

A — Thêm script vào user data khi tạo launch configuration.

Vì sao đúng

User data là script chạy tự động ở lần khởi động đầu tiên của mọi instance được tạo từ launch configuration (hoặc launch template):

#!/bin/bash
yum update -y
yum install -y httpd
systemctl enable --now httpd
echo "Instance $(ec2-metadata --instance-id) đã sẵn sàng" > /var/www/html/index.html

Khai trong launch template:

aws ec2 create-launch-template --launch-template-name mau-ung-dung \
  --launch-template-data '{
    "ImageId": "ami-0abc123",
    "InstanceType": "t3.medium",
    "UserData": "'$(base64 -w0 script.sh)'"
  }'

Vì sao đây là cách ĐƠN GIẢN NHẤT: | Lợi ích | Chi tiết | |---|---| | Tự động, không cần dịch vụ nào khác | AWS chạy nó như một phần của quá trình boot | | Chạy đúng lúc | trước khi instance nhận traffic | | Áp cho mọi instance mới | kể cả những máy do ASG tạo lúc scale-out | | Không cần quyền hay agent gì | script chạy bằng quyền root |

Điểm thứ hai đáng nhấn mạnh: user data chạy trong quá trình khởi động, nên khi instance được đăng ký vào target group và bắt đầu nhận traffic thì cấu hình đã xong.

(Lưu ý về launch configuration: đề dùng thuật ngữ này, nhưng trong thực tế hãy dùng launch template — AWS đã ngừng phát triển launch configuration, và chỉ launch template mới hỗ trợ mixed instances policy, nhiều instance type, và phiên bản hoá.)

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

  • C. Dùng AWS Systems Manager Run Command — chạy được nhưng phức tạp hơn và sai thời điểm: bạn phải tự phát hiện instance mới (qua EventBridge hoặc lifecycle hook) rồi mới gửi lệnh. Trong khoảng thời gian đó, instance đã có thể nhận traffic khi chưa được cấu hình. Ngoài ra instance cần cài SSM Agent và có IAM role phù hợp.
  • B. CloudWatch Events kích hoạt AWS CLI khi instance khởi chạy — CLI không tự chạy được từ EventBridge: EventBridge gọi được Lambda, Step Functions, SSM Run Command… nhưng không "chạy AWS CLI" theo cách phương án mô tả. Và vẫn vướng vấn đề thời điểm như trên.
  • D. Đóng gói script cùng mã Lambda và chạy hàm khi instance khởi chạy — phức tạp nhất và vẫn sai thời điểm: Lambda không chạy được script BÊN TRONG instance — nó chỉ gọi được SSM Run Command để làm việc đó, tức là quay về phương án C nhưng thêm một tầng.

Ghi nhớ

Ba cách cấu hình instance khi khởi chạy: | Cách | Thời điểm | Độ phức tạp | |---|---|---| | User data | trong lúc boot, lần đầu tiên | thấp nhất | | AMI tuỳ chỉnh | đã có sẵn trong ảnh — boot NHANH NHẤT | trung bình (phải bảo trì AMI) | | SSM Run Command / State Manager | sau khi boot | cao hơn |

Vài đặc điểm của user data: | Đặc điểm | Chi tiết | |---|---| | Chạy bằng quyền root | không cần sudo | | Chỉ chạy MỘT LẦN ở lần boot đầu | (đổi được bằng cloud-boothook hoặc MIME multipart) | | Giới hạn kích thước | 16 KB (trước khi mã hoá base64) | | Log | /var/log/cloud-init-output.log | | Không có phản hồi lỗi | script hỏng thì instance vẫn khởi động bình thường |

Hai dòng cuối rất quan trọng khi gỡ lỗi: nếu instance khởi động nhưng ứng dụng không chạy, đọc /var/log/cloud-init-output.log trước tiên.

Và với script nặng (cài nhiều gói), cân nhắc nướng sẵn vào AMI tuỳ chỉnh bằng EC2 Image Builder — instance khởi động nhanh hơn nhiều, và ASG phản ứng kịp thời hơn khi cần scale-out gấp.

Mẫu tốt nhất trong thực tế thường là kết hợp: AMI chứa phần cài đặt nặng và ít đổi, user data lo phần cấu hình theo môi trường.

Câu 717 AWS Application Integration

An application uses Amazon Kinesis Data Streams to ingest and process large streams of data records in real time. Amazon EC2 instances consume and process the data using the Amazon Kinesis Client Library (KCL). The application handles the failure scenarios and does not require standby workers. The application reports that a specific shard is receiving more data than expected. To adapt to the changes in the rate of data flow, the “hot” shard is resharded.

Assuming that the initial number of shards in the Kinesis data stream is 6, and after resharding the number of shards increased to 8, what is the maximum number of EC2 instances that can be deployed to process data from all the shards?

  1. A

    8

  2. B

    6

  3. C

    1

  4. D

    12

Xem giải thích

Đáp án

A — 8 instance.

Vì sao đúng

Quy tắc nền tảng của KCL: mỗi shard chỉ được MỘT KCL worker xử lý tại một thời điểm.

8 shard sau khi resharding → tối đa 8 worker hoạt động
                           → tối đa 8 EC2 instance có việc làm

Instance thứ 9 trở đi sẽ nằm không — KCL không cấp shard nào cho nó, vì cả 8 shard đã có chủ.

Cách KCL phân phối shard: | Số instance | Kết quả | |---|---| | 1 | một worker xử lý cả 8 shard | | 4 | mỗi worker xử lý 2 shard | | 8 | mỗi worker xử lý ĐÚNG 1 shard — tối ưu | | 12 | 8 worker có việc, 4 nằm không |

KCL tự lo việc phân phối và cân bằng lại: nó dùng một bảng DynamoDB làm sổ theo dõi — mỗi shard có một dòng ghi worker nào đang giữ và đã đọc tới đâu (checkpoint). Khi có worker mới tham gia hoặc worker cũ chết, KCL tự phân phối lại.

Đề còn nói rõ "does not require standby workers" — nghĩa là không cần dự phòng thêm, nên con số đúng là bằng số shard.

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

  • B. 6 — là số shard TRƯỚC khi resharding. Đề nói rõ sau khi tách shard nóng, số shard tăng lên 8.
  • D. 12 — vượt quá số shard, nên 4 instance sẽ nằm không mà vẫn tính tiền.
  • C. 1 — chạy được (một worker xử lý cả 8 shard) nhưng không phải số TỐI ĐA mà đề hỏi.

Ghi nhớ

Quan hệ giữa shard và consumer:

1 shard ←→ tối đa 1 KCL worker tại một thời điểm
N shard ←→ tối đa N worker chạy song song

Giới hạn của mỗi shard trong Kinesis Data Streams: | 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, tối đa 5 lời gọi GetRecords/giây | | Đọc (enhanced fan-out) | 2 MB/giây RIÊNG cho mỗi consumer |

Hai cách resharding: | Thao tác | Việc | |---|---| | SplitShard | tách một shard nóng thành hai — đúng tình huống trong đề | | MergeShards | gộp hai shard kề nhau thành một | | UpdateShardCount | để AWS tự tính toán, đơn giản hơn |

Trong thực tế, UpdateShardCount thường tiện hơn:

aws kinesis update-shard-count \
  --stream-name du-lieu-cam-bien \
  --target-shard-count 8 --scaling-type UNIFORM_SCALING

Một chi tiết quan trọng về resharding: shard cũ không biến mất ngay — chúng chuyển sang trạng thái CLOSED và vẫn giữ dữ liệu cho tới hết thời gian retention. KCL đọc hết shard cũ trước khi chuyển sang shard con, để giữ đúng thứ tự.

Với Lambda thay cho KCL, quan hệ cũng tương tự — nhưng có thêm ParallelizationFactor cho phép tới 10 batch song song trên MỘT shard, vẫn giữ thứ tự theo partition key:

aws lambda update-event-source-mapping --uuid <id> --parallelization-factor 10

Và metric cần theo dõi để biết consumer có theo kịp không: GetRecords.IteratorAgeMilliseconds — nếu nó tăng dần, bạn cần thêm shard hoặc thêm năng lực xử lý.

Câu 718 AWS Networking & Content Delivery

A company provides a large number of services on AWS to customers. The customers connect to one or more services directly and the architecture is becoming complex. How can the architecture be refactored to provide a single interface for the services?

  1. A

    AWS X-Ray

  2. B

    AWS Single Sign On (SSO)

  3. C

    Amazon API Gateway

  4. D

    AWS Cognito

Xem giải thích

Đáp án

C — Amazon API Gateway.

Vì sao đúng

Đề mô tả đúng vấn đề mà API Gateway giải: khách hàng kết nối trực tiếp tới nhiều dịch vụ riêng lẻ, khiến kiến trúc ngày càng phức tạp.

API Gateway đóng vai trò cổng vào duy nhất (API façade) cho toàn bộ hệ thống:

Trước:  Khách hàng ─┬→ Dịch vụ A (endpoint riêng)
                    ├→ Dịch vụ B (endpoint riêng)
                    └→ Dịch vụ C (endpoint riêng)

Sau:    Khách hàng → API Gateway ─┬→ /don-hang  → Lambda
                                  ├→ /kho       → ECS
                                  └→ /thanh-toan → HTTP backend

Khách hàng chỉ cần biết một tên miền, một cơ chế xác thực, một bộ tài liệu.

Và API Gateway còn gánh hộ nhiều mối lo ngang (cross-cutting concerns) mà nếu không có nó thì mỗi dịch vụ phải tự làm: | Mối lo | API Gateway lo sẵn | |---|---| | Xác thực và uỷ quyền | Cognito authorizer, Lambda authorizer, IAM | | Giới hạn tần suất | throttling và usage plan theo từng khách hàng | | Caching | ở mức stage | | Phiên bản hoá | stage và stage variable | | Ghi log và theo dấu | access log, execution log, X-Ray | | CORS, biến đổi payload | mapping template |

Nó cũng cho phép thay đổi backend mà không ảnh hưởng khách hàng — chuyển một dịch vụ từ EC2 sang Lambda chỉ là sửa integration, URL công khai không đổi.

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

  • B. AWS Single Sign-On (IAM Identity Center) — quản lý truy cập của NHÂN SỰ vào tài khoản AWS. Nó không phải cổng cho API và không định tuyến request của khách hàng.
  • D. Amazon Cognito — xác thực người dùng, giải quyết được một phần (thống nhất cơ chế đăng nhập), nhưng không định tuyến request và không hợp nhất endpoint. Nó thường dùng CÙNG API Gateway, không thay thế.
  • A. AWS X-Ray — theo dấu và phân tích request qua các dịch vụ. Nó giúp hiểu kiến trúc phức tạp, nhưng không đơn giản hoá nó.

Ghi nhớ

Ba loại API của API Gateway: | Loại | Đặc điểm | Chi phí | |---|---|---| | REST API | đầy đủ tính năng: caching, usage plan, request validation, mapping template | cao nhất | | HTTP API | nhanh hơn, rẻ hơn ~70%, ít tính năng hơn | thấp | | WebSocket API | hai chiều, giữ kết nối | riêng |

Ba loại endpoint: | Loại | Đường đi | |---|---| | Edge-optimized | qua CloudFront edge — cho người dùng toàn cầu | | Regional | thẳng tới Region | | Private | chỉ truy cập được từ VPC qua interface endpoint |

Bốn cơ chế uỷ quyền: | Cơ chế | Dùng khi | |---|---| | Lambda authorizer | logic tuỳ ý — header riêng, CSDL riêng, IdP bên thứ ba | | Cognito user pool | dùng thư mục người dùng của AWS | | IAM (SigV4) | client có danh tính AWS | | JWT authorizer (HTTP API) | OIDC/OAuth2 chuẩn |

Và usage plan đặc biệt hữu ích cho tình huống trong đề — nhiều khách hàng dùng chung một API:

aws apigateway create-usage-plan --name "Goi-Doanh-Nghiep" \
  --throttle burstLimit=200,rateLimit=100 \
  --quota limit=1000000,period=MONTH

Nó cho phép đo và giới hạn theo từng khách hàng bằng API key — điều mà kiến trúc "kết nối trực tiếp" trong đề hoàn toàn không có.

Nhận dạng nhanh: đề nói "single interface", "unified entry point", "API façade" ⇒ API Gateway.

Câu 719 AWS Compute

A Developer is migrating Docker containers to Amazon ECS. A large number of containers will be deployed across some newly deployed ECS containers instances using the same instance type. High availability is provided within the microservices architecture. Which task placement strategy requires the LEAST configuration for this scenario?

  1. A

    spread

  2. B

    random

  3. C

    binpack

  4. D

    Fargate

Xem giải thích

Đáp án

B — random.

Vì sao đúng

Đề đưa ra một tiêu chí duy nhất và khá bất thường: chiến lược nào cần CẤU HÌNH ÍT NHẤT. Và các dữ kiện khác giải thích vì sao điều đó hợp lý:

Dữ kiện trong đề Ý nghĩa
Mọi instance dùng CÙNG loại không cần lọc theo instance type
Sẵn sàng cao đã có ở tầng microservices không cần spread để đảm bảo phân tán
Triển khai số lượng lớn container cần đơn giản

random là chiến lược đơn giản nhất — nó không cần khai trường (field) nào:

"placementStrategy": [{"type": "random"}]

So sánh với các chiến lược khác:

{"type": "spread", "field": "attribute:ecs.availability-zone"}   ← phải khai field
{"type": "binpack", "field": "memory"}                           ← phải khai field
{"type": "random"}                                               ← không cần gì

Và vì mọi instance giống hệt nhau về cấu hình, việc đặt ngẫu nhiên cho ra kết quả phân bố khá đều theo luật số lớn khi số container đủ lớn — nên trong tình huống cụ thể này, nó chấp nhận được.

(Cần nói rõ: random hiếm khi là lựa chọn tốt trong thực tế. Đề này cố tình dựng một tình huống mà mọi ràng buộc khác đều đã được giải quyết ở nơi khác, chỉ còn lại tiêu chí "ít cấu hình nhất".)

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

  • A. spread — chiến lược được khuyến nghị cho hầu hết trường hợp, nhưng nó cần khai field để biết rải theo chiều nào (AZ, instance ID, hay thuộc tính tuỳ chỉnh). Và đề đã nói sẵn sàng cao được đảm bảo ở tầng kiến trúc microservices, nên lợi ích chính của spread đã có sẵn.
  • C. binpack — cũng cần khai field (memory hoặc cpu), và mục tiêu của nó là tiết kiệm chi phí bằng cách dồn chặt — đề không nêu yêu cầu đó.
  • D. "Fargate" — không phải placement strategy: Fargate là launch type (chế độ chạy container không cần quản lý server). Và với Fargate thì placement strategy không dùng được — AWS tự quản lý toàn bộ hạ tầng.

Ghi nhớ

Ba strategy của ECS và mục tiêu của chúng: | Type | Mục tiêu | Cần khai field? | |---|---|---| | spread | rải đều — sẵn sàng cao | ✅ | | binpack | dồn chặt — tiết kiệm chi phí | ✅ | | random | không mục tiêu cụ thể | ❌ — ít cấu hình nhất |

Hai constraint của ECS (bộ lọc, khác với strategy): | Type | Hành vi | |---|---| | distinctInstance | mỗi instance tối đa một task | | memberOf | chỉ instance thoả biểu thức Cluster Query Language |

Khác biệt cốt lõi: strategy là ưu tiên (sắp xếp), constraint là bộ lọc (loại bỏ). Constraint áp trước để thu hẹp tập ứng viên, rồi strategy mới chọn trong tập đó.

Cách chọn theo từ khoá trong đề: | Đề nói | Chọn | |---|---| | "least configuration" | random ← câu này | | "high availability", "distribute evenly" | spread | | "minimize instances", "reduce cost" | binpack | | "must", "only on instance type X" | constraint memberOf | | "each task on a different instance" | constraint distinctInstance |

Cấu hình được dùng nhiều nhất trong production thực tế là kết hợp hai tầng:

"placementStrategy": [
  {"field": "attribute:ecs.availability-zone", "type": "spread"},
  {"field": "instanceId", "type": "spread"}
]

— rải đều giữa các AZ trước, rồi rải đều giữa các máy trong mỗi AZ.

Và với Fargate, toàn bộ câu hỏi này biến mất: mỗi task chạy trên hạ tầng riêng do AWS quản lý, không có instance nào để đặt.

Câu 720 AWS Security, Identity, & Compliance

A large quantity of sensitive data must be encrypted. A Developer will use a custom CMK to generate the encryption key. The key policy currently looks like this:

{
"Sid": "Allow Key Usage",
"Effect": "Allow",
"Principal": {"AWS": [
"arn:aws:iam::111122223333:user/CMKUser"
]},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:DescribeKey"
],
"Resource": "*"
}

What API action must be added to the key policy?

  1. A

    kms:GetKeyPolicy

  2. B

    kms:EnableKey

  3. C

    kms:GenerateDataKey

  4. D

    kms:CreateKey

Xem giải thích

Đáp án

C — kms:GenerateDataKey.

Vì sao đúng

Đề có hai dữ kiện quyết định: cần mã hoá một khối lượng lớn dữ liệu, và CMK dùng để sinh khoá mã hoá.

Cả hai đều chỉ về envelope encryption, và API cho việc đó là GenerateDataKey:

# 1. Xin data key — KMS trả về CẢ HAI dạng
r = kms.generate_data_key(KeyId='arn:aws:kms:...:key/abc', KeySpec='AES_256')
khoa_ban_ro = r['Plaintext']        # dùng để mã hoá TẠI CHỖ
khoa_ban_ma = r['CiphertextBlob']   # lưu kèm dữ liệu

# 2. Mã hoá dữ liệu lớn bằng AES cục bộ
du_lieu_ma = ma_hoa_aes(du_lieu, khoa_ban_ro)

# 3. Xoá khoá bản rõ khỏi bộ nhớ
del khoa_ban_ro

Vì sao kms:Encrypt có sẵn trong policy vẫn không đủ: nó có giới hạn cứng 4 KB. Với "large quantity of data", mọi lời gọi đều bị từ chối.

Ý tưởng cốt lõi của envelope encryption: chỉ có khoá 256-bit đi qua mạng tới KMS, còn dữ liệu lớn được mã hoá ngay trong ứng dụng. Vừa không vướng giới hạn kích thước, vừa nhanh hơn nhiều.

Policy sau khi bổ sung:

"Action": [
  "kms:Encrypt",
  "kms:Decrypt",
  "kms:ReEncrypt*",
  "kms:DescribeKey",
  "kms:GenerateDataKey"        ← thêm dòng này
]

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

  • A. kms:GetKeyPolicy — đọc chính sách của khoá. Đây là thao tác quản trị, không tham gia vào việc mã hoá dữ liệu.
  • B. kms:EnableKey — bật lại một khoá đã bị vô hiệu hoá. Thao tác quản trị vòng đời khoá, không liên quan tới mã hoá.
  • D. kms:CreateKey — tạo một CMK MỚI. Đề nói rõ đã có CMK tuỳ chỉnh rồi; việc cần làm là dùng nó để sinh data key, không phải tạo thêm khoá.

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 — trả về bản rõ + bản mã 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
ReEncrypt đổi khoá cho ciphertext có sẵn ≤ 4 KB

Cách chọn nhanh:

  • ≤ 4 KB ⇒ Encrypt trực tiếp
  • > 4 KB ⇒ GenerateDataKey + envelope encryption

Ba nguyên tắc khi làm envelope encryption:

  1. Xoá khoá bản rõ khỏi bộ nhớ ngay sau khi dùng — đừng ghi ra log hay đĩa.
  2. Lưu khoá đã mã hoá cùng dữ liệu — mất nó là mất dữ liệu vĩnh viễn.
  3. Dùng encryption context để ràng buộc khoá với ngữ cảnh:
    kms.generate_data_key(KeyId=..., KeySpec='AES_256',
                          EncryptionContext={'loai': 'ho-so', 'phong': 'ke-toan'})
    
    Nó được xác thực nhưng không mã hoá, phải khớp chính xác khi giải mã, và xuất hiện trong CloudTrail — vừa ngăn dùng nhầm khoá, vừa làm log kiểm toán có nghĩa.

Với khối lượng rất lớn, nhớ thêm hai điều:

  • KMS có hạn mức request mỗi giây ở mức tài khoản và Region — gọi GenerateDataKey cho từng tệp nhỏ có thể chạm trần.
  • Dùng AWS Encryption SDK với LocalCryptoMaterialsCache để dùng lại một data key cho nhiều thông điệp trong giới hạn bạn đặt — giảm số lời gọi KMS hàng trăm lần.

Trong thực tế, nên dùng AWS Encryption SDK thay vì tự viết — nó đã cài đặt sẵn toàn bộ mẫu này kèm định dạng thông điệp chuẩn.