ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

K8s二进制部署多主多从集群:证书、etcd与组件实战

K8s二进制部署多主多从集群:证书、etcd与组件实战 最近有个做运维的朋友问我kubeadm 都这么成熟了还有必要折腾二进制部署么我当时正在给一套生产环境规划多主多从架构正好在这块踩了不少坑。kubeadm 确实快点两下就能拉起集群但它把很多东西都封装成了黑盒——证书怎么签的、组件参数怎么拼的、apiserver 和 etcd 之间到底怎么认证的出了问题你很难第一时间定位。换成二进制部署每个组件都是自己亲手拉起来的配置文件逐行写逻辑链路自然就清楚了。这篇文章把我在 Ubuntu 24.04 上基于 containerd 部署 K8S 1.35.0 二进制多主多从集群的完整过程记录下来包括架构规划、证书体系设计、etcd 集群搭建、各组件配置细节以及我在实际部署中踩过的坑和排查思路。适合想深入理解 Kubernetes 组件交互、或者需要在离线环境/定制化环境中交付集群的读者。1. 部署前必须想清楚的事——架构设计远远先于命令执行1.1 为什么选二进制部署而不是 kubeadmkubeadm 的定位是快速拉起一个标准集群它帮你把 kubelet、kube-proxy、control plane 组件以静态 Pod 或 systemd 服务的形式装好证书、kubeconfig、RBAC 这些全都自动处理。好处是快坏处是出问题时你面对的是一个黑盒。比如证书 SAN 里漏了某个 IP、apiserver 连不上 etcd、kubelet 的 bootstrap 证书轮换失败这类问题用 kubeadm 排查时你还需要反向去猜它到底生成了一份什么配置。二进制部署则把每一步都摊开在眼前组件从哪里下载、怎么解压、放到哪个目录完全由你定义。证书体系从 CA 开始手工签发每一个证书的用途、SAN、签发者都清清楚楚。apiserver、controller-manager、scheduler 各自以独立的 systemd 服务运行参数逐行可查。更容易做离线交付或者定制化改造比如替换网络插件、调整审计日志策略、对接企业内部 PKI二进制方式完全不依赖 kubeadm 的固定逻辑。当然二进制方式也有明显的代价首次部署需要准备的步骤多容易出错对操作者的理解深度要求高。但反过来想你一旦手工把集群拉起来一遍后面再遇到任何集群故障脑子里对组件间的调用关系已经有了完整的图景。1.2 多主多从的组件分布与流量路径这次部署采用 3 主 3 从的拓扑。3 个 master 节点运行 apiserver、controller manager、scheduler 以及 etcd 集群这里选择 etcd 与控制面混部适合中小规模环境如果数据量很大建议把 etcd 拆到独立节点。3 个 worker 节点运行 kubelet、kube-proxy 及业务负载。在动手之前先画清楚各组件的数据流用户或客户端通过负载均衡器我这里用 HAProxy Keepalived 提供虚拟 IP访问任意一个 master 的 6443 端口请求进入 kube-apiserver。apiserver 是所有组件通信的唯一入口。它需要访问 etcd 集群读写集群状态同时接收 controller-manager 和 scheduler 的连接——这两个组件自身不直接对外提供服务它们通过 kubeconfig 指向 apiserver 完成认证然后持续 watch 资源变化。kubelet 运行在每个节点上主动向 apiserver 注册节点、上报状态并从 apiserver 获取分配给本节点的 Pod 定义。kube-proxy 通过 watch apiserver 中的 Service/EndpointSlice 资源维护节点上的转发规则。这套架构里有一个很关键的细节controller-manager 和 scheduler 对 apiserver 的访问走的是内部 kubeconfig而 kubelet 访问 apiserver 走的是客户端证书认证。所以在证书体系设计阶段就要把每个角色的身份区分好避免一个证书到处用。1.3 版本选型与下载清单K8S 1.35.0 属于较新的版本部署时需要注意内核版本和系统版本的兼容性。Ubuntu 24.04 默认内核是 6.8 系列配合 containerd 2.x 使用比较稳妥。以下是本次使用的版本组合组件版本说明Kubernetesv1.35.0官方二进制 tar 包内含所有组件etcdv3.5.183.5 系列稳定性比较好containerd2.0.x使用 CRI 集成方式无需额外安装 cri-containerdCNI pluginsv1.6.0提供基础网络插件支持cfssl1.6.x用于签发集群证书下载地址方面Kubernetes 二进制包从官方 GitHub Releases 页面获取etcd 和 containerd 同样从官方仓库下载。下载之后必须做校验官方包一般会提供 sha512 或 sha256 校验值这一步能避免很多莫名其妙的问题尤其是离线中转场景。2. 环境基线主机规划、内核参数与 containerd 落地2.1 主机规划与系统基础配置节点规划表如下这里用私有网段示例实际按企业环境替换主机名IP角色k8s-master01192.168.10.11control plane / etcdk8s-master02192.168.10.12control plane / etcdk8s-master03192.168.10.13control plane / etcdk8s-worker01192.168.10.21workerk8s-worker02192.168.10.22workerk8s-worker03192.168.10.23workerk8s-lb192.168.10.10虚拟 IPKeepalived VIP所有节点在部署前先做几件基础工作关闭 swap原因是 kubelet 对 swap 的支持虽然从 1.22 开始逐步放开但生产环境仍然建议关掉避免内存回收影响 Pod 稳定性禁用防火墙或者放行必要端口Ubuntu 自带的 ufw 如果不关后面组件之间通信会被莫名阻断设置主机名和 hosts 解析。在 hosts 里建议不仅写节点 IP 对应关系还要加一条虚拟 IP 对应 apiserver 域名的记录比如192.168.10.10 apiserver.k8s.local这样各节点的 kubeconfig 里可以直接用域名访问 apiserver后续如果换 LB 地址不需要重新分发 kubeconfig。SSH 免密登录也在这个阶段配置好。二进制部署经常需要在三台 master 之间互传证书和配置没有免密会很痛苦。用 ssh-keygen 生成密钥后把公钥分发到所有节点即可。2.2 内核参数与模块加载Kubernetes 集群对内核参数有明确要求。主要调整以下几项把 net.bridge.bridge-nf-call-iptables 设为 1确保经过 bridge 的流量也能被 iptables 规则处理这是 Kubernetes Service 和 Pod 网络正常工作的前提。net.ipv4.ip_forward 必须为 1否则容器网络无法转发数据包。此外还需要加载 overlay 和 br_netfilter 这两个内核模块containerd 的 overlayfs 存储驱动依赖 overlay 模块而 bridge 流量过滤依赖 br_netfilter。写入配置文件时注意持久化。在 /etc/modules-load.d/k8s.conf 里写上 overlay 和 br_netfilter在 /etc/sysctl.d/k8s.conf 里写上上述参数然后执行 modprobe 加载模块、sysctl --system 应用参数。这一步做完建议 reboot 一次再继续避免模块加载问题在集群运行后才暴露。2.3 containerd 部署与配置细节containerd 的安装方式有两种用 apt 直接装或者用官方二进制包解压。推荐后者因为 apt 源里的版本可能滞后而且二进制包解压到 /usr/local 目录即可运行方便统一管理。安装 containerd 之后并没有默认配置文件需要先执行containerd config default /etc/containerd/config.toml生成默认配置然后修改几个关键位置。第一个是 sandbox_image。默认配置里指向的是 registry.k8s.io/pause:3.x 镜像国内网络环境拉取可能超时。我一般改成registry.aliyuncs.com/google_containers/pause:3.10或者内网镜像仓库对应的地址。这里要特别注意K8S 1.35.0 对 pause 镜像版本有要求太旧版本可能无法正常启动 Pod 沙箱。第二个是 SystemdCgroup。找到SystemdCgroup false改成SystemdCgroup true。这个参数决定了 containerd 采用哪种 cgroup driver 管理容器资源。Ubuntu 24.04 默认使用 systemd 作为 init 系统如果 containerd 用 cgroupfs 而 kubelet 用 systemd两个组件对 cgroup 的管理方式不一致轻则节点状态异常重则 Pod 无法启动。这个锅我背过不止一次务必检查。第三个是镜像仓库配置。在企业内网环境通常需要配置 mirror。containerd 2.x 支持在 config.toml 里通过 [plugins.io.containerd.grpc.v1.cri.registry.mirrors] 段落配置格式和旧版本略有不同以官方文档为准。配置完成后重启 containerd 服务并用ctr ns list或crictl version验证启动是否正常。crictl 需要单独安装它是排查 CRI 运行时问题的最常用工具。3. 证书体系牵一发动全身的 PKI 设计3.1 证书规划清单与核心原则Kubernetes 集群内部几乎所有的安全通信都依赖 TLS 证书。二进制部署时证书体系的合理设计直接决定了集群能不能健康运行。需要签发的证书包括CA 根证书etcd CA 和 Kubernetes CA 可以合并也可以分开建议分开这样风险隔离更好etcd 服务端证书供 etcd 各节点之间 peer 通信、以及客户端访问 etcd 使用kube-apiserver 服务端证书需要包含所有 master 节点 IP、虚拟 IP、域名、Service 网段中第一个 IP通常是 kubernetes.default 解析到的地址kube-controller-manager 客户端证书kube-scheduler 客户端证书kubelet 客户端证书支持自动轮换kube-proxy 客户端证书admin 用户证书用于 kubectl 访问集群这里有一个最常见的坑apiserver 证书的 SAN 列表少填了虚拟 IP 或 Service IP。一旦少填kubectl 通过虚拟 IP 访问 apiserver 时证书校验失败报 x509: certificate is valid for xxx, not xxx。而且这类问题只影响通过该 IP 访问的场景用节点 IP 访问可能完全正常隐蔽性很强。所以签发 apiserver 证书时把下面这些全部列进去三台 master 的 IP、虚拟 IP、hostnamek8s-master01/02/03、域名 apiserver.k8s.local、kubernetes.default.svc、kubernetes.default.svc.cluster.local、127.0.0.1、以及 Service 网段第一个 IP例如 10.96.0.1。3.2 用 cfssl 还是 openssl生成证书的工具链有两种选择。cfssl 是 cloudflare 推出的 PKI 工具配置文件是 JSON 格式生成逻辑更贴合 Kubernetes 的证书需求。openssl 是传统工具写配置文件时自由度更高。我在实际项目中两种都用过cfssl 适合一次性批量签发多张证书配置模板复用性强openssl 适合临场单张签发生成但是多条命令组合容易写错。这次推荐 cfssl原因是 Kubernetes 证书的使用场景里需要重复签发多个具有不同 CN 和 SAN 的证书cfssl 用配置文件一跑就完事不容易漏字段。安装 cfssl 时注意它会拆成 cfssl、cfssljson、cfssl-certinfo 三个工具。生成证书时用到 cfssl 生成 CSR、cfssljson 把 JSON 输出转成文件、cfssl-certinfo 校验证书内容。3.3 CA 与组件证书的签发过程先创建 CA 配置文件 ca-config.json里面定义证书的有效期企业内部建议 10 年和使用场景client/server/peer。再创建 ca-csr.json 定义 CA 的 CN 和 key 大小这里 CN 建议写一个不容易和集群内组件混淆的名字比如 k8s-ca。执行cfssl gencert -initca ca-csr.json | cfssljson -bare ca得到 ca.pem 和 ca-key.pem然后根据同样的逻辑签发 etcd CA。组件证书签发时通过 hostname 字段指定 SAN。以 apiserver 为例{ CN: kube-apiserver, hosts: [ 192.168.10.11, 192.168.10.12, 192.168.10.13, 192.168.10.10, 10.96.0.1, 127.0.0.1, kubernetes.default, kubernetes.default.svc, kubernetes.default.svc.cluster.local, apiserver.k8s.local ], key: { algo: rsa, size: 2048 } }签发命令统一为cfssl gencert -caca.pem -ca-keyca-key.pem -configca-config.json -profileserver server-csr.json | cfssljson -bare kube-apiserver。注意 profile 的选择要与 ca-config.json 里定义的 profiles 对应server 和 client 不要搞混。etcd 证书要选 profile 为 peerKubernetes 内的组件证书用 client 或 server。3.4 证书分发与文件权限避坑证书生成之后需要按组件分发到对应节点的指定目录。我习惯统一放到 /etc/kubernetes/pki 下目录结构清晰方便后续查看。分发完成之后必须关注文件权限kubelet 运行时会读取证书目录如果权限过宽可能报警生产环境一般设置成 644 权限、root 属主即可。kubeconfig 文件权限设置为 600因为这些文件里包含私钥信息。另外kubelet 的证书轮换机制在二进制部署中建议直接开启。在 kubelet 配置里设置 rotateCertificates: true并在 apiserver 中配置对应的 RBAC 权限允许 kubelet 通过 node authorization 模式申请新证书。这样证书到期后 kubelet 会自动续签不需要人工介入。初期忘了配置轮换运营一年后证书突然集体过期那种全家桶式故障的滋味不好受。4. etcd 集群先把控制面的存储底座立起来4.1 etcd 节点间通信与成员发现机制etcd 集群需要三个节点互相通信peer 端口默认 2380client 端口默认 2379。集群成员发现通过 initial-cluster 参数静态指定每一个节点启动时都会带上自己和其他两个节点的地址。这里有一个常见误区initial-cluster 里的地址格式必须是hostnamehttps://192.168.10.11:2380等号左边的名字要与节点的 name 参数完全一致否则 etcd 启动会报成员冲突。我先在三台 master 上分别建好 etcd 数据目录和证书目录。数据目录位置建议单独规划比如 /var/lib/etcd确保有足够的磁盘空间。生产环境 etcd 对磁盘 IO 比较敏感最好在单独的磁盘或 SSD 上。etcd 的 systemd 服务配置里关键参数有这几个--name 指定节点名--data-dir 指定数据目录--listen-client-urls 监听地址建议同时监听 127.0.0.1 和本机 IP方便本机维护和远程访问--listen-peer-urls 监听 peer 通信必须监听集群可达的地址--initial-advertise-peer-urls 用于其他节点发现本节点--advertise-client-urls 用于 apiserver 访问。证书相关的参数同样重要。--cert-file 和 --key-file 是 etcd 服务端证书--peer-cert-file 和 --peer-key-file 是 peer 通信证书--client-cert-authtrue 表示启用客户端证书校验--peer-client-cert-authtrue 同理。4.2 三节点 etcd 的 systemd 配置与服务启动以 k8s-master01 为例/etc/systemd/system/etcd.service 主要内容如下[Unit] Descriptionetcd server Afternetwork.target [Service] Typenotify ExecStart/usr/local/bin/etcd \ --namek8s-master01 \ --data-dir/var/lib/etcd \ --listen-client-urlshttps://192.168.10.11:2379,https://127.0.0.1:2379 \ --advertise-client-urlshttps://192.168.10.11:2379 \ --listen-peer-urlshttps://192.168.10.11:2380 \ --initial-advertise-peer-urlshttps://192.168.10.11:2380 \ --initial-clusterk8s-master01https://192.168.10.11:2380,k8s-master02https://192.168.10.12:2380,k8s-master03https://192.168.10.13:2380 \ --initial-cluster-statenew \ --cert-file/etc/kubernetes/pki/etcd-server.pem \ --key-file/etc/kubernetes/pki/etcd-server-key.pem \ --client-cert-authtrue \ --trusted-ca-file/etc/kubernetes/pki/etcd-ca.pem \ --peer-cert-file/etc/kubernetes/pki/etcd-peer.pem \ --peer-key-file/etc/kubernetes/pki/etcd-peer-key.pem \ --peer-client-cert-authtrue \ --peer-trusted-ca-file/etc/kubernetes/pki/etcd-ca.pem Restarton-failure RestartSec5 LimitNOFILE65536 [Install] WantedBymulti-user.targetTypenotify 这里有一个细节etcd 通过 systemd notify 机制向 systemd 报告自己启动完成如果配置错了服务明明已经运行但 systemctl 显示仍在 activating排查起来很迷惑。三台节点配好之后先启动第一台等它正常进入运行状态再启动第二台、第三台。全部启动后用etcdctl endpoint health --cluster检查集群健康状态。如果出现超时多半是证书里的 SAN 没包含对端地址或者防火墙没放行 2380 端口用 etcdctl 加 --debug 参数可以看到具体卡在哪一步。4.3 数据安全与备份策略etcd 是整个集群唯一的持久化状态存储备份不是可选而是必须。二进制部署环境下一般用 etcdctl snapshot save 做定时快照。生产环境建议每小时全量快照一次保留 24 小时的备份文件同时每日异地备份。快照文件可以压缩后归档etcd 的数据通常不会特别大但恢复流程要提前演练。恢复的时候先停掉所有 etcd 节点用 etcdctl snapshot restore 在每台节点上把快照恢复到本地数据目录再重新启动 etcd 集群。这个流程里的一个关键是恢复后的 etcd 集群需要用 --initial-clusternew 重新初始化成员关系同时各节点的 name 不能重复否则恢复后的集群会拒绝启动。5. 控制平面组件逐一落地——apiserver、controller-manager 与 scheduler5.1 kube-apiserver 的配置文件与启动参数apiserver 是整个集群的中枢部署时把它放在所有组件最前面。二进制包里已经包含了 kube-apiserver 可执行文件拷贝到 /usr/local/bin 后需要把它运行所需的主要参数一条条列清楚。首先是服务监听相关--bind-address0.0.0.0--secure-port6443。注意 apiserver 默认还有一个 8080 端口--insecure-port新版本已经默认关掉不要开启避免绕过 TLS 直接访问集群。其次是与 etcd 的对接--etcd-servershttps://192.168.10.11:2379,https://192.168.10.12:2379,https://192.168.10.13:2379同时指定 --etcd-cafile、--etcd-certfile、--etcd-keyfile 三个证书参数。这三个参数对应的是 apiserver 作为 etcd 客户端时使用的 CA 和证书如果证书配置不对apiserver 会一直报 etcd 连接错误。然后是集群 CIDR 规划--service-cluster-ip-range10.96.0.0/16--service-node-port-range30000-32767。这个网段要在部署前就定好后续不能随意修改否则 Service 的 ClusterIP 会全部失效。Pod 网段 --cluster-cidr172.26.0.0/16 在 apiserver 层面配置这是为网络插件预留的 Pod 地址范围与 Service 网段要避开。认证授权相关--client-ca-file 指定 CA 证书用于校验客户端证书--service-account-key-file 指定 Service Account token 签名公钥对应 controller-manager 那边的私钥--authorization-modeNode,RBAC 开启节点授权和 RBAC。sertificate SAN 相关--tls-cert-file 和 --tls-private-key-file 就是前面签的 apiserver 证书和私钥。apiserver 的 systemd 单元里还要注意几个通用参数--enable-admission-plugins 保持默认即可--audit-log-path 建议开启审计日志并配置 log 目录避免后续排查问题时没有日志可查。配置完后用curl --cacert /etc/kubernetes/pki/ca.pem https://192.168.10.11:6443/healthz验证 apiserver 是否正常。这里 curl 返回 ok 说明 apiserver 已经能与 etcd 通信并启动成功。5.2 controller-manager 与 scheduler 的参数配置kube-controller-manager 和 kube-scheduler 相对简单它们都通过 kubeconfig 连接 apiserver。需要为它们各自生成专属的 kubeconfig 文件kubeconfig 里嵌入了客户端证书和 apiserver 地址。这里有一个关键参数--leader-electtrue。多主架构下这三个控制面组件必须开启选主否则多个副本同时执行调度或控制器逻辑会产生重复操作。比如多个 controller-manager 同时处理 Deployment 扩容可能创建出多余副本。开了 leader-elect 后同一时刻只有一个实例持有 lease 并工作其他实例处于 standby 状态。验证选主是否生效可以在这两台节点上用kubectl get leases -n kube-system能看到对应的 lease 对象只有一个 holder。controller-manager 还需要配置 --cluster-cidr 与 apiserver 保持一致--service-account-private-key-file 指向刚才 apiserver 公钥对应的私钥--root-ca-file 指向 CA 证书这是让 controller-manager 在创建 ServiceAccount 时把 CA 注入到 Pod 里的原因。scheduler 的 kubeconfig 指向 apiserver 后基本参数不多。需要注意的是 --bind-address 建议绑定到 127.0.0.1避免调度器端口暴露到外部网络。这是一个很好的安全习惯controller-manager 同样如此这两个组件本来就不需要对外提供服务。5.3 多主高可用接入与本地验证三台 master 的 apiserver 都起来后还缺少统一的入口。生产环境一般用 HAProxy 加 Keepalived 的方式虚拟 IP 192.168.10.10 漂移在三台 master 之间。Keepalived 负责 VIP 漂移HAProxy 负责把 6443 流量负载均衡到三台 apiserver。haproxy.cfg 里配置 backend 时注意 balance 算法用 roundrobin加 option tcp-check 做健康检查——检查的是 apiserver 的 6443 端口是否可连接而不是简单的 TCP 握手。配置完成后先本地验证每个 apiserver 的 /healthz 是否返回 ok再用虚拟 IP 验证curl --cacert ca.pem https://192.168.10.10:6443/healthz。这一步通了说明外部的流量入口已经没有问题。接下来生成 kubectl 使用的 admin kubeconfig。admin 证书的 CN 必须是 kubernetes-admin因为集群默认的 RBAC 里有 cluster-admin 绑定到这个用户。配置好 kubectl 后先执行kubectl cluster-info和kubectl get cs看各组件健康状态。注意新版 Kubernetes 里kubectl get cs经常返回 Unhealthy其实是因为组件端口的健康检查方式变了不代表真的有问题不要被误导。6. worker 节点接入kubelet 引导、kube-proxy 与网络打通6.1 kubelet 目录结构与启动参数worker 节点相对 master 简单核心是 kubelet 加 kube-proxy再加上 CNI 插件。首先要把 kubelet、kube-proxy 二进制文件拷到 /usr/local/bin并把 CNI 插件解压到 /opt/cni/bin网络配置目录放在 /etc/cni/net.d。kubelet 这里有一个二进制部署独有的细节它需要配置 /var/lib/kubelet、/etc/kubernetes/pki 等目录在启动参数里明确指定 --root-dir、--kubeconfig、--bootstrap-kubeconfig。有两种接入集群的方式手动签发 kubelet 证书和生产 kubeconfig或者用 bootstrap token 机制让 kubelet 自动申请证书。推荐后者操作更便捷也支持证书轮换。先在 master 上生成一个 bootstrap token写入 worker 节点的 bootstrap-kubeconfig指定 apiserver 地址和 token然后 kubelet 首次启动时会自动用 token 向 apiserver 发起 CSR管理员审批后kubelet 会自动下载签发的证书并写入 /var/lib/kubelet 下的 kubeconfig。kubelet 参数中几个容易踩坑的地方--cgroup-driver 必须与 containerd 保持一致即 systemd--network-plugincni 开启 CNI 支持否则 Pod 创建后没有网络--cluster-dns 指向 CoreDNS 的 ClusterIP--cluster-domain 对应集群域名后缀缺了这两个参数Pod 内 DNS 解析会异常--hostname-override 建议配置为节点主机名和 kubelet 注册到集群的名字保持一致。开启证书轮换的配置需要放到 kubelet 配置文件中。在 systemd unit 里用 --config 参数指定 YAML 格式的 kubelet 配置文件内容里设置 rotateCertificates: true。启动 kubelet 后用kubectl get csr查看是否有 Pending 状态的请求逐个 approve。全部 approve 后kubectl get nodes应该能看到 worker 节点进入 Ready 状态。经常出现节点一直 NotReady 的情况排查优先级是容器运行时是否正常crictl ps 能不能返回、CNI 插件是否装好、kubelet 日志里有没有连接 apiserver 的异常。6.2 kube-proxy 与网络插件选型kube-proxy 以 DaemonSet 方式运行在集群中比较常见但二进制部署场景下一般直接以 systemd 服务方式启动。kube-proxy 需要生成一个独立的 kubeconfig默认的启动参数是 --proxy-modeiptables这是最稳妥的模式iptables 性能在小规模集群下完全够用。如果集群规模很大、Service 数量很多可以考虑 ipvs 模式但需要节点内核加载 ip_vs 相关模块。网络插件方面我在生产环境用得比较多的是 Calico 和 Flannel。Calico 功能更丰富支持 NetworkPolicy适合对安全隔离有要求的场景Flannel 简单轻量配置少适合中小集群快速起步。这里以 Calico 为例安装时只需要在 master 节点上应用一个 manifest 文件但需要注意Calico 默认读取的 Pod 网段是 192.168.0.0/16如果 apiserver 的 --cluster-cidr 规划的 Pod 网段不是这个需要修改 manifest 中的 CALICO_IPV4POOL_CIDR 环境变量否则 Calico 创建的 Pod 分配出来的 IP 和预期不一致。同类问题在 Flannel 里也存在——--iface 参数如果没有正确指定网卡跨节点 Pod 通信会断。网络插件起来的标志是 kube-system 命名空间下所有 pod 变成 Running。CoreDNS 经常因为 pending 无法分配 IP就是因为网络插件没有就绪。一旦网络插件正常CoreDNS 会自动调度并获取 IP。6.3 集群验证清单与常见故障排查所有节点接入集群后按以下清单逐项自检kubectl get nodes 所有节点处于 Ready。kubectl get pods -n kube-system 所有系统组件处于 Running。kubectl run test-pod --imagebusybox -- sleep 3600 能成功创建 Pod进入 Pod 执行 ping 外部 IP确保网络出网正常。创建两个测试 Pod一个访问另一个的 ClusterIP验证 Service 转发正常。对 Service 执行 DNS 解析测试CoreDNS 正常返回解析结果。将 Keepalived 的主节点网卡 down 掉用 kubectl 工具通过 VIP 访问集群验证仍能正常工作。我在一次部署中遇到过 CoreDNS 反复 CrashLoopBackOff 的情况排查时发现 kubelet 配置的 --cluster-dns 是 10.96.0.10而 CoreDNS 实际分配的 ClusterIP 却是 10.96.0.2。原因是修改 Calico 网段配置时不小心把 CoreDNS manifest 里的 ClusterIP 也改了。这类低级错误在手工部署时很容易出现排查思路是始终围绕组件之间约定的 IP、证书、密码是否完全一致。逻辑链断在哪一环故障就在哪一环。还有一个高频问题是节点 kubelet 一直报 x509 certificate signed by unknown authority。夸张的是有时候重启服务器后这个问题就出现原因是 etcd 的 CA 证书和 Kubernetes 的 CA 证书在节点上被某个操作覆盖了。所以证书分发时同一台节点的 /etc/kubernetes/pki 目录里要同时存放 all CA 和组件证书文件命名要带前缀区分避免覆盖。最后再分享几点实际体会这套集群从规划到全部跑通总共用了两天时间。第一次做二进制部署的读者大概率会卡在证书签发和组件参数这两块。证书的问题往往不是生成出错而是 SAN 漏了、有效期设短了、或者分发错了节点。组件的问题更多是参数不一致比如 cgroup driver、CIDR 规划、apiserver 地址同一份配置在三台 master 之间反复复制时很容易手误改掉一个端口或 IP。建议在动手前把表设计做细每台节点的角色、IP、证书清单、配置文件路径都列清楚。部署过程中每完成一步就做一次验证不要攒到最后一起排查——组件之间是强依赖关系apiserver 没起来就往下装 kubelet日志会把你绕晕。另外这套方法最大的价值还是排错和定制能力。之后如果要在集群上接入自建的证书体系、修改审计策略、或者把 etcd 迁到独立节点你手里有完整的配置文件和启动参数改起来心里有底。
返回列表