news 2026/10/22 3:21:43

Redis主从复制“三次握手”源码拆解:状态机与同步机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis主从复制“三次握手”源码拆解:状态机与同步机制

用INFO replication观察过一次主从同步的人,应该都有过类似的经历:从库刚配好replicaof,日志里刷出一堆“MASTER <-> REPLICA sync started”,主库那边同步进度也跳了好几个状态,最后两边都指向online,数据也追平了。过程看起来很简单,但真去翻Redis源码,你会发现主从之间从建立连接到数据完全同步,中间夹杂着身份确认、能力协商、同步请求、全量搬数据、进度上报等好几个环节,远比想象中复杂。

很多人一听到“三次握手”,第一反应是TCP三次握手,其实Redis主从复制里的“三次握手”完全是另一码事。它指的是从库与主库在应用层的三轮交互:先确认链路和质量,再做同步协商、决定全量还是增量,最后通过ACK确认把从库正式转正。把这三个阶段搞清楚,主从复制的源码就入门了大半。这篇文章是Redis主从复制源码阅读系列的第2篇,目标很明确:把主从之间这三次握手,从replication.c和server状态机出发,一层层拆开给你看。

1. 先理解主从复制的整体图景

1.1 主从复制不是“复制”那么简单

很多人对主从复制的理解停留在“从库把主库的数据拿过来一份”。这个说法方向没错,但它远远低估了这套机制的严谨程度。Redis的主从复制在实现上是一套完整的状态机,从执行REPLICAOF命令开始,到从库进入online状态,中间要经历连接、握手、协商、传输、加载、确认等阶段,任何一个环节出问题,都会影响最终结果。

我在阅读源码前,习惯先用状态机的视角把流程过一遍。Redis把整个复制过程拆成了多个状态,核心状态定义在replication.c里,常见的有:REPL_STATE_NONE(初始无复制)、REPL_STATE_CONNECT(等待连接主库)、REPL_STATE_CONNECTING(连接已建立)、REPL_STATE_RECEIVE_PING_REPLY(等待PONG)、REPL_STATE_SEND_PSYNC(发送同步请求)、REPL_STATE_RECEIVE_PSYNC_REPLY(等待同步回复)、REPL_STATE_TRANSFER(接收RDB)、REPL_STATE_CONNECTED(已在线)。你看到这一长串状态,就知道主从复制绝不是一个简单的“拷贝”动作,而是一套严谨的、可追踪的通信协议。

从源码阅读的角度,这套状态机是最好的“地图”。你不需要一次性看懂所有函数,只需要跟着状态跳转走:从库每次状态变化,背后一定有一个对应的函数在驱动;主库每收到一条指令,也一定有一个对应的命令处理器在响应。把这套地图刻在脑子里,看代码时就不会迷路。

1.2 “三次握手”这个提法是怎么来的

严格来说,Redis官方文档里并没有“主从三次握手”这个术语。这个说法更多是源码阅读者在分析过程中的一种归纳,目的是把这套冗长的交互流程,简化成三个便于理解和记忆的阶段。正因为这是“约定俗称”的分析模型,不同的人可能划分方式不同,你需要先接受我这里的划分。

我习惯把三次握手定义为三个阶段。第一次握手:从库与主库建立TCP连接后,先发送PING探活,随后通过REPLCONF上报自己的监听端口和能力(capa),主库完成对该客户端的初步标记;第二次握手:从库发送PSYNC命令,携带runid和偏移量,主库根据自身复制积压缓冲区情况,决定回复+FULLRESYNC还是+CONTINUE,双方确认同步方式;第三次握手:全量数据RDB传输完成后,从库加载完毕并向主库发送REPLCONF ACK,主库确认从库的复制进度并标记为online,随后进入持续的增量传播阶段。

这样划分的好处是:第一次解决“连接是否可用、你是谁”的问题,第二次解决“怎么同步、从哪开始”的问题,第三次解决“数据交接是否完成、后续怎么持续”的问题。和TCP三次握手一样,每一轮都有明确目的,每一轮失败都能在状态里找到对应的位置。

1.3 源码地图:把要反复打开的文件提前摊开

主从复制的核心代码几乎都集中在src/replication.c,少量状态定义散落在server.h和server.c里。我的建议是,读源码前先把下面这张“函数地图”过一遍,理解每个函数的角色,再跟着流程走会轻松很多。

