多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

K8s架构详解:从控制面到数据面,一次讲透Pod调度与集群部署

K8s架构详解:从控制面到数据面,一次讲透Pod调度与集群部署 K8s架构这个话题网上讲的人很多但大部分不是太抽象就是太零碎。有人给你画一张组件图标上APIServer、Scheduler、Controller Manager、Kubelet然后告诉你“这就是架构”你看了半天还是不知道这些东西到底怎么配合、从哪开始学、部署完为什么老出问题。我做了几年K8s相关的落地和排障说实话K8s真正难的不是某个组件怎么用而是脑子里要能建立起一套关于“状态如何流转、组件如何协作、故障如何扩散”的完整模型。这套模型一旦立住了后面装集群、调优、处理故障就都顺了。这篇文章不画那些谁都会画的架构图而是从设计动机、组件协作方式、一次Pod从创建到运行的完整旅程再到具体部署和排障经验一层一层把K8s架构讲透。顺便也会把安装部署里的坑一并倒了保证看完能直接上手。1. 为什么K8s架构是这样的先理解设计动机再记组件1.1 从单机容器管理到集群编排的本质转变很多新手上来就背组件名这是最要不得的。理解K8s架构的第一步是先搞清楚——为什么它要拆成这么多组件早期用Docker的时候单机管理还简单docker run一个容器端口映射出来数据卷挂进去完事。但到了生产环境单机方案立刻露馅容器挂了谁来拉起来流量过来要找谁磁盘满了往哪腾配置变了要不要逐个重新部署这些单靠“单机容器运行时”根本没答案。于是编排系统出现了。编排要做的事本质上就是三件调度把容器放到哪台机器上跑、服务发现流量来了怎么找到对应的容器、自愈容器出问题怎么自动恢复。而要做这三件事就必须有个东西能跟所有节点对话、能持久保存集群状态、能随时知道每台机器上发生什么。这就逼出了一个“控制面 数据面”的架构。控制面负责决策数据面负责干活中间通过统一的API进行通信。K8s这套架构的巧妙之处在于它把“决策”和“执行”彻底拆开了。APIServer是唯一的入口相当于公司前台所有请求都得从这过etcd是数据库存的是全员档案Scheduler是HR专门给新来的Pod分配工位Controller Manager是一群盯着各部门纪律的巡查员而Kubelet是各工位上的执行者每天听指挥干活再上报情况。这套分层的好处非常明显每一层可以独立升级、独立扩缩、独立故障而且决策层完全不依赖具体业务容器的运行状态哪怕业务容器把节点搞崩了控制面照样能进行下一次调度。1.2 声明式APIK8s架构里最容易被低估的一块基石如果说组件拆分是K8s的骨架那“声明式API”就是K8s的灵魂。传统运维是命令式的你告诉系统“帮我启动一个容器”、“帮我创建10个副本”系统执行完就完事了以后副本挂了它不管。K8s则是声明式的你提交一个Deployment对象里面写清楚“我要3个副本、镜像版本、端口、健康检查”然后你就撒手不管了。K8s的Controller会持续对比“当下现状”和“期望状态”发现不一致就立即调整。这个机制带来的连锁反应是巨大的——所有K8s组件本质上都在围绕着“调和Reconcile”这个动作转。APIServer负责存取这些期望状态Controller负责感知偏差并纠偏Kubelet和kube-proxy负责在节点上落实局部状态。你后续学各种Controller、Operator学的其实都是“怎么编写更聪明的调和逻辑”。这套机制落地到架构里还有一个关键产物就是“List-Watch”模型。各组件不主动轮询APIServer而是通过API建立长连接订阅自己关心的资源变化。变化发生时APIServer推送事件组件收到后再动手处理。这极大减轻了APIServer压力也让整个集群的事件响应基本是准实时的。2. 控制面组件逐个拆解它们的职责、协作与关键机制2.1 kube-apiserver集群唯一入口所有请求的咽喉APIServer在整个架构里地位再怎么强调也不过分。它是整个集群唯一对接etcd的组件也是唯一对外开放API的组件。其他组件之间的横向通信都得绕过它或通过它传递数据——这杜绝了集群内各个模块各自为政的混乱局面。从架构角度来看APIServer做了三件关键事情认证/授权/准入控制请求进来后APIServer会依次做Authentication你是谁、Authorization你能干什么、Admission Control这个请求内容是否符合集群策略比如资源配额校验、Pod安全策略检查。这三道关卡全过了请求才真正被持久化到etcd。API对象存取所有K8s资源的增删改查最终都反映为对etcd的读写。APIServer负责将人类可读的YAML转换成etcd里的KV存储同时维护版本转换和资源校验。事件广播这里是List-Watch机制的核心服务端。所有组件通过它对资源变化进行订阅APIServer把变化以事件形式推送给监听者。我见过很多新手去直接访问etcd端口想自己捞数据结论是不要这么做。一切操作走APIServeretcd只是背后的存储。你绕过APIServer写数据等于绕过公司前台直接改员工档案早晚出事。2.2 etcd分布式键值存储K8s的“大脑记忆体”etcd这个东西架构上最容易被忽略出问题也最容易被忽略。对于K8s来说etcd里存的东西分成两类。一类是集群自身的状态比如节点列表、Pod列表、ConfigMap、Secret、Namespace、ServiceAccount这些。另一类是所有声明式API的期望状态——你提交的Deployment YAML、你的副本数配置都存在etcd里。这类数据有一个共同特点量不大但极其关键。它不是日志不是监控指标是集群的“数据库”。所以etcd的设计是搞强一致性的通过Raft共识算法保证多副本之间数据一致。换句话说想要etcd高可用就得起奇数个节点通常是3个或者5个。实际使用中有几个血泪教训etcd不要和其他高负载应用混部。它的性能对磁盘IO延迟极其敏感混部之后经常导致心跳超时进而触发整个集群的领导选举风暴。建议做定期快照备份。etcd挂了或者被误删数据靠快照是唯一快速恢复的手段。没有做备份就敢动生产集群的我只能说胆子是真大。提交间隔和磁盘同步不要乱调。默认的100ms提交间隔可能偏保守但你先跑稳定再考虑调优别上来就为了那点性能牺牲一致性。2.3 kube-controller-manager一堆控制器各管一摊事这个组件是最容易让人困惑的。名字很长看起来好像是个单一功能模块其实它是一个控制器合集Controller Manager里面跑着几十个独立控制器每个控制器各管一类资源。有管副本数的ReplicationController现在已由DeploymentController替代其大部分职责、有管节点健康状态的NodeController、有管Service和Endpoint的EndpointController、有管Namespace的NamespaceController还有管ServiceAccount、Token、Job、CronJob等等的。这些控制器的共性工作模式都一样从APIServer监听目标资源的变化发现期望状态与实际状态不一致就下发变更指令去纠正。比如DeploymentController会监听所有Deployment发现实际Pod数少于期望副本数就会通过创建ReplicaSet来补充Pod数量。这里有一个特别值得留意的架构细节Controller之间的“竞争”行为是良性的。比如DeploymentController和JobController同时监听到某个Pod需要创建但Deployment只负责管理它自己创建的ReplicaSet下的PodJob只管它负责的那批Pod两组控制器靠API对象上的OwnerReference做归属判定不会互相抢活。2.4 kube-scheduler给Pod找“工位”并做影响调度的权衡Scheduler听起来简单就是“给新Pod找一台合适的节点跑起来”但真正实现时远比想象复杂。而且它做的是一个实时决策每次决策都可能影响集群的负载分布和后续的稳定性。调度分为两个阶段过滤Filtering先把不能满足Pod基本需求的节点筛掉。比如节点资源不够、有污点不容忍、端口冲突等全部淘汰。优选Scoring在满足条件的剩余节点里按照资源余量、亲和性、反亲和性、数据本地性等打分选最高分的。这句话翻译成人话就是先看出身合不合格再看综合素质谁最优。优选时要考虑的因素非常多默认策略包括LeastRequestedPriority优先选资源使用率低的、BalancedResourceAllocation优先选CPU和内存配比均匀的、SelectorSpreadPriority尽量把同一副本散落在不同节点上防止一台挂了全没等。另外调度器本身也是可以扩展的。K8s提供了Scheduler Framework机制允许你通过插件方式自定义调度逻辑比如实现自己的优先策略或者绑定策略。业界常见的做法是接入“拓扑感知调度”让Pod优先调度到数据所在的机器减少跨机数据传输。2.5 控制面哪个级别才算高可用三条命令验证你的集群是否健康控制面组件虽然多但部署上都是多副本配合选主机制运行的。整个控制面的高可用主要取决于两点etcd集群能写以及APIServer能响应。检查控制面健康经常用这几条命令# 检查节点状态 kubectl get nodes # 检查核心组件状态 kubectl get pods -n kube-system # 查看APIServer当前健康状态 curl -k https://127.0.0.1:6443/healthz我习惯的排障第一步是看APIServer的/healthz返回什么。如果这个接口慢或者超时则直接怀疑APIServer负载过高或者etcd响应变慢。如果接口没问题但kubectl命令还是报错才会继续查证书、RBAC权限或本地kubeconfig配置。3. 数据面组件逐层解析Pod、kubelet、网络与存储的协作3.1 Pod调度、扩缩容和网络的最小单元原子里必要但设计容易被误解很多新手会问K8s里最小的调度单元为什么不是一个容器而是一个PodPod里到底该塞几个容器是把所有相关的进程都塞进去吗要回答这个问题得回到设计动机。容器技术本身并不提供“同生共死”的概念。但有些业务场景下多个进程之间的生命周期必须强绑定共享同一个网络命名空间、共享同一份数据卷彼此通信走localhost就行。你想想数据库主从切换里的“Sidecar”模式或者日志采集和业务应用“同生死”的需求就明白Pod存在的意义了。Pod的设计原则在K8s官方文档里有明确说法一个Pod应该只包含一个“主容器”和若干个紧密耦合的辅助容器Sidecar并且这些容器共享同一个生命周期。不要把无关的服务硬塞进同一个Pod那是K8s最容易被误用的一点。比如你有一个Web服务需要一个日志采集Sidecar这两个容器可以放一个Pod里共享lifecycle。如果只是单纯觉得“机器多多塞点容器省资源”那你已经违背了Pod的设计初衷。3.2 kubelet节点的“工头”认真执行但不负责决策kubelet是每个节点上必然运行的核心代理也是K8s里唯一常驻在节点上的控制面相关组件。它的职责范围非常具体从APIServer监听分配到本节点的Pod通过容器运行时接口CRI调用docker/containerd创建或销毁容器定期上报节点状态和Pod运行状态执行Pod探针liveness/readiness并根据结果自动重启或摘除流量挂载卷、管理Pod网络等。日常排障中kubelet日志是被查得最多的东西之一。但它有个坏毛病日志量极大默认可能被系统journald吃掉大量磁盘。建议给kubelet单独配置日志轮转不然哪天磁盘爆了都不知道怎么查。3.3 kube-proxy与Service流量怎么找到PodK8s里Pod的IP是不稳定的每次重启都可能变直接让客户端访问Pod IP是不现实的。所以K8s设计了一个抽象层——Service。Service的架构位置非常关键。它不直接跑某个具体进程而是由一个叫做Endpoints/EndpointSlice的资源来维护“这个服务背后有哪些Pod IP列表”。kube-proxy则负责在每个节点上把这些Service的ClusterIP转换为具体的Pod IP并对流量做转发。kube-proxy支持三种模式userspace最古老性能差基本已淘汰、iptables默认且最常见、IPVS模块化且性能更好的替代方案。iptables模式最大的坑是规则数量膨胀。集群Pod数量多的时候iptables规则可能几千上万条新增Service的时候规则更新会很慢并且容易因为并发操作导致规则错乱。IPVS则规避了这个问题使用哈希表做转发规则数量多的情况下性能依然稳定。所以这里直接给个经验结论如果集群规模超过50个节点或者Service数量超过500个果断切IPVS模式。切换方法简单改kube-proxy的ConfigMap后重启即可。3.4 CNI与网络模型每个Pod都要有全网唯一IP这事背后没那么简单K8s对网络模型有一条硬性规定每个Pod都要有一个全网唯一的IP地址Pod之间直接通过IP通信网络设备不做过多的NAT转换。这个模型让应用层通信变得简单但实现起来却极其复杂——因为Pod是随时飘的创建、销毁极其频繁每次都要动态分配IP、动态更新路由。这个复杂层就交给CNI插件来解耦。常见的CNI插件有Calico以BGP和网络策略出名、Flannel以简单出名、Cilium基于eBPF性能和观测性出色。我个人的选型建议很简单规模小、讲究快速上手Flannel配置简单到感人生产环境、需要网络策略隔离和多租户Calico对性能和可观测性有硬性要求、且已经在跟进eBPF生态Cilium。另外还要专门提一个真实场景坑集群里Pod网段如果和主机所在网段冲突了那是折磨人到崩溃的级联故障。编排网络的时候一定保证Pod网段、Service网段、宿主机网段三段互不重叠。3.5 CSI存储架构Pod要持久化背后的CSI插件体系怎么工作K8s原本对存储的定义很简单把存储卷抽象成PV和PVC存储的具体实现细节交给In-Tree卷插件。但In-Tree方式有个致命问题——插件代码和K8s核心代码绑定在一起更新和修复都极其麻烦。社区后来演化出了CSI接口规范用独立的Pod提供服务K8s核心只负责调用标准接口。这个架构模式的好处是存储厂商只需要实现CSI插件K8s不用管具体是NFS还是云盘还是分布式存储统一走一套标准协议。部署新存储对接时再也不用重新编译核心组件。CSI插件的生命周期管理也很有意思它通常包含三个类型的组件CSI Controller负责创建/删除卷、CSI Node负责把卷挂载到具体节点、以及外部Provisioner等Sidecar。4. 从一条命令开始走进架构深处kubeadm部署K8s集群的关键细节4.1 环境准备与硬件要求踩过的坑先从准备阶段说起理论讲得再多不落地等于零。我建议第一次学K8s架构的人不要花三个月去看文档直接动手装一个集群。装完之后很多抽象概念全都变成看得见摸得着的实体了。硬件方面给一个“别太穷酸”的参考控制面节点2核4G起步实际生产建议4核8G或往上工作节点2核4G起步视业务负载往上加磁盘控制面节点最好用SSDetcd对磁盘延迟敏感工作节点普通磁盘即可但日志多了会占很厉害注意留余量。操作系统我通常选Ubuntu 22.04 LTS或者CentOS 7.9虽然CentOS 7已停止维护但不少存量生产还是它。容器运行时首选containerd现在默认不需要再单独装docker了。系统初始化里面有几项是很多人容易漏的漏了后面就会出现各种奇怪问题关闭swapK8s要求强制关闭不然kubelet会罢工加载内核模块overlay、br_netfilter设置net.bridge.bridge-nf-call-iptables1让iptables正确处理桥接流量时间同步必须配置不然后面证书校验和日志时间线都会扭曲。4.2 通过kubeadm初始化控制面我踩过的坑和推荐参数第一步装好容器运行时后接下来就是用kubeadm初始化集群。这里给一个可以直接拿来用的初始化参数模板kubeadm init \ --apiserver-advertise-address192.168.1.10 \ --pod-network-cidr10.244.0.0/16 \ --service-cidr10.96.0.0/12 \ --kubernetes-versionv1.28.2 \ --cri-socketunix:///run/containerd/containerd.sock \ --upload-certs这里几个参数的含义要说一下--apiserver-advertise-address指定APIServer对外广播的IP一般就是控制面节点的内网IP。如果你是多网卡机器这一步最容易踩坑——kubeadm自动探测的IP可能不是你要用的那个连不上API多半就是这个原因。--pod-network-cidrPod网段要跟后续安装的CNI插件要求保持一致否则网络起不来。--service-cidrService虚拟IP网段注意和Pod网段错开。初始化完成后按照提示配置kubeconfigmkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config然后用kubectl get nodes确认控制面节点是Ready状态。4.3 Worker节点接入集群token过期和证书路径是两大坑工作节点接入集群时标准流程是先在控制面上获取加入命令kubeadm token create --print-join-command然后到worker节点上把带完整参数的join命令执行一遍kubeadm join 192.168.1.10:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx这里有个经典的坑token默认有效期为24小时如果你过几天再往集群里加worker节点这个token早就失效了你还在那傻乎乎的拿旧token去join怎么加都失败。用kubeadm token create --print-join-command重新生成就行。另一个坑是join命令里的--discovery-token-ca-cert-hash必须跟控制面的CA证书指纹对得上否则会报安全错误。排错时很多人卡在这一步纠结怎么算出hash其实用kubeadm token create --print-join-command打出来的命令默认就带上了别自己算。4.4 CNI安装时机很关键不装网络插件CoreDNS永远Pending初始化完集群后检查核心组件状态会发现kube-system里一堆Pod处于Pending状态其中CoreDNS最容易看起来像“挂了”。其实不是CoreDNS的问题而是你没有安装CNI网络插件目前的kubelet根本没法给Pod建网络。安装Calico的操作流程kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml装完以后等一两分钟kubectl get pods -n kube-system里所有Pod才会变成Running。这是一个非常常见的“假故障”也是初次接触K8s架构最容易困惑的一个环节——网络这一层不装上整个集群的Pod都寸步难行。4.5 kubeadm部署vs二进制部署两种方式两种心境kubeadm是官方支持的快速部署工具也是我推荐所有初学者的入门方式。它大幅简化了证书生成、组件静态Pod配置、引导令牌管理这些脏活累活。二进制部署则更接近“手工搭建”每个组件自己下二进制、自己写systemd服务、自己生成证书、自己规划配置。它对架构理解的要求更高但好处也很诱人完全掌控、便于定制、不依赖kubeadm的版本配对关系。坦白讲除非你是在管理特殊定制的生产集群或者需要对某些组件版本做深度定制否则现在真没必要再手动二进制部署一个K8s了。kubeadm已经把物理机/云主机上部署这件事压缩到一条命令级别再怎么追求“理解原理”装第一遍用kubeadm是效率最高的。5. K8s架构里那些“看到了但容易忽略”的部件扩展5.1 Ingress ControllerService之外的第二层流量入口Service解决了Pod间互访问题但如果是外部流量进入集群比如来自浏览器的HTTP请求只靠Service是不够的。传统方案是通过LoadBalancer类型的Service绑定云厂商负载均衡器但这样的做法很浪费资源每暴露一个服务就创建一堆LB实例管理也麻烦。Ingress的思路是在集群内提供一个反向代理层所有外部HTTP请求先打到这个代理再按规则转发到不同Service。这个代理就是Ingress Controller常见的有Nginx Ingress、Traefik、HAProxy Ingress等。架构上Ingress Controller本身也是跑在集群里的Pod通常由Deployment部署并通过NodePort或LoadBalancer类型的Service对外暴露。它的核心运作是靠监听Ingress、Service、Endpoints等资源的变化来动态更新自身的反向代理配置文件。在业务架构里Ingress Controller往往就是那扇“正门”。做多集群、多环境隔离时你甚至可以给每个集群单独部署一套Ingress实现流量层面的完全隔离。5.2 HPA与Controller扩展生态从“手动扩缩”到“自动伸缩”前面提到Controller Manager里跑着一堆内置控制器但K8s最吸引人的地方在于它的控制器机制是可以扩展的。最经典的扩展案例就是HPAHorizontal Pod Autoscaler水平Pod自动伸缩。HPA的架构逻辑其实跟内置Controller一样它持续从Metrics API获取业务Pod的指标通常是CPU、内存使用率或者自定义指标跟期望阈值做对比然后动态调整Deployment的副本数。使用HPA前要确保集群里已经有metrics-server提供基础指标数据否则HPA根本无法工作kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml配置一个最简单的HPAkubectl autoscale deployment my-app --cpu-percent70 --min3 --max10这条命令意思是让my-app这个Deployment的Pod数维持在3-10之间当平均CPU使用率超过70%时就自动扩容低于预设等待时间后降回。从架构视角来看HPA的意义远不止“帮你自动加副本”。它证明了K8s的控制器模式是可以无限扩展的——你要做任何自动化运维能力都能通过写一个自定义Controller或Operator来实现架构上没有任何阻碍。5.3 多集群架构形态从单集群到平台化的演进路径最后聊一下架构的演进方向。单集群部署解决的是“让容器跑起来”的问题。但业务规模大了以后会发现单集群本身成了瓶颈和单点一个region的主集群挂了所有业务都受影响不同团队共用一套集群也容易产生“奴资源抢成风”的混乱。多集群架构常见的三种形态联邦集群Federation一个联邦控制面统一管理多个集群的资源和应用分发适合多地域容灾和统一配置集群内分隔Namespace租户仍然是单集群但靠Namespace加上RBAC和NetworkPolicy做多租户隔离这是最轻量级的方案Hub-Cluster中心-子集群中心集群只负责策略管理和应用下发子集群独立运行业务负载中间通过API层面联通。多集群架构里常见的开源方案有KubeFed、Rancher的Cluster API、Karmada等。对于开始要做平台化的团队我建议的路径是*先把单集群的掌控力练足再上多集群管理。很多人单集群还没玩明白就急着上一个“统一管理平台”结果平台层的复杂度比业务本身还高好几倍不出半年就维护不动了。6. 实操中不得不说的故障排查经验与技巧6.1 哪些故障最容易发生以及排查方法论K8s的故障排查几十种但高频故障相对集中。整理一张速查表遇到问题时不用慌着查屎山。故障现象大概率原因排查命令Pod一直Pending节点资源不足、调度约束不满足kubectl describe pod name看EventsPod一直ContainerCreating镜像拉取失败、存储卷挂载卡住、CNI网络未就绪kubectl describe pod namejournalctl -u kubeletPod反复CrashLoopBackOff容器内程序启动失败或健康检查探针太激进kubectl logs name --previous看退出前日志Service无法访问选择器selector不匹配、Pod没有Ready、kube-proxy规则未生效kubectl get endpoints service看Endpoints是否有IPCoreDNS一直Pending / CrashLoopCNI未安装或kube-dns配置出错、节点DNS解析异常kubectl describe pod -n kube-system -l k8s-appkube-dns节点状态NotReadykubelet失联、负载过高、Docker/containerd故障journalctl -u kubeletkubectl describe node nameAPServer高延迟 / 超时etcd磁盘慢、APIServer资源不足、大量并发List请求curl -k https://127.0.0.1:6443/healthzetcdctl endpoint health排查的第一原则永远是从Events开始而不是从代码开始。kubectl describe是所有排查动作的起点它会把K8s调度器、kubelet在各个环节产生的详细事件按时间顺序展示出来。6.2 三个真实场景复盘从故障现场还原系统协作逻辑场景一Deployment滚动更新卡住新旧Pod同时存在。原因通常是新的ReplicaSet卡在创建Pod阶段而Deployment的MaxUnavailable设置保守默认25%导致既不能缩旧Pod也不能建新Pod。解决思路看ReplicaSet的事件定位Pod卡在哪个环节然后从describe事件里看到的“FailedCreate”或“ImagePullBackOff”反推原因。场景二服务间歇性超时但所有Pod看起来都正常。这种是典型的网络层问题。排查顺序先从Service的Endpoints确认后端Pod都Ready再用kubectl exec进Pod内直接curl后端IP和端口分离“Service转发”和“后端服务”的问题最终定位到可能是kube-proxy的iptables规则在大量Pod创建时出错导致部分新连接丢了。切换到IPVS模式后稳定。场景三节点重启后加入集群发现老的Pod全都找不回来了。大概率是因为Pod所在的数据卷是普通的emptyDir或hostPath节点重启后绑定关系丢失再加上Pod调度策略把Pod飘去了新的节点而数据卷没有跟着走。生产环境的持久化方案要么用NFS/云盘动态PV要么用分布式存储Pod调度层面同时配上PVC跨区调度约束防止数据卷和Pod不在一块。6.3 架构思维的最后一个提醒把故障当成观察架构的窗口很多人遇到故障就急着复制粘贴解决方案这能解决一时问题却没法建立长久的架构掌控力。我自己的习惯是每个故障都能在“组件协作链路”上找到对应的环节——API层、调度层、执行层、网络层还是存储层。比如说Pod Pending问题本质是Scheduler没找到合适节点而不是“kubectl有问题”。Service访问不通本质是Endpoint Controller和kube-proxy有没有正确同步的问题不是“网络环境问题”。把这个思维建立起来以后你会发现K8s这个系统其实并不神秘。它所有的故障最终都能在“控制面决策、数据面执行、状态通过APIServer流转”这个模型里找到对应的坐标。我个人的体会是K8s架构这件事第一次装集群的兴奋感远不如第一次能从describe输出里准确推断出调度和网络哪个环节出了问题来得踏实。这套架构不复杂复杂的只是没有建立起联系的零散概念。希望这篇内容能把那些散落的组件在你脑子里串成一张真正的地图。
返回列表