- 文档
- 教程
- DevOps
- 运维
【免费下载链接】devops-exercises
Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions
本篇文章基于 devops-exercises 仓库中的 AWS 故障排查练习(No Application)展开,深入讲解在 EC2 上部署应用后,客户端出现 "time out"(连接超时)与 "connection refused"(连接被拒绝)两类典型网络错误的成因、排查思路与修复方法。读完本文,你将掌握一套从安全组、实例存活、OS 防火墙到应用监听的逐层诊断流程,并能直接使用文中给出的 AWS CLI 命令与配置示例复现和解决实际问题。
练习背景:这道题在考什么
该练习位于仓库 topics/aws/exercises/no_application/exercise.md,被收录在 topics/aws/README.md 的 "Misc" 练习列表中,标注主题为Troubleshooting(故障排查)。
练习要求读者解释以下两类问题的可能原因:
- 尝试访问运行在 EC2 实例上的应用时,出现"time out"(连接超时)
- 出现"connection refused"(连接被拒绝)错误
这是一个典型的"症状→根因"分析型题目,考察的是对 EC2 网络访问链路各环节的理解:从客户端发起请求到应用响应,中间要经过公网路由、安全组、实例操作系统网络栈、应用进程监听等多个关卡,任何一环出错都会表现为上述两类错误之一。仓库给出的标准解答位于 topics/aws/exercises/no_application/solution.md,本文将以此为骨架,结合仓库内其他相关练习与源码级配置,展开完整讲解。
先理解 TCP 层面:超时与被拒绝的本质区别
在讨论具体原因之前,先明确两个错误在 TCP 协议层面的根本区别,这是快速定位问题的关键:
- time out(超时):客户端发送的 TCP SYN 包到达了目的地,但始终没有收到任何回应(SYN-ACK 或 RST)。数据包可能在传输途中被丢弃,也可能被目的端的防火墙静默丢弃(drop)。客户端的连接请求在等待超时后失败。
- connection refused(连接被拒绝):客户端发出的 SYN 包得到了明确回应——通常是 RST(Reset)包。这说明网络链路是通的,有设备主动拒绝了连接请求。最常见的原因是目标端口上没有进程在监听,或防火墙以 reject(发送 RST)方式拒绝了该端口。
一句话概括:timeout 是"无声无息",connection refused 是"有话直说"。前者意味着网络路径或防火墙在丢包,后者意味着路径通畅但目标端口不接受连接。这一区分直接对应下文的两类排查清单。
原因一:time out(连接超时)
根据仓库解答,time out 可能由以下三种原因导致:
1. 安全组(Security Group)不允许入站访问
安全组是 AWS 为 EC2 实例提供的虚拟防火墙,位于实例网络层之前。默认情况下,安全组会阻止所有入站流量,只允许所有出站流量(见 topics/aws/README.md 中 "True or False? By default, when using security groups, all inbound traffic to an EC2 instance is blocked and all outbound traffic is allowed" 的解答)。
如果你的应用监听在 80 端口,但安全组没有开放 TCP 80 的入站规则,那么客户端发来的 SYN 包会被 AWS 网络层直接丢弃,客户端表现为time out。这是 AWS 场景下最常见、也是最该优先检查的原因——事实上,仓库的 AWS 面试题库中就有对应一问:"You get time out when trying reach your application which runs on an EC2 instance. Specify one reason why it would possibly happen",标准答案是"安全组配置不正确"。
验证方法(控制台):进入 EC2 服务 → 左侧菜单 "Network & Security" → "Security Groups",查看实例绑定的安全组的入站规则。需要保证存在类似这样的规则:Type 为 HTTP、端口范围为 80、Source 为0.0.0.0/0(允许任意来源)。
验证方法(CLI):使用aws ec2 describe-security-groups列出当前区域的安全组及入站规则,确认目标端口是否开放。
修复方法(CLI):仓库 topics/aws/exercises/security_groups/solution.md 给出了添加入站规则的标准命令:
aws ec2 authorize-security-group-ingress \ --group-name someHTTPSecurityGroup --protocol tcp \ --port 80 \ --cidr 0.0.0.0/0注意安全组的特性(同样来自 topics/aws/README.md 题库):
- 安全组只包含 allow(允许)规则,没有 deny 规则;
- 一个安全组可以挂载到多个实例;
- 安全组绑定在特定区域和 VPC,切换区域时需要新建。
实验佐证:在仓库的 Security Groups 练习 中,操作步骤就是"启动一台带 web 应用的 EC2 实例 → 移除安全组中的 HTTP 入站规则 → 尝试访问应用",得到的结果是"No. There is a time out because we removed the rule allowing HTTP traffic";随后加回规则(Type: HTTP,Port range: 80,Source:0.0.0.0/0),访问恢复正常。这个实验完整复现了"安全组导致 time out"这一根因。
2. 主机不存在(No host)
解答中特别提醒(原文原话:"yes, I know. Not the first thing to check and yet...",即"我知道这不是第一个要检查的,但确实有可能"):目标主机根本不存在,请求到达不了任何实例。
这听起来过于基础,但在真实环境中经常被忽略,常见情形包括:
- IP 地址错误:你访问的 IP 并非该实例的公网 IP,例如实例已重启且未绑定弹性 IP,公网 IP 已变化(旧地址不再属于任何主机);
- 实例已停止或终止:目标实例处于
stopped/terminated状态,没有实例响应请求; - DNS 解析指向错误目标:使用域名访问时,记录指向的地址已不存在或指向了错误的资源;
- 网络路径本身不可达:如 VPC 路由配置错误、实例位于私有子网且没有 NAT/负载均衡器等出口,外部流量根本无法路由到实例。
验证方法:
# 先确认实例状态与公网 IP aws ec2 describe-instances --instance-ids i-xxxxxxxx # 再测试网络可达性(注意:ping 测试 ICMP 需安全组放行 ICMP 协议) ping <instance-public-ip>如果实例存在且 IP 正确,但 ping 不通(且安全组已放行 ICMP),则问题可能出在安全组或 OS 防火墙层面,见下一小节。
3. 操作系统防火墙阻止了流量
即使 AWS 安全组放行了端口,实例操作系统内部的防火墙(如 Linux 的firewalld或iptables)仍可能在第二层把关。如果 OS 防火墙以DROP(丢弃)方式处理入站数据包,客户端同样表现为 time out——这与安全组丢包的表现完全一致,区别只在于拦截发生的层级。
验证方法:登录实例(通过 EC2 Instance Connect 或 SSH),检查防火墙规则:
# RHEL/CentOS/Amazon Linux(基于 firewalld) sudo firewall-cmd --list-all # 通用 iptables 查看 sudo iptables -L -n确认目标端口(如 80)是否有 DROP 或 REJECT 规则,必要时放行:
sudo firewall-cmd --permanent --add-port=80/tcp sudo firewall-cmd --reloadtime out 排查小结
出现 time out 时,按"外→内"顺序排查:路由/DNS(主机是否存在)→ AWS 安全组入站规则 → 实例 OS 防火墙 → 实例存活状态。其中安全组是最常见的根因,且最容易通过控制台或describe-security-groups快速验证。
原因二:connection refused(连接被拒绝)
根据仓库解答,connection refused 可能由以下两种原因导致:
1. 应用未正常启动或未监听目标端口
如果客户端收到的不是超时而是明确的拒绝,说明网络路径是通的(安全组、防火墙都已放行),但目标端口上没有进程在监听。典型情形:
- 应用进程启动失败:如启动脚本报错、依赖服务未就绪、端口被占用导致启动异常;
- 应用未监听预期端口:例如配置错误导致应用监听在 8080 而客户端访问 80,或应用只绑定了
127.0.0.1(回环地址)而未绑定0.0.0.0或实例私有 IP,导致外部请求无法到达; - 应用服务未设置开机自启:实例重启后应用没有随之启动。
验证方法:登录实例,检查进程与端口监听状态:
# 确认进程在运行 ps aux | grep <your-app> # 确认端口监听在正确的地址上(0.0.0.0 表示所有接口) sudo ss -tlnp | grep :80输出中如果看不到 80 端口对应的 LISTEN 记录,或监听的地址是127.0.0.1:80而非0.0.0.0:80,即可确认根因。此时需要修复应用启动配置,并确保服务在开机时自启(例如systemctl enable <service>)。
2. 防火墙以 reject(拒绝)方式响应,而非 drop(丢弃)
这是理解两类错误差异的关键场景:防火墙对目标端口采取 REJECT 策略时,会主动回送 RST 包,客户端立即收到 "connection refused";而采取 DROP 策略时则静默丢弃,客户端表现为 time out。
在 AWS 语境下还有一层需要注意:AWS 安全组本身只会丢弃(drop)不符合规则的流量,因此由安全组导致的失败表现为 time out。而"connection refused"通常来自实例 OS 防火墙(如 iptables 的 REJECT 规则)或应用层的主动拒绝。这一区别可以帮助你快速缩小排查范围:
- 表现为time out→ 重点查 AWS 安全组、OS 防火墙 DROP 规则、主机可达性;
- 表现为connection refused→ 重点查应用是否监听、OS 防火墙 REJECT 规则、目标端口是否被关闭。
connection refused 排查小结
出现 connection refused 时,优先登录实例检查:应用进程是否存在 → 端口是否处于 LISTEN 状态 → 监听地址是否对外可达 → OS 防火墙是否存在 REJECT 规则。由于网络路径已被证明通畅,这类问题绝大多数落在应用本身。
配套实操:在仓库中复现完整的排查链路
为了让上述理论可落地,仓库提供了多个相互衔接的练习,共同构成一条完整的"部署→故障→修复"链路:
步骤 1:启动一台可访问的 Web 实例
Launch EC2 Web Instance 练习 要求启动一台 Amazon Linux 2 实例(如t2.micro,1 vCPU / 1 GiB),并在启动时通过EC2 User Data安装并启动 httpd 服务:
yum update -y yum install -y httpd systemctl start httpd systemctl enable httpd echo "<h1>I made it! This is is awesome!</h1>" > /var/www/html/index.html该练习的 解决方案 还给出了等价的基础设施即代码(IaC)写法——Terraform 配置,其中包含aws_security_group资源,明确开放了 80 端口入站:
resource "aws_security_group" "web_sg" { name = "web_sg" description = "Security group for web server" ingress { from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } }注意:这里的安全组规则(0.0.0.0/0、TCP 80)正是上一节"安全组未放行导致 time out"的对照组——规则存在时应用可访问,移除后立即超时。
步骤 2:通过安全组实验制造并观察 time out
Security Groups 练习 的核心目标就是验证"安全组是 time out 的根因":
- 列出账户当前区域的安全组;
- 移除 HTTP 入站规则;
- 访问应用,观察结果——按 解决方案 所述,此时访问失败,表现为time out;
- 加回规则(Type: HTTP,Port range: 80,Source:
0.0.0.0/0); - 再次访问,应用恢复可访问。
对应的 CLI 操作(同样是 solution.md 中的标准命令):
移除规则:
aws ec2 revoke-security-group-ingress \ --group-name someHTTPSecurityGroup --protocol tcp \ --port 80 \ --cidr 0.0.0.0/0加回规则:
aws ec2 authorize-security-group-ingress \ --group-name someHTTPSecurityGroup --protocol tcp \ --port 80 \ --cidr 0.0.0.0/0步骤 3:用健康检查与故障转移验证"安全组→不可达"的连锁反应
安全组未放行不仅影响手动访问,还会触发依赖探测的自动化机制失效,仓库中有两个练习直接印证了这一点:
- Route 53 Health Checks(solution.md):为每个实例创建健康检查后,编辑安全组并移除 HTTP 规则,健康检查状态会在几秒内变为 "unhealthy"。这证明 AWS 健康检查也是通过真实 HTTP 请求探测的,安全组丢包会直接反映为探测失败。
- Route 53 Failover(solution.md):移除实例安全组的 HTTP 规则后,配合健康检查的故障转移记录会自动把流量切到另一台实例——这是一个"故障由安全组引发、由 DNS 层自动修复"的完整实战场景。
系统性诊断流程:一张从外到内的检查清单
综合原文档解答与仓库配套练习,可以把 EC2 应用无法访问的排查整理为如下递进式流程:
| 层级 | 检查项 | 失败表现 | 主要验证手段 |
|---|---|---|---|
| 1. 目标主机 | 实例是否运行、IP/DNS 是否正确 | time out | aws ec2 describe-instances、ping |
| 2. AWS 安全组 | 入站规则是否放行目标端口 | time out(静默丢弃) | 控制台查看规则、describe-security-groups |
| 3. OS 防火墙 | 是否有 DROP / REJECT 规则 | DROP→time out;REJECT→connection refused | firewall-cmd --list-all、iptables -L -n |
| 4. 应用进程 | 进程是否存在、端口是否 LISTEN | connection refused | ps aux、ss -tlnp |
| 5. 监听地址 | 是否绑定0.0.0.0而非仅回环地址 | connection refused | ss -tlnp观察 Local Address |
两条关键判定法则贯穿始终:
- time out = 数据包被静默丢弃,问题大概率出在路径可达性、安全组或 DROP 型防火墙;
- connection refused = 数据包被主动拒绝,问题大概率出在应用未监听或 REJECT 型防火墙。
总结
"time out"与"connection refused"是 EC2 应用运维中最常见的一对"姊妹错误",它们的区分本身就是一次精准的故障定位。本练习给出的答案是简洁的,但其背后的排查逻辑覆盖了从 AWS 网络层(安全组)到操作系统层(防火墙、进程、端口监听)的完整链路。本文结合仓库中的 Security Groups、Launch EC2 Web Instance、Health Checks 与 Route 53 Failover 等配套练习,给出了可复现的实验步骤、可执行的 AWS CLI 命令与 Terraform 配置,帮助你在真实环境中快速落地这套排查方法论。下次再看到浏览器里的超时图标,不妨先问自己一句:包是被丢了,还是被拒了?
- 文档
- 教程
- DevOps
- 运维
【免费下载链接】devops-exercises
Linux, Jenkins, AWS, SRE, Prometheus, Docker, Python, Ansible, Git, Kubernetes, Terraform, OpenStack, SQL, NoSQL, Azure, GCP, DNS, Elastic, Network, Virtualization. DevOps Interview Questions
相关推荐
devops-exercises AWS 实战:EC2 应用不可达时 Timeout 与 Connection Refused 的故障排查指南
devops exercises AWS 实战:EC2 应用不可达时 Timeout 与 Connection Refused 的故障排查指南 在 AWS 上部
文档教程DevOps运维AWS EC2 实战:使用 User Data 与 Terraform 启动一个 Web 实例(devops-exercises 演练)
AWS EC2 实战:使用 User Data 与 Terraform 启动一个 Web 实例(devops exercises 演练) 本文基于开源仓库 de
文档教程DevOps运维Marlin 串口通信配置指南:USB 连接、波特率与 Meatpack 压缩一次讲清
Marlin 串口通信配置指南:USB 连接、波特率与 Meatpack 压缩一次讲清 "Error:Unknown G code"、打印到一半掉线重连、切片软
智能硬件嵌入式固件物联网
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考