COMP5349 A2 — Live Demo Cheat Sheet (中英对照版)

10 分钟 · 6 分 · Week 14 · 黄字是中文翻译/口语表达参考,正式 demo 用英文

🔥 Intel: tutor 深挖的三大块 / Areas the tutor probed deeply

同学反馈 tutor 重点问了:IAM policy、VPC description、ASG policy。下面是这三块的深度问答,重点准备。这三块的回答必须流利。其他问题答错可以补救,这三块结巴会很扣分。

🛡️ IAM policy — 深挖问答

List the policies attached to your role and tell me what each one does.
列举你角色挂的 policy,说每个干嘛的。
EN: "Role a2-ec2-role has four AWS-managed policies. AmazonS3FullAccess for the web tier to PutObject and the worker to GetObject. AmazonSQSFullAccess for workers to ReceiveMessage and DeleteMessage. AmazonSNSFullAccess — actually only needed if I were to publish from EC2; in the current design the publisher is S3, but I added it for completeness in case I extend the app to publish directly. AmazonSSMManagedInstanceCore lets Systems Manager Session Manager work, which I kept for emergency access if I lost the SSH key."
中文要点: 4 个 managed policy。S3FullAccess 给 Web 写、Worker 读。SQSFullAccess 给 Worker 收发消息。SNSFullAccess 现在 EC2 其实不发 SNS(S3 才是 publisher),但加上是为了将来扩展。SSMManagedInstanceCore 是给 Session Manager 备用通道。
Why FullAccess? Isn't that violating least privilege?
为什么用 FullAccess?这不是违反最小权限原则吗?
EN: "Yes it does, and I called this out explicitly in the report. The assignment specification allows broader permissions for simplicity as long as it's acknowledged. The blast radius is bounded because the application code only ever calls a small set of APIs — PutObject and GetObject on one bucket prefix, ReceiveMessage and DeleteMessage on two specific queues, and SQL through the connection string. In a production deployment I would split into per-tier custom policies scoped to those specific resource ARNs."
中文要点: 是违反,报告里明确承认了。作业 PDF 允许放宽只要 acknowledge。实际代码只调一小撮 API,影响面有限。生产环境会分 per-tier 自定义 policy,限到具体 ARN。
What does the trust policy on this role look like?
这个角色的 trust policy 长什么样?
EN: "Standard EC2 service trust. It allows ec2.amazonaws.com to call sts:AssumeRole, which is what lets an EC2 instance assume this role via the instance metadata service. Without that statement, the role couldn't be attached to an instance profile at all."
中文要点: 标准 EC2 service trust。允许 ec2.amazonaws.com 调 sts:AssumeRole。这是让 EC2 通过 instance metadata service 拿临时凭证的前提。没这条就挂不到 instance profile。
How does the worker actually get credentials at runtime?
Worker 运行时怎么拿到凭证?
EN: "boto3 fetches them from the EC2 instance metadata service at 169.254.169.254. The credentials are rotated automatically every few hours. There are no static access keys anywhere on the instance, which is what the IAM role pattern is designed to avoid. If you SSH into the worker right now and run curl http://169.254.169.254/latest/meta-data/iam/security-credentials/a2-ec2-role, you'll see the current temporary credentials."
中文要点: boto3 自动从 169.254.169.254(EC2 metadata service)拿。几小时自动轮换。机器上没有任何静态 access key —— 这就是 IAM role 模式的核心好处。可以现场 curl 演示。
If you scoped this down, what would the worker's policy actually look like?
如果做最小权限,Worker 的 policy 实际会写成什么样?
EN: "Something like this conceptually: s3:GetObject on arn:aws:s3:::a2-pdf-rag-johnyang-2026/uploads/*; sqs:ReceiveMessage, sqs:DeleteMessage, sqs:GetQueueAttributes on the two queue ARNs; nothing else. No S3 list, no S3 write, no SNS at all, no other queue access. That's exactly what worker_common.py uses, nothing more."
中文要点: Worker 只要 GetObject 在 uploads/* 前缀,ReceiveMessage/DeleteMessage/GetQueueAttributes 在两个队列 ARN 上,其他全砍。这就是 worker_common.py 实际用到的全部。

🌐 VPC description — 深挖问答

Walk me through your VPC structure.
走一遍你的 VPC 结构。
EN: "VPC a2-vpc is 10.0.0.0/16. It has four subnets across two Availability Zones — 2a and 2b. Each AZ has a public /20 and a private /20: public subnets are 10.0.0.0/20 in 2a and 10.0.16.0/20 in 2b; private subnets are 10.0.128.0/20 in 2a and 10.0.144.0/20 in 2b. The Internet Gateway is attached to the VPC; the public route table sends 0.0.0.0/0 to the IGW. There's one NAT Gateway in the public-1 subnet of 2a, and the private route tables both send 0.0.0.0/0 to that NAT."
中文要点: 10.0.0.0/16,2 个 AZ 每个分公私两个 /20。Public route table 默认路由指 IGW,private 路由表指 NAT。NAT 只放一个在 2a。
Why /16 for the VPC and /20 for subnets? Did you calculate this?
为什么 VPC 用 /16,子网用 /20?算过吗?
EN: "/16 gives 65,536 addresses and avoids overlap with any future VPC peering — it's the default the wizard suggests and there's no reason to restrict it. /20 gives 4091 usable addresses per subnet, which is hugely over-provisioned for this workload but costs nothing to keep. AWS reserves 5 addresses from each subnet (network, VPC router, DNS, future, broadcast), which is where the 4091 instead of 4096 comes from."
中文要点: /16 是 65536 个地址,留余地。/20 给 4091 可用,远超需要但不花钱。AWS 每个子网保留 5 个地址(网络号、路由器、DNS、保留、广播),所以是 4091 不是 4096。
How is "public" vs "private" actually enforced? Is it a flag?
公私子网到底怎么区分?是个属性吗?
EN: "It's not a flag — it's purely determined by the route table. A subnet is 'public' if its associated route table has a route to an Internet Gateway. A subnet is 'private' if it doesn't. That's the only difference. AWS calls it 'public subnet' as a convention but at the API level it's just routing. If I attached the public route table to a private subnet, that subnet would immediately become reachable from the internet, assuming SG rules allow."
中文要点: 不是属性 —— 完全由路由表决定。子网"公开"就是它的路由表有指向 IGW 的路由。"私有"就是没有。AWS 命名是习惯,本质是路由。换路由表就能瞬间变公开(前提 SG 也允许)。
Why two AZs? Why not just one?
为什么用两个 AZ,一个不行吗?
EN: "Two reasons. First, the Application Load Balancer requires subnets in at least two AZs — it's a hard constraint, you can't create an ALB with only one subnet. Second, even if I could, two AZs gives basic fault tolerance: an outage in 2a doesn't take the whole deployment down because the ALB still has a node in 2b. The cost of the second AZ is essentially zero for empty subnets."
中文要点: 两个原因。一、ALB 硬性要求至少 2 个 AZ 的子网,单 AZ 创建不了。二、就算能,2 AZ 给基本容灾,2a 挂了 ALB 还有 2b 的节点。空子网零成本。
What's the difference between Internet Gateway and NAT Gateway?
IGW 和 NAT 有什么区别?
EN: "IGW is bidirectional — it lets traffic in from the internet to public-IP instances and out from those instances back. NAT Gateway is outbound-only — it lets private-subnet instances reach the internet to make outgoing calls, like the worker polling SQS, but the internet cannot initiate connections back through it. IGW is free; NAT costs about 5 cents an hour plus data."
中文要点: IGW 双向 —— 外面进来和里面出去都行(前提有公网 IP)。NAT 单向 —— 只允许私有子网主动出网,外面进不来。IGW 免费,NAT 大约 5 美分/小时 + 流量费。

⚙️ ASG policy — 深挖问答

What's your scaling policy?
你的 scaling policy 是什么?
EN: "I deliberately did not add a scaling policy. The ASG is sized at desired=1, min=1, max=2 to satisfy the requirement that the web tier be ASG-managed, but there's no CloudWatch alarm or target-tracking policy driving scaling. The reason is honest: the assignment workload doesn't generate enough load to justify autoscaling, and adding a policy would just make the cost analysis noisy without showing anything meaningful. What the ASG does give me is automatic instance replacement — if I terminate the running instance, the ASG launches a new one within about a minute."
中文要点: 我故意没加 scaling policy。ASG 配 desired=1 max=2 是满足要求,但没有 CloudWatch 警报或 target tracking 驱动扩缩。诚实说:作业流量根本不够触发扩缩。但 ASG 给的好处是 —— 我 terminate 当前实例,ASG 1 分钟内自动拉一个新的。
Why min=1 max=2 instead of min=1 max=1?
为什么 max=2 不是 max=1?
EN: "Max=2 gives room for instance refresh. If I ever needed to roll a new AMI or change the launch template, the ASG can launch a replacement before terminating the old one — zero downtime. With max=1 the ASG would have to terminate first and the application would be down during the boot of the replacement. Costs nothing extra because desired stays at 1; max is just a ceiling."
中文要点: Max=2 是为了 instance refresh 留余地。换 AMI 或 launch template 时,可以先起新的再杀旧的,零停机。Max=1 就得先杀再起,应用会断。Max 只是上限,不额外花钱(desired 还是 1)。
Show me the launch template. What's in user-data?
给我看 launch template。User-data 写了什么?
EN: "Launch template a2-web-lt, default version. AMI is a2-app-ami, the custom AMI I baked from the worker with Python 3.11 and the application code already installed. Instance type t3.small, key pair a2-key, security group a2-web-sg, IAM instance profile a2-ec2-role. User-data does two things: writes /etc/a2-env with the five required environment variables — region, S3 bucket, two SQS URLs, DATABASE_URL — and creates a systemd unit a2-web.service that runs python3.11 app.py as ec2-user with that environment file. Then it enables the unit. Python is in the AMI so user-data doesn't install anything."
中文要点: a2-web-lt,AMI 是我自己烤的 a2-app-ami(Python + 代码已装)。t3.small + a2-key + a2-web-sg + a2-ec2-role。User-data 就两件事:写 /etc/a2-env(5 个环境变量)+ 写 systemd unit + enable。Python 在 AMI 里所以不装。
How do you know the ASG actually replaces a failed instance? Can you demo it?
你怎么知道 ASG 真的会替换失败的实例?能现场演示吗?
EN: "Yes. Right now there's one instance in the target group, healthy. If I go to EC2 → Instances, select the ASG-launched web instance, and click Terminate, the ASG will see current=0 and desired=1 within about 30 seconds, launch a new instance from the launch template, run user-data, and the new instance will register with the target group as healthy in about 90 seconds total. The application is back up." [If asked to actually do this — open EC2 → Instances → terminate → watch ASG Activity tab.]
中文要点: 可以。现在 TG 里一个 Healthy 实例。我 terminate 它,ASG 30 秒内看到 current=0 desired=1,启动新实例,跑完 user-data,大约 90 秒后注册到 TG 成 Healthy。应用恢复。
What's the health check grace period and why?
Health check grace period 设多少?为什么?
EN: "120 seconds. The ELB health check probes GET / every 30 seconds. Without a grace period, the ASG would mark the instance unhealthy and terminate it before user-data even finished writing the systemd unit. 120 seconds is enough for user-data to run, systemd to start the app, and the ALB to register the instance. I tuned this by watching the boot logs the first time I deployed."
中文要点: 120 秒。ELB 30 秒探测一次 GET /。没有 grace period,ASG 会在 user-data 还没跑完时就把实例标为 unhealthy 然后 terminate。120 秒够 user-data 跑完 + systemd 起 app + ALB 注册。第一次部署看 boot log 调出来的。
What's "Balanced best effort" AZ distribution?
Balanced best effort 是什么意思?
EN: "It's the ASG's strategy when launching across AZs. With Balanced best effort, the ASG tries to keep instance count even across AZs, but if a launch in one AZ fails — say due to capacity — it'll launch in the other AZ rather than retrying. The alternative is Strict, which would only launch in the configured AZ even if it fails. For desired=1 it barely matters; for higher desired counts it matters more."
中文要点: ASG 在多 AZ 启动时的策略。Balanced best effort 努力平均分配,但 AZ 失败就转移到另一个。Strict 则严守 AZ 即使失败也不转。Desired=1 时基本没差别。

Architecture logic — how the pieces nest and constrain each other / 架构逻辑:嵌套关系与互相制衡

This is what your tutor expects you to be able to explain in your own words. 这部分 tutor 期待你用自己的话解释。

1) Nesting / 嵌套层级(从外到内)

  1. AWS Account (370613533613) 是顶层。所有资源都属于这个账号。IAM 决定哪个 principal 能做什么。 所有 AWS 资源的根。账号是计费和权限边界。
  2. Region (ap-southeast-2) 是地理边界。VPC、S3 bucket、SNS topic、SQS queue、RDS 实例都绑定到一个 region。 这个 region 内的资源彼此通信不走互联网,延迟低、不收 inter-region 流量费。
  3. VPC (a2-vpc, 10.0.0.0/16) 是网络隔离边界。EC2、RDS、NAT、ALB 必须放在 VPC 内。S3/SNS/SQS 是 region 级服务,不在 VPC 内,但 VPC 内的实例通过 NAT 出网访问它们。 VPC 是一个虚拟私有网络。EC2 只能跟同 VPC 的资源用私有 IP 通信。
  4. AZ (2a / 2b) 是物理故障域。每个 AZ 是一个独立的数据中心。架构里用 2 个 AZ 是为了高可用:ALB 在两个 AZ 都有 node,ASG 可以在任一 AZ 起实例,RDS subnet group 跨 2 个 AZ 所以将来能升级 Multi-AZ。 AZ 之间互相独立,一个挂了另一个还在。作业要求至少 2 个 AZ。
  5. Subnet (4 个 /20) 是 VPC 内的 IP 段,每个绑定一个 AZ 和一个路由表。Public subnet 的路由表默认路由指向 IGW;private subnet 的默认路由指向 NAT。资源放在哪个 subnet 决定了它有没有公网入口和出口。 同一个 subnet 内的实例不需要路由就能互通。跨 subnet 走路由表。
  6. Security Group 是实例级的有状态防火墙。一个实例可以挂多个 SG;规则是"允许"的,没有"拒绝"。SG 是最关键的访问控制,不是路由表,不是 NACL。 SG 控制谁能连进来,谁能连出去,按端口和源/目的地。
  7. IAM Role + Instance Profile 是 EC2 调 AWS API 时用的身份。Role 决定"这个实例能调哪些 AWS API"。 代码里 boto3 自动从 instance metadata 拿临时凭证,不用写 access key。

2) Security group chain / SG 制衡链(这是 tutor 最爱问的)

每一对 SG 之间的关系都有明确目的。不是随便写规则。

SGAllow inbound fromWhy / 为什么这样设
a2-alb-sg
ALB 的 SG
HTTP:80 from 0.0.0.0/0 ALB 是公网入口,必须接受所有人的 80 请求。 没有别的办法 —— 用户能从家里访问就靠这条。SG 范围最宽的就是它。
a2-web-sg
Web EC2 的 SG
TCP:5000 from a2-alb-sg 关键点:source 是 SG ID 不是 CIDR。意思是"只要请求是从挂着 a2-alb-sg 的实例来的,就放行"。即使有人猜到 Web 的私有 IP,也连不上 —— 他不在 ALB SG 里。 这就是为什么 Web 在私有子网还能正常工作:ALB 在公网,Web 信任 ALB;外人不在 ALB SG 里就连不上 Web。
a2-worker-sg
Worker 的 SG
SSH:22 from a2-bastion-sg Worker 完全不接受应用流量入站(它是 poll 出去拿 SQS 消息的)。唯一的入站是 SSH,且只能从 bastion 来。 运维渠道唯一。没有 0.0.0.0/0 的 SSH 规则。
a2-bastion-sg
Bastion 的 SG
SSH:22 from 203.158.41.210/32 整个部署里唯一带公网 CIDR 的 SSH 规则,而且锁到我家的单个 IP。换 WiFi 这条规则就要更新。 这是攻击面 —— 但范围被锁到一个 IP,比 0.0.0.0/0 安全 N 倍。
a2-rds-sg
RDS 的 SG
5432 from web-sg / worker-sg / bastion-sg 三个内部 SG 来源,每条规则都说明用途。Web 要写元数据,Worker 要写 chunks,Bastion 要跑 psql 做管理。没有任何 CIDR 规则,没有 0.0.0.0/0。 数据库是最敏感的资源,所以规则最严:只允许三类内部源,且 RDS 本身 Publicly accessible = No。

3) Why this layering works / 为什么这样分层能成立

4) IAM vs SG — 不要搞混 / Don't confuse

Security GroupIAM Role
控制什么网络层:谁能连到哪个 portAPI 层:哪个身份能调哪个 AWS API
边界实例的网卡 (ENI)EC2 内 boto3 / CLI 调 AWS
例子Worker 能不能 telnet 到 RDS 的 5432Worker 能不能 ReceiveMessage from SQS
没有它会怎样实例之间断网boto3 调 API 报 AccessDenied

One-liner / 一句话总结: SG = "能不能连过去"; IAM = "连过去之后能不能调 API"。两个都要对,应用才能工作。

5) Event flow constraints / 事件链上的约束

每一跳都有明确的允许策略。这条链里任何一环坏掉应用就停。

  1. S3 → SNS: 由 SNS topic 的 access policy 控制。Policy 里有 statement 允许 s3.amazonaws.com 服务主体 Publish,并用 aws:SourceAccount 条件锁定到本账号。 如果这条 policy 没写,S3 上传后 SNS 收不到事件。
  2. SNS → SQS: 每个 SQS 的 access policy 允许 SNS topic ARN SendMessage,用 aws:SourceArn 条件锁定到那个 topic。 两个队列各自有一份 policy。如果只配一个,另一个 worker 就拿不到消息。
  3. Worker poll SQS: 靠 IAM role a2-ec2-role 的 SQSFullAccess。不是靠 SG —— SQS 不在 VPC 内,SG 管不到它。 这就是为什么 IAM 比 SG 关键 —— SG 只保护 VPC 内的资源。
  4. Worker GetObject from S3: 同样靠 IAM,不是 SG。S3 是 region 级服务。 Worker 出网先经过 NAT,但 S3 endpoint 的访问权限是 IAM 决定的。
  5. Worker write RDS: 靠 SG(a2-rds-sg 允许 worker-sg)+ 数据库密码(DATABASE_URL 里的 app_user/password)。这一跳同时受 SG 和 DB 凭证保护。 两层:网络通不通 + 密码对不对。

Timing plan / 时间分配

0:00 – 0:30
Open report PDF + architecture diagram. One sentence intro.
打开报告 PDF 和架构图。一句话开场白。
0:30 – 3:30
End-to-end demo via ALB DNS: upload PDF, see both strategies complete, run a query.
通过 ALB DNS 完整 demo:上传 PDF、看两种 chunking 完成、输入查询。
3:30 – 7:30
AWS console walk-through: 11 tabs in order.
AWS 控制台资源核对:按顺序过 11 个标签页。
7:30 – 10:00
Q&A. If unsure, say "let me check" — don't guess.
回答问题。不确定就说 "let me check",不要乱猜。
Before demo / Demo 前必做:
(1) Worker EC2 is running, (2) RDS not stopped, (3) ASG desired=1 and web instance Healthy, (4) you can hit ALB DNS from your browser.
(1) Worker EC2 在跑 (2) RDS 没停 (3) ASG desired=1 且 Web 实例 Healthy (4) 你能从浏览器打开 ALB DNS。

Opening line / 开场白

EN: "Good afternoon. I'll show you a 3-tier event-driven PDF RAG comparison application I deployed on AWS. Let me start with the user-facing flow, then walk you through the AWS resources."

中文译: 下午好。我会演示一个我部署在 AWS 上的三层事件驱动 PDF RAG 比较应用。先演示用户侧流程,再带你过 AWS 资源。

2 pts Criterion 1: End-to-End Functionality / 端到端功能

Steps / 步骤

  1. Open http://a2-web-alb-1389107220.ap-southeast-2.elb.amazonaws.com in browser. 浏览器打开 ALB DNS(不是 EC2 IP)。明确告诉 tutor 这是 ALB 域名。
  2. Click Choose File → pick a small PDF prepared on Desktop. 点 Choose File,选桌面上准备好的小 PDF。
  3. Click Upload to S3. 点 Upload to S3。
  4. Wait 3–5 seconds, refresh if needed. Show both fixed_size and paragraph_aware marked completed with different chunk counts. 等 3-5 秒,必要时刷新。展示两种策略都 completed,chunk 数不一样。
  5. Scroll to Query Comparison, type a real query (e.g. "What are the required AWS services?"). Click Compare Retrieval. 滚到 Query Comparison,输入一个查询,点 Compare Retrieval。
  6. Point out two strategies return different top-ranked chunks with different scores. 指出两种策略召回不同的 chunks,分数不同 —— 这就是作业要的比较。

What to say while waiting / 等待时说什么

EN: "While that processes — the upload is asynchronous. The web tier put the file in S3 and inserted a metadata row. S3 fired an event into SNS, SNS fanned it out to two SQS queues, and both worker processes on the worker EC2 are picking up their respective copies right now."

中文译: 上传是异步的。Web 端把文件放到 S3 然后写了一行元数据。S3 触发了 SNS 事件,SNS 扇出到两个 SQS 队列,worker EC2 上的两个进程正在分别处理。

2 pts Criterion 2: AWS Resource Verification / AWS 资源核对

Open each in console, point at the key field. 每个在控制台打开,指给 tutor 看关键字段。

Order / 顺序(提前准备好 11 个浏览器标签)

  1. EC2 → Load Balancers → a2-web-alb 看 Internet-facing、2 个 public subnet、HTTP:80 listener forward 到 a2-web-tg、SG = a2-alb-sg。
  2. EC2 → Target Groups → a2-web-tg target port 5000,状态 Healthy。
  3. EC2 → Auto Scaling Groups → a2-web-asg desired=1, max=2, 两个 private subnet, 关联 a2-web-tg, 用 launch template a2-web-lt。
  4. EC2 → Instances 3 个实例:bastion 有 public IP,worker 没有,ASG 起的 web 也没有。
  5. VPC → Your VPCs → Resource map 展示 4 个子网、IGW、NAT。
  6. VPC → Security Groups → a2-rds-sg 3 条 SG-to-SG 规则在 5432,证明 RDS 不接受公网。
  7. S3 → bucket Block all public access = On,进 uploads/ 看到上传的 PDF。
  8. RDS → Databases → a2-pdf-rag-db Available, Publicly accessible = No, DB subnet group = a2-db-subnet-group。
  9. SNS → Topics → pdf-upload-topic → Subscriptions 2 个 confirmed SQS 订阅。
  10. SQS → Queues 两个 queue 都在;可以点开 access policy 展示 SNS source 条件。
  11. IAM → Roles → a2-ec2-role 4 个 managed policy 都挂上了。

2 pts Criterion 3: Explanation & Understanding / 高频问题与回答

每个问题都有英文标准回答和中文要点。Demo 时用英文,但中文是你的"我到底想说什么"提示。

Q1: Why SNS + SQS instead of just one SQS?
为什么用 SNS + SQS 而不是单个 SQS?
EN: "Two reasons. First, the two chunking strategies need to run independently — with a single queue, both workers would compete for the same message and only one would process each PDF. Second, fan-out keeps the web tier decoupled from the number of strategies. Adding a third strategy is a new SQS plus a new SNS subscription, zero web-tier code changes."
中文要点: 两个原因。一是两种策略要独立处理同一份 PDF,单队列的话两个 worker 会抢同一条消息只有一个能处理。二是 fan-out 让 Web 端跟策略数量解耦,加第三种策略只要加一个 SQS 和一个订阅,Web 代码不用改。
Q2: Why is the web tier in a private subnet if users need to reach it?
用户要访问 Web 应用,为什么 Web 还放在私有子网?
EN: "Users reach the ALB, not the web tier directly. The ALB is internet-facing in the public subnets; the web EC2 is in a private subnet and only accepts inbound on port 5000 from the ALB's security group. So there is no public IP on the application server."
中文要点: 用户连的是 ALB,不是直接连 Web。ALB 在公网子网,Web EC2 在私有子网,只接受 ALB 安全组的 5000 入站。应用服务器本身没有公网 IP。
Q3: Why one NAT Gateway instead of two?
为什么只用一个 NAT Gateway 而不是每个 AZ 一个?
EN: "Cost. A NAT Gateway runs about USD 0.05/hour plus data, and the assignment workload doesn't justify paying for two. The trade-off is that an AZ-2a outage would cut off egress from both private subnets, including the worker. In production I would deploy one per AZ."
中文要点: 成本。NAT 大约 0.05 美元/小时,作业规模不需要付两份。代价是 2a 挂了所有私有子网都出不了网。生产环境会每个 AZ 一个。
Q4: What's in your user-data script?
User data 脚本里写了什么?
EN: "It writes /etc/a2-env with the five required environment variables — region, S3 bucket, two SQS URLs, DATABASE_URL. Then it creates a systemd unit a2-web.service that runs python3.11 app.py as ec2-user, and enables the unit. Python and the application code are already in the AMI a2-app-ami."
中文要点: 写 /etc/a2-env 含 5 个环境变量,再写一个 systemd 单元 a2-web.service 启动 app.py,然后 enable。Python 和代码都在 AMI 里已经装好了。
Q5: How does each worker know which strategy to apply?
两个 worker 怎么知道用哪种 chunking 策略?
EN: "Each strategy runs as its own process bound to its own SQS queue. worker_fixed_size.py only polls fixed-size-queue; worker_paragraph_aware.py only polls paragraph-aware-queue. SNS delivers the same S3 event to both queues, so each process gets its own copy and applies its own chunking function."
中文要点: 每个策略是一个独立进程绑一个 SQS。worker_fixed_size.py 只 poll fixed-size-queue,paragraph 那个只 poll 自己的队列。SNS 把同一个 S3 事件发到两个队列,所以每个进程拿到自己的拷贝。
Q6: Why FullAccess IAM policies? Isn't that insecure?
为什么 IAM 用 FullAccess,不是不安全吗?
EN: "The assignment explicitly allows broader permissions for simplicity with the requirement to acknowledge them, and I documented this in the report. A least-privilege version would scope to specific resource ARNs — PutObject and GetObject on the bucket prefix, ReceiveMessage and DeleteMessage on the queue ARNs, and the connection-string credentials for PostgreSQL."
中文要点: 作业明确允许更宽权限只要在报告里承认,我报告里写了。最小权限版本应该限定具体的资源 ARN —— bucket 前缀上的 PutObject/GetObject,队列 ARN 上的 ReceiveMessage/DeleteMessage,加上数据库连接串。
Q7: How does the bastion let you reach RDS if RDS isn't publicly accessible?
RDS 不对外开放,那 bastion 怎么连?
EN: "RDS is in the private subnets with publicly accessible set to No. The bastion's security group is one of the three sources allowed inbound on the RDS security group on port 5432. So I SSH into the bastion from my home IP, then run psql on the bastion itself. RDS never gets a public IP and is never reachable from the internet."
中文要点: RDS 在私有子网,公网访问关闭。但 RDS 的安全组允许 a2-bastion-sg 在 5432 入站。我从家 SSH 到 bastion,然后在 bastion 上跑 psql。RDS 全程没有公网 IP。
Q8: What happens if the worker crashes mid-PDF?
Worker 处理 PDF 中途挂了会怎样?
EN: "The worker only calls DeleteMessage after the chunks are written. If it crashes before that, the SQS visibility timeout — 300 seconds — expires and the message becomes visible again. Another worker picks it up. It's not idempotent on the database side though, so duplicate chunks could be inserted; that's acceptable for this assignment but I'd add a unique constraint before going to production."
中文要点: Worker 只在 chunks 写完后才 delete 消息。如果先挂了,SQS 5 分钟可见性超时后消息重新可见,另一个 worker 拿走。数据库写入不是幂等的,会插重复行;这对作业够用,生产要加 unique constraint。
Q9: Why t3.small for the worker? Why not Lambda?
Worker 为什么用 t3.small 不用 Lambda?
EN: "t3.small because the worker pulls in scikit-learn and pypdf, and t3.micro's 1 GB RAM is tight for two worker processes. Lambda would actually be a reasonable fit for the chunking — I discuss this in the report — but scikit-learn pushes the deployment package near the Lambda zip limit, so you'd need a container image or a layer. EC2 was simpler for the assignment."
中文要点: t3.small 是因为 scikit-learn + pypdf 跑两个进程,1 GB 内存吃紧。Lambda 对 chunking 也合适,报告里讨论了,但 scikit-learn 太大接近 zip 上限,要用容器镜像或 layer。EC2 对作业更简单。
Q10: If I terminate the web EC2 right now, what happens?
如果我现在直接 terminate Web EC2 会怎样?(tutor 可能要你现场演示)
EN: "The Auto Scaling Group sees desired equals 1, current equals 0, and launches a replacement from the launch template within about a minute. The new instance comes up with the application already installed in the AMI, runs the user-data, and is attached to the target group automatically. I can demonstrate that if you'd like."
中文要点: ASG 看到 desired=1 current=0 会从 launch template 起一个新实例,大概 1 分钟。新实例从 AMI 起来代码已经装好,跑完 user-data 自动注册到 target group。可以现场演示。

Quick facts / 必背速查

Region
ap-southeast-2
VPC CIDR
10.0.0.0/16
Account ID
370613533613
ALB DNS
a2-web-alb-1389107220.ap-southeast-2.elb.amazonaws.com
Web / Worker
t3.small (both)
Bastion
t3.micro · 13.211.90.132
RDS class
db.t4g.micro · PostgreSQL 17.6
S3 bucket
a2-pdf-rag-johnyang-2026
ASG sizing
desired=1, min=1, max=2
SQS visibility
300 s
App port
5000 (Flask 0.0.0.0)
SNS subscriptions
2 SQS, raw delivery

Security group rules / 安全组规则

SGInbound rule中文
a2-alb-sgHTTP:80 from 0.0.0.0/0公网到 ALB
a2-web-sgTCP:5000 from a2-alb-sg只接受 ALB 来的请求
a2-worker-sgSSH:22 from a2-bastion-sg只能从 bastion 登录
a2-bastion-sgSSH:22 from 203.158.41.210/32只允许我家 IP
a2-rds-sg5432 from web-sg / worker-sg / bastion-sg3 个内部源能连数据库

End-to-end flow (matches diagram) / 端到端流程(对应架构图编号)

  1. Web → S3: PutObject 上传 PDF
  2. Web → RDS: 插入 document 元数据
  3. S3 → SNS: 发 ObjectCreated 事件到 topic
  4. SNS → 两个 SQS: fan-out 分发
  5. 两个 worker: 长轮询 ReceiveMessage
  6. Workers → S3: GetObject 下载 PDF
  7. Workers → RDS: 写 chunks 和 processing run
  8. RDS → Web: 用户刷新时读结果

Pitfalls / 避坑提示

Pre-demo restart / 提前 15 分钟启动资源

如果你为了省钱 stop 了资源,demo 前要重启。RDS 启动最慢(5-10 分钟),先做。

  1. EC2 → Instances → start a2-worker and a2-bastion. 启动 worker 和 bastion(没挂 Elastic IP 的话 IP 会变,记下新 IP)。
  2. RDS → start a2-pdf-rag-db. Takes 5–10 min. 启动 RDS,最慢,先做。
  3. ASG → set desired=1 if it was at 0. New web instance launches. ASG 改 desired=1,新 Web 实例自动启。
  4. Wait until Target Group shows Healthy. 等 Target Group 显示 Healthy。
  5. Open ALB DNS in browser, confirm upload page loads. 浏览器打开 ALB DNS 确认页面能加载。
  6. SSH into worker, restart tmux workers: SSH 进 worker,重启两个 tmux 进程:
    tmux kill-server
    tmux new -d -s fixed "source ~/a2-env.sh && cd ~/aws && python3.11 worker_fixed_size.py 2>&1 | tee ~/worker_fixed.log"
    tmux new -d -s paragraph "source ~/a2-env.sh && cd ~/aws && python3.11 worker_paragraph_aware.py 2>&1 | tee ~/worker_paragraph.log"
  7. Upload a test PDF through ALB before the tutor joins. Tutor 加入前先上传一个测试 PDF 确认整条链路通。