函数名所属节点职责说明
replicaofCommand从库/主库REPLICAOF命令入口,触发复制关系建立
replicationSetMaster从库记录主库地址,设置连接状态
replicationCron从库周期性检查复制状态,负责发起连接和重连
syncWithMaster从库主从连接建立后的核心回调,驱动三次握手
readSyncBulkPayload从库读取并加载主库发来的RDB数据
syncCommand主库处理从库发来的PSYNC命令,决定全量/增量
replconfCommand主库处理REPLCONF命令,识别从库端口、能力与ACK
replicationFeedSlaves主库把写命令传播给所有在线从库

你需要记住一个总原则:从库侧的动作集中在“如何发起连接、如何发起请求、如何处理回复”,主库侧的动作集中在“如何接受请求、如何判断同步方式、如何发送数据”。接下来每一节,我都会一边贴代码逻辑,一边解释它在这张地图上的位置。

2. 第一次握手:从库连上来,先把“我是谁”说清楚

2.1 连接从何开始:REPLICAOF之后的内部状态变化

先看从库侧。当你在从库执行REPLICAOF masterip masterport时,入口函数是replicaofCommand。这个命令的工作分两种情况:如果参数是“NO ONE”,就清空复制设置;如果带了主库地址,就调用replicationSetMaster。

replicationSetMaster的核心逻辑很简短,但信息量很大:它会记录主库的host和port,把server.repl_state置为REPL_STATE_CONNECT,同时把master_runid清空、master_initial_offset设为-1。这几个动作的含义是:从库还没连上主库,也不知道主库的身份标识和同步起点,一切要从零开始。

之后进入复制的主循环。从库的replicationCron定时任务(由server.hz驱动,默认每秒10次)会检查server.repl_state,如果发现处于REPL_STATE_CONNECT,就会调用connectWithMaster尝试建立TCP连接。这里的连接是非阻塞的,connectWithMaster注册一个可写事件,事件回调就是syncWithMaster。换句话说,当TCP连接真正建立的那一刻,Redis的io线程会触发syncWithMaster,第一次握手正式开场。

这里有个值得新手注意的细节:从库并不是自己写了个死循环去connect,而是把连接过程交给事件循环,连接成功后再由回调函数接管后续动作。理解这一点对读源码非常重要,Redis很多网络交互都是这种事件驱动模型,函数之间不是“顺序调用”,而是“通过事件串联”。

2.2 先PING后报身份:SYNC握手的第一步干了三件事

syncWithMaster是第一次握手的关键函数。站在源码角度,它内部会根据server.repl_state的不同取值,完成阶段性的任务。连接刚建立时状态是REPL_STATE_CONNECTING,此时从库会向主库发送一条PING命令,并等待PONG回复。这一步和TCP握手里的SYN很相似,本质是验证链路是通的、主库的协议解析是正常的、版本兼容性没问题。

收到PONG后,状态进入下一步,从库紧接着发送两条REPLCONF命令。第一条是“REPLCONF listening-port <从库端口>”,作用是把从库的监听端口告知主库。主库收到后,会把端口记录到对应client结构体的repl_listening_port字段,之后你在主库执行INFO replication时,看到的“slave0:ip=xxx,port=xxx”就是靠这个字段展示的。第二条是“REPLCONF capa eof capa psync2”,这是能力协商,告诉主库“我支持RDB的EOF格式,我支持psync2协议”。能力协商是一个很容易被忽略但对兼容性至关重要的机制,不同版本的Redis对同步协议的支持程度不同,主库需要根据从库上报的能力选择合适的数据传输方式。

我对第一次握手有一个形象类比:PING是敲门,听没听见;REPLCONF listening-port是递名片,让主库知道来访者是谁;REPLCONF capa是亮出自己带了哪些证件,方便后面办业务。这三个动作全部完成,从库的状态才推进到REPL_STATE_SEND_PSYNC,准备进入第二次握手。

2.3 主库侧的反应:第一次握手时主库做了什么

从主库的视角看,第一次握手接收到的PING、REPLCONF都只是普通命令,但主库对待它们的方式早有设计。当从库建立TCP连接后,主库在accept时会给这个client打上CLIENT_SLAVE以外的普通标记,直到从库发送REPLCONF后,主库才在replconfCommand中提取出端口、能力等元数据。

