RKE配置文件详解:从集群部署到生产运维实战
1. 为什么要用RKE从裸机到K8s集群怎么选型1.1 RKE是什么和kubeadm的核心差异如果你已经啃完了Kubernetes的基础概念正准备把手上的服务器拉起来一个真正的集群那么Kubernetes集群部署这个环节大概率是你绕不开的一关。而RKE配置文件详解恰恰是这个环节里最值得花时间搞清楚的内容之一。RKEKubernetes Engine是开源社区里一个老牌的集群部署工具。它最大的特点是不需要在节点上预装kubelet、kubeadm、kube-proxy这些二进制文件而是通过Docker容器把Kubernetes的核心组件跑起来。换句话说节点上只要有Docker环境和SSH通道RKE就能把整个集群拉起来。这个设计从底层改变了部署K8s的体验。kubeadm是官方提供的部署方式它的逻辑是先在master节点上执行kubeadm init再通过kubeadm token让worker节点join进来。过程中要自己处理CA证书、kubelet配置、CNI插件、高可用VIP等一堆事情每一步的配置分散在多个文件里对于多节点高可用集群来说手动操作的环节非常多。RKE的做法则完全不同把所有期望状态写进一份cluster.yml节点角色、组件参数、网络方案、附加组件全部声明式表达然后执行一个命令集群就起来了。我这里用一个不严谨但很好懂的类比kubeadm像手动挡车离合油门都得自己配合但熟悉之后确实很灵活RKE像是自动挡规范化程度高适合日常通勤。生产环境里RKE这套一份配置管全家的思路对运维非常友好配置文件可以直接进Git仓库每次变更都留痕出问题还能快速回滚到上一版配置重新执行这在多人协作的团队里是刚需。1.2 选型考量与适用场景RKE适合什么场景我自己的判断标准是这样你手头是裸金属服务器或者自建的虚拟机需要一套可重复、可审计的部署方式。你要搭的是高可用集群多个controlplane节点加多个etcd节点而不是单机玩票。你处于离线或内网环境需要配合私有镜像仓库来部署集群。你希望集群的配置纳入版本管理让每一次变更都有迹可循。反过来如果只是想本地快速体验K8s那用kind或者minikube会更轻量如果你对Kubernetes组件的参数定制到了需要编译定制版本的程度那RKE默认的镜像体系和参数暴露面可能满足不了你这种场景还是用kubeadm从头到尾手动控制更合适。这里要提前说明一下RKE这个工具本身在社区里已经逐渐让位于新一代的RKE2但存量生产环境里用RKE的集群依然非常多。很多公司跑了好几年的业务集群就是当年用RKE搭起来的维护这些集群就必须读懂RKE的配置文件。所以掌握RKE的配置文件逻辑并不是在学一门过时的技术而是在补一项能直接解决生产问题的实战技能。2. cluster.yml整体架构一份文件如何管起整个集群2.1 配置维度与声明式管理思路cluster.yml是RKE的唯一配置入口它的内容可以分成几个维度。nodes区块定义集群由哪些节点组成每个节点是什么角色services区块定义apiserver、controller-manager、scheduler、kubelet、etcd这些核心组件的参数network区块选择CNI网络方案authentication区块默认用x509证书认证system_images区块指定集群各组件的镜像版本addons区块用来在集群创建后自动部署额外组件后面还有ingress、dns、private_registries、cloud_provider等二级配置。为什么RKE要把这么多内容压缩到一份文件里因为集群状态在RKE看来就是一个声明式对象。你修改配置文件再执行一次rke upRKE会去对比当前集群实际状态和你期望状态之间的差异然后自动完成滚动更新或者配置变更。这个思路和Kubernetes本身声明式API的理念是完全一致的。这种设计带来的好处非常实际。比如你要给kube-apiserver加一个启动参数不需要登录每台节点去改systemd unit文件只需要在cluster.yml的services.kube-api里加几行extra_args然后执行rke up。RKE会自己判断哪些节点需要重启哪些组件需要滚动替换整个过程不用人工介入。2.2 一个最小可用的完整配置示例先看一个最小的单节点全角色配置用于本地测试或者临时环境cluster_name: demo-local nodes: - address: 192.168.1.30 user: ubuntu roles: [controlplane, etcd, worker] ssh_key_path: ~/.ssh/id_rsa services: kube-api: service_cluster_ip_range: 10.43.0.0/16 kube-controller: cluster_cidr: 10.42.0.0/16 service_cluster_ip_range: 10.43.0.0/16 kubelet: cluster_dns_server: 10.43.0.10 cluster_domain: cluster.local network: plugin: flannel这份配置里roles写的是[controlplane, etcd, worker]意味着这台机器身兼数职。它能在单机上把集群完整跑起来但注意这种架构下etcd只有一份数据副本没有任何高可用能力只适合拿来学习和验证流程绝对不能当作生产环境的参考模板。同时要注意网段规划。RKE默认Pod网段是10.42.0.0/16Service网段是10.43.0.0/16这两个网段的默认值在配置里必须和节点所在的内网网段错开。如果节点网段本身就在10.42.0.0/16里那创建Pod之后路由就会乱套。这个坑是我见过最多的集群初始化问题后面会专门在排查章节里展开。3. nodes区块详解节点角色划分与SSH连接配置3.1 三种角色怎么分配才是高可用nodes区块是整个cluster.yml的基础RKE通过它认识集群里的每一台机器。每个节点可以分配三种角色controlplane、etcd、worker。controlplane节点跑的是kube-apiserver、kube-controller-manager、kube-scheduler相当于集群的大脑etcd节点保存着集群全部状态相当于数据库worker节点运行kubelet和kube-proxy承载实际的业务Pod。RKE允许一个节点同时承担多个角色这是它在部署灵活性上的一大特点。比如常见的生产配置里三台机器每个都同时跑controlplane和etcd另外再挂两组worker节点。这样既保证了控制面的高可用又不需要单独准备额外的etcd机器。关于角色规划有几条硬性经验etcd节点数量必须是奇数3台或5台不要用偶数。这不是什么性能优化而是raft协议对quorum的硬性要求。etcd集群里超过半数节点存活才能选出leader3台允许挂1台4台也只允许挂1台但5台就能允许挂2台。所以偶数数量在容灾上没有任何优势只会白白增加同步开销。controlplane至少2台前面配VIP或者负载均衡避免单点故障。worker节点按业务流量规划如果希望控制面组件不被打满worker和controlplane尽量分离开。我自己就见过一个生产集群6台机器却只配置了单etcd那台机器宕机之后整个集群直接瘫痪所有节点的Pod全部失控最后只能靠快照重建。这个教训印象太深了。3.2 SSH连接参数与权限细节RKE通过SSH协议连接并操作节点所以nodes区块里最关键的内容除了角色就是SSH连接信息。nodes: - address: 10.0.0.11 user: deploy roles: [controlplane] ssh_key_path: /root/.ssh/cloud.key port: 22 labels: region: east这里的address必须是RKE执行机能够直接访问到的IP。user则是用来执行部署命令的SSH用户这个用户需要有docker命令的执行权限同时要能创建和操作/var/lib/docker下的目录。address和user写错下面一切免谈。SSH配置里有几个特别容易踩的坑私钥权限不能太宽松否则SSH服务端会直接拒绝。chmod 600 ~/.ssh/id_rsa是必须的。不同云平台默认用户不一样Ubuntu镜像默认ubuntuCentOS默认root没有确认好就填地址部署时会一直卡在认证失败。如果使用普通用户加sudo的方式要注意RKE在非交互式SSH会话里没法自动输入sudo密码。所以要么直接给这个用户加入docker组要么配置NOPASSWD的sudo规则否则执行过程中会报权限错误。我自己的习惯是单独建一个deploy用户把docker组加入进去再配合一把独立的部署密钥。这样即使密钥泄露影响范围也仅限于Docker操作不会直接暴露整台机器的root权限。3.3 节点labels与专用字段nodes区块里还可以给节点打labels这些标签会同步到Kubernetes节点的metadata里后续做Pod调度、亲和性配置都可以直接引用。比如把节点按机房或区域打上region标签业务侧就可以通过nodeSelector把工作负载固定到特定区域的机器上。RKE还支持内联私钥的方式直接把私钥内容写进配置里的ssh_key字段。这种方式适合做一些临时性的自动化任务但我建议生产环境还是走ssh_key_path把密钥文件独立管理避免私钥内容散落在配置文件里。4. services区块详解网段规划、etcd备份这些关键参数4.1 kube-api和kube-controller的核心网段参数services区块是cluster.yml里参数最密集的地方负责定义Kubernetes各组件的运行参数。其中最容易被忽视也最容易出问题的是几组网段参数。services: kube-api: service_cluster_ip_range: 10.43.0.0/16 kube-controller: cluster_cidr: 10.42.0.0/16 service_cluster_ip_range: 10.43.0.0/16 kubelet: cluster_dns_server: 10.43.0.10 cluster_domain: cluster.localkube-api区块里的service_cluster_ip_range决定了Service可以使用的虚拟IP范围kube-controller区块里同样要声明一遍service_cluster_ip_range同时还要声明cluster_cidr作为Pod网段。kubelet里则要配置cluster_dns_server和cluster_domain其中cluster_dns_server的默认值就是Service网段中的第10个IP10.43.0.0/16对应的就是10.43.0.10。为什么Service网段要在两个地方重复声明因为kube-apiserver在处理Service代理时需要知道哪些IP属于Service虚拟IP而kube-controller-manager在创建Service时也需要从这个网段里分配具体的IP。漏掉任何一个集群起来之后就会出现Service分配不到IP或者DNS解析不正常的诡异问题。Pod网段、Service网段、节点网段三者必须完全不重叠。这个规划最好在部署前画一张表把三个网段都写清楚贴到团队文档里。花5分钟做这件事能省下后面好几天排障的时间。4.2 kubelet与extra_args扩展参数services区块里每个组件都支持extra_args、extra_env、extra_binds这些扩展字段用来追加默认配置里没有暴露的参数。比如kubelet的max-pods限制默认值对于大批量启动Pod的场景未必够用就可以这样配置services: kubelet: extra_args: max-pods: 200 image-gc-high-threshold: 85注意extra_args的value必须是字符串即使数字也要加引号。这个细节很多人第一次写会漏。RKE会自动把这些参数追加到对应组件的启动命令里比起手动改systemd配置这种方式的可维护性高出很多。4.3 etcd备份参数详解etcd是整个集群里唯一有状态、不可轻易重建的组件所以services.etcd的参数值得单独说。RKE内置了etcd自动快照机制services: etcd: backup_config: interval_hours: 12 retention: 7 safe_timestamp: falseinterval_hours表示每隔多少小时自动做一次快照retention表示本地最多保留多少个快照文件safe_timestamp控制快照文件名是否带上精确的秒级时间戳。快照会存放在节点内部的/opt/rke/etcd-snapshots目录。自动快照只是一个底线保障我建议在它之上再加一层用cron任务定期把快照文件同步到独立的存储位置比如对象存储或者另一台机器。否则一旦节点整机故障快照和节点一起没了等于没备份。手动备份的命令是rke etcd snapshot-save --name before-upgrade --config cluster.yml这个命令在每次集群升级、配置大改、证书轮换之前都必须执行。不是可选步骤而是运维习惯问题。快照文件便宜恢复代价昂贵宁可多存几份也不要赌运气。5. network、ingress与addons网络插件选型和附加组件5.1 CNI插件怎么选network区块决定集群Pod网络的实现方式。RKE支持的插件有flannel、calico、canal、weave各有侧重点。插件核心特点适用场景flannel轻量VXLAN叠加网络配置简单对网络策略无要求的简单集群calicoBGP路由转发支持NetworkPolicy性能好生产环境首选特别是多租户隔离场景canalcalico网络策略加flannel数据通路想用策略又不想折腾BGP路由的环境weave老牌方案内置加密能力节点间通信需要强加密的特定场景我生产环境基本都用calico。选择网络插件这件事一定要在集群创建初期定下来因为CNI涉及所有节点上的网络规则和路由表后期想更换就是一场大手术所有节点要重新初始化网络栈风险极高。配置方式很简单network: plugin: calico如果选择calico可以进一步在network.options里配置veth_mtu等参数但大部分情况下默认值就够用不需要动。5.2 ingress与addonsingress区块用来配置集群的Ingress Controller。RKE默认支持nginx ingress开启后会以DaemonSet形式在所有节点上部署nginx-ingress-controlleringress: provider: nginx extra_args: enable-ssl-passthrough: 如果你的业务需要对外暴露HTTP服务这个模块非常重要。它可以省去自己手动部署Ingress Controller的步骤而且和集群生命周期管理绑定在一起rke up执行时自动完成升级。addons字段则是RKE里非常灵活的一个配置项它允许你直接把一段或多段Kubernetes manifest写进cluster.yml。RKE在集群创建完成后会自动apply这些内容用于部署metrics-server、Dashboard、监控采集器等附加组件。addons: | --- apiVersion: v1 kind: Namespace metadata: name: monitoring --- apiVersion: apps/v1 kind: Deployment metadata: name: metrics-server namespace: kube-system ...多个YAML之间用---分隔RKE会自动拼接并应用。这个机制的好处是集群重建后不需要人工去补装组件只要配置文件还在一切都能自动恢复。把addons当作集群基础设施的一部分来管理是RKE运维里很实用的一招。6. 实操过程三节点高可用集群部署实录6.1 节点与工具准备我以一套5节点高可用集群为例3台controlplaneetcd节点2台worker节点。操作系统是Ubuntu 22.04Docker已经提前装好。这里强调一下RKE本身不关心操作系统发行版是什么但Docker版本和内核版本需要满足Kubernetes的要求尤其是老版本RKE对Docker版本有限制如果版本过新反而会出现兼容问题。每台节点上先做基本验证docker version docker ps确保docker命令可以正常执行。然后配置SSH密钥把公钥复制到每台节点ssh-keygen -t rsa -b 4096 ssh-copy-id deploy192.168.1.11 ssh-copy-id deploy192.168.1.12 ssh-copy-id deploy192.168.1.13在工作机上准备rke二进制文件chmod x rke sudo mv rke /usr/local/bin/ rke --version下载的时候要确认版本对应的Kubernetes支持范围。RKE不同版本对Kubernetes版本的支持矩阵不同选错版本会在初始化阶段直接报错这个信息一般都在工具的发布说明里有明确标注。6.2 高可用配置与rke up完整的cluster.yml配置如下cluster_name: prod-demo nodes: - address: 192.168.1.11 user: deploy roles: [controlplane, etcd] ssh_key_path: ~/.ssh/id_rsa - address: 192.168.1.12 user: deploy roles: [controlplane, etcd] ssh_key_path: ~/.ssh/id_rsa - address: 192.168.1.13 user: deploy roles: [controlplane, etcd] ssh_key_path: ~/.ssh/id_rsa - address: 192.168.1.14 user: deploy roles: [worker] ssh_key_path: ~/.ssh/id_rsa - address: 192.168.1.15 user: deploy roles: [worker] ssh_key_path: ~/.ssh/id_rsa services: etcd: backup_config: interval_hours: 12 retention: 7 kube-api: service_cluster_ip_range: 10.43.0.0/16 kube-controller: cluster_cidr: 10.42.0.0/16 service_cluster_ip_range: 10.43.0.0/16 kubelet: cluster_dns_server: 10.43.0.10 cluster_domain: cluster.local network: plugin: calico ingress: provider: nginx这个配置前三个节点同时承担controlplane和etcd角色后面两个节点纯worker。比较关键的一点controlplane节点前面最好再挂一个负载均衡器指向6443端口这样即使某一台控制面节点宕机kubeconfig里始终能用同一个VIP地址访问apiserver。执行部署命令rke up --config cluster.yml这个过程会持续几分钟RKE会先初始化etcd集群再拉起controlplane组件最后配置worker节点。日志输出很长中间出现WARN级别信息通常是提示某些配置弃用不一定要立刻处理但看到Finished building Kubernetes cluster successfully才算真正完成。6.3 验证集群与高可用测试rke up成功后会生成kube_config_cluster.yml文件用它连接集群export KUBECONFIG$PWD/kube_config_cluster.yml kubectl get nodes kubectl get pods -A正常的输出应该能看到所有节点处于Ready状态kube-system命名空间下的核心组件全部Running。可以做一次高可用测试手动停掉其中一台controlplane节点观察集群是否继续可用。由于etcd是3副本挂掉一台仍然有quorumapiserver还会正常工作业务Pod不受影响。测试做完再把节点恢复重新执行一次rke upRKE会自动把etcd成员加回集群。验证一次性部署成功后可以往集群里扔一个简单的测试应用kubectl create deployment nginx --imagenginx:stable kubectl expose deployment nginx --typeNodePort --port80确认Service分配到IP、Pod调度到worker节点整个链路才算真正打通。7. 常见问题与排查技巧实录7.1 SSH连接失败RKE报错Failed to connect to node ... ssh: handshake failed是出现频率最高的初始化问题。这种问题基本集中在几个地方。先确认网络连通性执行telnet 192.168.1.11 22看看端口是不是通的。然后检查私钥权限chmod 600 ~/.ssh/id_rsa。如果之前测试过但没连上过用ssh-keygen -R 192.168.1.11清掉旧的hostkey记录再重试。还有一个容易被忽略的点RKE执行机到节点之间的SSH必须是可交互成功的。先在命令行直接ssh deploy192.168.1.11验证一次如果能登录再看配置里的user、address是否和真实环境一致。几次排查下来大部分问题都是用户写错或者私钥放错位置。7.2 CoreDNS一直起不来集群创建成功了但coredns的Pod一直处于ContainerCreating或者CrashLoopBackOff状态。这个问题十有八九是CNI网络插件没有就绪。排查路径是kubectl get pods -n kube-system -o wide kubectl describe pod coredns-xxxxx -n kube-system查看Pod的事件信息如果里面反复出现网络相关报错就去看calico或者flannel组件的Pod状态。如果是calico还有一个特别隐蔽的坑Ubuntu系统的NetworkManager可能会在启动时重新配置网络接口把calico创建的路由规则冲掉导致Pod网络断断续续。解决办法是在NetworkManager的配置里忽略集群相关的网卡接口让这些接口不受系统网络管理服务干扰。7.3 etcd节点故障生产环境里etcd节点故障是最让人紧张的。etcd挂掉一台只要其余节点健康集群短时间内不会全丢但必须尽快处理。正确的处理流程是先修改cluster.yml把故障节点从nodes里移除或者替换成新节点然后对其他健康节点执行一次手动快照最后执行rke up让RKE完成etcd成员更替。RKE在处理etcd节点变更时有一套自己的流程它会将新节点加入etcd集群再从集群里移除故障节点整个过程尽量保证集群可用性。在执行任何etcd变更前先做一次快照rke etcd snapshot-save --name pre-repair --config cluster.yml这个快照就是最后的救命稻草。如果变更过程中出现意外导致etcd集群完全不可用唯一能走的路就是通过快照恢复。7.4 常见错误速查我把平时踩过的坑整理成一张速查表供参考现象可能原因快速处理SSH握手失败IP不通、密钥权限过大、用户错误先手动ssh验证再chmod 600rke up卡在拉镜像节点无法访问镜像仓库配置private_registries或镜像代理节点一直NotReadyCNI组件异常、容器运行时权限问题查看kube-system Pod事件Service无法分配IP网段参数配置不一致检查kube-api和kube-controller证书过期报错超过一年未轮换执行rke cert rotate并更新kubeconfig8. 运维进阶备份恢复、升级与证书轮换8.1 从快照恢复集群当etcd集群发生不可逆的损坏时快照恢复是唯一的出路。恢复命令本身不复杂rke etcd restore --name pre-repair --config cluster.yml但恢复过程是一个重操作。RKE会先停掉集群各节点上的Kubernetes相关容器再用指定快照重新拉起etcd最后把集群整体恢复到可用状态。整个过程中集群对外完全不可用所有写操作都会失败所以一定要提前申请维护窗口并且通知业务方。恢复完成后RKE会重新生成kube_config_cluster.yml需要用新文件连接集群。我之前处理过一次恢复操作当时业务侧没有提前降级流量恢复期间大量请求超时事后排查日志才发现报警系统也被集群中断影响了。这个教训说明etcd恢复不只是一个技术动作事前通知和业务降级同样重要。8.2 集群升级流程RKE的集群升级思路和部署一模一样修改配置里的镜像版本然后执行rke up。RKE会把新的镜像tag推到各个节点然后按顺序滚动替换etcd、controlplane、worker上的容器。升级前必须做两件事备份etcd快照以及整理一份详细的变更清单。rke etcd snapshot-save --name before-upgrade --config cluster.yml为什么必须先升级etcd再升级controlplane因为新版本的kube-apiserver往往需要读写新版本的etcd数据格式反过来新版本etcd不一定兼容旧版本的apiserver。所以RKE按依赖关系排定滚动顺序这个顺序不要自己去打乱。升级过程中如果发现某个组件反复重启最稳妥的做法是停止升级检查日志确认是不是版本兼容问题。不要强行执行多次rke up盲目重试可能会把部分节点升级到新版本、另一部分还在旧版本制造出更复杂的中间状态。8.3 证书轮换RKE默认签发的证书有效期是1年到期前需要做轮换。命令也很简单rke cert rotate --config cluster.ymlRKE支持只轮换某个组件的证书比如只想处理kubelet的证书rke cert rotate --service kubelet --config cluster.yml轮换完成后集群里的证书文件都会更新同时kube_config_cluster.yml也会重新生成。这里有个特别容易踩的坑证书轮换后如果继续使用旧的kubeconfig文件kubectl就会报证书过期或未知CA。这时候不要急着怀疑集群坏了先确认KUBECONFIG环境变量指向的到底是不是最新生成的配置文件。RKE的配置文件能力远不止这些还有private_registries私有仓库配置、cloud_provider云厂商集成、dns配置等。不过只要把nodes、services、network、addons这几个核心模块吃透再配合上面的运维实操生产环境的日常维护基本都能覆盖。最后分享一个我自己坚持了很久的工作习惯每次修改cluster.yml之前先复制一份带着日期后缀的备份文件比如cluster-20250115.yml。RKE跑完一轮变更之后再回头对比两个文件的差异任何配置漂移都能直接看出来。这个习惯帮我挡掉过好几次因为手误把某个节点label改掉的意外。另外强烈建议把cluster.yml纳入Git仓库每次变更都走评审和留痕这比任何团队内部的口头交接都靠谱。配网段之前先画拓扑图动etcd之前先打快照改完配置之后先看diff记住这三件事RKE这条路上最大的坑基本就都绕开了。