简介:这份PDF面向准备技术岗春季招聘的运维工程师求职者,尤其适合具备一定工作经验与技术基础的候选人,用于系统梳理高频考点、查漏补缺并提升面试应对能力。内容按Linux系统管理、网络与安全、自动化与监控、容器与云原生、故障排查与开放问题五大模块组织,每道题均附参考答案,涉及日志清理命令、Shell服务监控脚本、TCP三次握手异常排查、SSH防暴力破解、Ansible核心机制、CPU飙升定位、Docker与虚拟机差异、Kubernetes滚动更新与回滚、502错误分层排查等实战场景,并给出动手实验与模拟面试等复习建议。资源包共1个PDF文件,约867KB,轻量便于随时查阅。目前已有74人学习。读者可借助其中的命令示例、脚本模板与排错思路,对照参考答案检验自身掌握程度,并针对开放性问题先独立思考再比对,从而强化独立分析与解决实际问题的能力。
1. 春招运维岗面试题拆解:这份 PDF 到底值不值得刷
春招投运维岗的人,简历上写“熟悉 Linux、Docker、K8s”的十有八九,但真到面试官让你手写一条清理日志的命令、说清 TCP 三次握手丢包怎么排查,能答利索的没几个。这份《技术岗春招 - 运维工程师高频面试题(附参考答案)》PDF 就是冲着这个落差来的——它把 Linux 系统管理、TCP/IP 协议栈、Docker 与虚拟化、Kubernetes 运维场景、自动化工具使用、监控系统设计、故障排查与开放问题这几块高频考点,按题目加参考答案的形式整理成了一份可以直接拿来练的清单。适合谁?准备春招的运维求职者、想从传统运维往云原生方向转的工程师,以及工作两三年但基础概念开始模糊、需要快速回炉的人。它不是教程,是一份带答案的模拟卷,价值在于帮你把“好像会”变成“能写出来、能讲清楚”。
2. Linux 系统管理与 Shell 脚本:从命令到脚本的落地写法
2.1 日志清理命令的参数拆解与安全边界
PDF 里第一道题就很典型:如何快速定位并删除 7 天前的日志文件。参考答案给的是find /var/log/app -name "*.log" -mtime +7 -exec rm -f {} \;。这条命令看着简单,但面试官真正想听的是你对每个参数的理解,以及你有没有安全意识。
# 先干跑一遍,确认要删的文件列表,别上来就 rm find /var/log/app -name "*.log" -mtime +7 -print # 确认无误后再执行删除 find /var/log/app -name "*.log" -mtime +7 -exec rm -f {} \; # 更稳妥的写法:用 -delete,但注意它和 -exec 的差异 find /var/log/app -name "*.log" -mtime +7 -delete逻辑说明:-name "*.log"限定只匹配日志后缀,避免误伤同目录下的配置文件;-mtime +7表示修改时间在 7 天以前,注意是“大于 7 天”不是“等于 7 天”;-exec rm -f {} \;对每个匹配结果执行删除,{}是占位符,\;是命令结束符。参数上最容易翻车的是-mtime的计数方式——它是按 24 小时为单位的整数天,如果你想要“7 天前到今天凌晨”这种精确边界,得用-mmin按分钟算。
关于延伸问题“是否建议用-delete替代-exec rm”,我的经验是:-delete更高效,因为它不需要为每个文件 fork 一个进程,但它有个坑——-delete会隐式开启-depth,也就是先处理子目录再处理父目录,如果你在删除条件里混了目录匹配,行为可能和预期不一致。另外-delete不支持-exec那种“先确认再删”的交互,所以生产环境我一般会先-print干跑,确认列表没问题再换成-delete或-exec rm。避免误删的关键不是选哪个删除方式,而是路径写死、条件收紧、先看后删。
2.2 服务监控脚本的返回值处理与告警链路
第二道 Shell 题是写一个检查 Nginx 是否运行、未运行则启动并记录日志、启动失败发邮件告警的脚本。PDF 给的参考答案结构清晰,但有几个细节值得展开。
#!/bin/bash SERVICE="nginx" LOG="/var/log/service_monitor.log" EMAIL="admin@example.com" # systemctl is-active --quiet 只返回状态码,不输出内容 if systemctl is-active --quiet $SERVICE; then echo "$(date): $SERVICE is running." >> $LOG else systemctl start $SERVICE # $? 取上一条命令的退出码,0 表示成功 if [ $? -ne 0 ]; then echo "$(date): Failed to start $SERVICE." >> $LOG echo "Alert: $SERVICE is down!" | mail -s "Service Failure" $EMAIL else echo "$(date): Restarted $SERVICE successfully." >> $LOG fi fi逻辑说明:systemctl is-active --quiet是判断服务状态最干净的方式,它只返回退出码,不往标准输出打东西,适合在脚本里做条件判断。$?紧跟在systemctl start之后取返回值,这里有个常见坑——如果你在systemctl start和if [ $? -ne 0 ]之间插了任何其他命令,$?就被覆盖了。参数上,mail -s指定主题,邮件正文通过管道传入,但很多最小化安装的服务器根本没有 mail 命令,常见做法是换成curl调邮件 API 或者用sendmail。
考察点里提到的“日志记录与邮件通知”,实际落地时我一般会把日志格式统一成时间戳 + 服务名 + 状态,方便后续用awk或grep做统计。另外这个脚本如果放进 crontab,建议加个锁文件防止上一次还没跑完下一次就起来了,flock是常用方案。脚本本身不难,面试官看的是你有没有考虑幂等性、告警收敛和日志轮转——这三个点答上去,基本就稳了。
3. 网络与安全:TCP 排查思路和 SSH 防护的实操细节
3.1 三次握手异常的分层排查方法
TCP 三次握手客户端发了 SYN 但收不到 SYN-ACK,PDF 列了三个可能原因:服务端未监听端口、中间防火墙拦截、网络拥塞或路由问题。排查步骤给了netstat、tcpdump、traceroute三个工具。这套思路是对的,但面试时如果你能按分层顺序讲清楚先查什么后查什么,会比罗列工具更加分。
# 服务端:确认端口是否在监听,注意 -p 需要 root 权限 netstat -tulnp | grep <端口> # 客户端:抓包看 SYN 是否发出、有没有收到回应 tcpdump -i eth0 port <端口> -nn # 网络层:看路由路径在哪一跳断了或延迟飙升 traceroute <目标IP> # 或者用 mtr 持续观察 mtr --report <目标IP>逻辑说明:netstat -tulnp里-t是 TCP,-u是 UDP,-l只看监听状态,-n不做 DNS 反解,-p显示进程。如果服务端根本没监听,客户端发再多 SYN 也是石沉大海。tcpdump抓包时加-nn避免解析主机名和端口名,输出更干净。traceroute默认走 UDP,有些网络会过滤,可以加-T走 TCP 或者-I走 ICMP。排查顺序我一般是从服务端往客户端推:先确认服务在不在、端口通不通,再抓包看握手到哪一步断了,最后看路由和防火墙规则。
延伸问题“四次挥手为什么等 2MSL”也是高频考点。简单说,主动关闭方最后发的 ACK 如果丢了,被动关闭方会重发 FIN,主动方需要保持一段时间能收到并重发 ACK;2MSL 就是“一个来回”的最大时间,确保老连接的残留报文在网络中消失,不会干扰新连接。这个点面试官想听的是你对 TIME_WAIT 状态的理解,以及为什么服务器上大量 TIME_WAIT 不一定是坏事。
3.2 SSH 防暴力破解的配置组合拳
PDF 列了五种方法:改端口、禁 root 登录、密钥认证、Fail2ban、限制 IP。这五条单独用都有局限,组合起来才有效。我一般按这个顺序落地:
# /etc/ssh/sshd_config 关键配置 Port 2222 # 改默认端口,减少扫描面 PermitRootLogin no # 禁止 root 直接登录 PasswordAuthentication no # 关闭密码认证,只走密钥 AllowUsers deploy@192.168.1.0/24 # 限制来源 IP 段 # 改完重启 sshd,注意别把自己关在外面 systemctl restart sshd逻辑说明:改端口和禁 root 是降低被扫概率,密钥认证是提高认证强度,AllowUsers是白名单兜底。Fail2ban 是动态封禁,它读/var/log/secure或/var/log/auth.log,匹配到多次失败就调 iptables 封 IP。配置 Fail2ban 时注意bantime和findtime的配合——比如findtime=600、maxretry=5、bantime=3600,意思是 10 分钟内失败 5 次就封 1 小时。
这里有个血泪经验:改 SSH 配置之前一定先开一个已连接的会话别关,改完用新会话测试能登进去再关旧会话。我见过不止一次改完PasswordAuthentication no结果密钥没配好,直接把自己锁在服务器外面的情况。另外AllowUsers写 IP 段时注意格式,写错了 sshd 可能直接起不来,sshd -t可以先做配置语法检查。
4. 自动化与监控:Ansible 机制和 CPU 飙高的定位链路
4.1 Ansible 与 Shell 脚本的本质差异
PDF 里问 Ansible 和 Shell 脚本部署的区别,参考答案提了三点:声明式 vs 命令式、幂等性、批量主机管理。这三点都对,但面试时如果能结合一个具体场景讲,说服力会强很多。
假设你要在 10 台机器上确保 Nginx 安装并运行。Shell 脚本的写法是yum install -y nginx && systemctl start nginx,跑第二遍会报“已安装”但退出码可能非零,你得自己加判断。Ansible 的写法是:
# playbook 片段 - hosts: webservers tasks: - name: ensure nginx installed yum: name: nginx state: present - name: ensure nginx running service: name: nginx state: started enabled: yes逻辑说明:state: present表示“只要装了就行”,state: started表示“只要在跑就行”,Ansible 会先检查当前状态,已经满足就不做任何操作,这就是幂等性。hosts: webservers对应 inventory 文件里的主机组。Ansible 的核心机制是“SSH + 模块 + inventory”,不需要在被控端装 agent,模块推过去执行完就删,这也是它比 Puppet/Chef 轻量的原因。
参数上,enabled: yes是设置开机自启,这个在 Shell 里对应systemctl enable nginx,但 Ansible 会先检查是否已经 enable,避免重复操作。实际用的时候,inventory 文件可以按环境分组,比如[prod]、[staging],playbook 里用hosts: prod就能只跑生产环境。Ansible 的坑在于它的“幂等”是靠模块实现的,如果你用command或shell模块,幂等性就没了,所以能用专用模块就别用 command。
4.2 Java 应用 CPU 飙高的五步定位法
PDF 给了一个很实用的排查链路:top找进程 →ps -mp找线程 →printf转十六进制 →jstack抓栈 → 分析代码热点。这套流程在面试里能完整讲出来,基本能证明你有真实排查经验。
# 第一步:找到 CPU 最高的 Java 进程 PID top -c # 第二步:查看该进程下各线程的 CPU 占用,拿到 TID ps -mp <PID> -o THREAD,tid,time # 第三步:把 TID 转成十六进制,jstack 里用的是十六进制 printf "%x\n" <TID> # 第四步:抓取线程栈,匹配 nid jstack <PID> | grep -A 20 <nid> # 第五步:结合代码分析是死循环、频繁 GC 还是锁竞争逻辑说明:ps -mp的-m显示线程,-p指定 PID,-o THREAD,tid,time自定义输出列。printf "%x\n"把十进制的 TID 转成十六进制,因为jstack输出里的nid是十六进制。grep -A 20是显示匹配行及其后 20 行,方便看完整栈信息。
这里有个容易翻车的点:top里按H可以切换到线程视图,但很多人不知道,还在用ps一层层查。另外jstack需要和 Java 进程同一用户执行,否则会报“Unable to open socket file”。如果jstack卡住没输出,可能是进程处于 D 状态或者 JVM 参数没开-XX:+HeapDumpOnOutOfMemoryError之类的诊断选项。延伸问题问 Prometheus + Grafana 怎么做自动化告警,常见做法是用jmx_exporter暴露 JVM 指标,Prometheus 抓取后配rate(jvm_threads_cpu_time[5m])之类的规则,Alertmanager 负责发通知。
5. 容器与云原生:Docker 隔离边界和 K8s 滚动更新
5.1 容器与虚拟机的隔离差异及生产注意点
PDF 里 Docker 与虚拟化的题,参考答案说容器共享宿主机内核、轻量、启动快,VM 独立内核、资源占用高。这个对比没错,但面试官如果追问“容器隔离性弱在哪里”,你得能说出具体点。
容器共享内核意味着/proc、/sys、/dev这些内核暴露的接口没有完全隔离,容器里的进程能看到宿主机的一些信息。比如容器里cat /proc/cpuinfo看到的是宿主机的 CPU 信息,dmesg可能读到宿主机内核日志。另外容器默认的seccomp和capabilities虽然做了限制,但如果你用--privileged跑容器,基本等于把宿主机内核暴露给容器了。
# 查看容器默认的 capabilities docker run --rm alpine capsh --print # 查看容器内的 /proc 是否和宿主机共享 docker run --rm alpine cat /proc/version逻辑说明:capsh --print列出当前进程的 capabilities,默认 Docker 容器会丢掉CAP_SYS_ADMIN等危险权限。/proc/version显示的是宿主机内核版本,因为容器没有独立内核。生产环境用容器时,我一般会加--read-only把根文件系统挂成只读,用--tmpfs挂临时目录,再加--security-opt no-new-privileges防止提权。这些参数在面试里能说出来,比只背“容器轻量”要加分得多。
5.2 K8s 滚动更新与回滚的命令细节
PDF 里 K8s 的题是“如何不中断服务更新 Deployment 镜像版本”,答案给了kubectl set image和kubectl rollout undo。命令本身简单,但滚动更新的参数和回滚的边界条件值得展开。
# 更新镜像,--record 记录这次变更,方便回滚时看历史 kubectl set image deployment/myapp mycontainer=myimage:v2 --record # 查看滚动更新状态 kubectl rollout status deployment/myapp # 回滚到上一个版本 kubectl rollout undo deployment/myapp # 回滚到指定版本 kubectl rollout undo deployment/myapp --to-revision=3 # 查看历史版本 kubectl rollout history deployment/myapp逻辑说明:set image的格式是deployment/<名称> <容器名>=<新镜像>,容器名必须和 Deployment YAML 里定义的一致,写错了会报“container not found”。--record在新版本 K8s 里已经废弃,改用kubernetes.io/change-cause注解,但很多面试题还在用旧写法,答的时候可以提一句。
滚动更新的默认策略是RollingUpdate,关键参数是maxSurge和maxUnavailable。maxSurge控制最多超出期望副本数的 Pod 数量,默认 25%;maxUnavailable控制最多不可用的 Pod 数量,默认 25%。如果服务对可用性要求极高,可以把maxUnavailable设成 0,maxSurge设成 1,这样先起新 Pod 再停旧 Pod,但滚动速度会慢。回滚的坑在于rollout undo只能回滚 Deployment 的 Pod 模板,如果你改了 Service 或 ConfigMap,回滚 Deployment 不会把这些一起回滚,得单独处理。
6. 故障排查与开放问题:502 分层排查和高可用架构的答题框架
6.1 502 错误的分层排查清单
PDF 里 502 的排查思路分了五层:客户端、服务端、后端、中间件、日志。这个分层框架很好用,面试时按这个顺序讲,逻辑清晰不容易乱。
# 服务端:确认 Nginx 是否在跑,配置有没有语法错误 systemctl status nginx nginx -t # 后端:确认应用端口是否监听,进程是否存活 ss -tlnp | grep <应用端口> ps aux | grep <应用名> # 中间件:Redis 和数据库连接是否正常 redis-cli ping mysqladmin -u root -p status # 日志:看 Nginx error.log 和应用日志的具体报错 tail -f /var/log/nginx/error.log tail -f /var/log/app/app.log逻辑说明:nginx -t检查配置文件语法,改完配置先跑这个再 reload。ss -tlnp比netstat更快,-tTCP,-l监听,-n不解析,-p显示进程。redis-cli ping返回 PONG 说明 Redis 活着。日志是排查 502 最关键的一步,Nginx 的error.log会告诉你到底是“connection refused”还是“upstream timed out”,前者是后端没起来,后者是后端响应太慢。
常见坑:502 不一定是后端挂了,也可能是 Nginx 的proxy_read_timeout设太短,后端处理时间长于这个值就被 Nginx 断掉返回 502。另外如果后端是 K8s 里的 Pod,Pod 重启期间 Endpoints 还没更新,Nginx 可能把请求转发到已经挂掉的 Pod 上,这种要看kubectl get endpoints确认。
6.2 高可用电商架构的答题要素
开放性问题“设计高可用电商系统运维架构”,PDF 列了负载均衡、冗余设计、自动扩缩容、监控告警、灾备方案五个要素。面试时如果只背这五个词,容易显得空。我的建议是每个要素配一个具体技术选型和一句为什么。
| 要素 | 技术选型 | 关键理由 |
|---|---|---|
| 负载均衡 | Nginx/HAProxy + Keepalived | Keepalived 做 VIP 漂移,避免单点 |
| 冗余设计 | 多可用区部署、数据库主从 | 单可用区故障不影响整体 |
| 自动扩缩容 | K8s HPA | 按 CPU/内存指标自动调副本数 |
| 监控告警 | Prometheus + Alertmanager | 指标采集和告警分离,灵活配规则 |
| 灾备方案 | 异地多活、定期备份验证 | 备份不验证等于没备份 |
逻辑说明:这张表在面试时可以直接画在白板上,每个要素讲一句选型理由。比如 Keepalived 的 VIP 漂移是通过 VRRP 协议实现的,主节点挂了备节点接管 VIP,对上层透明。HPA 的触发指标可以自定义,不一定只看 CPU,QPS 或队列长度也可以。灾备的“定期备份验证”是很多人忽略的点——备份文件能不能恢复、恢复要多久,这些得实际演练过才算数。
7. 把 PDF 当模拟卷用:我的刷题节奏和验证方法
这份 PDF 最大的价值不是“读”,而是“写”和“讲”。我自己的用法是:第一遍按模块过,每道题先不看答案,自己在纸上写命令或画排查链路,写完再对照参考答案,差在哪标出来。第二遍只刷标出来的题,重点看参数细节和边界条件。第三遍找人模拟面试,让对方随机抽题,我口述排查思路,练的是表达的逻辑性而不是背诵。
具体到验证方法,Linux 命令类的题一定要在虚拟机里跑一遍。比如find -mtime +7到底删哪些文件,你建几个不同时间戳的文件试一下就清楚了。Shell 脚本类的题,写完要跑shellcheck看有没有语法和常见错误,然后实际执行看日志输出对不对。K8s 和 Docker 的题,本地起个 minikube 或 kind 集群,把kubectl set image和rollout undo实际跑一遍,比看十遍答案都管用。
网络类的题比如 TCP 三次握手排查,可以用tcpdump在本地抓包,然后人为制造“服务端没监听”的场景,看抓包结果长什么样。SSH 防护的配置,在虚拟机里改完sshd_config用sshd -t验证语法,再开新会话测试登录,确认没问题再固化到配置管理里。
开放性问题比如高可用架构设计,我的习惯是画图。把负载均衡层、应用层、数据层、监控层画出来,每层标注技术选型和单点风险,然后问自己“这一层挂了会怎样”。画完再对照 PDF 的参考答案,看有没有漏掉灾备或自动扩缩容。这种题没有标准答案,面试官看的是你有没有体系化的思考框架,而不是背了多少技术名词。
从那以后我每次准备面试,都会把 PDF 里的题按“能写出来”“能讲清楚”“能画出图”三个标准过一遍,任何一个标准没过就回去补。希望帮到你。
本文还有配套的精品资源,点击获取