这里需要特别提示一点:第一次握手的过程中,主库并不会立刻把这个连接当作正式的复制客户端。真正让主库“认定”这是一个从库的,是第二次握手时收到的PSYNC命令。所以在源码里,你会在syncCommand函数中找到明确的处理逻辑:一旦收到PSYNC,主库才会启动复制相关的数据结构,比如创建复制积压缓冲区(repl_backlog)、把客户端标记为从库、加入server.slaves链表。

我最初读这块源码时,一直以为“从库连接成功 = 已经是复制客户端了”,后来发现不是。这个认知纠正很重要:主库对从库的“身份认定”是分步完成的,第一步只登记信息,第二步才生效复制关系。这也解释了为什么主库日志里出现“Replica asks for synchronization”的时机,总是比连接建立的时机晚——因为那是PSYNC到达的时刻。

3. 第二次握手:PSYNC协商,真正决定的是全量还是增量

3.1 别把PSYNC理解成“同步请求”:它是断点续传协商

很多资料把PSYNC解释成“同步命令”,这没错,但不够准确。从源码角度来看,PSYNC更接近于一种“断点续传协商”:从库请求的不是“给我一份全量数据”,而是“我已知某个数据流位置,请你告诉我能否从这个位置继续”。Redis把从库已知的复制进度抽象成两个核心参数:主库的runid和复制偏移量offset。

runid是一个40位十六进制随机字符串,在Redis每次启动时生成,用于标识主库的“身份代际”。如果主库重启,runid就变了。offset则是复制数据流的字节偏移量,从库消费到哪就到哪。从库发起PSYNC时,会带上自己记录的master_runid和master_repl_offset。如果这是从库第一次同步,它对主库的runid和offset一无所知,就会带上特殊的“? -1”。

源码里PSYNC命令的经典形态是“PSYNC ”。从库在syncWithMaster中构建这条命令时,会检查server.master_runid是否为空,为空就发送“PSYNC ? -1”,否则发送“PSYNC ”。为什么首次要用“?-1”?因为-1表示“我不知道同步位置”,?表示“我不知道主库身份”。主库收到这种请求,只能认为从库没有任何基础,必须做全量同步。

3.2 主库的判决:+FULLRESYNC还是+CONTINUE

主库收到PSYNC后,进入syncCommand函数。这个函数的职责是“判决同步方式”。判决的逻辑可以拆成三步。第一步,主库检查从库发送的runid是否等于当前主库的server.replid(即当前身份);第二步,主库检查从库发送的offset是否落在自己的复制积压缓冲区repl_backlog范围内;第三步,主库检查复制积压缓冲区是否存在。只有三个条件同时满足,主库才回复“+CONTINUE ”,表示可以继续增量复制。

任何一个条件不满足,主库都会选择全量重同步,回复“+FULLRESYNC ”。这条回复信息量很大:从库收到后,会把主库的replid写进server.master_runid,把回复的offset记成server.master_initial_offset。此后从库的复制位置就从master_initial_offset开始追。你看到这里会发现,第二次握手的本质是:主库做一个数学判断——你能不能从我记录的进度继续;能,就增量;不能,就全量。

我有一段时间对“+CONTINUE”有一个误解:以为支持增量同步的前提是从库之前连过、且数据没断过。其实核心是runid + backlog。就算网络断过,只要主库没重启(runid没变),且从库的offset还在backlog里,就能部分重同步。反过来,如果主库重启导致runid变了,即使网络一直连着,也必须全量。Redis重启丢runid这件事,是生产环境里“周期性全量同步”最常见的元凶之一。

3.3 全量重同步背后的准备:BGSAVE与传输方式选择

当主库决定全量同步后,还有一堆细节要处理。syncCommand会先把从库加入server.slaves链表,设置它的复制状态为SLAVE_STATE_WAIT_BGSAVE_START(等待开启后台保存),然后尝试触发BGSAVE。这里有一个优化点:如果主库本身已经有一份正在生成的RDB,且当前没有其他从库在等这份RDB,主库可以让该从库复用同一份RDB,而不是再fork一次。

