ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

生产环境从零搭建与维护:系统工程师的完整实战指南

生产环境从零搭建与维护:系统工程师的完整实战指南 看到“哔哩哔哩2019秋招技术岗系统工程师笔试题”这个题目我第一反应不是去回忆当年的选择题考了什么而是想聊聊这套题背后真正想筛选的人。系统工程师这个岗位在视频网站这类业务形态下说白了就是既要懂Linux、网络、数据库又要懂中间件、监控、自动化还得扛得住突发流量和故障。笔试题里那些看似零散的知识点最后都指向同一个核心能力给你一批机器你能不能从零把一个生产系统搭起来并且长期稳定地维护下去。这恰好对应了最近很热的那个话题——“作为一个运维工程师如何在生产环境从零搭建一个系统并做好后续维护”。我做了这么多年系统工程师参加过校招也当过面试官可以负责任地说这题就是那套笔试题的“隐藏大题”。这篇文章我就借这个机会把这道大题从头到尾拆一遍覆盖容量规划、基础环境初始化、中间件部署、监控告警、日常维护和故障排查希望能给准备面试的朋友以及刚入行的运维新人一些真正能落地的参考。1. 这道笔试题的真考点不是背知识点而是考察系统化工程能力1.1 表面题面与真实能力模型的差距很多人备考系统工程师笔试时习惯去刷Linux命令题、网络协议题、数据库SQL题觉得把知识点背熟就能过。但如果你真看过BAT、B站这类互联网公司的系统工程师笔试题会发现题目虽然以选择题、简答题的形式出现但考察的从来不是孤立的知识点记忆而是你能不能把这些知识串成一条完整的链路。举几个典型的例子。笔试里考“Linux系统中如何查看系统负载”表面答案是uptime或top但考官真正想看到的是你知道load average的数值和CPU核数之间的关系吗你能区分CPU密集型负载和I/O等待导致的负载升高吗当生产环境出现负载飙高时你的排查思路是什么再比如考“MySQL主从复制的原理”表面答案是多线程回放binlog但真正的问题可能是主从延迟了怎么办binlog格式选row还是statement从库误删数据怎么恢复所以系统工程师这个岗位的笔试题本质上是在有限的时间里通过少量题目来考察你对系统整体架构的认知深度。它要求你脑子里不是一个个零散的知识点而是一张完整的系统运行拓扑图流量从用户端进来经过DNS、负载均衡、接入层、应用层、缓存、消息队列最后落到数据库和存储上每一层都有对应的组件、监控指标、常见故障和维护手段。你有没有真正从零搭过一套系统从你的回答里是藏不住的。1.2 从岗位JD反推知识结构我们再看一下系统工程师岗位的常见JD负责公司业务的日常运维、保障业务连续性、参与系统架构评审、推进自动化运维建设、处理突发故障。这些要求全部指向同一个核心能力交付一个可运行、可维护、可扩展的生产系统。我把系统工程师完整的知识结构拆成了六个方面这基本就是那套笔试题的覆盖范围知识域核心内容对应的生产场景Linux基础文件系统、进程管理、权限、systemd、内核参数系统安装配置、故障排查、性能调优网络基础TCP/IP、HTTP/DNS、负载均衡、防火墙接入层架构、网络问题定位、安全策略数据存储MySQL、Redis、对象存储数据持久化、缓存加速、备份恢复中间件Nginx、Kafka/RabbitMQ、ZooKeeper流量接入、异步解耦、分布式协调自动化运维Shell/Python、Ansible、CI/CD、监控平台批量部署、变更发布、告警处理稳定性治理容量规划、高可用、灾备、故障演练大促保障、限流降级、应急预案这套知识结构不是凭空想的而是从“从零搭建一个生产系统并维护好它”这个完整流程里倒推出来的。你每掌握一个模块就能回答出这套系统里的一块拼图当你拼完所有模块你不仅知道笔试题的答案更知道这些答案在生产环境里到底意味着什么。2. 生产环境从零搭建主机与基础环境到底怎么落地2.1 容量规划与机器选型先算清楚再动手很多新手拿到“从零搭建系统”这个任务第一反应是安装操作系统、配环境这其实是本末倒置。真正有经验的系统工程师拿到需求后会先做容量规划。为什么因为机器买多了浪费成本买少了上线就宕机这个度把握不好后面全是坑。容量规划核心就三件事算QPS、算存储、算带宽。假设你要上线一个日活10万用户的视频类应用先估算核心接口的QPS。日活10万假设每个用户每天发起200次请求总共2000万次请求按8小时业务高峰折算平均QPS约700考虑到高峰是平均的3到5倍核心接口的峰值QPS大概在2000到3500之间。一台4核8G的云主机经过优化后扛500到1000 QPS问题不大那你至少要准备4到6台应用服务器。存储方面10万用户每天产生约100GB的日志和上传数据保留30天就得3TB原始容量按三副本冗余算就是9TB左右这还没算数据库。带宽就更直观了视频类业务按平均码率2Mbps算高峰期同时在线5000人需要约10Gbps出口带宽。做完这些估算你才能回答笔试题里最常见的那个问题给你一个业务需求你怎么设计系统架构当你把容量账算清楚架构自然就出来了前端挂Nginx做接入和静态资源分发中间挂应用集群底层用MySQL存核心数据、Redis做缓存、消息队列削峰存储用对象存储扛大文件。每一步都有数据支撑这才是系统工程师的思考方式而不是凭感觉选组件。2.2 操作系统安装与初始化清单标准化是第一原则容量规划做完之后才进入真正的搭建环节。关于操作系统这里必须强调一个原则标准化。生产环境的每一台机器从操作系统版本、分区方案到内核参数都应该保持一致。我自己踩过的坑是不同机器内核版本不一致结果在排查一个网络问题的时候同一套sysctl参数在两台机器上表现完全不同那叫一个痛苦。初始化清单我一般是这样做的。系统层面统一使用CentOS 7.9或Ubuntu 20.04 LTS这类稳定版本分区单独划出/data给业务数据避免系统盘被日志写满。安装完系统后第一批必调的内核参数包括vm.swappiness调低到10以下避免swap频繁交换影响性能fs.file-max调大到655360以上防止高并发下文件句柄耗尽net.core.somaxconn和net.ipv4.tcp_max_syn_backlog适当调大应对突发连接。然后是基础服务配置公司内部的NTP时间同步服务器服务器时间漂移会导致日志排查错乱、分布式系统数据不一致这是很多人会忽略的问题配置公司内部的DNS解析避免每次域名解析都走公网延迟高还不安全配置统一的Yum或APT源保证所有机器安装的软件版本一致。SSH加固也必须在这个阶段做。生产环境绝不能开放密码登录全部改用密钥认证禁用root直接登录SSH端口建议改掉虽然不能说这样就绝对安全但能挡住绝大部分扫描攻击。做完这些我还会把每台机器的hostname、IP、用途、负责人信息都登记到资产表里后续的监控、告警、自动化操作都依赖这份资产信息。基础环境搞标准化了后面几十台、几百台机器的管理才有基础不然天天给每台机器“擦屁股”就够你忙的。2.3 基础环境初始化的常见坑时间、句柄、分区基础环境搭建过程看似简单实际上暗坑不少这里分享几个我真实遇到过的也特别像笔试题里的“事故分析题”。第一个坑是分区规划不合理。我见过一台业务机器根分区只给了20GMySQL的datadir放在默认路径/var/lib/mysql结果跑了一个月磁盘直接满了数据库只读业务全线挂掉。后来排查才发现binlog和慢查询日志全写在系统盘上。合理的做法是数据盘单独挂载日志、临时文件、核心数据都放到容量充足的数据分区并且提前做好磁盘空间监控告警。第二个坑是文件句柄限制。很多应用比如Nginx、Java应用在高并发下会报“Too many open files”。这不是系统bug而是ulimit默认值太低。CentOS 7默认的ulimit -n是1024对生产环境来说远远不够。需要在/etc/security/limits.conf里给进程用户设置nofile为65535或更高同时确认systemd服务文件里的LimitNOFILE也同步修改了否则不生效。第三个坑是时间不同步导致的连锁反应。有一次线上一个基于时间戳的分布式ID生成服务突然出现重复ID排查了半天最后发现是几台新加的机器没有配置NTP系统时间比标准时间慢了将近一分钟。所以我在初始化检查里专门加了一条配置完NTP后必须用ntpdate -q 时间服务器地址确认时间偏差在100ms以内才算通过。3. 核心组件部署数据库、缓存、队列与接入层的选型落地3.1 数据库初始化MySQL参数不是默认就能用系统里最不能出问题的组件就是数据库所以数据库的初始化也是笔试题必定会覆盖的重头戏。面试官问你“MySQL如何优化”如果只回答“加索引、开慢查询日志”分数一定不高因为生产环境的MySQL从安装那一刻起就要为性能和稳定做规划。我习惯用二进制方式部署MySQL不用系统自带的包管理器原因很简单版本可控、目录可控、参数可控。部署完成后第一件事是调整my.cnf参数。innodb_buffer_pool_size一般设置为物理内存的70%左右这是InnoDB的缓存池直接影响读写性能innodb_log_file_size建议设置为512M到1G太小会导致频繁刷盘、性能抖动binlog_format必须设置为row模式虽然会产生更大的binlog但对数据一致性和误操作恢复有极大帮助。慢查询日志必须打开long_query_time设为1秒这是排查SQL性能问题最重要的数据来源。数据库的高可用一定不能省。主从复制是标配从库至少一个既做读写分离又做备份源。主从搭建完必须验证复制是否正常在从库执行SHOW SLAVE STATUS\G确认Slave_IO_Running和Slave_SQL_Running都是Yes然后写一条测试数据看看从库能不能同步到。这一步做不好后面主库挂了切从库发现从库数据落后几万条那就真的是事故了。备份策略更要在初始化阶段定好。每天凌晨用mysqldump做全量备份配合binlog做增量恢复备份文件必须异地存储绝不能和数据库在同一台机器上。备份策略好不好不是看备份过程顺不顺利而是看恢复演练能不能过关。我的标准是每季度至少做一次从空库开始的全量恢复binlog增量恢复到任意时间点的演练没做过恢复演练的备份等于没有备份。3.2 缓存与消息队列Redis、Kafka选型与核心参数视频网站这类业务数据库下面一定要有缓存层和消息队列层它们决定了系统能不能扛住突发流量。这些中间件的部署参数也是系统工程师笔试的重点考察方向。Redis部署看似简单但有几个关键点极易踩坑。第一maxmemory必须设置否则Redis会把机器内存吃满触发OOM我建议设置成物理内存的70%到80%给操作系统和fork子进程留足余量。第二maxmemory-policy要按业务场景选缓存场景用allkeys-lru需要精确控制的场景用volatile-lru。第三开启AOF持久化并设置appendfsync everysec兼顾数据安全和性能。Redis主从结构要为从节点配置replica-read-only yes防止误写入导致主从数据不一致。Kafka这里要重点说因为很多新手会忽略它的一个特点就是部署前必须先想好主题分区数。分区的数量需要跟消费端的并发度匹配同时也要考虑分区过多带来的文件句柄占用和rebalance时间变长。一般情况下一个主题的分区数建议是消费组消费者数量的整数倍比如4个消费者就配8个或12个分区这样负载相对均衡。Kafka的log.retention.hours按日志保留需求设置比如168小时7天log.segment.bytes用默认的1G就行。队列监控方面生产环境一定要监控消费延迟如果消费端挂了一个小时积压了几百万条消息等发现的时候可能已经影响到业务数据的实时性了。3.3 接入层与高可用Nginx、负载均衡和健康检查用户流量进入系统的第一个入口是接入层这一层的高可用直接决定了系统能不能对外服务。部署Nginx时除了常规配置我后来才意识到还有一个非常关键的细节启用了upstream后必须配置合理的健康检查参数。max_fails和fail_timeout要调成适合业务的值比如连续3次失败、30秒内标记为不可用。如果不配Nginx默认将失败的请求转发给挂掉的后端用户就会间歇性看到502。接入层的高可用方案传统的做法是Keepalived Nginx主备模式。Keepalived通过VRRP协议提供一个虚拟IP主节点挂了备节点自动接管整个过程对用户透明。这个方案配置不复杂但要注意主备之间必须开启组播或单播通信而且建议在Keepalived的脚本里加一个对Nginx进程的检测不要只检测Keepalived本身存活。为什么因为如果Nginx进程挂掉了但Keepalived还活着虚拟IP不会漂移用户请求照样是502等于高可用失效了。现在云上环境更推荐直接用云负载均衡由云平台负责健康检查和流量切换省心很多。但不管是自建还是云上核心的检查项都是后端服务器的端口存活检测、HTTP状态码检测、以及后端挂掉时的自动摘除与恢复。这一层配好了业务架构的地基才算稳固。4. 自动化、监控与发布从“能跑”到“可持续维护”的关键4.1 从人工到自动化配置管理与CMDB建设系统搭起来只是第一步更难的是后续维护。如果所有操作都靠人肉SSH到机器上执行几十台机器还能勉强应付到了上百台机器效率低下不说还容易出错。这也是为什么系统工程师面试里自动化运维几乎是必考题。自动化运维的第一步是搭建配置管理工具。以Ansible为例它的优势是无Agent、基于SSH、学习曲线平缓。我会把前面说的操作系统初始化清单写成Ansible Playbook新机器交付后直接执行一遍所有初始化动作自动完成。Playbook里不仅包含内核参数调整、NTP配置、DNS配置、SSH加固还包含基础监控Agent的安装。这样一来新机器从交付到纳入监控体系时间从过去的人工操作半小时压缩到几分钟而且保证了每台机器的状态完全一致。自动化运维的第二步是建设CMDB配置管理数据库。以我的经验CMDB不一定要用多复杂的平台核心是把资产关系理清楚这台机器属于哪个业务线、运行什么应用、依赖哪些数据库、负责人是谁、告警通知谁。只有把这些信息结构化后面的监控告警、故障排查、容量管理才有数据基础。很多团队在业务量小的时候觉得CMDB是负担等出了事故找机器、找人、找依赖关系找半天的时候才知道CMDB的价值。4.2 监控告警体系搭建四类监控信号缺一不可系统上线之后监控就是你的眼睛。一个系统工程师如果只能回答出“用prometheus监控CPU和内存”那离合格还有很大距离。一套完整的监控体系至少包含四个维度基础监控、日志监控、链路追踪和拨测监控。基础监控用Prometheus Grafana是当前的主流方案。需要采集的指标不止是CPU、内存、磁盘、网络还包括每个组件的核心指标MySQL的QPS、连接数、慢查询数、主从延迟Redis的命中率、内存使用率、阻塞客户端数Nginx的QPS、5xx状态码比例、平均响应时间Kafka的消费延迟、分区leader分布。每个指标都要设置合理的告警阈值告警分级要清晰P0是影响业务的故障比如数据库挂了、服务大面积5xx电话通知立即响应P1是潜在风险比如磁盘使用率超80%、Redis内存告警邮件/钉钉通知P2是日常提醒按周汇总。日志监控也必不可少。建议搭建ELK或轻量化的Loki方案把所有机器上的应用日志统一收集、集中检索。日志的价值不仅在于排障更在于发现潜在问题比如通过分析Nginx访问日志中的5xx状态码趋势可以提前发现某个接口的稳定性隐患。链路追踪比如SkyWalking、Jaeger在微服务架构下尤其重要没有它一个请求经过三四个服务的耗时分布你就完全看不清楚。拨测监控则是从用户视角模拟访问能发现机房网络问题、域名解析异常等内部监控发现不了的问题建议至少5分钟一次。4.3 发布与变更管理最容易被忽视的稳定性杀手排查了很多次生产故障之后我得出了一个很扎心的结论大多数故障不是硬件问题而是变更引发的。变更包括代码发布、配置修改、数据库变更、服务器扩容缩容等等。做好变更管理能避免70%以上的线上事故。具体的落地方式是建立一套完整的发布流程。代码发布必须走CI/CD流水线经过编译、单元测试、镜像构建然后部署到测试环境验证最后才发布到生产环境。生产发布一定要支持灰度发布先发布一台机器观察监控指标正常后再逐步扩展到整个集群。一旦发现异常能够一键回滚到上一个版本。这一点上Kubernetes等容器化平台的滚动更新和回滚机制非常有用如果公司还没容器化也要通过脚本做好版本管理和回滚预案。配置变更同样需要规范。我见过很多次线上事故是有人在生产机器上临时改了一个配置项改完没有同步给其他机器结果流量一上来各机器行为不一致引发了雪崩。我的办法是所有配置变更必须走配置中心或版本控制禁止在机器上临时改配置改完必须通过自动化工具下发到所有机器并在变更记录里留下人和时间。数据库变更更要注意比如加索引这类操作如果表很大MySQL 5.6以下版本会锁表必须在业务低峰期执行并且先在从库执行验证后再切换。5. 后续维护的核心工作巡检、备份、扩容与故障排查5.1 日常巡检与备份恢复演练维护工作不能靠“等故障”系统交付之后每天的维护工作更考验耐心和专业性。日常巡检不是随便看看监控面板就完事而是要有一套固定的检查节奏和检查项。我的巡检清单包含四个层面。第一系统层确认CPU负载趋势、内存使用率、磁盘空间、inode使用率、系统日志有没有异常报错。第二应用层确认Nginx的QPS和5xx比例是否正常、MySQL的连接数和慢查询有没有异常增长、Redis的命中率和内存使用是否健康、消息队列的消费延迟有没有在正常范围。第三安全层检查登录日志有没有异常IP尝试登录、关键文件有没有被篡改、安全补丁是否需要更新。第四容量层根据近期的增长趋势推算磁盘、内存、带宽还能支撑多久提前安排扩容计划。备份检查要纳入巡检项不能只依赖备份脚本。每天的备份任务执行后要检查备份文件是否存在、大小是否正常突然变小可能意味着备份失败或数据丢失。在此基础上我还坚持一个原则每季度至少做一次恢复演练。恢复演练不是走过场而是真正把备份文件恢复到一台临时机器上启动数据库验证数据完整性再模拟一个“误删一张表”的场景尝试从备份和binlog恢复到误删前的状态。只有经过这种演练你才能确定真出事时你是有把握的。5.2 核心故障排查思路从现象到根因的五步定位法故障排查能力是系统工程师最核心的竞争力也是笔试题里最难的场景题。我在带新人时会反复强调一套排查方法普通人容易像无头苍蝇一样乱试但老手都是按套路出牌的。第一步确认影响范围。先搞清楚是单台机器的问题还是整个集群的问题是某个接口变慢还是全站不可用是只影响部分用户还是所有用户都受影响。这一步能快速缩小排查方向。第二步看监控回顾。查看故障开始前后机器负载、网络流量、业务指标有没有突变监控面板通常能直接告诉你问题出在哪个环节。第三步看日志定位。登录到可疑机器先看系统日志/var/log/messages再看应用日志搜索当时时间点的错误关键字比如“OutOfMemory”“Connection refused”“deadlock”。第四步做现场验证。用命令验证你的猜测top看进程CPU、free -h看内存、iostat -x 1看磁盘I/O、ss -anp看连接数、ping和traceroute看网络。第五步临时止血根因修复。先通过重启、切换流量、降级等手段恢复业务再深入分析根因做永久修复。举一个我实际遇到的案例。某天线上告警服务A的接口耗时翻倍用户开始投诉。我先确认影响范围只有服务A受影响其他服务正常。然后看监控服务A所在机器的CPU使用率99%但应用本身的QPS并没有明显增长。看日志发现大量“GC overhead limit exceeded”基本可以判断是JVM内存问题。用jstat查看GC情况发现Full GC非常频繁老年代持续增长。用jmap导出堆转储分析后发现一个缓存类对象持有大量数据导致内存泄漏。定位到根因后先通过重启快速恢复业务然后开发修复代码走发布流程修复。事后复盘这类问题如果在监控里加上JVM的GC指标和堆内存使用率告警其实可以更早发现根本不用等用户投诉。5.3 系统维护常见问题速查表我把生产环境里最常遇到的几个问题整理成了一张速查表建议收藏备用。这些场景也可以当成面试场景题来准备想清楚每行的排查思路。问题现象可能原因快速定位命令处理建议服务响应变慢CPU高应用死循环、SQL全表扫描、GC频繁top、jstack、show processlist抓线程栈/慢SQL定位热点后优化或扩容磁盘写入失败磁盘满或inode耗尽df -h、df -i清理日志、扩容数据盘大量TIME_WAIT连接短连接过多、负载均衡配置不合理ss -s、netstat -anp开启连接复用、调大端口范围、长连接改造数据库主从延迟大事务、从库磁盘慢、DDL锁表SHOW SLAVE STATUS\G优化大事务、升级从库硬件、错峰执行DDL内存持续增长内存泄漏、缓存配置过大free -h、top、jstat分析堆转储、限制缓存内存、及时重启验证Redis出现阻塞大key操作、fork耗时、AOF重写redis-cli slowlog get拆分大key、错峰AOF重写、关闭耗时命令排查故障时有一个心态建议越是紧急的时刻越要冷静按步骤来。我见过太多人在故障发生时胡乱重启、随手改参数结果把现场破坏了最后连根因都找不到。正确的做法是先定位再操作每做一步都记录时间点和结果方便事后复盘。这套方法不仅能帮你解决笔试里的“故障分析题”更是日常工作中保护自己的基本功。做了这么多年系统工程师我最大的体会是这套笔试题目背后的真实问题不是“你会不会做这道题”而是“你敢不敢把一个系统从零交付到线上并且为它长期负责”。从容量规划、基础环境初始化到数据库、缓存、中间件部署再到监控告警、自动化运维和故障排查每一个环节都是经验的积累也都是笔试和面试真正的分水岭。希望这篇拆解能帮你把脑子里零散的知识点串成一张完整的系统工程师能力地图。如果你也在准备类似岗位的面试我的建议是别只刷题去真正找几台机器从零搭一套环境出来你亲自踩过的每一个坑都比背下来的答案值钱得多。
返回列表