古人学问无遗力，少壮工夫老始成。 纸上得来终觉浅，绝知此事要躬行。
别再傻傻分不清！SMB协议到底是个啥？和NFS有什么区别？
前几天那篇《踩坑无数！NFS服务从入门到放弃再到真香的血泪史》看到有好多小伙伴问SMB协议的事，想起之前面试的时候被问什么SMB、NFS、FTP，我眼前一黑只是感觉都是用来传文件的，但又说不出个所以然来。今天我们就来好好盘盘他们！顺便说说它和NFS的区别。毕竟这两个协议在我们日常运维工作中还是经常遇到的，搞清楚了对工作帮助挺大。SMB协议是个什么鬼？SMB全称是Server Message Block，翻译过来就是服务器消息块协议。听起来很高大上对吧？其实说白了就是让不同设备之间能够共享文件和打印机的一个协议。我记得刚开始接触这个协议的时候，公司有台Windows服务器总是出现文件共享的问题。那时候我还不知道这背后就是SMB在起作用，只知道用户抱怨说访问共享文件夹特别慢，有时候还会断开连接。SMB协议最初是IBM开发的，后来微软拿过来改进了一下，就成了现在我们常见的样子。这个协议经历了好几个版本的迭代：SMB 1.0是最早的版本，现在基本上已经被淘汰了，因为安全性太差。SMB 2.0开始性能有了明显提升，支持更大的缓冲区，减少了网络往返次数。SMB 2.1又增加了一些新特性，比如大MTU支持。到了SMB 3.0，这个版本可以说是一个里程碑，增加了端到端加密、多通道支持等功能。SMB 3.1.1是目前最新的版本，在安全性和性能方面都有进一步的改进。SMB协议的工作原理说到工作原理，SMB其实是基于客户端-服务器模式的。客户端发送请求，服务器响应请求，就这么简单。但是这个过程涉及到几个关键步骤。首先是协商阶段，客户端和服务器要商量用哪个版本的SMB协议，支持哪些功能。然后是认证阶段，验证用户身份。最后才是真正的数据传输。我之前遇到过一个有趣的问题，一台Linux服务器通过Samba访问Windows共享时总是很慢。后来发现是协商阶段出了问题，Linux这边默认尝试从SMB 1.0开始协商，而Windows那边已经禁用了SMB 1.0，所以要经过好几轮协商才能确定使用SMB 2.0，这就浪费了很多时间。SMB协议在网络层面使用TCP协议，默认端口是445。不过在早期版本中，SMB还会使用139端口，这个端口是NetBIOS over TCP/IP使用的。SMB的实际应用场景说了这么多理论，来看看SMB在实际工作中都用在哪些地方。最常见的就是Windows环境下的文件共享了。你在Windows资源管理器里输入\server\share这样的路径访问共享文件夹，背后就是SMB协议在工作。之前做跨境电商的时候（对，没错我还搞过跨境！技多不压身），他们的所有Excel文件都放在一个共享文件夹里。需要修改的时候就打开，但是一次只能一个人保存，所以几个人同时打开这些文件，总是保存出错，会出现出现文件锁定的问题，A同事打开了一个文件，B同事就只能以只读模式打开。这种情况下，了解SMB的文件锁定机制就很重要了。另一个常见的应用场景是打印机共享。虽然现在网络打印机很普及，但还是有不少公司使用共享打印机的方式。打印机连接到一台电脑上，然后通过SMB协议共享给其他用户使用。在虚拟化环境中，SMB也有用武之地。比如Hyper-V可以使用SMB 3.0作为存储后端，这样可以实现高可用的虚拟机存储。我之前参与过一个项目，就是用SMB 3.0搭建了一个Scale-Out File Server，为虚拟化环境提供存储服务。还有一个比较新的应用是容器环境。Docker和Kubernetes都可以使用SMB作为持久化存储的后端。不过说实话，在容器环境中使用SMB还是有一些坑的，特别是权限管理方面。SMB和NFS的区别现在来说说大家最关心的问题：SMB和NFS到底有什么区别？从平台兼容性来说，SMB主要是Windows的天下，虽然Linux可以通过Samba来支持SMB，但总感觉不是那么原生。NFS则是Linux/Unix的主场，Windows虽然也可以支持NFS，但需要安装额外的组件。性能方面，这个就比较复杂了。在相同的网络环境下，NFS的性能通常会好一些，特别是在大文件传输和高并发访问的场景下。但是SMB 3.0之后，性能差距已经不是很明显了。今天做过一个测试，在千兆网络环境下，用相同的硬件配置分别测试SMB和NFS的性能。结果发现，在顺序读写方面，NFS确实要快一些，但在随机读写方面，差距就不太明显了。安全性方面，两个协议都有自己的安全机制。SMB支持多种认证方式，包括NTLM、Kerberos等。NFS在早期版本中安全性比较弱，主要依赖于网络层的安全，但NFSv4增加了强认证和加密支持。文件锁定机制也不太一样。SMB的文件锁定比较严格，一个文件被一个用户以写模式打开后，其他用户就不能同时写入。NFS的文件锁定相对宽松一些，但这也可能导致数据一致性的问题。还有一个重要的区别是状态管理。SMB是有状态的协议，服务器会记住每个客户端的连接状态。NFS（特别是NFSv2和NFSv3）是无状态的，服务器不记住客户端的状态信息。这个区别在网络不稳定的环境下会比较明显。实际部署中的考虑在实际工作中选择SMB还是NFS，需要考虑很多因素。如果你的环境主要是Windows，那SMB肯定是首选。Windows对SMB的支持是最好的，各种高级特性都能用上。而且用户也比较熟悉，\server\share这种访问方式大家都会用。如果是Linux环境，NFS可能是更好的选择。配置相对简单，性能也不错。我们公司的开发环境就是用NFS来共享代码和数据的，效果还不错。混合环境就比较纠结了。如果Windows和Linux都要访问同一份数据，你可能需要同时配置SMB和NFS，或者选择一个折中的方案。网络环境也是一个重要考虑因素。如果网络不太稳定，SMB可能会有一些问题，因为它是有状态的协议，连接断开后需要重新建立。NFS在这方面相对好一些。还有就是管理复杂度。SMB的配置相对复杂一些，特别是涉及到域认证的时候。NFS的配置相对简单，但权限管理可能会有一些坑。性能优化的一些经验不管用SMB还是NFS，性能优化都是绕不开的话题。对于SMB，有几个参数可以调整。比如增大缓冲区大小，启用多通道支持（如果是SMB 3.0的话），调整TCP窗口大小等。我之前遇到过一个案例，调整了SMB的缓冲区大小后，文件传输速度提升了30%左右。NFS的优化主要集中在挂载参数上。rsize和wsize参数控制读写缓冲区大小，通常设置为32768或65536会有比较好的性能。还有就是选择合适的NFS版本，NFSv4在很多场景下性能会更好。网络层面的优化也很重要。确保网络带宽足够，延迟尽可能低。如果是跨广域网的访问，可能需要考虑使用一些加速技术。安全性配置安全性是另一个重要话题。SMB和NFS都有各自的安全风险。SMB的安全配置主要包括禁用旧版本协议（特别是SMB 1.0），启用加密传输，配置合适的认证方式等。我建议在生产环境中至少使用SMB 2.1以上的版本，最好是SMB 3.0。NFS的安全配置相对复杂一些。早期的NFS版本安全性比较弱，主要依赖于IP地址限制和UID/GID映射。NFSv4增加了Kerberos认证支持，安全性有了很大改善。防火墙配置也不能忽视。SMB使用445端口，NFS使用2049端口，还有一些辅助端口。确保只有必要的端口对外开放。故障排查经验在实际使用中，SMB和NFS都可能遇到各种问题。SMB常见的问题包括连接超时、认证失败、文件锁定等。我遇到过最多的问题是版本协商失败，通常是因为客户端和服务器支持的SMB版本不匹配。NFS的问题主要集中在挂载失败、权限错误、性能问题等方面。有一次我们的NFS服务器出现了问题，所有客户端的挂载点都变成了只读，后来发现是磁盘空间不足导致的。排查这些问题的时候，日志是最重要的工具。Windows的事件查看器、Linux的/var/log/messages都能提供有用的信息。网络抓包工具如Wireshark也很有用，可以看到协议层面的交互过程。有一次我遇到一个很奇怪的问题，用户反映访问SMB共享特别慢，但网络和服务器都没问题。最后用Wireshark抓包发现，客户端在每次文件操作前都要进行一次完整的认证过程，这就导致了大量的网络往返。后来调整了客户端的缓存策略，问题就解决了。未来发展趋势SMB和NFS这两个协议都在不断发展。SMB 3.1.1增加了更多的安全特性和性能改进，微软还在继续推进SMB协议的发展。NFS也在向NFSv4.2发展，增加了一些新的特性。云计算的兴起也给这些传统协议带来了新的机遇和挑战。很多云服务商都提供基于SMB或NFS的文件存储服务，但在云环境中使用这些协议也有一些新的考虑因素，比如网络延迟、安全性等。容器化和微服务架构的普及也在改变文件共享的需求。传统的大文件共享可能会被更细粒度的数据交换方式所替代，但SMB和NFS在某些场景下仍然有其价值。选择建议说了这么多，到底该怎么选择呢？我的建议是：如果你的环境主要是Windows，而且用户习惯了Windows的文件共享方式，那就选SMB。特别是在办公环境中，SMB的用户体验会更好一些。如果是Linux/Unix环境，特别是服务器环境，NFS可能是更好的选择。配置相对简单，性能也不错。混合环境的话，可能需要根据具体需求来选择。如果主要是Windows用户访问，可以在Linux服务器上配置Samba。如果主要是Linux服务器之间的数据共享，NFS会更合适。还有一个考虑因素是团队的技术栈。如果团队对Windows技术更熟悉，选择SMB可能会减少维护成本。如果团队主要是Linux背景，NFS可能是更好的选择。实际案例分享最后分享几个我遇到的实际案例。案例一：某公司的财务系统需要在多个办公室之间共享数据。最初他们选择了FTP，但发现用户体验很差，而且安全性也有问题。后来改用SMB，配置了域认证和加密传输，效果好了很多。案例二：一个科研机构需要在计算集群中共享大量的数据文件。最初他们用的是本地存储+rsync同步，但数据量增长后同步变得很困难。改用NFS后，所有计算节点都可以直接访问共享数据，大大简化了数据管理。案例三：某互联网公司的开发环境需要在容器中挂载共享存储。他们尝试了SMB和NFS两种方案，最终选择了NFS，主要是因为在容器环境中NFS的兼容性更好一些。这些案例说明，选择哪种协议很大程度上取决于具体的应用场景和需求。没有绝对的好坏，只有合适不合适。总结写了这么多，其实SMB和NFS都是很成熟的协议，各有各的优势和适用场景。SMB在Windows环境中表现更好，用户体验也更友好。NFS在Linux/Unix环境中更有优势，性能和稳定性都不错。在实际工作中，我们需要根据具体的环境和需求来选择。不要被技术本身所束缚，关键是要解决实际问题。有时候一个简单的解决方案可能比复杂的技术架构更有效。当然，不管选择哪种协议，安全性和性能优化都是需要重点关注的。定期更新系统，合理配置参数，做好监控和故障排查，这些基础工作一个都不能少。技术在不断发展，SMB和NFS也在持续改进。作为运维人员，我们需要保持学习的心态，及时了解新的特性和最佳实践。同时也要有实践精神，在实际环境中验证和优化这些技术方案。**如果这篇文章对你有帮助，别忘了点赞转发支持一下！想了解更多运维实战经验和技术干货，记得关注微信公众号@运维躬行录，领取学习大礼包！！！我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习，共同进步！公众号：运维躬行录个人博客：躬行笔记**
别再让服务器"拖后腿"了！Linux内核优化实战，让你的机器跑得飞起来
最近在做一个架构实验，一台1c1g的服务器，部署lnmp服务器，qps只有14左右。我在思考如何提高这个qps，极限压榨这台服务器的性能。说实话，Linux内核优化这个话题，很多人觉得很高深，其实真正用起来，掌握几个关键点就够了。我在这个行业摸爬滚打这么多年，踩过的坑可以绕地球一圈，今天就把这些经验分享给大家。为什么要做内核优化你可能会问，系统默认配置不是挺好的吗？为什么还要折腾？我给你举个例子，就像买了一辆新车，厂家的默认设置是为了适应大部分人的驾驶习惯，但如果你是个赛车手，肯定要根据赛道特点来调整悬挂、轮胎气压这些参数对吧？Linux内核也是一样的道理。默认配置考虑的是通用性，但我们的服务器往往有特定的使用场景，比如高并发Web服务、数据库服务器、文件服务器等等，每种场景的优化重点都不一样。我们之前有个客户项目，用户量突然暴增，服务器压力巨大。当时我们的第一反应是加机器，但预算有限，只能先从优化入手。通过一系列内核参数调整，性能提升了30%多，硬是撑过了那波流量高峰。网络参数优化 - 让数据传输更顺畅网络优化是我最常遇到的需求，特别是做Web服务的时候。TCP连接数限制经常是个大问题。默认情况下，系统的文件描述符限制比较保守，高并发场景下很容易成为瓶颈。# 查看当前限制 ulimit -n # 临时修改 ulimit -n 65535 # 永久修改需要编辑 /etc/security/limits.conf * soft nofile 65535 * hard nofile 65535不过光改这个还不够，还得调整内核的网络参数。我一般会这样配置：# 编辑 /etc/sysctl.conf #设置系统级别的socket监听队列的最大长度,当应用程序调用listen()时，backlog参数不能超过这个值。提高此值可以允许更多的连接请求排队等待处理 net.core.somaxconn = 32768 #网络设备接收数据包的队列最大长度,当网络接口接收数据包的速度超过内核处理速度时，数据包会在此队列中排队 net.core.netdev_max_backlog = 32768 #设置SYN_RECV状态的连接队列最大长度,控制处于半连接状态的TCP连接数量，防止SYN flood攻击 net.ipv4.tcp_max_syn_backlog = 32768 #设置TCP连接在FIN-WAIT-2状态的超时时间,缩短TIME_WAIT状态的持续时间，更快释放连接资源 net.ipv4.tcp_fin_timeout = 10 #设置TCP keepalive探测的间隔时间,更频繁地检测死连接，及时清理无效连接 net.ipv4.tcp_keepalive_time = 1200 #设置系统中TIME_WAIT状态连接的最大数量,限制TIME_WAIT连接数，防止占用过多系统资源 net.ipv4.tcp_max_tw_buckets = 32768这里面每个参数都有它的作用。比如somaxconn控制的是监听队列的最大长度，如果你的应用连接数很高，这个值设小了就会导致连接被拒绝。tcp_fin_timeout我一般设置得比较小，因为TIME_WAIT状态的连接太多会占用大量资源。当然这个值也不能设得太小，否则可能会有问题。有一次我把这个值设成了5秒，结果发现偶尔会有连接异常，后来查资料发现是因为网络延迟导致的，最后调整到10秒比较合适。内存管理优化内存这块的优化主要集中在几个方面。交换分区的使用策略是个重点。很多人觉得swap就是内存不够时的备胎，其实不完全是这样。Linux会根据swappiness参数来决定什么时候使用swap。# 查看当前值 #cat /proc/sys/vm/swappiness [root@webtest ~]# cat /proc/sys/vm/swappiness 30 [root@webtest ~]# # 修改为10（默认通常是60） #echo 10 > /proc/sys/vm/swappiness我一般把这个值设置得比较低，特别是数据库服务器。因为数据库对延迟很敏感，一旦数据被swap到磁盘，性能就会急剧下降。内存回收策略也很重要：vm.dirty_ratio = 10 vm.dirty_background_ratio = 5 vm.dirty_expire_centisecs = 3000 vm.dirty_writeback_centisecs = 500这几个参数控制的是脏页的回写策略。脏页就是在内存中被修改但还没写入磁盘的数据页。如果脏页太多，系统性能会受影响；但如果回写太频繁，磁盘IO压力又会很大。我记得有次处理一个文件服务器的性能问题，发现写入大文件时系统会卡顿。后来发现是脏页比例设置得太高，导致积累了大量脏页，集中回写时把磁盘IO打满了。调整这几个参数后问题就解决了。进程调度优化CPU调度器的优化相对来说比较少用到，但在某些场景下效果很明显。Linux有几种调度器可以选择，默认的CFS（完全公平调度器）适合大部分场景，但如果你的应用对延迟要求很高，可能需要调整一些参数。# 查看当前调度策略 #cat /proc/sys/kernel/sched_* [root@webtest ~]# cat /proc/sys/kernel/sched_* 0 5000 0 4194304 100 cat: /proc/sys/kernel/sched_domain: Is a directory 1 6000000 500000 10000000 32 100 1000000 950000 0 1 15000000 # 调整时间片长度 echo 1000000 > /proc/sys/kernel/sched_latency_ns调度器相关参数解释1. sched_autogroup_enabled = 0作用：控制是否启用自动分组调度值：0表示禁用，1表示启用影响：禁用后所有进程在同一调度组中竞争CPU2. sched_cfs_bandwidth_slice_us = 5000作用：CFS带宽控制的时间片长度（微秒）默认值：5000微秒（5毫秒）影响：控制cgroup带宽限制的精度3. sched_child_runs_first = 0作用：控制fork后是否让子进程优先运行值：0表示父进程优先，1表示子进程优先影响：影响进程创建后的调度顺序4. sched_latency_ns = 4194304作用：CFS调度器的目标延迟时间（纳秒）值：4194304纳秒 ≈ 4.19毫秒影响：所有可运行进程至少运行一次的时间周期5. sched_migration_cost_ns = 100作用：进程迁移的成本估算（纳秒）影响：影响负载均衡时进程在CPU间的迁移决策6. sched_min_granularity_ns = 1000000作用：进程运行的最小时间粒度（纳秒）值：1000000纳秒 = 1毫秒影响：保证每个进程至少运行的时间7. sched_nr_migrate = 32作用：负载均衡时单次迁移的最大进程数影响：控制负载均衡的开销和效果8. sched_rr_timeslice_ms = 100作用：SCHED_RR调度策略的时间片长度（毫秒）影响：实时轮转调度的时间片大小9. sched_rt_period_us = 1000000作用：实时调度的周期时间（微秒）值：1000000微秒 = 1秒影响：实时进程调度的时间窗口10. sched_rt_runtime_us = 950000作用：实时进程在一个周期内可使用的最大CPU时间（微秒）值：950000微秒 = 0.95秒影响：限制实时进程的CPU使用，为普通进程保留5%的CPU时间11. sched_schedstats = 0作用：控制是否启用调度统计信息收集值：0表示禁用，减少统计开销12. sched_tunable_scaling = 1作用：控制调度参数是否根据CPU数量自动缩放值：1表示启用对数缩放13. sched_wakeup_granularity_ns = 15000000作用：唤醒抢占的粒度控制（纳秒）值：15000000纳秒 = 15毫秒影响：控制进程被唤醒时是否能抢占当前运行的进程不过说实话，调度器参数我很少动，除非遇到特殊需求。因为这块的影响面比较大，改错了可能会影响整个系统的稳定性。倒是进程优先级的调整用得比较多。对于关键业务进程，可以通过nice值来提高优先级：# 启动时设置优先级 nice -n -10 ./important_service # 运行时调整 renice -10 -p 进程ID文件系统优化文件系统这块的优化主要看你用的是什么文件系统。ext4的话，挂载参数很重要：# /etc/fstab 中的配置示例 /dev/sda1 /data ext4 defaults,noatime,nodiratime,barrier=0 0 2noatime参数可以避免每次读取文件时更新访问时间，对于读多写少的场景能提升不少性能。barrier=0可以提高写入性能，但要确保硬件有电池保护，否则可能有数据丢失风险。如果是数据库服务器，我更推荐使用xfs文件系统，它在大文件和高并发场景下表现更好。# 格式化为xfs mkfs.xfs -f /dev/sda1 # 挂载时的优化参数 mount -t xfs -o noatime,nodiratime,logbufs=8,logbsize=256k /dev/sda1 /dataIO调度器选择IO调度器的选择对性能影响很大，特别是在高IO负载的场景下。Linux提供了几种IO调度器：# 查看当前调度器 cat /sys/block/sda/queue/scheduler # 修改调度器 echo deadline > /sys/block/sda/queue/scheduler对于SSD，我一般推荐使用noop或者deadline调度器，因为SSD没有机械磁盘的寻道时间，复杂的调度算法反而会增加延迟。传统机械硬盘的话，cfq调度器通常是个不错的选择，它能保证各个进程的IO请求相对公平。我之前遇到过一个案例，数据库服务器使用的是SSD，但IO调度器还是默认的cfq，导致数据库响应时间不稳定。改成deadline后，响应时间的波动明显减小了。内核模块和服务优化系统启动时会加载很多内核模块和服务，但并不是所有的都是必需的。可以通过以下命令查看当前加载的模块：lsmod对于不需要的模块，可以加入黑名单：# 编辑 /etc/modprobe.d/blacklist.conf blacklist 模块名系统服务也是一样，可以关闭不必要的服务：# 查看所有服务状态 systemctl list-units --type=service # 关闭不需要的服务 systemctl disable 服务名 systemctl stop 服务名不过这里要小心，关闭服务前一定要确认它的作用，别把重要的服务给关了。我见过有人把网络服务给关了，结果远程连不上服务器，只能跑机房去恢复。监控和调试工具优化完了还得有监控手段，不然怎么知道效果如何？我常用的监控工具有这些：# 系统整体性能 top, htop, atop # 网络监控 iftop, nethogs, ss # 磁盘IO监控 iotop, iostat # 内存使用情况 free, vmstat # 进程跟踪 strace, ltraceperf工具特别好用，可以分析系统的性能瓶颈：# 采样系统性能 perf record -g ./your_program # 查看报告 perf report通过perf可以看到哪些函数占用CPU最多，对于性能优化很有帮助。实际案例分享我来分享一个真实的优化案例。去年有个电商客户，双11期间服务器压力巨大，经常出现响应超时。我们接到求助后，第一时间上去看了看系统状态。通过监控发现，CPU使用率不高，内存也够用，但网络连接数接近上限，而且TIME_WAIT状态的连接特别多。分析后发现主要问题在于：文件描述符限制太小TCP参数没有针对高并发场景优化应用层面的连接池配置不合理我们的优化步骤是这样的：调整系统参数：# 增加文件描述符限制 echo "* soft nofile 65535" >> /etc/security/limits.conf echo "* hard nofile 65535" >> /etc/security/limits.conf # 优化TCP参数 echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf echo "net.ipv4.tcp_fin_timeout = 10" >> /etc/sysctl.conf echo "net.core.somaxconn = 32768" >> /etc/sysctl.conf sysctl -p同时建议应用团队调整了连接池的配置，增加了连接复用。优化后，系统的并发处理能力提升了40%多，成功撑过了双11的流量高峰。客户特别满意，后来还介绍了其他项目给我们。注意事项和踩坑经验做内核优化有几个要特别注意的地方。参数不是越大越好。我见过有人觉得缓冲区大一点总是好的，结果把各种buffer都设得很大，反而导致内存不够用。修改前一定要备份原始配置。我的习惯是每次修改前都会把原来的值记录下来，万一有问题可以快速回滚。# 修改前先备份 cp /etc/sysctl.conf /etc/sysctl.conf.backup.$(date +%Y%m%d)测试要充分。内核参数的影响往往不是立竿见影的，需要在实际负载下运行一段时间才能看出效果。我一般会先在测试环境验证，然后在生产环境小范围试点，最后才全面推广。不要一次改太多参数。如果同时修改很多参数，出了问题很难定位是哪个参数导致的。我的建议是每次只改一两个相关的参数，观察一段时间后再继续。还有就是要考虑业务特点。同样的优化参数，在不同的业务场景下效果可能完全不同。比如说，对于批处理任务，可能更关注吞吐量；但对于在线服务，延迟可能更重要。不同场景的优化重点Web服务器的优化重点通常在网络和并发连接数上。除了前面提到的TCP参数，还要关注Apache或Nginx的配置。数据库服务器就不一样了，内存和磁盘IO是关键。我一般会把swappiness设得很低，甚至直接关闭swap。同时调整内存分配策略：vm.overcommit_memory = 2 vm.overcommit_ratio = 80这样可以避免系统过度分配内存导致OOM killer被触发。文件服务器的话，磁盘IO和文件系统参数是重点。除了前面说的挂载参数，还可以调整读写缓存：vm.dirty_ratio = 15 vm.dirty_background_ratio = 5缓存服务器（比如Redis、Memcached）对内存延迟特别敏感，可能需要调整NUMA相关的参数：# 查看NUMA信息 numactl --hardware # 绑定进程到特定NUMA节点 numactl --cpunodebind=0 --membind=0 redis-server自动化优化脚本手动一个个改参数太麻烦了，我写了个脚本来自动化这个过程：#!/bin/bash # 系统优化脚本 # 备份原始配置 cp /etc/sysctl.conf /etc/sysctl.conf.backup.$(date +%Y%m%d) # 网络优化 cat >> /etc/sysctl.conf << EOF # 网络优化参数 net.core.somaxconn = 32768 net.core.netdev_max_backlog = 32768 net.ipv4.tcp_max_syn_backlog = 32768 net.ipv4.tcp_fin_timeout = 10 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_keepalive_time = 1200 EOF # 内存优化 cat >> /etc/sysctl.conf << EOF # 内存优化参数 vm.swappiness = 10 vm.dirty_ratio = 10 vm.dirty_background_ratio = 5 EOF # 应用配置 sysctl -p echo "优化完成，建议重启系统使所有配置生效"当然，这只是个基础版本，实际使用时还要根据具体场景来调整。性能测试和验证优化完了怎么验证效果呢？我一般会用几种方法。压力测试是必不可少的。对于Web服务，我常用ab或者wrk：# Apache Bench测试 ab -n 10000 -c 100 http://your-server/ # wrk测试（功能更强大） wrk -t12 -c400 -d30s http://your-server/数据库的话，可以用sysbench：# MySQL压力测试 sysbench oltp_read_write --mysql-host=localhost --mysql-user=root --mysql-password=password --mysql-db=test --tables=10 --table-size=100000 run网络性能可以用iperf：# 服务端 iperf -s # 客户端 iperf -c server_ip -t 60除了压力测试，日常监控也很重要。我会设置一些关键指标的监控，比如连接数、响应时间、CPU使用率等。一旦发现异常，就能及时处理。容器化环境的特殊考虑现在很多应用都跑在容器里，容器化环境的内核优化有些特殊之处。Docker容器默认会继承宿主机的内核参数，但有些参数是容器级别的，需要在容器启动时指定：# 启动容器时调整参数 docker run --sysctl net.core.somaxconn=32768 --sysctl net.ipv4.tcp_keepalive_time=600 your-imageKubernetes环境下，可以通过securityContext来设置：apiVersion: v1 kind: Pod spec: securityContext: sysctls: - name: net.core.somaxconn value: "32768" - name: net.ipv4.tcp_keepalive_time value: "600"不过要注意，不是所有的内核参数都能在容器里修改，有些涉及到安全的参数是受限制的。云环境的优化策略在云环境下，有些优化策略需要调整。比如在AWS EC2上，网络性能跟实例类型关系很大。小实例的网络带宽有限，再怎么优化TCP参数也提升不了多少。这时候可能需要考虑升级实例类型。云硬盘的IOPS也是有限制的，特别是gp2类型的EBS，IOPS跟存储容量相关。如果IO是瓶颈，可能需要换成io1或者gp3类型。还有就是云厂商通常会提供一些优化建议，比如AWS的Enhanced Networking，阿里云的多队列网卡等，这些特性要充分利用起来。监控和告警设置优化不是一次性的工作，需要持续监控和调整。我一般会设置这些监控指标：系统层面：CPU使用率和负载内存使用率和swap使用情况磁盘IO和使用率网络流量和连接数应用层面：响应时间和吞吐量错误率连接池状态缓存命中率告警阈值不要设得太敏感，否则会有很多误报。我的经验是先设置得宽松一点，运行一段时间后根据实际情况再调整。# 简单的监控脚本示例 #!/bin/bash CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1) MEMORY_USAGE=$(free | grep Mem | awk '{printf "%.2f", $3/$2 * 100.0}') DISK_USAGE=$(df -h / | awk 'NR==2{print $5}' | cut -d'%' -f1) if [ $(echo "$CPU_USAGE > 80" | bc) -eq 1 ]; then echo "CPU使用率过高: $CPU_USAGE%" fi if [ $(echo "$MEMORY_USAGE > 85" | bc) -eq 1 ]; then echo "内存使用率过高: $MEMORY_USAGE%" fi版本升级的考虑Linux内核版本的选择也很重要。新版本通常会有性能改进和新特性，但稳定性可能不如LTS版本。对于生产环境，我一般推荐使用LTS版本，比如目前的5.4或5.15。这些版本经过了长期的测试和验证，bug相对较少。不过如果你的应用需要某些新特性，比如eBPF、io_uring等，可能就需要使用较新的内核版本。这时候要做好充分的测试。升级内核前一定要做好备份和回滚准备。我见过因为内核升级导致系统无法启动的情况，如果没有备份就很麻烦了。结论测试上面都是理论。我开了一台1c1g虚拟机实用ab测试结果如下：测试前的qps：59.54测试后的qps：61.53结论：不如加机器，当然还是有点作用的。这次是1c1g的。经过优化后有微量提升。但是在大点的实例上面，或许效果会更好！！！最后一哆嗦Linux内核优化确实是个技术活，但掌握了基本原理和常用参数，大部分场景都能应对。关键是要理解你的应用特点和性能瓶颈在哪里。网络密集型应用重点优化网络参数，IO密集型应用关注磁盘和文件系统，内存密集型应用调整内存管理策略。优化是个持续的过程，不要指望一次就能解决所有问题。先解决最明显的瓶颈，然后逐步完善。最重要的是要有监控和测试手段。没有数据支撑的优化都是盲目的，可能会适得其反。我这些年踩过的坑总结起来就是：备份、测试、监控、渐进式优化。只要按照这个原则来，基本不会出大问题。当然，每个环境都有自己的特点，我分享的这些经验只是个参考。具体怎么优化，还是要结合实际情况来分析。如果你在优化过程中遇到问题，欢迎交流讨论。毕竟这个领域的坑确实不少，大家一起填坑，能少走很多弯路。希望这篇文章对你有帮助。如果觉得有用的话，别忘了点赞转发，让更多的朋友看到。关注@运维躬行录，我会持续分享更多实用的运维技术和经验，咱们一起在运维这条路上越走越远！
生产环境血泪史：LVS+Keepalived高可用负载均衡从入门到跑路
今天跟大家分享一下用LVS+Keepalived搭建高可用负载均衡的实践（踩坑）。说起来也是巧，刚开始接触负载均衡的时候，我以为Nginx就是万能的（多希望能一招鲜吃遍天）。后来业务量上来了才发现，Nginx是七层的负载均衡。与四层负载均衡的主要区别在于工作层级和处理的数据内容。在四层负载均衡方面还是有局限性的。特别是那种大流量、高并发的场景，LVS的优势就体现出来了。什么是LVSLVS全称Linux虚拟服务器（LVS）是由章文嵩（国防科技大学）博士于1998年5月发起的一个开源项目，旨在通过集群技术构建高性能、高可用的虚拟服务器系统，是中国早期具有代表性的自由软件项目之一。其核心功能是通过IP负载均衡技术将客户端请求分发至服务器集群，实现服务的可伸缩性与透明性，支持TCP/UDP协议及持久连接。LVS采用三层架构：前端负载调度器（负责分发请求）、中间服务器池（处理实际服务）和底层共享存储（保障数据一致性）。系统提供三种IP负载均衡模式：基于网络地址转换的VS/NAT、基于IP隧道的VS/TUN以及基于直接路由的VS/DR，分别适配不同网络环境。调度算法包括轮询、加权最少连接等八种策略，优化资源分配。随着技术演进，LVS被集成至Linux内核，并广泛应用于Web、邮件等高并发场景，形成覆盖千级节点的集群框架。为什么选择LVS+Keepalived这个组合？这个问题我被问过无数次了。简单来说，LVS负责干活，Keepalived负责保命。LVS工作在内核空间，处理数据包的效率极高。我记得当时做压测，单台LVS能轻松处理几十万的并发连接，这个数据在当时简直让人不敢相信。而且LVS对后端服务器完全透明，不需要修改任何应用代码。但LVS有个致命缺陷，就是没有健康检查功能。如果后端服务器挂了，LVS还是会继续往那台机器上转发请求，用户就会看到连接超时的错误页面。这时候Keepalived就派上用场了。它不仅能提供健康检查，还能实现LVS的高可用。两台LVS服务器互为备份，主服务器挂了，备服务器立马接管，用户基本感觉不到。我之前用过F5这种硬件负载均衡器，功能确实强大，但价格也是真的贵。一台设备几十万，小公司根本用不起。LVS+Keepalived这个组合，成本低，性能好，稳定性也不差，性价比超高。架构设计和规划在开始配置之前，我们先来理一下整体架构。我一般会采用这样的设计：Internet | v VIP (虚拟IP) | v LVS Master/Backup (Keepalived) | v Real Servers (Web服务器集群)这个架构的好处是简单清晰，用户访问VIP，LVS负责将请求分发到后端的真实服务器上。如果主LVS挂了，备LVS会自动接管VIP，保证服务不中断。在实际部署中，我会准备至少4台服务器：2台LVS服务器（主备）2台以上的Web服务器当然，如果预算有限，也可以把LVS和Web服务器部署在同一批机器上，但这样会增加故障的风险。LVS的工作模式选择LVS有三种工作模式，我在生产环境中主要用DR模式。NAT模式虽然配置简单，但所有的响应流量都要经过LVS，容易成为瓶颈。我曾经在一个小项目中用过NAT模式，刚开始还好，但随着用户量增长，LVS的网卡很快就跑满了。TUN模式适合跨地域的部署，但配置复杂，而且对网络环境要求比较高。除非是特殊需求，否则我不建议使用。DR模式是我的首选。在这种模式下，LVS只处理入站流量，出站流量直接从后端服务器返回给客户端，避免了流量瓶颈。而且配置相对简单，性能也最好。DR模式的关键在于MAC地址重写。LVS收到客户端请求后，修改数据包的目标MAC地址，然后转发给后端服务器。后端服务器需要配置VIP作为回环地址，这样才能正确处理请求。实际配置过程好了，理论说得差不多了，现在开始实际配置。我以一个典型的Web服务负载均衡为例。环境准备假设我们有以下服务器：LVS1: 192.168.1.10 (主)LVS2: 192.168.1.11 (备)Web1: 192.168.1.20Web2: 192.168.1.21VIP: 192.168.1.100所有服务器都是CentOS 7系统，网卡名称为eth0。LVS服务器配置首先在两台LVS服务器上安装必要的软件：yum install -y ipvsadm keepalived然后配置内核参数，开启IP转发：echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf sysctl -pKeepalived主服务器配置在LVS1上创建keepalived配置文件 /etc/keepalived/keepalived.conf：! Configuration File for keepalived global_defs { notification_email { admin@example.com } notification_email_from keepalived@example.com smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id LVS_MASTER } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.100 } } virtual_server 192.168.1.100 80 { delay_loop 6 lb_algo wlc lb_kind DR persistence_timeout 0 protocol TCP real_server 192.168.1.20 80 { weight 3 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } real_server 192.168.1.21 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 80 } } }这个配置文件看起来复杂，但其实逻辑很清晰。上半部分是VRRP配置，用于实现主备切换；下半部分是LVS配置，定义了虚拟服务器和真实服务器。Keepalived备服务器配置在LVS2上的配置基本相同，只需要修改几个参数：vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 90 # 优先级要低于主服务器 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.100 } }注意priority参数，备服务器的优先级必须低于主服务器，这样才能保证正常情况下主服务器持有VIP。后端服务器配置这是DR模式配置中最容易出错的地方。每台后端服务器都需要配置VIP作为回环地址，并且设置ARP参数。在Web1和Web2上执行以下命令：# 配置VIP到回环接口 ifconfig lo:0 192.168.1.100 netmask 255.255.255.255 up # 设置ARP参数，防止ARP冲突 echo "1" > /proc/sys/net/ipv4/conf/lo/arp_ignore echo "2" > /proc/sys/net/ipv4/conf/lo/arp_announce echo "1" > /proc/sys/net/ipv4/conf/all/arp_ignore echo "2" > /proc/sys/net/ipv4/conf/all/arp_announce为了让配置永久生效，还需要写到系统配置文件中：# 写入网络配置文件 cat > /etc/sysconfig/network-scripts/ifcfg-lo:0 << EOF DEVICE=lo:0 IPADDR=192.168.1.100 NETMASK=255.255.255.255 ONBOOT=yes EOF # 写入内核参数配置 cat >> /etc/sysctl.conf << EOF net.ipv4.conf.lo.arp_ignore = 1 net.ipv4.conf.lo.arp_announce = 2 net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.all.arp_announce = 2 EOF sysctl -p启动和测试配置完成后，就可以启动服务了。在两台LVS服务器上启动keepalived：systemctl start keepalived systemctl enable keepalived启动后，可以通过以下命令检查状态：# 查看VIP是否绑定成功 ip addr show eth0 # 查看LVS规则 ipvsadm -ln # 查看keepalived日志 tail -f /var/log/messages如果一切正常，你应该能看到VIP绑定在主服务器的网卡上，LVS规则也正确加载了。测试的时候，我一般会用curl命令访问VIP：curl -I http://192.168.1.100如果能正常返回HTTP响应头，说明负载均衡工作正常。踩过的坑和解决方案在实际部署过程中，我遇到了不少问题，这里分享几个典型的。ARP问题这是DR模式最常见的问题。如果ARP参数配置不正确，会导致网络混乱，客户端无法正常访问。症状：客户端访问VIP时，有时能访问，有时不能访问，表现很不稳定。解决方案：确保所有后端服务器都正确配置了arp_ignore和arp_announce参数。这两个参数的作用是：arp_ignore=1：只响应目标IP是本机IP的ARP请求arp_announce=2：使用最合适的本地IP作为ARP请求的源IP脑裂问题有一次网络出现故障，两台LVS服务器都认为对方挂了，结果都绑定了VIP，造成了脑裂。为了避免这个问题，我在keepalived配置中增加了脚本检查：vrrp_script chk_http_port { script "/etc/keepalived/check_web.sh" interval 2 weight -2 fall 3 rise 2 } vrrp_instance VI_1 { # ... 其他配置 track_script { chk_http_port } }检查脚本 /etc/keepalived/check_web.sh：#!/bin/bash counter=$(ps -C httpd --no-heading|wc -l) if [ "${counter}" = "0" ]; then exit 1 else exit 0 fi这样，如果本机的Web服务出现问题，keepalived会自动降低优先级，让备服务器接管。性能调优刚开始部署的时候，性能并没有达到预期。后来发现是一些内核参数没有优化。# 增加连接跟踪表大小 echo 'net.netfilter.nf_conntrack_max = 1048576' >> /etc/sysctl.conf # 调整TCP参数 echo 'net.ipv4.tcp_tw_reuse = 1' >> /etc/sysctl.conf echo 'net.ipv4.tcp_tw_recycle = 1' >> /etc/sysctl.conf echo 'net.ipv4.tcp_fin_timeout = 30' >> /etc/sysctl.conf # 增加端口范围 echo 'net.ipv4.ip_local_port_range = 1024 65535' >> /etc/sysctl.conf sysctl -p还有一个重要的优化是网卡中断绑定。在高并发场景下，把网卡中断绑定到特定的CPU核心上，能显著提升性能：# 查看网卡中断号 cat /proc/interrupts | grep eth0 # 绑定中断到CPU核心（假设中断号是24） echo 2 > /proc/irq/24/smp_affinity监控和运维部署完成后，监控是必不可少的。我一般会监控以下几个指标：LVS连接状态# 查看连接统计 ipvsadm -ln --stats # 查看当前连接 ipvsadm -ln --connection # 查看连接数 cat /proc/net/ip_vs_stats系统资源监控# CPU使用率 top # 内存使用情况 free -h # 网络流量 iftop日志监控keepalived的日志通常记录在 /var/log/messages 中，需要定期检查是否有异常信息。我写了一个简单的监控脚本，定期检查服务状态：#!/bin/bash # 检查keepalived进程 if ! pgrep keepalived > /dev/null; then echo "Keepalived is not running!" # 发送告警邮件或短信 fi # 检查VIP是否绑定 if ! ip addr show eth0 | grep 192.168.1.100 > /dev/null; then echo "VIP is not bound to this server" fi # 检查后端服务器健康状态 ipvsadm -ln | grep -v "RemoteAddress" | while read line; do if echo $line | grep -q "Route"; then server=$(echo $line | awk '{print $2}') if ! nc -z ${server%:*} ${server#*:}; then echo "Server $server is down!" fi fi done故障处理经验在生产环境中，故障是不可避免的。我遇到过几次比较典型的故障，这里分享一下处理经验。主服务器宕机这种情况下，keepalived会自动进行主备切换，理论上用户不会感知到。但有一次切换过程中，发现新的主服务器上LVS规则没有正确加载。原因是keepalived配置文件中的virtual_server配置有问题。解决方法是在备服务器上手动执行：ipvsadm -C # 清空现有规则 systemctl restart keepalived # 重启keepalived为了避免这种情况，我现在都会在keepalived配置中添加notify脚本：vrrp_instance VI_1 { # ... 其他配置 notify_master "/etc/keepalived/notify_master.sh" notify_backup "/etc/keepalived/notify_backup.sh" notify_fault "/etc/keepalived/notify_fault.sh" }notify_master.sh脚本内容：#!/bin/bash echo "$(date) - Becoming MASTER" >> /var/log/keepalived-state.log # 确保LVS规则正确加载 sleep 2 ipvsadm -ln > /dev/null || systemctl restart keepalived后端服务器故障有一次其中一台Web服务器的磁盘满了，导致Apache无法正常工作。虽然keepalived的健康检查发现了问题，把这台服务器从负载均衡池中移除了，但用户还是反映偶尔会遇到访问异常。后来发现是健康检查的间隔时间设置得太长了。我把检查间隔从6秒调整到2秒，故障检测的敏感度提高了很多：virtual_server 192.168.1.100 80 { delay_loop 2 # 从6秒改为2秒 # ... 其他配置 }还有一个问题是TCP_CHECK只能检查端口是否开放，不能检查应用是否正常工作。比如Apache进程还在，但已经无法处理请求了。为了解决这个问题，我改用HTTP_GET检查：real_server 192.168.1.20 80 { weight 3 HTTP_GET { url { path /health.html status_code 200 } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } }在每台Web服务器上创建一个简单的健康检查页面 /var/www/html/health.html：OK这样就能更准确地检测应用的健康状态了。网络分区故障最麻烦的一次故障是机房网络出现了分区，两台LVS服务器之间无法通信，但都能正常访问外网。结果两台服务器都认为对方挂了，都绑定了VIP，造成了严重的网络混乱。这种情况下，最好的解决方案是引入第三方仲裁。我后来在配置中增加了多个检查点：vrrp_instance VI_1 { # ... 其他配置 unicast_src_ip 192.168.1.10 unicast_peer { 192.168.1.11 } }使用单播模式可以减少网络广播，提高稳定性。高级配置和优化随着业务的发展，基本的负载均衡配置可能无法满足需求。这里分享一些高级配置技巧。会话保持有些应用需要会话保持，比如购物车功能。LVS支持基于源IP的会话保持：virtual_server 192.168.1.100 80 { # ... 其他配置 persistence_timeout 300 # 会话保持5分钟 }但这种方式有个问题，如果用户通过NAT网关访问，多个用户可能会被分配到同一台服务器上，造成负载不均衡。更好的解决方案是在应用层实现会话共享，比如使用Redis存储session数据。多端口负载均衡如果需要对多个端口进行负载均衡，可以配置多个virtual_server：virtual_server 192.168.1.100 80 { # HTTP服务配置 } virtual_server 192.168.1.100 443 { # HTTPS服务配置 lb_algo wlc lb_kind DR protocol TCP real_server 192.168.1.20 443 { weight 1 TCP_CHECK { connect_port 443 } } }防火墙配置在生产环境中，防火墙配置很重要。需要开放以下端口：# LVS服务器之间的VRRP通信 firewall-cmd --permanent --add-rich-rule="rule family='ipv4' source address='192.168.1.0/24' protocol value='vrrp' accept" # 允许客户端访问VIP firewall-cmd --permanent --add-port=80/tcp firewall-cmd --permanent --add-port=443/tcp # 重新加载防火墙规则 firewall-cmd --reload容量规划和扩展随着业务增长，单个负载均衡集群可能无法满足需求。这时候需要考虑扩展方案。水平扩展最简单的方式是增加后端服务器。在keepalived配置中添加新的real_server即可：real_server 192.168.1.22 80 { weight 1 HTTP_GET { url { path /health.html status_code 200 } } }添加完配置后，重新加载keepalived：systemctl reload keepalived垂直扩展如果LVS服务器成为瓶颈，可以考虑升级硬件配置，特别是网卡和CPU。我曾经遇到过网卡成为瓶颈的情况，单个千兆网卡在高峰期跑满了。后来换成万兆网卡，问题就解决了。多层负载均衡对于超大规模的应用，可以考虑多层负载均衡架构：DNS轮询 -> LVS集群 -> Nginx集群 -> 应用服务器集群这样可以充分发挥每种技术的优势，实现更好的性能和可扩展性。与云服务的对比现在很多公司都在上云，云厂商提供的负载均衡服务确实很方便。但自建LVS集群也有它的优势。成本方面：云负载均衡按流量计费，对于大流量应用来说成本不低。自建LVS集群虽然需要投入人力维护，但硬件成本相对较低。可控性方面：自建集群可以根据业务需求进行深度定制，云服务的可定制性相对有限。数据安全方面：对于一些对数据安全要求极高的企业，自建集群可以避免数据经过第三方。当然，云服务也有明显的优势，比如免运维、高可用保障、弹性扩展等。具体选择哪种方案，需要根据企业的实际情况来决定。未来发展和新技术虽然LVS已经是个"老古董"了，但它的核心理念到现在还是很先进的。随着技术的发展，也出现了一些新的负载均衡技术。DPDK：基于用户空间的高性能数据包处理框架，能够实现更高的性能。XDP：Linux内核的新特性，可以在网卡驱动层进行数据包处理，性能比传统的netfilter更好。eBPF：可编程的内核技术，为负载均衡提供了更多的可能性。不过对于大部分企业来说，LVS的性能已经完全够用了。而且这些新技术的学习成本比较高，维护难度也更大。运维自动化手工维护LVS集群是很累的，特别是当集群规模比较大的时候。我现在都会用一些自动化工具来简化运维工作。Ansible自动化部署我写了一个Ansible playbook来自动化部署LVS集群：--- - hosts: lvs_servers tasks: - name: Install packages yum: name: "{{ item }}" state: present with_items: - ipvsadm - keepalived - name: Configure keepalived template: src: keepalived.conf.j2 dest: /etc/keepalived/keepalived.conf notify: restart keepalived - name: Start and enable keepalived service: name: keepalived state: started enabled: yes监控告警我用Zabbix来监控LVS集群的状态，配置了以下监控项：keepalived进程状态VIP绑定状态LVS连接数统计后端服务器健康状态系统资源使用情况当出现异常时，会自动发送邮件和短信告警。配置管理为了避免配置漂移，我把所有的配置文件都放在Git仓库中管理。每次修改配置都要经过代码审查，然后通过CI/CD流水线自动部署到生产环境。这样做的好处是配置变更有记录，出问题时可以快速回滚。总结和思考回顾之前使用LVS+Keepalived的经历，总的来说还是很满意的。虽然配置相对复杂一些，但稳定性和性能都很不错。特别是在一些对性能要求极高的场景中，LVS的优势非常明显。当然，技术选型没有银弹，适合的才是最好的。如果你的业务规模不大，用Nginx可能更合适；如果预算充足，云负载均衡也是不错的选择。但如果你面临高并发、大流量的挑战，又希望有更多的控制权，LVS+Keepalived绝对值得考虑。最后想说的是，运维这个工作就是这样，没有一劳永逸的解决方案。技术在不断发展，业务需求也在不断变化，我们需要保持学习的心态，不断提升自己的技能。LVS虽然不是最新的技术，但它经受了时间的考验，在很多大型互联网公司都有应用。掌握LVS的配置和优化，对于运维工程师来说还是很有价值的。希望我的这些经验能对大家有所帮助。运维路上，我们一起加油！好了，今天关于LVS+Keepalived的分享就到这里。这套方案我看人在生产环境中用了好几年，踩过不少坑，也积累了一些经验。如果你正在考虑搭建高可用的负载均衡集群，希望这篇文章能给你一些参考。当然，技术这东西日新月异，我分享的可能不是最新最炫的方案，但绝对是经过实战检验的可靠方案。在选择技术方案的时候，稳定性往往比新颖性更重要。如果你在实施过程中遇到问题，欢迎留言讨论。运维这条路上，大家互相帮助，共同进步。记得关注@运维躬行录，领取学习资料。我会持续分享更多实用的运维技术和经验！
踩坑无数！NFS服务从入门到放弃再到真香的血泪史
前言说起NFS，我估计很多搞运维的兄弟都有一肚子话要说。这玩意儿吧，看起来简单，用起来坑多，但是真正搞明白了又觉得挺香的。前几天有个朋友问我，说他们公司要搭建一个文件共享系统，问我推荐什么方案。我第一反应就是NFS，毕竟这货在Linux环境下用了这么多年，虽然毛病不少，但胜在稳定可靠。结果这哥们儿一脸懵逼地看着我："NFS是啥？"好吧，看来有必要写篇文章好好聊聊NFS了。我从2020年开始接触这东西，到现在也算是爱恨交加了。今天就把我这些年踩过的坑和积累的经验分享给大家。NFS到底是个什么鬼NFS全称Network File System，网络文件系统。简单来说，就是让你可以像访问本地文件一样访问远程服务器上的文件。听起来很牛逼对吧？实际上原理也不复杂。NFS的工作原理其实就是客户端和服务端的通信。服务端把某个目录"导出"（export），客户端就可以把这个远程目录"挂载"（mount）到本地的某个挂载点上。挂载完成后，你在客户端操作这个目录，实际上就是在操作服务端的文件。不过这里有个坑，NFS默认使用的是UDP协议，在网络不稳定的环境下容易出问题。现在一般都推荐用TCP，虽然性能稍微差一点，但稳定性好很多。搭建NFS服务的那些事儿服务端配置在CentOS系统上安装NFS还是比较简单的：yum install -y nfs-utils rpcbind安装完成后需要启动相关服务：systemctl start rpcbind systemctl start nfs-server systemctl enable rpcbind systemctl enable nfs-server这里要注意一个细节，rpcbind必须先启动，因为NFS依赖RPC服务。我之前就因为这个顺序问题折腾了半天。接下来就是配置导出目录了，编辑/etc/exports文件：/data/share 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check) /home/backup 192.168.1.100(ro,sync,root_squash)这个配置文件的语法看起来有点奇怪，但其实很好理解。第一行表示把/data/share目录共享给192.168.1.0/24网段的所有主机，权限是读写，同步写入，不压缩root权限。说到权限配置，这里面的坑可不少。no_root_squash这个选项要慎用，它允许客户端的root用户在NFS服务器上也有root权限。如果你的网络环境不够安全，这就是个巨大的安全隐患。配置完成后，重新加载配置：exportfs -ra可以用exportfs -v查看当前的导出状态。客户端挂载客户端的配置相对简单一些，同样需要安装nfs-utils：yum install -y nfs-utils然后就可以挂载了：mount -t nfs 192.168.1.10:/data/share /mnt/nfs不过我建议在挂载时指定一些参数：mount -t nfs -o tcp,rsize=32768,wsize=32768,hard,intr 192.168.1.10:/data/share /mnt/nfs这些参数的含义：tcp：使用TCP协议rsize/wsize：读写缓冲区大小hard：硬挂载，网络中断时会一直重试intr：允许中断如果要开机自动挂载，可以在/etc/fstab中添加：#添加完成一定要记得mount -a，检查下配置是否正确！！！！ 192.168.1.10:/data/share /mnt/nfs nfs tcp,rsize=32768,wsize=32768,hard,intr 0 0性能调优这个老大难问题NFS的性能一直是个让人头疼的问题。我记得有一次，业务部门抱怨说文件传输太慢了，让我优化一下。当时我就想，这能有多慢？结果一测试，好家伙，传输速度只有几MB/s，这在千兆网络环境下简直不能忍。网络层面的优化网络配置对NFS性能影响很大。我发现很多人在配置时都忽略了网络参数的调整。在服务端，可以增加NFS守护进程的数量：# 编辑 /etc/sysconfig/nfs RPCNFSDCOUNT=16默认情况下，NFS只启动8个守护进程，在高并发场景下明显不够用。我一般会根据CPU核心数来设置，比如16核的服务器就设置16个进程。另外，网络缓冲区的大小也很关键：# 在 /etc/sysctl.conf 中添加 net.core.rmem_default = 262144 net.core.rmem_max = 16777216 net.core.wmem_default = 262144 net.core.wmem_max = 16777216存储层面的考虑NFS的性能很大程度上取决于底层存储。如果你的服务器用的是机械硬盘，那性能肯定好不到哪里去。我之前在一个项目中，把NFS服务器的存储从SATA硬盘换成SSD，性能提升了好几倍。文件系统的选择也很重要。ext4虽然稳定，但在大文件和高并发场景下性能一般。如果条件允许，我更推荐使用XFS文件系统，特别是在处理大文件时。挂载参数的调整客户端的挂载参数对性能影响也不小。我一般会这样配置：mount -t nfs -o tcp,rsize=65536,wsize=65536,hard,intr,timeo=14,intr 192.168.1.10:/data/share /mnt/nfsrsize和wsize设置得大一些可以减少网络往返次数，但也不能设置得太大，否则可能会出现网络包分片的问题。安全配置不能马虎NFS的安全性一直是个争议话题。说实话，NFS在设计之初就没有太多考虑安全问题，所以在使用时需要格外小心。网络层面的安全最基本的安全措施就是限制访问网段。在/etc/exports中，一定要明确指定允许访问的IP地址或网段，千万不要使用通配符。我见过有人这样配置：/data/share *(rw,sync,no_root_squash)这简直就是在裸奔！任何能访问到你服务器的主机都可以挂载你的NFS共享，而且还有root权限。正确的做法应该是：/data/share 192.168.1.100(rw,sync,root_squash) /data/share 192.168.1.101(rw,sync,root_squash)防火墙配置NFS使用的端口比较多，除了固定的111端口（rpcbind）和2049端口（nfs）外，还有一些随机端口。为了方便防火墙配置，可以固定这些端口。在/etc/sysconfig/nfs中添加：RQUOTAD_PORT=875 LOCKD_TCPPORT=32803 LOCKD_UDPPORT=32769 MOUNTD_PORT=892 STATD_PORT=662然后在防火墙中开放这些端口：firewall-cmd --permanent --add-port=111/tcp firewall-cmd --permanent --add-port=2049/tcp firewall-cmd --permanent --add-port=875/tcp firewall-cmd --permanent --add-port=32803/tcp firewall-cmd --permanent --add-port=32769/udp firewall-cmd --permanent --add-port=892/tcp firewall-cmd --permanent --add-port=662/tcp firewall-cmd --reload用户权限管理NFS的用户权限管理是个比较复杂的话题。默认情况下，NFS会根据UID和GID来判断用户权限，这就要求客户端和服务端的用户ID必须一致。在实际使用中，我一般会创建专门的NFS用户：# 在服务端和客户端都创建相同的用户 useradd -u 1001 nfsuser然后把共享目录的所有者设置为这个用户：chown -R nfsuser:nfsuser /data/share故障排查的血泪经验搞NFS这么多年，遇到的奇葩问题不计其数。有些问题看起来很简单，但排查起来却让人抓狂。挂载失败的常见原因最常见的问题就是挂载失败。每次遇到这种问题，我都会按照这个顺序排查：检查网络连通性ping 192.168.1.10 telnet 192.168.1.10 2049检查服务状态systemctl status rpcbind systemctl status nfs-server检查导出状态exportfs -v showmount -e 192.168.1.10有一次我遇到一个很奇怪的问题，showmount可以看到导出的目录，但就是挂载不上。折腾了半天才发现是SELinux的问题。setsebool -P nfs_export_all_rw 1 setsebool -P nfs_export_all_ro 1性能问题的排查性能问题相对比较难排查，因为影响因素太多了。我一般会从这几个方面入手：网络层面，用iperf测试网络带宽：# 服务端 iperf -s # 客户端 iperf -c 192.168.1.10存储层面，用dd测试磁盘性能：dd if=/dev/zero of=/data/share/testfile bs=1M count=1024NFS层面，用nfsstat查看统计信息：nfsstat -c # 客户端统 nfsstat -s # 服务端统计有一次我就是通过nfsstat发现了问题，客户端的retrans（重传）次数特别高，说明网络有问题。后来发现是交换机的某个端口有故障。文件锁的诡异问题NFS的文件锁机制真的是让人又爱又恨。理论上很美好，实际使用中问题一大堆。我印象最深的一次是，有个应用程序在NFS上创建了文件锁，结果服务器突然断电了。重启后，这个锁就一直释放不掉，导致应用程序无法正常工作。当时试了各种方法，最后只能这样解决：# 停止相关服务 systemctl stop nfs-server systemctl stop rpc-statd # 清理锁文件 rm -rf /var/lib/nfs/sm/* rm -rf /var/lib/nfs/sm.bak/* # 重启服务 systemctl start rpc-statd systemctl start nfs-server不过这种方法比较暴力，会影响所有客户端。在生产环境中要慎用！！！！！！！！！！！实际应用场景的经验分享这么多年下来，我在不同的场景中都用过NFS，每种场景都有自己的特点和坑点。Web服务器集群的文件共享最常见的应用就是Web服务器集群了。多台Web服务器需要共享静态文件，比如图片、CSS、JS等。在这种场景下，我一般会这样配置：# 服务端导出配置 /var/www/html/static 192.168.1.0/24(ro,sync,root_squash,no_subtree_check)注意这里用的是只读权限，因为静态文件一般不需要在Web服务器上修改。如果需要上传文件，我会单独配置一个可写的目录。客户端挂载时，我会使用这样的参数：mount -t nfs -o tcp,ro,rsize=32768,wsize=32768,hard,intr,noatime 192.168.1.10:/var/www/html/static /var/www/html/staticnoatime参数很重要，它可以避免每次读取文件时更新访问时间，能显著提升性能。数据库备份的存储另一个常见场景就是数据库备份。我们有多台数据库服务器，需要把备份文件统一存储到一个地方。这种场景下，安全性比性能更重要：# 服务端配置 /data/backup 192.168.1.100(rw,sync,root_squash,no_subtree_check) /data/backup 192.168.1.101(rw,sync,root_squash,no_subtree_check)客户端挂载时，我会设置比较保守的参数：mount -t nfs -o tcp,rw,rsize=8192,wsize=8192,hard,intr,timeo=30 192.168.1.10:/data/backup /backup缓冲区设置得小一些，超时时间长一些，确保数据的完整性。开发环境的代码共享在开发环境中，经常需要多个开发者共享代码。这时候NFS就很方便了，大家都可以直接在自己的机器上编辑代码。不过这种场景下要注意权限问题。我一般会创建一个开发组：groupadd -g 2000 developers然后把所有开发者都加到这个组里，共享目录的权限设置为组可写：chgrp -R developers /data/code chmod -R g+w /data/codeNFS的替代方案思考虽然我用NFS用了这么多年，但不得不承认，它确实有不少局限性。在某些场景下，其他方案可能更合适。SSHFS的优势SSHFS基于SSH协议，安全性比NFS好很多。配置也特别简单：sshfs user@192.168.1.10:/data/share /mnt/sshfs我在一些对安全性要求比较高的项目中会选择SSHFS。虽然性能比NFS差一些，但胜在安全可靠。分布式文件系统的崛起现在越来越多的公司开始使用分布式文件系统，比如GlusterFS、CephFS等。这些系统在可用性和扩展性方面比NFS强很多。我之前参与过一个项目，就是把原来的NFS系统迁移到GlusterFS。虽然迁移过程比较复杂，但迁移完成后，系统的可用性确实提升了不少。对象存储的兴起在云计算时代，对象存储也是个不错的选择。比如AWS的S3、阿里云的OSS等。虽然访问方式和传统文件系统不太一样，但在某些场景下更适合。一些实用的小技巧这些年积累了不少NFS使用的小技巧，分享给大家：自动挂载的配置手动挂载NFS比较麻烦，可以配置自动挂载。安装autofs：yum install -y autofs编辑/etc/auto.master：/mnt/auto /etc/auto.nfs --timeout=60创建/etc/auto.nfs：share -tcp,rw 192.168.1.10:/data/share这样，当你访问/mnt/auto/share时，系统会自动挂载NFS。监控脚本的编写NFS服务的稳定性监控很重要，我写了个简单的监控脚本：#!/bin/bash NFS_SERVER="192.168.1.10" NFS_PATH="/data/share" MOUNT_POINT="/mnt/nfs" if ! mountpoint -q $MOUNT_POINT; then echo "NFS not mounted, trying to mount..." mount -t nfs $NFS_SERVER:$NFS_PATH $MOUNT_POINT fi if ! timeout 5 ls $MOUNT_POINT > /dev/null 2>&1; then echo "NFS access failed, remounting..." umount -f $MOUNT_POINT mount -t nfs $NFS_SERVER:$NFS_PATH $MOUNT_POINT fi把这个脚本加到crontab里，每分钟执行一次，可以自动处理一些常见的NFS问题。性能测试的方法想要知道NFS的性能如何，可以用这个简单的测试：# 写入测试 time dd if=/dev/zero of=/mnt/nfs/testfile bs=1M count=1024 # 读取测试 echo 3 > /proc/sys/vm/drop_caches # 清理缓存 time dd if=/mnt/nfs/testfile of=/dev/null bs=1M这个测试虽然简单，但能大致反映NFS的性能水平。踩过的坑和经验教训说了这么多技术细节，最后想分享一些我踩过的坑，希望大家能避免。不要忽视网络质量有一次，业务部门反映NFS访问特别慢，我检查了服务器配置、存储性能，都没问题。最后发现是网络设备有问题，丢包率达到了5%。在这种网络环境下，NFS的性能肯定好不了。所以在部署NFS之前，一定要先测试网络质量。备份配置文件的重要性还有一次，我在调整NFS配置时，不小心把/etc/exports文件搞坏了。结果所有客户端都挂载不上了，业务直接中断。幸好我有备份配置文件的习惯，很快就恢复了。从那以后，我每次修改配置前都会先备份：cp /etc/exports /etc/exports.bak.$(date +%Y%m%d)权限问题要提前规划NFS的权限管理比较复杂，如果不提前规划好，后期会很麻烦。我建议在部署之前就把用户权限体系设计好，包括用户ID的分配、组的设置等。监控和告警不能少NFS服务虽然相对稳定，但也会出现各种问题。一定要做好监控和告警，及时发现问题。我一般会监控这些指标：NFS服务的运行状态挂载点的可用性网络连通性磁盘空间使用率总结写了这么多，感觉还有很多东西没有涉及到。NFS这个东西，说简单也简单，说复杂也复杂。关键是要在实践中不断积累经验。我的建议是：在内网环境下使用，不要暴露到公网做好安全配置，不要图省事给过大权限根据实际场景调整性能参数做好监控和备份，及时发现和解决问题在高可用要求的场景下考虑其他方案NFS虽然有这样那样的问题，但在合适的场景下，它依然是个不错的选择。特别是在中小型企业的内网环境中，NFS的简单易用还是很有优势的。当然，技术在不断发展，新的文件共享方案也在不断涌现。我们要保持学习的心态，根据实际需求选择最合适的方案。希望这篇文章能帮到正在使用或者准备使用NFS的朋友们。如果你们在使用过程中遇到什么问题，或者有更好的经验分享，欢迎在评论区交流讨论！记得关注微信公众号@运维躬行录，我会持续分享更多实用的运维经验和技术干货。如果这篇文章对你有帮助，别忘了点赞转发，让更多的朋友看到！
最近在群里看到好多小伙伴都在问Linux网络配置的问题，有的说CentOS 7升级到8之后网络配置文件找不到了，有的说Ubuntu的netplan怎么这么难用，还有人抱怨RHEL的网络服务老是起不来。我也是被这个问题搞得焦头烂额，有一次配置服务器网络，折腾了一很久，最后发现是NetworkManager和network服务冲突了...今天就来聊聊Linux网络配置这个话题，把我这些年踩过的坑和总结的经验分享给大家。为什么Linux网络配置这么复杂？说起来也挺无奈的，Linux发行版那么多，每个都有自己的网络配置方式。RedHat系的用一套，Debian系的用另一套，新版本又和老版本不一样。就像我们平时用的手机，安卓和iOS操作方式完全不同，同一个品牌的不同版本界面也会变。我记得刚开始接触Linux的时候，用的是CentOS 6，网络配置还算简单，就是编辑/etc/sysconfig/network-scripts/下面的配置文件。后来CentOS 7出来了，多了个NetworkManager，配置方式又变了。再后来CentOS 8直接把network服务给废弃了，只能用NetworkManager。你说这不是折腾人吗？不过话说回来，这些变化也不是没有道理的。新的网络管理工具确实功能更强大，支持动态配置，图形界面也更友好。只是我们这些搞运维的，总是要适应各种变化。CentOS系列的网络配置先说说CentOS，这个应该是大家接触最多的发行版了。CentOS 6/7 传统配置方式在CentOS 6和7上，最传统的方式就是直接编辑配置文件。网卡配置文件一般在/etc/sysconfig/network-scripts/目录下，文件名格式是ifcfg-网卡名。# 查看网卡名称 ip addr show # 或者用老命令 ifconfig -a比如我要配置eth0网卡的静态IP，就编辑/etc/sysconfig/network-scripts/ifcfg-eth0文件：TYPE=Ethernet BOOTPROTO=static NAME=eth0 DEVICE=eth0 ONBOOT=yes IPADDR=192.168.1.100 NETMASK=255.255.255.0 GATEWAY=192.168.1.1 DNS1=8.8.8.8 DNS2=8.8.4.4这里有几个参数需要注意：BOOTPROTO：启动协议，static表示静态IP，dhcp表示动态获取ONBOOT：开机是否启动网卡，一般设置为yesIPADDR：IP地址NETMASK：子网掩码，也可以用PREFIX=24这种CIDR格式GATEWAY：网关地址配置完成后重启网络服务：systemctl restart network # 或者只重启某个网卡 ifdown eth0 && ifup eth0我之前遇到过一个坑，就是配置文件里有多余的空格或者特殊字符，导致网络服务启动失败。所以编辑配置文件的时候一定要小心，最好用vim的话开启语法高亮。CentOS 7/8 NetworkManager方式CentOS 7开始引入了NetworkManager，这个工具确实方便很多，支持命令行和图形界面配置。用nmcli命令可以很方便地配置网络：# 查看网络连接状态 nmcli con show # 配置静态IP nmcli con mod eth0 ipv4.addresses 192.168.1.100/24 nmcli con mod eth0 ipv4.gateway 192.168.1.1 nmcli con mod eth0 ipv4.dns "8.8.8.8 8.8.4.4" nmcli con mod eth0 ipv4.method manual # 激活配置 nmcli con up eth0NetworkManager的好处是配置立即生效，不需要重启网络服务。而且它会自动生成传统的配置文件，兼容性比较好。不过我发现有些同事不太习惯用nmcli，觉得命令太长记不住。其实可以用tab键自动补全，多用几次就熟悉了。RHEL 8/9 的变化RHEL 8开始，传统的network服务被完全移除了，只能使用NetworkManager。这个变化刚开始确实让人不适应，特别是一些自动化脚本需要重写。RHEL 9又引入了一些新特性，比如更好的网络团队（team）和绑定（bond）支持。不过基本的配置方式和RHEL 8差不多。Ubuntu系列的网络配置Ubuntu的网络配置和CentOS完全不同，特别是从18.04开始引入netplan之后，很多人都不太适应。Ubuntu 16.04及之前版本老版本的Ubuntu使用的是/etc/network/interfaces文件：# 静态IP配置 auto eth0 iface eth0 inet static address 192.168.1.100 netmask 255.255.255.0 gateway 192.168.1.1 dns-nameservers 8.8.8.8 8.8.4.4 # DHCP配置 auto eth0 iface eth0 inet dhcp配置完成后重启网络：sudo /etc/init.d/networking restart # 或者 sudo service networking restart这种配置方式比较直观，语法也不复杂。但是功能相对简单，不支持一些高级特性。Ubuntu 18.04+ Netplan配置从18.04开始，Ubuntu引入了netplan作为网络配置工具。配置文件是YAML格式，位于/etc/netplan/目录下。# /etc/netplan/01-netcfg.yaml network: version: 2 renderer: networkd ethernets: eth0: dhcp4: false addresses: - 192.168.1.100/24 gateway4: 192.168.1.1 nameservers: addresses: [8.8.8.8, 8.8.4.4]应用配置：sudo netplan applyYAML格式对缩进要求很严格，必须用空格不能用tab。我刚开始用的时候经常因为缩进问题导致配置失败，后来养成了用vim显示空白字符的习惯。netplan的好处是支持多种后端（networkd和NetworkManager），配置也比较灵活。但是YAML语法确实需要适应一下。Debian系列配置Debian的网络配置和Ubuntu早期版本类似，主要使用/etc/network/interfaces文件。# /etc/network/interfaces source /etc/network/interfaces.d/* auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 192.168.1.100/24 gateway 192.168.1.1DNS配置在/etc/resolv.conf文件中：nameserver 8.8.8.8 nameserver 8.8.4.4重启网络服务：sudo systemctl restart networkingDebian 11开始也可以选择使用NetworkManager，但默认还是传统的配置方式。这个不错，我很喜欢！网络配置的常见问题和解决方案网卡名称变化问题现在的Linux系统网卡名称不再是传统的eth0、eth1，而是类似ens33、enp0s3这样的名称。这是因为systemd引入了可预测的网络接口命名规则。如果想改回传统命名，可以在grub配置中添加参数：# 编辑/etc/default/grub GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0" # 更新grub配置 grub2-mkconfig -o /boot/grub2/grub.cfg不过我个人建议还是适应新的命名规则，因为它确实更稳定，不会因为硬件变化导致网卡名称改变。NetworkManager和network服务冲突在CentOS 7上，如果同时启用了NetworkManager和network服务，可能会出现冲突。一般建议只使用其中一个：# 使用NetworkManager systemctl enable NetworkManager systemctl disable network # 或者使用传统network服务 systemctl enable network systemctl disable NetworkManagerDNS配置不生效有时候配置了DNS服务器，但是解析还是有问题。这可能是因为/etc/resolv.conf被其他程序覆盖了。在使用NetworkManager的系统上，DNS配置应该通过NetworkManager设置，而不是直接编辑/etc/resolv.conf。网络配置后无法连接配置静态IP后如果无法连接网络，首先检查几个方面：IP地址是否和网关在同一网段网关地址是否正确DNS服务器是否可达防火墙规则是否阻止了连接可以用这些命令进行诊断：# 检查IP配置 ip addr show # 检查路由表 ip route show # 测试网关连通性 ping 192.168.1.1 # 测试DNS解析 nslookup www.baidu.com一些实用的网络配置技巧配置网络别名有时候需要在一个网卡上配置多个IP地址，可以使用网络别名：# CentOS方式 cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0:1 # 修改ifcfg-eth0:1文件中的IP地址 # 或者用ip命令临时添加 ip addr add 192.168.1.101/24 dev eth0配置网络绑定（bond）在生产环境中，为了提高网络可靠性，经常需要配置网络绑定：# 创建bond配置文件 # /etc/sysconfig/network-scripts/ifcfg-bond0 DEVICE=bond0 TYPE=Bond BONDING_MASTER=yes BOOTPROTO=static IPADDR=192.168.1.100 NETMASK=255.255.255.0 BONDING_OPTS="mode=1 miimon=100"然后配置物理网卡：# /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 TYPE=Ethernet BOOTPROTO=none MASTER=bond0 SLAVE=yes # /etc/sysconfig/network-scripts/ifcfg-eth1 DEVICE=eth1 TYPE=Ethernet BOOTPROTO=none MASTER=bond0 SLAVE=yes重启网络服务后，两块网卡就会绑定在一起，提供冗余和负载均衡。使用nmtui图形界面对于不熟悉命令行的同事，我一般推荐用nmtui这个文本图形界面工具：nmtui这个工具提供了菜单式的操作界面，用方向键和回车就能完成网络配置，比较适合新手使用。不同环境下的网络配置策略物理服务器环境物理服务器的网络配置相对简单，一般就是配置静态IP。需要注意的是要提前规划好IP地址段，避免冲突。我们公司的做法是用Excel表格记录每台服务器的网络信息，包括IP、MAC地址、用途等。虚拟化环境在VMware或者KVM环境中，网络配置需要考虑虚拟交换机的设置。有时候虚拟机网络不通，不一定是虚拟机内部配置问题，可能是虚拟交换机或者宿主机网络配置有问题。我遇到过一次，虚拟机怎么配置都上不了网，最后发现是VMware的NAT服务没有启动。这种问题排查起来比较麻烦，需要从虚拟机到宿主机逐层检查。云环境配置在阿里云、腾讯云这些公有云环境中，网络配置又有所不同。云服务器通常使用cloud-init进行初始化配置，支持在创建实例时指定网络参数。# cloud-init网络配置示例 network: version: 1 config: - type: physical name: eth0 subnets: - type: static address: 10.0.0.100/24 gateway: 10.0.0.1云环境的好处是网络配置相对标准化，但是要注意安全组规则的设置，有时候网络不通是因为安全组阻止了流量。网络配置的自动化实践随着服务器数量增加，手动配置网络显然不现实。我们团队现在主要用Ansible进行批量配置。Ansible网络配置模板- name: Configure network interface template: src: ifcfg-eth0.j2 dest: /etc/sysconfig/network-scripts/ifcfg-{{ ansible_default_ipv4.interface }} backup: yes notify: restart network - name: Restart network service systemd: name: network state: restarted when: ansible_os_family == "RedHat"模板文件ifcfg-eth0.j2：TYPE=Ethernet BOOTPROTO=static DEVICE={{ ansible_default_ipv4.interface }} ONBOOT=yes IPADDR={{ server_ip }} NETMASK={{ server_netmask }} GATEWAY={{ server_gateway }} DNS1={{ dns_server1 }} DNS2={{ dns_server2 }}这样可以根据不同服务器的变量自动生成配置文件，大大提高了效率。配置管理的最佳实践版本控制：所有网络配置都要纳入Git管理，方便追踪变更历史。环境隔离：开发、测试、生产环境使用不同的IP段，避免相互影响。文档化：维护详细的网络拓扑图和IP地址分配表。监控告警：部署网络监控工具，及时发现网络异常。我们现在用Zabbix监控网络状态，一旦发现网络中断或者延迟过高，会立即发送告警信息。网络故障排查思路网络问题排查是运维工作中的常见任务，我总结了一套比较实用的排查思路：分层排查法按照OSI七层模型从下往上排查：物理层：检查网线、网卡指示灯数据链路层：检查交换机端口状态网络层：检查IP配置、路由表传输层：检查端口监听状态应用层：检查应用程序配置常用排查命令# 检查网卡状态 ethtool eth0 # 检查网络连通性 ping -c 4 192.168.1.1 # 检查路由 traceroute 8.8.8.8 # 检查端口 netstat -tlnp | grep :80 ss -tlnp | grep :80 # 检查DNS解析 dig www.baidu.com nslookup www.baidu.com # 抓包分析 tcpdump -i eth0 host 192.168.1.100有一次我们的Web服务突然访问很慢，用ping测试网络延迟正常，最后用tcpdump抓包发现是DNS解析慢导致的。换了DNS服务器后问题就解决了。安全考虑网络配置不仅要考虑功能，还要考虑安全性：防火墙配置# CentOS 7/8 使用firewalld firewall-cmd --permanent --add-service=ssh firewall-cmd --permanent --add-port=80/tcp firewall-cmd --reload # Ubuntu使用ufw ufw allow ssh ufw allow 80/tcp ufw enableSSH安全配置# 修改/etc/ssh/sshd_config Port 2222 # 修改默认端口 PermitRootLogin no # 禁止root直接登录 PasswordAuthentication no # 禁用密码认证，只允许密钥认证网络访问控制可以通过iptables或者云安全组限制网络访问：# 只允许特定IP访问SSH iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j DROP这些安全措施看起来简单，但是在实际环境中经常被忽视。我见过不少因为网络安全配置不当导致的安全事件。总结Linux网络配置确实比较复杂，不同发行版有不同的方式，新老版本之间也有差异。但是掌握了基本原理和常用方法，处理起来也不算太难。关键是要理解每种配置方式的特点：传统配置文件方式适合静态环境，配置相对固定NetworkManager适合需要动态配置的场景netplan提供了统一的配置接口，语法相对现代化我的建议是选择一种方式深入掌握，然后再了解其他方式。这样遇到不同环境时也能快速适应。最重要的是多实践多总结。网络配置这种东西，光看理论没用，必须自己动手配置才能真正掌握。我当年就是在虚拟机里反复练习，把各种配置方式都试了一遍。现在云计算和容器技术发展很快，网络配置也在不断演进。比如Kubernetes的网络模型、Docker的网络配置等，都需要我们持续学习。技术在变，但基础原理不会变。掌握好Linux网络配置的基础知识，对理解更复杂的网络架构也很有帮助。希望这篇文章能帮到大家解决一些实际问题。如果你在网络配置过程中遇到了其他问题，或者有什么好的经验分享，欢迎在评论区讨论。毕竟技术这东西，大家一起交流才能进步得更快。如果这篇文章对你有帮助，别忘了点赞转发支持一下！想了解更多运维实战经验和技术干货，记得关注微信公众号@运维躬行录，我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习，共同进步！
时间同步终极指南！NTP vs Chrony实战对比，选错了可能要背锅
前几天刚处理完一个让人哭笑不得的故障，某个微服务集群因为时间不同步，导致分布式锁失效，整个系统差点瘫痪。事后复盘的时候发现，居然还有服务器在用系统默认的时间同步配置，时间差了快10分钟！我刚开始的时候，对时间同步这块也是完全不重视。直到有一次因为服务器时间不一致，日志分析的时候完全理不清头绪，花了一整夜才找到问题根源。还有oracle数据库 集群故障。因为时间不同部导致同步数据异常等。从那以后我就明白了，在分布式系统里或者需要数据同步的系统里，时间同步绝对不是小事。现在主流的时间同步方案主要有两个：传统的NTP和相对较新的Chrony。今天就来详细聊聊这两个工具，看看在不同场景下该怎么选择。为什么时间同步这么重要你可能觉得几分钟的时间差能有什么大不了的，但在生产环境中，这可能就是灾难的开始。我遇到过最典型的一个案例，某个金融系统的风控规则依赖时间戳来判断交易的时效性。结果几台服务器时间不一致，导致部分正常交易被误判为异常，客户投诉电话接到手软。还有一次更离谱的，因为数据库主从服务器时间差了几分钟，主从同步的延迟判断完全错乱，差点造成数据不一致。除了业务逻辑问题，运维工作也会受到很大影响。当你需要分析分布式系统的调用链路时，如果各个服务的时间都不一样，根本没法按时间线来追踪问题。这就像看一部时间线错乱的电影，完全搞不清楚剧情发展。更要命的是，现在很多监控告警系统都依赖时间戳。如果时间不同步，可能会出现告警时间错乱，甚至漏掉重要的告警信息。NTP：老牌时间同步方案NTP（Network Time Protocol）是个非常成熟的协议，从1985年就开始发展，到现在已经是第四版了。它的设计思路很巧妙，不是简单地复制时间，而是通过复杂的算法来计算网络延迟和时间偏差。NTP的工作原理有点像你和朋友约时间见面的过程。客户端发送一个带时间戳的请求，服务器收到后记录接收时间，然后把自己的时间和接收时间一起发回去。客户端收到回复后，通过这四个时间戳来计算网络延迟，然后调整本地时间。NTP还有个分层的概念叫Stratum。Stratum 0是最准确的时间源，比如原子钟、GPS时钟。Stratum 1直接连接到Stratum 0，Stratum 2从Stratum 1同步，以此类推。我们平时用的公共NTP服务器一般都是Stratum 2或3。NTP的安装配置在CentOS/RHEL系统上安装NTP：yum install ntp -yUbuntu/Debian系统：apt-get install ntp -yNTP的核心配置文件是 /etc/ntp.conf，刚开始看可能有点复杂，但核心就几个配置项：# 配置上游NTP服务器 server 0.centos.pool.ntp.org iburst server 1.centos.pool.ntp.org iburst server 2.centos.pool.ntp.org iburst server 3.centos.pool.ntp.org iburst # 允许内网客户端同步（如果作为服务器） restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap # 本地时钟作为备用时间源 server 127.127.1.0 fudge 127.127.1.0 stratum 10 # 禁用监控功能，防止被利用进行DDoS攻击 disable monitor # 日志配置 logfile /var/log/ntp.log这里几个参数解释一下：iburst可以加快初始同步速度，启动时会连续发送8个包。restrict用来控制访问权限，nomodify表示客户端不能修改服务器配置，notrap表示不提供trap服务。配置完成后启动服务：systemctl start ntpd systemctl enable ntpd启动后需要等几分钟才能完全同步。可以用 ntpq -p 查看同步状态：[root@server ~]# ntpq -p remote refid st t when poll reach delay offset jitter ============================================================================== *ntp1.aliyun.com .PTP. 1 u 64 64 377 23.123 -2.123 1.234 +ntp2.aliyun.com .PTP. 1 u 32 64 377 25.456 1.456 2.345星号(*)表示当前使用的时间源，加号(+)表示备用时间源。reach列显示377表示最近8次通信都成功了。NTP的常见问题NTP有个让人头疼的特点，就是同步速度比较慢，特别是时间差比较大的时候。这是因为NTP默认采用渐进式调整，而不是直接跳跃到正确时间。如果时间差超过1000秒，NTP甚至会拒绝同步。这时候你可能需要先强制同步一次：ntpdate -s time.nist.gov不过现在很多发行版都不推荐用ntpdate了，建议用 ntpd -gq 来做初始同步。另一个常见问题是防火墙。NTP使用UDP 123端口，记得开放：firewall-cmd --permanent --add-port=123/udp firewall-cmd --reloadChrony：新一代时间同步工具Chrony是相对较新的时间同步实现，设计目标是在各种网络环境下都能提供准确的时间同步。相比NTP，Chrony有几个明显的优势：首先是同步速度快。Chrony能够更快地适应网络条件的变化，在网络不稳定的环境下表现更好。其次是资源占用少，特别适合虚拟化环境。最重要的是，Chrony对时间跳跃的处理更加智能。现在很多新的Linux发行版，比如RHEL 8、CentOS 8、Ubuntu 18.04以后的版本，都默认使用Chrony而不是传统的NTP。Chrony的安装配置在RHEL/CentOS 8上，Chrony通常已经预装了：yum install chrony -yUbuntu系统：apt-get install chrony -yChrony的配置文件是 /etc/chrony.conf，语法和NTP稍有不同：# 配置NTP服务器 server ntp1.aliyun.com iburst server ntp2.aliyun.com iburst server ntp3.aliyun.com iburst # 如果作为服务器，允许客户端同步 allow 192.168.1.0/24 # 本地时钟配置 local stratum 10 # 时间调整策略 makestep 1.0 3 # 日志目录 logdir /var/log/chrony # RTC同步 rtcsync这里有几个Chrony特有的配置：makestep 1.0 3：如果时间偏差超过1秒，前3次同步时直接跳跃调整rtcsync：启用硬件时钟同步allow：允许指定网段的客户端同步时间启动Chrony服务：systemctl start chronyd systemctl enable chronydChrony的管理命令Chrony使用 chronyc 命令来管理，这点和NTP的 ntpq 不太一样：# 查看时间源状态 chronyc sources -v # 查看同步统计信息 chronyc sourcestats # 查看当前同步状态 chronyc tracking # 强制同步 chronyc makestep # 手动添加时间源 chronyc add server ntp.example.com # 查看客户端连接 chronyc clientschronyc sources -v 的输出比较详细：210 Number of sources = 4 .-- Source mode '^' = server, '=' = peer, '#' = local clock. / .- Source state '*' = current synced, '+' = combined , '-' = not combined, | / '?' = unreachable, 'x' = time may be in error, '~' = time too variable. || .- xxxx [ yyyy ] +/- zzzz || Reachability register (octal) -. | xxxx = adjusted offset, || Log2(Polling interval) --. | | yyyy = measured offset, || \ | | zzzz = estimated error. || | | \ MS Name/IP address Stratum Poll Reach LastRx Last sample =============================================================================== ^* ntp1.aliyun.com 2 6 377 34 +123us[ +456us] +/- 12ms ^+ ntp2.aliyun.com 2 6 377 35 -234us[ -567us] +/- 15msNTP vs Chrony：详细对比经过这几年的使用，我总结了一下两者的主要区别：同步速度和精度Chrony在这方面明显更优秀。我做过测试，在同样的网络环境下，Chrony通常能在几分钟内完成初始同步，而NTP可能需要十几分钟甚至更长时间。特别是在虚拟化环境中，虚拟机的时钟可能会因为宿主机负载而出现跳跃，Chrony对这种情况的处理更加智能。它能够检测到时间跳跃，并快速调整同步策略。网络适应性Chrony对网络条件变化的适应能力更强。在网络延迟不稳定或者间歇性断网的环境下，Chrony能够更好地维持时间精度。这对于移动设备或者网络条件不太好的环境特别重要。资源占用从资源占用来看，Chrony确实更轻量级。在我的测试中，chronyd进程的内存占用通常只有ntpd的一半左右。CPU使用率也更低，这对于资源受限的环境，比如嵌入式设备或者容器，优势很明显。不过说实话，现在服务器配置都不错，这点资源差异在大多数场景下可能感觉不出来。但在大规模部署的时候，积少成多，还是能省不少资源的。配置复杂度这点上两者差不多，都不算太复杂。不过我个人觉得Chrony的配置语法稍微更直观一些，错误提示也更友好。比如配置文件有语法错误时，Chrony会给出比较明确的提示，而NTP的错误信息有时候比较模糊。兼容性和生态NTP作为老牌协议，兼容性肯定更好，几乎所有的网络设备都支持。而且很多监控工具和脚本都是基于NTP的命令和输出格式开发的。Chrony虽然功能更强，但在一些老旧系统或者特殊设备上可能不被支持。我遇到过一些工控设备只支持NTP，不认Chrony的情况。实际生产环境的选择建议新部署的系统优先选择Chrony，特别是：虚拟化环境（VMware、KVM等）云环境（AWS、阿里云等）容器环境（Docker、Kubernetes）网络条件不稳定的环境对时间精度要求较高的场景继续使用NTP的场景：已经稳定运行的老系统，没有特殊需求的话就别折腾了需要和老旧设备兼容的环境对NTP有特殊定制需求的场景团队对NTP更熟悉，运维成本考虑高可用时间同步架构设计在生产环境中，单点故障是大忌。时间同步服务也不例外，需要考虑高可用性。分层架构设计我们公司现在采用的是三层架构：第一层是主时间服务器，通常部署2-3台物理服务器，直接从公网权威时间源同步。这些服务器配置要相对高一些，网络也要稳定。# 主时间服务器配置示例（Chrony） server 0.pool.ntp.org iburst server 1.pool.ntp.org iburst server 2.pool.ntp.org iburst server time.cloudflare.com iburst # 允许内网访问 allow 10.0.0.0/8 allow 172.16.0.0/12 allow 192.168.0.0/16 # 本地时钟作为备用 local stratum 10 # 日志配置 logdir /var/log/chrony log measurements statistics tracking第二层是区域时间服务器，每个机房或者网络区域部署1-2台，从主时间服务器同步。这样可以减少跨网络的时间同步流量，提高同步效率。第三层就是业务服务器，都从本区域的时间服务器同步。监控和告警时间同步的监控很重要，我写了个简单的脚本来检查同步状态：#!/bin/bash # time_sync_check.sh # 检查是否使用Chrony if systemctl is-active --quiet chronyd; then # Chrony监控 offset=$(chronyc tracking | grep "System time" | awk '{print $4}') if [ -z "$offset" ]; then echo "ERROR: Cannot get time offset from chronyd" exit 1 fi # 转换为毫秒 offset_ms=$(echo "$offset * 1000" | bc -l) elif systemctl is-active --quiet ntpd; then # NTP监控 offset=$(ntpq -c "rv 0 offset" | grep -o '[+-][0-9.]*') if [ -z "$offset" ]; then echo "ERROR: Cannot get time offset from ntpd" exit 1 fi offset_ms=$offset else echo "ERROR: Neither chronyd nor ntpd is running" exit 1 fi # 检查偏移量（阈值100ms） if (( $(echo "${offset_ms#-} > 100" | bc -l) )); then echo "WARNING: Time offset is ${offset_ms}ms" exit 1 fi echo "OK: Time offset is ${offset_ms}ms"这个脚本可以放到crontab里定期执行，配合Zabbix或者Prometheus使用。如果偏移量超过阈值就发告警。容器环境的特殊考虑在容器环境中，时间同步有些特殊情况需要注意。Docker容器默认是不能修改系统时间的，如果需要在容器中运行时间同步服务，需要添加特权：docker run --privileged -d my-chrony-container但这样做会带来安全风险。更好的做法是在宿主机上配置时间同步，让容器继承宿主机时间。在Kubernetes环境中，可以通过hostNetwork来让Pod使用宿主机的网络和时间：apiVersion: v1 kind: Pod spec: hostNetwork: true containers: - name: chrony image: chrony:latest securityContext: privileged: true不过一般情况下，我们都是在Node节点上配置时间同步，Pod直接继承就行了。云环境的最佳实践在云环境中，时间同步有一些特殊的考虑。各大云服务商都提供了自己的NTP服务：AWS：169.254.169.123阿里云：ntp.cloud.aliyuncs.com腾讯云：ntpupdate.tencentcloudapi.comAzure：time.windows.com使用云服务商的NTP服务通常延迟更低，稳定性也更好。而且不会产生额外的外网流量费用。# 阿里云ECS推荐配置 server ntp.cloud.aliyuncs.com iburst server ntp1.cloud.aliyuncs.com iburst server ntp2.cloud.aliyuncs.com iburst # AWS EC2推荐配置 server 169.254.169.123 iburst prefer server 0.amazon.pool.ntp.org iburst server 1.amazon.pool.ntp.org iburst在云环境中，还要注意一个问题就是实例的时间可能在创建时就不准确。建议在实例启动脚本中加入强制同步：#!/bin/bash # 云主机初始化脚本 chronyd -q 'server ntp.cloud.aliyuncs.com iburst' systemctl start chronyd systemctl enable chronyd安全考虑和防护措施时间同步服务也存在一些安全风险，最常见的是NTP反射攻击。攻击者利用NTP服务器的monlist命令来放大DDoS攻击。虽然新版本的NTP已经默认禁用了monlist，但还是建议在配置中明确禁用：# NTP安全配置 disable monitor restrict default kod nomodify notrap nopeer noquery restrict 127.0.0.1 restrict ::1 # 只允许内网访问 restrict 192.168.1.0 mask 255.255.255.0 nomodify notrapChrony的安全配置相对简单一些：# Chrony安全配置 # 只允许特定网段同步 allow 192.168.1.0/24 # 禁用命令端口（如果不需要远程管理） cmdport 0 # 限制客户端连接数 clientloglimit 100另外，建议定期检查时间同步服务的日志，看看有没有异常的访问请求。我写了个简单的脚本来分析访问日志：#!/bin/bash # 分析Chrony访问日志 tail -1000 /var/log/chrony/measurements.log | \ awk '{print $3}' | sort | uniq -c | sort -nr | head -20如果发现有大量来自同一IP的请求，可能就需要注意了。故障排查经验分享这些年遇到的时间同步问题还挺多的，分享几个典型的排查思路：问题1：时间同步不生效首先检查服务是否正常运行，然后看配置文件是否正确。经常遇到的情况是防火墙阻挡了UDP 123端口，或者上游时间服务器不可达。# 检查服务状态 systemctl status chronyd # 检查端口 netstat -unlp | grep :123 # 测试网络连通性 chronyc sources -v问题2：时间偏移过大如果时间差太大，可能需要先手动同步一次。Chrony可以用makestep，NTP可能需要先停服务，用ntpdate同步后再启动。问题3：虚拟机时间跳跃这个在虚拟化环境比较常见，通常是宿主机负载过高导致的。可以考虑调整虚拟机的时钟源，或者使用VMware Tools的时间同步功能。问题4：容器时间不一致容器环境中，要确保宿主机的时间是准确的。如果容器需要独立的时间同步，要注意权限和网络配置。问题5：时区没有修改需要手动修改时区未来发展趋势时间同步技术也在不断发展。现在比较热门的是PTP（Precision Time Protocol），精度可以达到纳秒级别。虽然主要用在金融交易、工业控制等对时间精度要求极高的场景，但随着5G、边缘计算的发展，可能会有更广泛的应用。另外，随着容器和微服务架构的普及，分布式时间同步也面临新的挑战。在网络条件复杂的云原生环境中，如何保证时间同步的准确性和可靠性，确实是个值得关注的问题。还有就是安全性方面，现在越来越多的攻击利用时间同步服务作为跳板。未来可能会有更多基于加密和认证的时间同步方案出现。写在最后时间同步虽然看起来是个基础设施问题，但在分布式系统中的重要性真的不容忽视。选择合适的时间同步方案，不仅能避免很多奇怪的问题，还能提高系统的整体稳定性和可维护性。从我这几年的实践来看，Chrony确实在很多方面都比传统NTP有优势，特别是在虚拟化和云环境中。同步速度快，资源占用少，对网络条件变化的适应能力也更强。但NTP作为成熟稳定的方案，在很多场景下仍然是不错的选择，特别是需要兼容老旧设备的环境。最重要的是，不管选择哪种方案，都要做好监控和维护。时间同步服务一旦出问题，影响面可能会很大，所以宁可多花点时间做好预防，也不要等出问题了再临时抱佛脚。另外，在设计系统架构的时候，也要考虑时间同步的高可用性。单点故障在任何环节都是要避免的，时间同步也不例外。希望这篇文章能帮到正在纠结时间同步方案选择的朋友们。如果你有其他的实践经验或者遇到过特殊的问题，也欢迎留言交流。如果这篇文章对你有帮助，别忘了点赞转发支持一下！想了解更多运维实战经验和技术干货，记得关注@运维躬行录，我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习，共同进步！公众号：运维躬行录
云计算专业术语大揭秘！这些"黑话"你都懂吗？
最近在公司开会，听到同事们各种云计算术语满天飞，什么"弹性伸缩"、"容器编排"、"微服务架构"...说实话，刚入行那会儿我也是一脸懵，感觉大家说的都是外星语。做了这么多年运维，我发现很多朋友都有这样的困扰：技术文档看不懂，会议听不明白，跟开发沟通像是在打哑谜。其实云计算的这些专业术语并没有想象中那么高深，今天我就来给大家捋一捋，用最接地气的方式解释这些"黑话"。基础设施即服务，听起来很高大上IaaS（Infrastructure as a Service），翻译过来就是基础设施即服务。简单说就是云服务商把服务器、存储、网络这些硬件资源虚拟化之后租给你用。我记得以前公司要上个新项目，得先采购服务器，等设备到货，然后机房上架，网络配置...整个流程下来至少要一个月。现在用云服务，几分钟就能开出一台虚拟机，这就是IaaS的魅力。PaaS（Platform as a Service）更进一步，不仅提供基础设施，还提供了开发和运行环境。比如你要部署一个Java应用，传统方式需要自己安装JDK、配置Tomcat、设置数据库连接等等。用PaaS的话，这些环境都给你准备好了，你只需要把代码扔上去就行。SaaS（Software as a Service）就更直接了，软件即服务。像我们平时用的钉钉、腾讯会议、Office 365都属于SaaS。用户不需要安装任何软件，打开浏览器就能使用。说到这里想起个笑话，有次我跟一个做传统IT的朋友聊天，他问我："你们云计算到底是干什么的？"我说："就是把别人的电脑当自己的电脑用。"他恍然大悟："那不就是网吧模式吗？"...虽然这个比喻不太准确，但某种程度上还真有点像。虚拟化技术，一台机器变多台虚拟化（Virtualization）是云计算的基石。通过虚拟化技术，一台物理服务器可以运行多个虚拟机，每个虚拟机都像是一台独立的计算机。Hypervisor是虚拟化的核心组件，负责管理和分配物理资源给各个虚拟机。常见的有VMware vSphere、Microsoft Hyper-V、开源的KVM等。容器（Container）是另一种虚拟化技术，比传统虚拟机更轻量级。如果说虚拟机是把一栋楼分成若干套房子，那容器就是把一套房子分成若干个房间。Docker是目前最流行的容器技术。我刚接触Docker的时候觉得特别神奇，一个应用连同它的运行环境可以打包成一个镜像，在任何支持Docker的机器上都能运行。这解决的是运行环境标准化的问题，避免了“一杯茶一包烟，一个环境配一天”的悲剧发生。容器编排（Container Orchestration）就是管理大量容器的技术。想象一下，如果你有成百上千个容器需要管理，手工操作肯定要疯掉。Kubernetes（简称K8s）是目前最主流的容器编排平台，虽然学习曲线比较陡峭，但掌握之后确实很强大。弹性和可扩展性，云计算的杀手锏弹性伸缩（Auto Scaling）是云计算的一大优势。系统可以根据负载情况自动增加或减少资源。比如电商网站在促销期间访问量暴增，系统会自动启动更多服务器来应对；活动结束后又会自动释放多余的资源。传统电商公司活动页面，平时访问量很少，但每次做活动就会有大量用户涌入。以前总是要提前评估流量，手动扩容，经常出现要么资源不够导致页面卡顿，要么准备过多造成浪费。现在配置了弹性伸缩，系统会根据CPU使用率和响应时间自动调整，省心多了。负载均衡（Load Balancing）是把请求分发到多个服务器上，避免某台服务器过载。就像银行有多个窗口，客户排队时会被引导到空闲的窗口一样。CDN（Content Delivery Network）内容分发网络，把静态资源缓存到离用户最近的节点上，加快访问速度。比如你在北京访问一个网站，如果服务器在深圳，数据要跑很远；但如果在北京有CDN节点，就能就近获取内容。按量计费，云计算的经济学革命说到云计算，不得不提它最吸引人的特点之一——按量计费。这个模式彻底改变了企业的IT成本结构。传统IT模式下，你要上个项目，先得买服务器、买软件许可证、租机房位置...这些都是一次性的大笔投入。以前公司要上个ERP系统，光硬件采购就花了几十万，结果项目上线后发现性能过剩，大部分资源都闲置着。更要命的是，三年后硬件过保了，又得花钱升级。云计算的按量计费就像用水用电一样，用多少付多少。你的应用今天访问量大，系统自动扩容，多用了资源就多付费；明天访问量小，资源自动释放，费用也跟着降下来。比如某电商公司，平时一天可能就几百个访问，但做促销活动的时候一小时就有几万个访问。以前为了应对峰值流量，得准备足够的服务器，但99%的时间这些服务器都在"睡觉"。现在用云服务，平时只需要一台小配置的虚拟机，活动期间自动扩展到十几台，活动结束又缩回去。算下来一年能省好几万块。按需付费（Pay-as-you-go）的好处不仅仅是省钱，更重要的是降低了试错成本。想试个新技术？开个虚拟机测试一下，用完就删掉，可能就花几块钱。以前要试个新东西，得写申请、走流程、采购设备，等折腾完了热情都没了。资源池化（Resource Pooling）是按量计费能够实现的技术基础。云服务商把大量的物理资源放在一起，通过虚拟化技术分配给不同的用户。就像共享单车一样，一辆车可以被多个人在不同时间使用，提高了利用率，降低了成本。不过按量计费也有个坑，就是如果不注意控制，费用可能会超出预期。我听说过有个创业公司，因为代码bug导致无限循环调用云服务API，一夜之间产生了几万块的费用...所以现在各大云服务商都提供了费用预警（Cost Alert）功能，超过设定金额会自动通知。预付费（Prepaid）和后付费（Postpaid）是两种常见的计费模式。预付费就是先充值再使用，用完了再充；后付费是先使用再结算，每月出账单。对于用量比较稳定的业务，预付费通常有折扣；对于用量波动大的业务，后付费更灵活。现在很多云服务商还推出了Savings Plans这种新的计费模式，承诺在一定时间内使用一定金额的服务，就能享受更大的折扣。这对于有长期规划的企业来说是个不错的选择。微服务架构，化整为零的艺术微服务（Microservices）是把一个大的应用拆分成多个小的、独立的服务。每个服务负责特定的业务功能，可以独立开发、部署和扩展。传统的单体应用（Monolithic Application）就像一个大杂烩，所有功能都打包在一起。要修改一个小功能，整个应用都要重新部署。微服务架构下，各个服务相对独立，修改用户服务不会影响订单服务。不过微服务也不是银弹，它带来了新的复杂性。服务之间的通信、数据一致性、分布式事务等问题都需要考虑。我们公司从单体应用迁移到微服务架构的过程中就踩了不少坑，比如服务调用链路过长导致性能下降，服务间依赖关系复杂导致故障传播等。API网关（API Gateway）是微服务架构中的重要组件，作为所有服务的统一入口，负责请求路由、认证授权、限流熔断等功能。服务网格（Service Mesh）是处理服务间通信的基础设施层，通过代理的方式为服务间通信提供安全、快速、可靠的连接。Istio是目前比较流行的服务网格实现。数据存储的各种花样云计算环境下的数据存储也有很多种类。对象存储（Object Storage）适合存储非结构化数据，比如图片、视频、文档等。AWS S3、阿里云OSS都属于对象存储。它的特点是容量几乎无限，但不能像文件系统那样直接修改文件内容好处就是按量付费用多少付多少。块存储（Block Storage）提供原始的块级别存储，可以挂载到虚拟机上当作硬盘使用。性能比较好，适合数据库等对IO要求较高的应用。文件存储（File Storage）提供标准的文件系统接口，多个服务器可以同时挂载和访问。适合需要共享文件的场景。NoSQL数据库在云环境中也很流行，包括文档数据库（如MongoDB）、键值数据库（如Redis）、列族数据库（如Cassandra）、图数据库（如Neo4j）等。它们各有特点，适合不同的应用场景。常见的用户画像系统用的是MongoDB，因为用户属性比较灵活，关系型数据库的固定表结构不太适合。缓存层用的是Redis，因为它的性能特别好。不同的数据用不同的存储方案，这也是云计算时代的一个趋势。安全和合规，不能忽视的重要话题身份和访问管理（IAM）是云安全的基础，控制谁可以访问什么资源。通过角色、策略等机制实现细粒度的权限控制。虚拟私有云（VPC）为用户提供逻辑隔离的网络环境，就像在公共的云环境中划出一块私人领域。安全组（Security Group）类似于虚拟防火墙，控制进出虚拟机的网络流量。数据加密包括传输加密和存储加密。传输加密确保数据在网络传输过程中不被窃听，存储加密确保数据在磁盘上是加密保存的。合规性（Compliance）对很多企业来说都很重要，特别是金融、医疗等行业。云服务商通常会提供各种合规认证，比如ISO 27001、SOC 2、PCI DSS等。监控和运维，保障系统稳定运行可观测性（Observability）是最近比较热门的概念，包括监控（Monitoring）、日志（Logging）、链路追踪（Tracing）三个方面。监控主要关注系统的各种指标，比如CPU使用率、内存使用率、网络流量、响应时间等。Prometheus、Grafana是目前比较流行的监控组合。日志记录了系统运行过程中的详细信息，是排查问题的重要依据。ELK（Elasticsearch、Logstash、Kibana）是经典的日志处理方案，不过现在也有很多新的选择，比如Fluentd、Loki等。链路追踪可以跟踪一个请求在分布式系统中的完整调用路径，对于排查微服务架构下的性能问题特别有用。Jaeger、Zipkin是这个领域的代表产品。SLA（Service Level Agreement）服务等级协议，定义了服务的可用性标准。比如99.9%的可用性意味着一年中服务不可用的时间不能超过8.76小时。SLO（Service Level Objective）服务等级目标，是SLA的具体实现目标。SLI（Service Level Indicator）服务等级指标，是衡量服务性能的具体指标。我们团队现在每周都会开SLA回顾会议，分析上周的服务可用性情况，如果有故障会进行根因分析。刚开始觉得这个流程有点繁琐，但坚持下来确实对提升服务质量很有帮助。DevOps和CI/CD，开发运维一体化DevOps强调开发和运维的协作，通过自动化工具和流程提高软件交付的效率和质量。这不仅仅是技术问题，更是文化和组织结构的变革。CI/CD（Continuous Integration/Continuous Deployment）持续集成和持续部署是DevOps的重要实践。开发人员提交代码后，系统会自动进行构建、测试、部署等操作。Jenkins是最老牌的CI/CD工具，虽然界面比较古老，但功能很强大。GitLab CI、GitHub Actions是比较新的选择，与代码仓库集成得更紧密。基础设施即代码（Infrastructure as Code）把基础设施的配置用代码来描述和管理，提高了基础设施管理的一致性和可重复性。AWS CloudFormation、Terraform、Ansible、是这个领域的代表工具。我记得以前部署一个新环境，需要手工配置各种服务器、网络、数据库等，不仅耗时而且容易出错。现在用AWS CloudFormation写好配置文件，一个命令就能创建整套环境，而且每次创建的环境都是一模一样的。蓝绿部署（Blue-Green Deployment）是一种零停机部署方式，通过维护两套相同的生产环境来实现无缝切换。金丝雀部署（Canary Deployment）是另一种部署策略，先把新版本部署到少量服务器上，观察运行情况，没问题再逐步扩大范围。云原生，面向云环境设计的应用云原生（Cloud Native）是一种构建和运行应用的方法，充分利用云计算的优势。云原生应用通常具有微服务架构、容器化、动态编排、DevOps等特征。十二要素应用（The Twelve-Factor App）是构建云原生应用的方法论，包括代码库、依赖、配置、后端服务等12个方面的最佳实践。无服务器计算（Serverless）是云原生的一种极致形式，开发者只需要关注业务逻辑，不需要管理服务器。AWS Lambda、阿里云函数计算都属于Serverless服务。比如你公司有个数据处理任务，每天只运行几分钟，但需要很大的计算资源。以前要专门准备服务器，大部分时间都是闲置的。现在用AWS Lambda，任务来了就自动启动，处理完就自动释放，成本降低了很多。事件驱动架构（Event-Driven Architecture）通过事件来触发和连接各个服务，实现松耦合的系统设计，如AWS EventBridge。边缘计算和混合云边缘计算（Edge Computing）把计算能力部署到靠近数据源的地方，减少延迟，提高响应速度。比如自动驾驶汽车需要实时处理传感器数据，不可能把数据传到云端处理再返回结果。混合云（Hybrid Cloud）结合了公有云和私有云的优势，敏感数据放在私有云，其他业务使用公有云。多云（Multi-Cloud）是指同时使用多个云服务商的服务，避免厂商锁定，提高系统的可靠性。我们公司就是典型的混合云架构，核心业务系统部署在私有云上，确保数据安全和合规；一些边缘业务和临时需求使用公有云，灵活性更好。不过这样也带来了管理复杂性，需要统一的管理平台。人工智能和机器学习服务现在各大云服务商都提供了AI和ML相关的服务，降低了人工智能应用的门槛。机器学习平台（ML Platform）提供了从数据准备、模型训练、模型部署到模型管理的全流程服务。AWS SageMaker、Google AI Platform都是这类服务。预训练模型让没有AI背景的开发者也能快速集成AI能力，比如语音识别、图像识别、自然语言处理等。MLOps是机器学习运维，类似于DevOps，强调机器学习模型的自动化部署、监控和管理。说实话，AI这块我也在学习中，感觉变化特别快。前几天还在研究某个框架，过几天就出了新版本，功能完全不一样了。不过这也是技术发展的常态，保持学习的心态很重要。成本优化，云计算的必修课成本优化（Cost Optimization）是云计算使用中的重要话题。云服务按使用量付费的模式虽然灵活，但如果不注意控制，成本可能会失控。预留实例（Reserved Instance）通过预付费的方式获得更低的价格，适合长期稳定的工作负载。竞价实例（Spot Instance）使用云服务商的空闲资源，价格很便宜，但可能会被随时回收，适合容错性强的批处理任务。资源标签（Resource Tagging）通过给资源打标签来进行分类管理，便于成本分析和控制。总结云计算的专业术语确实很多，但掌握了这些基本概念，再看技术文档或者参加技术讨论就不会那么吃力了。其实很多概念并不复杂，关键是要理解它们解决了什么问题。比如微服务解决了单体应用难以扩展的问题，容器解决了环境一致性的问题，DevOps解决了开发和运维协作的问题。云计算技术发展很快，新的概念和工具层出不穷。我的建议是不要被这些术语吓到，也不要盲目追新。理解基本原理，根据实际需求选择合适的技术方案，这才是最重要的。另外，理论知识固然重要，但实践经验更宝贵。有机会的话多动手试试，搭个测试环境玩玩，踩踩坑，这样理解会更深刻。目前各大云厂商都有给测试套餐，大家可以免费注册来学习下。AWS 更是可以免费使用 40 余种核心云服务产品，长达 12 个月，这羊毛不薅白不薅！我写这篇文章的时候也在想，云计算发展到今天，已经不再是什么高深的技术，而是像水电一样的基础设施。掌握这些基本概念，对每个IT从业者来说都是必要的。希望这篇文章能帮到大家，如果觉得有用的话，记得点赞转发哦！有什么问题也欢迎在评论区讨论。想了解更多运维相关的干货内容，记得关注@运维躬行录，我会持续分享实用的技术经验和心得体会！