BGSAVE的落盘方式也分两种:RDB目标为磁盘(disk)和RDB目标为从库socket(socket)。disk方式先把RDB写到本地磁盘,再读出来发给从库;socket方式则直接把RDB流式地写给从库。源码中这个选择由repl-diskless-sync配置控制,二者有不同适用场景:disk方式实现简单,但对磁盘IO有压力;socket方式能减少一次磁盘读写,但对网络稳定性要求高,且从库必须实时接收。

从库侧此时进入REPL_STATE_RECEIVE_PSYNC_REPLY阶段,等待主库的+FULLRESYNC或+CONTINUE。一旦收到+FULLRESYNC,从库解析出主库的replid和初始offset,状态推进到REPL_STATE_TRANSFER,开始进入真正的全量数据传输阶段。到这里,第二次握手结束,但距离从库“转正”还差最后一步。

4. 第三次握手:RDB搬完后的身份转正与增量接力

4.1 RDB传输期间从库在干嘛

第二次握手确定了全量同步后,主库后台生成RDB,生成完毕就把RDB数据推送给从库。从库在REPL_STATE_TRANSFER阶段,readSyncBulkPayload函数会负责接收数据。这个函数的名字很形象:读取“同步的批量数据”,也就是RDB文件。

接收过程中有几个关键细节值得注意。首先,从库并不会一边收一边写磁盘,而是先把数据写入临时文件(通常是temp- .rdb),等整个RDB接收完整后,再一次性加载到内存。其次,RDB数据流会有一个EOF标记,老版本用“EOF作为文件结尾”的方式,新版本通过capa能力协商后,会用文件长度前缀的方式判断数据是否完整。这就是第一次握手时从库上报“capa eof”的用武之地。

等RDB文件完整接收后,从库会做两件事:先清空自己现有的数据,再把RDB加载进内存。源码中你会看到类似“FLUSHALL”逻辑的执行,紧接着调用rdbLoad加载新数据。这一过程对业务是有阻塞风险的,尤其是从库上数据量大的场景,加载期间从库无法对外服务。生产环境里安排全量同步,一定要评估好从库的容量和业务压力。

4.2 REPLCONF ACK:第三次握手的核心动作

RDB加载完成后,从库状态进入REPL_STATE_CONNECTED。这个状态代表着复制关系正式建立,但主库侧还没100%确认从库已经“接住”了数据。真正让主库确认的,是从库随后发起的REPLCONF ACK请求。

REPLCONF ACK的发送频率在Redis中是每秒一次或根据配置的repl-ping-replica-period调整。从库会周期性发送“REPLCONF ACK <已复制的偏移量>”,这个偏移量就是从库当前追到的主库复制流位置。主库在replconfCommand中收到ACK后,会更新该从库的repl_ack_off字段,同时记录最近一次收到ACK的时间。这个字段的作用很多:主库INFO replication里展示的lag就是据此计算,主从故障检测也依赖它,甚至在主库提升从库时也要参考ACK进度来决定可以放行多少数据。

我把这理解成第三次握手的核心:从库用ACK数据包告诉主库“我的数据已经加载完了,我从这个偏移量开始等你喂命令”。主库只有在收到ACK后,才会真正把从库标记为完全online状态,开始正常推送增量命令。对增量复制而言,ACK不只是一次性动作,它是一种持续的心跳和进度上报,类似TCP连接建立后的保活机制。

4.3 online之后,增量数据是怎么喂给从库的

第三次握手完成,主从之间的数据流转才进入常态:增量传播。增量传播的底层机制是命令传播管道。主库每处理一条写命令,在真正执行的同时,会调用propagate把命令写入AOF缓冲和复制缓冲,最终由replicationFeedSlaves函数把命令追加到每个在线从库的输出缓冲区。

源码里replicationFeedSlaves做的事情有两件:一是把命令写入server.repl_backlog(复制积压缓冲区),保留最近一段时间的命令供断线重连时部分重同步;二是遍历server.slaves链表,把命令写入每个非WAIT状态的从库client发送缓冲区。主库靠事件循环把缓冲区数据刷到网络,从库再接收到、追加到自己的复制流里。

从库同时也在继续向上汇报自己的offset。主库每次收到ACK时更新进度,如果发现从库的offset已经追平,lag就变小;如果长时间收不到ACK,lag会增长,主库会认为从库可能断连。整个循环就是:主库写命令并分发,从库消费并回报进度,二者通过offset对齐。第三握手里那个“REPLCONF ACK”机制,在这一阶段持续发挥着作用。

4.4 断线重连、重启场景下,三次握手有什么不同

如果说前三次握手描述的是“从零开始建立复制”的理想路径,那么生产环境里更常见、更需要理解的是“复制中断后重连”的路径。重连时有个重要差异:第一次握手仍然是PING + REPLCONF全套,但从库发送PSYNC时不再是“? -1”,而是会带上自己断线前记录的runid和offset。

这条信息的价值在于:如果主库身份没变(runid匹配)、且从库的断线位置还在主库backlog里,主库就回复+CONTINUE,把断线期间的命令补发给从库。这时第三次握手会省去RDB传输的漫长过程,从库只需要补齐一小段gap就能online,效率非常高。这也是Redis主从复制最优雅的地方:设计初期就把“断点续传”作为一等公民。

但要注意,部分重同步是有条件的。如果主库在从库断开期间也重启过,runid变化,部分重同步必然失败,回退为全量重同步;如果断线时间太长,backlog被覆盖也会全量。你在源码里找createReplicationBacklog和修改backlog大小的配置(repl-backlog-size),就能理解为什么建议生产环境把backlog调大——它直接决定了断线窗口可以多长。

5. 源码阅读实录:如何自己追一遍三次握手

5.1 跟着状态机走一遍:源码追踪路径

读主从复制源码最怕“一头扎进函数细节出不来”。我自己摸索下来,比较高效的方式是“状态驱动追踪法”:先明确当前状态,再找驱动状态变化的函数,然后顺藤摸瓜。第一次握手可以从replicaofCommand开始,顺着replicationSetMaster、replicationCron、connectWithMaster一路走到syncWithMaster;第二次握手在syncWithMaster内部看它如何发送PSYNC,然后跳到主库的syncCommand;第三次握手跟着readSyncBulkPayload和replconfCommand走。

如果你用gdb调试,建议在这几个地方打断点:syncWithMaster(看第一次握手时的状态流转)、syncCommand(看主库的判断逻辑,在返回+FULLRESYNC还是+CONTINUE处最直观)、replconfCommand(看ACK处理)。配合Redis的日志级别,你几乎能看到从库每一行日志背后对应的源码位置。比如从库日志“Master replied to PING, replication can continue...”对应的是第一次握手PONG到达;日志“Full resync requested by master”对应第二次握手的+FULLRESYNC回复;日志“MASTER <-> REPLICA sync: Finished with success”对应第三次握手完成。

5.2 用日志和INFO命令复现三次握手

光看代码还不够,实际操作一次能帮你把代码和现象对应起来。建议准备一个最小复现环境:本机起两个Redis实例,一个主一个从,从库执行REPLICAOF后,立刻观察两边日志。

主库侧出现的关键日志顺序是:“Replica : asks for synchronization”后紧跟“Full resync requested by replica : ”,代表第二次握手全量判决完成;随后“Starting BGSAVE for SYNC”代表RDB开始生成。从库侧则是:“MASTER <-> REPLICA sync started” → “Master replied to PING” → “Full resync requested” → “MASTER <-> REPLICA sync: receiving N bytes from master” → “MASTER <-> REPLICA sync: Flushing old data” → “Loading DB in memory” → “MASTER <-> REPLICA sync: Finished with success”。把日志按时间排一排,三次握手的轮廓就非常清晰了。

INFO replication也值得同时观察。从库侧,master_link_status从down变为up、master_sync_in_progress从1变0,是第三次握手完成的重要信号;主库侧,connected_slaves从0变1,且slave列表里的state字段从wait_bgsave变为online,说明主库已经认了这个从库。这套现象和源码对照着看,你会对状态机有非常具体的体感。

5.3 我在阅读和实验中踩过的三个坑

最后分享几个我实际踩过的坑。第一个坑是把REPLCONF ACK当成只有同步完成后才发送的东西,其实从库online后是周期性持续发送的,甚至在加载RDB期间也会尝试发送旧位置的ACK。理解了这一点,你就知道查看lag时,如果lag一直很大,可能不是网络问题,而是主库事务繁忙导致处理ACK延迟。

第二个坑是忽略了runid变化对部分重同步的致命影响。我给一个测试主库配置了maxmemory策略,在订阅压力下频繁崩溃重启,从库每次都会触发全量同步,日志里全是full resync。当时排查很久才意识到:重启后runid变了,backlog也是空的,部分重同步在理论上就不成立。这个案例也提醒我,生产环境里想让从库稳定走增量复制,主库的稳定性比网络带宽更重要。

第三个坑是RDB传输期间调整了repl-timeout,导致全量同步反复失败。repl-timeout控制的是主从之间各类交互的超时时间,如果设置得太小,比如1秒,遇到RDB传输耗时较长的情况,从库长时间没收到数据就会判断超时,主动断开,整个握手前功尽弃。源码里replicationCron的检活逻辑依赖这个超时值,调参之前一定要先评估全量数据量和网络环境。

回过头看,Redis主从复制的三次握手,并不存在一个名叫“handshake”的函数,而是由状态机、命令处理和事件回调共同搭起来的一套协作流程。这也是阅读网络协议类源码最容易踩坑的地方:功能不是某一个函数完成的,而是分散在一组函数里完成。当你习惯了按照“状态驱动函数、函数推进状态”的方式去读代码,Redis主从复制的全貌就会变得非常清晰。如果你也想自己动手追一遍,建议就从这篇文章里的函数地图开始,把日志和源码对照着啃一遍,比我在这里写一万字都管用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 3:20:55

MATLAB实战:深度置信网络(DBN)在股票时间序列预测中的应用

最近在折腾时间序列预测的时候&#xff0c;发现深度置信网络&#xff08;DBN&#xff09;这个老牌选手居然在股票数据上表现挺有意思。今天就拿MATLAB实操一把&#xff0c;咱们边写代码边聊门道。先说清楚我为什么回头看DBN。现在一提深度学习做预测&#xff0c;大家条件反射就…

作者头像 李华
网站建设 2026/10/22 3:20:51

Visual Studio 2017 Installer 闪退打不开?三步排查修复指南

各位搞 Visual Studio 2017 的朋友&#xff0c;不知道你们有没有遇到过这种情况&#xff1a;某天打开电脑&#xff0c;想继续写点代码&#xff0c;双击 VS2017 的快捷方式&#xff0c;图标转了两圈&#xff0c;然后就没有然后了。要么直接闪退&#xff0c;要么弹个提示说找不到…

作者头像 李华
网站建设 2026/10/22 3:20:00

均数估计与t检验:SAS、R、Stata、SPSS实战指南

下午刚把第三章的作业看完&#xff0c;十个里面至少有五个问我同一个问题&#xff1a;均数估计和假设检验的公式明明会手算&#xff0c;为什么换成SAS、R、Stata、SPSS就不知道点哪里、写什么命令。这个感觉我太懂了。学校课程往往只带一遍某一款软件&#xff0c;真到了自己手里…

作者头像 李华
网站建设 2026/10/22 3:19:44

CH341A编程器刷BIOS芯片全攻略:AsProgrammer与NeoProgrammer软件实测对比

很多玩主板维修和刷机的人&#xff0c;手头最常用的一件家伙就是CH341A编程器&#xff0c;再配上AsProgrammer或NeoProgrammer这两款软件&#xff0c;基本就能应付绝大多数BIOS芯片的读写和刷新工作。我刚开始接触的时候也懵&#xff0c;总觉得这东西又要装驱动又要选芯片型号&…

作者头像 李华
网站建设 2026/10/22 3:19:41

PyTorch图像识别完整实战:从数据处理到模型部署全流程

前阵子有个朋友问我&#xff0c;想用PyTorch做一个图像识别的小项目&#xff0c;但他翻了一堆教程&#xff0c;要么只跑通了单张图片的预测演示&#xff0c;要么一上来就丢一个几百层的模型让人直接复制。我听完就觉得&#xff0c;这类教程最大的问题是把“能跑”和“能落地”混…

作者头像 李华
网站建设 2026/10/22 3:19:40

K8s从入门到实战:kubeadm部署、Pod调度与踩坑全记录

上篇聊到我和K8s"相遇"的前半段&#xff0c;也就是从只会敲命令到真正看进去理论的部分。这篇继续往下写&#xff0c;也是这个系列里我最想认真记录的一段——从"好像明白了"到"亲手把它跑起来"之间那段漫长又痛苦的爬坡期。K8s这种级别的技术&a…

作者头像 李华