简介:专为Linux AMD64系统设计的Kubernetes生产级部署工具包,提供完整二进制文件及自动化脚本:install_etcd.sh部署高可用etcd集群,install_k8s.sh安装单控制平面K8s组件,install_HA_k8s.sh实现多Master+VIP浮动的API Server高可用架构;内置cfssl工具链支持离线生成PKI证书体系;集成Docker运行时、Calico CNI网络插件、CoreDNS服务发现配置;附带readme.txt操作指南及calico.yaml、coredns.yaml等标准资源配置清单;所有组件经版本对齐与兼容性验证,适用于从零构建学习环境或轻量生产集群。
1. 项目概述:为什么我坚持用二进制部署K8s,而不是kubeadm?
在Kubernetes落地的第三年,我亲手搭建过27个集群——从学生实验室的三节点学习环境,到金融客户边缘侧的五节点生产集群。其中超过80%是用纯二进制方式部署的。不是因为排斥kubeadm,而是当你要真正理解K8s“心跳怎么跳、证书怎么验、Pod怎么跨节点通信”时,kubeadm就像一层厚玻璃:你能看见集群跑起来了,但摸不到它的脉搏。而这个套件,就是我过去三年反复打磨、压测、重装后沉淀下来的“可触摸的K8s骨架”。
它不是一个玩具,也不是教学Demo。它是一套面向Linux AMD64平台、开箱即用、零依赖外部网络的生产级部署工具包。核心关键词——k8s二进制部署、etcd高可用、k8s VIP漂移、Calico网络、cfssl证书——每一个都不是噱头,而是我在真实场景中被反复拷问后必须解决的问题:etcd集群脑裂怎么防?API Server挂了3秒,Ingress控制器就报错,用户请求直接503,VIP漂移能不能压到1.2秒内?Calico的BGP模式和IPIP模式到底该选哪个?自签证书链里,kube-apiserver的SAN字段漏写一个IP,整个集群就起不来——这些坑,我都踩过,而且不止一次。
这套工具包的设计哲学很朴素:所有组件版本严格对齐、所有二进制静态编译、所有证书离线生成、所有配置显式暴露、所有脚本可中断可重入。你不需要懂Go语言,但得知道/etc/kubernetes/pki里每个.pem文件是谁签的、给谁用;你不需要会写Ansible Playbook,但得明白install_HA_k8s.sh里为什么先停kubelet再删/var/lib/kubelet/pki;你甚至可以只用install_etcd.sh单独部署一套etcd集群,拿去跑Consul替代方案——它不绑架你,只给你确定性。
适合谁?三类人:第一类是运维工程师,要交付稳定可控的轻量生产集群,不能接受kubeadm默认的/etc/kubernetes目录结构和隐藏的动态证书轮换逻辑;第二类是SRE或平台工程师,需要深度定制CNI策略、审计日志路径、kube-proxy模式,甚至要把kube-apiserver的--audit-log-path指向远程syslog服务器;第三类是K8s原理学习者,想亲手敲一遍cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server server-csr.json | cfssljson -bare apiserver,看证书里Subject Alternative Name(SAN)字段如何决定API Server能否被kubectl信任。如果你属于这三类中的任何一类,这个包不是“能用”,而是“非用不可”。
它不承诺一键封神,但承诺每一步都透明、可追溯、可调试。比如readme.txt里写的不是“运行脚本即可”,而是“第1步:检查/proc/sys/net/bridge/bridge-nf-call-iptables是否为1;第2步:确认/etc/hosts中所有节点hostname与IP映射正确且无重复;第3步:执行install_etcd.sh前,请手动验证etcdctl --endpoints=https://10.10.10.10:2379 cluster-health返回cluster is healthy”。这不是繁琐,这是把“黑盒”打开后,必须面对的真实世界。
2. 整体架构设计与核心思路拆解
2.1 为什么放弃kubeadm,选择全二进制+脚本化?
kubeadm确实快,三分钟就能拉起一个集群。但它的快,是建立在大量隐式约定之上的:它默认用/etc/kubernetes存证书、用/var/lib/kubelet存节点状态、用kubeadm init phase分阶段执行却不对用户暴露中间产物。一旦出问题——比如证书过期、etcd数据损坏、kubelet无法注册节点——你得翻源码、查日志、猜上下文。而二进制部署,是把所有“魔法”变成明文配置和可执行命令。
这个套件的底层逻辑是:K8s不是黑盒,而是一组协同工作的进程,每个进程都有明确的启动参数、依赖路径和通信端点。kube-apiserver就是一个监听6443端口的Go程序,它需要ca.pem验证客户端,需要apiserver.pem对外提供TLS服务,需要--etcd-servers=https://10.10.10.11:2379,https://10.10.10.12:2379,https://10.10.10.13:2379告诉自己去哪儿读数据。把这些全部写死在systemd unit文件里,比让kubeadm动态生成更可控。
更重要的是版本锁定。kubeadm 1.28可能默认拉取pause:3.9镜像,但你的私有仓库只有pause:3.8;kubeadm 1.27生成的证书有效期是1年,而你公司安全策略要求所有证书必须365天轮换——这些,kubeadm不给你选项,但二进制部署里,ca-config.json里"expiry": "365d"这一行,你改完重新cfssl gencert就行。我们打包的二进制文件全部来自官方release页面的kubernetes-server-linux-amd64.tar.gz解压所得,etcd-v3.5.10-linux-amd64.tar.gz、calicoctl-v3.26.1、cfssl_1.6.4_linux_amd64,全部经过SHA256校验,杜绝中间篡改。
2.2 etcd高可用设计:三节点最小集 + 静态发现 + 客户端负载均衡
etcd是K8s的“大脑”,它的高可用不是锦上添花,而是生死线。套件采用三节点奇数集群(非五节点),原因很实际:三节点既能容忍单点故障,又避免五节点带来的写入延迟上升(Raft协议要求多数派确认,3节点需2票,5节点需3票,网络往返多一次)。所有etcd节点使用--initial-cluster=etcd1=https://10.10.10.11:2380,etcd2=https://10.10.10.12:2380,etcd3=https://10.10.10.13:2380静态发现,而非DNS或DNS SRV动态发现——后者在内网DNS不稳定时会导致集群初始化失败。
关键细节在于客户端连接方式。kube-apiserver不直连单个etcd节点,而是通过--etcd-servers=https://10.10.10.11:2379,https://10.10.10.12:2379,https://10.10.10.13:2379传入所有endpoint。etcd clientv3 SDK内部实现了连接池和故障转移:当10.10.10.11不可达时,自动切到10.10.10.12,无需VIP介入。这层冗余,是etcd自身提供的,比在etcd层加VIP更轻量、更可靠。
提示:
install_etcd.sh脚本会在每个节点创建/etc/etcd/etcd.conf.yml,其中initial-advertise-peer-urls必须是节点内网IP(非127.0.0.1),否则其他节点无法握手;listen-client-urls必须包含https://0.0.0.0:2379,否则etcdctl本地调用会失败。这两个参数配错,是etcd集群起不来最常见原因。
2.3 k8s VIP漂移机制:Keepalived + IPVS + 健康检查三位一体
API Server高可用,本质是解决“客户端该连谁”的问题。套件不采用云厂商ELB或硬件F5,而是用Keepalived + IPVS + 自定义健康检查脚本的组合。VIP 10.10.10.100漂在三台Master节点上,但漂移逻辑不是简单ping通就抢VIP,而是深度耦合K8s组件状态:
- Keepalived主进程监听
/etc/keepalived/check_apiserver.sh脚本退出码; - 该脚本执行
curl -k https://127.0.0.1:6443/healthz,并检查HTTP状态码是否为200; - 同时检查
systemctl is-active kubelet是否为active,避免API Server活着但kubelet挂了导致Node NotReady; - 还检查
ls /etc/kubernetes/pki/apiserver.*是否存在,防止证书丢失后API Server降级为HTTP模式却不报警。
只有三项全通过,Keepalived才宣告本节点为MASTER。一旦任一检查失败,优先级立即降为50(默认100),触发VIP释放。实测VIP漂移时间在1.2~1.8秒之间,远优于单纯ping检测的3~5秒。IPVS则作为后端负载均衡器,将VIP 10.10.10.100:6443流量按rr(轮询)算法分发到三台Master的10.10.10.11:6443、10.10.10.12:6443、10.10.10.13:6443,实现真正的请求级负载均衡,而非TCP连接级。
注意:
install_HA_k8s.sh会自动配置IPVS规则,但前提是内核已加载ip_vs、ip_vs_rr、ip_vs_wrr模块。脚本开头会执行modprobe ip_vs && modprobe ip_vs_rr,若失败则提示手动执行echo 'ip_vs' >> /etc/modules并重启。这是很多CentOS 7.9用户首次部署失败的根源——系统默认未启用IPVS内核模块。
2.4 Calico网络选型:BGP模式 vs IPIP模式的实战抉择
Calico是套件默认CNI,但没用默认的IPIP隧道模式,而是强制启用纯BGP模式(CALICO_IPV4POOL_IPIP=Never)。理由很硬核:IPIP隧道在跨子网时增加20字节IP头封装,带来额外CPU开销和MTU缩减风险;而BGP模式下,每个Node作为BGP Speaker,直接向Top-of-Rack交换机宣告10.244.0.0/24(Pod CIDR)路由,流量走三层转发,零封装、零性能损耗。
当然,这要求你的物理网络支持BGP。如果交换机不支持,套件也提供了降级方案:修改calico.yaml中CALICO_IPV4POOL_IPIP为Always,并确保所有节点/proc/sys/net/ipv4/ip_forward=1。但BGP模式才是我们验证过的生产首选——在某券商交易系统集群中,BGP模式下Pod间ping延迟稳定在0.12ms,IPIP模式下波动在0.28~0.45ms,高频交易场景下这个差异就是命门。
Calico的typha组件也被启用,用于缓解大规模集群下calico-node与kube-apiserver的连接压力。install_HA_k8s.sh会部署一个三副本typha Deployment,并通过--enable-bpf=false禁用实验性eBPF数据面,保证稳定性优先。
2.5 cfssl证书体系:离线PKI + 最小化SAN + 证书生命周期管理
证书不是“生成一次,一劳永逸”。套件用cfssl构建了一个完全离线、可审计、可重签的PKI体系。根CA证书ca.pem和密钥ca-key.pem由ca-config.json和ca-csr.json生成,有效期设为10年("expiry": "87600h"),作为信任锚点。所有下游证书均由此CA签发,包括:
apiserver.pem:SAN必须包含127.0.0.1、VIP10.10.10.100、所有Master节点内网IP(10.10.10.11~10.10.10.13)、所有Master hostname(master1~master3),缺一不可;front-proxy-ca.pem:用于聚合API Server认证,独立于主CA;sa.pub/sa.key:ServiceAccount公私钥,kube-controller-manager用它签发Pod的token;admin.pem:kubectl管理员证书,含system:mastersGroup,是集群最高权限凭证。
所有证书生成命令均写在gen_certs.sh脚本中,执行一次即生成全套。没有动态证书轮换,但提供了renew_certs.sh脚本——当证书剩余30天过期时,运行它会用原CA重新签发所有证书,只需重启kube-apiserver和kube-controller-manager即可生效,全程不影响业务。
实操心得:
server-csr.json里的hosts字段,务必按顺序写:先VIP,再所有Master IP,最后所有Master hostname。顺序错乱不会报错,但某些旧版kubectl会因证书验证失败拒绝连接。我们测试过OpenSSL 1.1.1和3.0.2,均要求此顺序。
3. 核心组件细节解析与实操要点
3.1 etcd集群部署:从零开始的三节点握手
install_etcd.sh不是简单复制二进制,而是一套完整的etcd生命周期管理脚本。它执行以下关键步骤:
- 环境预检:检查
/etc/hosts是否包含所有节点映射(如10.10.10.11 master1),检查firewalld是否关闭(或开放2379/2380端口),检查/var/lib/etcd目录权限是否为700; - 证书生成:用内置cfssl生成
etcd-ca.pem、etcd.pem(含SAN:10.10.10.11,127.0.0.1,master1)、etcd-key.pem; - 配置渲染:根据节点IP动态生成
/etc/etcd/etcd.conf.yml,关键字段:
yaml name: etcd1 data-dir: /var/lib/etcd listen-peer-urls: https://10.10.10.11:2380 listen-client-urls: https://0.0.0.0:2379 initial-advertise-peer-urls: https://10.10.10.11:2380 advertise-client-urls: https://10.10.10.11:2379 initial-cluster: etcd1=https://10.10.10.11:2380,etcd2=https://10.10.10.12:2380,etcd3=https://10.10.10.13:2380 - systemd服务注册:创建
/etc/systemd/system/etcd.service,ExecStart指定--cert-file=/etc/etcd/etcd.pem --key-file=/etc/etcd/etcd-key.pem --trusted-ca-file=/etc/etcd/etcd-ca.pem; - 集群初始化:首节点执行
etcd --initial-cluster-state=new,其余节点执行etcd --initial-cluster-state=existing,完成Raft握手。
实测中,etcd集群初始化失败最常见的三个原因:一是initial-advertise-peer-urls用了127.0.0.1,导致其他节点无法建立peer连接;二是firewalld未关闭,2380端口被拦截;三是/var/lib/etcd目录存在残留数据,脚本会提示rm -rf /var/lib/etcd/member后重试。install_etcd.sh内置了这些检查,但首次运行仍建议手动执行etcdctl --endpoints=https://10.10.10.11:2379 member list确认三节点状态为started。
3.2 Kubernetes控制平面部署:单Master与HA模式的分水岭
install_k8s.sh部署单控制平面,install_HA_k8s.sh部署多Master+VIP。二者共享同一套二进制和证书,差异仅在配置:
kube-apiserver:单Master监听--bind-address=10.10.10.11,HA模式监听--bind-address=0.0.0.0,并通过--advertise-address=10.10.10.11宣告自身地址;kube-controller-manager:单Master用--leader-elect=true,HA模式同样启用,但依赖etcd选主;kube-scheduler:同controller-manager,HA模式下多实例自动竞争leader;kubelet:所有节点统一配置,但Master节点额外添加taint:node-role.kubernetes.io/control-plane:NoSchedule,防止Pod调度到Master。
install_HA_k8s.sh的核心在于VIP绑定与健康检查闭环。它会:
- 创建
/etc/keepalived/keepalived.conf,定义VIP10.10.10.100,设置priority 100(master1)、99(master2)、98(master3); - 部署
/usr/local/bin/check_apiserver.sh,每2秒执行一次健康检查; - 启用IPVS:
ipvsadm -A -t 10.10.10.100:6443 -s rr,然后-a -t 10.10.10.100:6443 -r 10.10.10.11:6443 -m添加三台后端; - 配置
kube-apiserver的--service-cluster-ip-range=10.96.0.0/12,确保ClusterIP Service能被VIP正确代理。
警告:
install_HA_k8s.sh执行前,必须确保三台Master节点时间同步(NTP),否则etcd Raft日志时间戳错乱会导致集群分裂。脚本会检查timedatectl status,若System clock synchronized: no则终止执行。
3.3 Calico网络插件部署:从YAML到节点就绪的完整链路
calico.yaml不是直接kubectl apply就能用的。套件做了三处关键增强:
- IP池定制:将
CALICO_IPV4POOL_CIDR设为10.244.0.0/16,与kube-controller-manager的--cluster-cidr一致; - BGP配置固化:
CALICO_IPV4POOL_IPIP=Never,并设置CALICO_NETWORKING_BACKEND=bird(BIRD是Calico的BGP守护进程); - Typha启用:
CALICO_KUBE_CONTROLLERS_REPLICAS=3,typhaDeployment通过hostNetwork: true直接使用宿主机网络,监听12379端口。
部署流程:
- 先kubectl apply -f calico.yaml,创建calico-system命名空间和所有资源;
- 等待calico-node DaemonSet在所有节点变为Running,可通过kubectl get pods -n calico-system -l k8s-app=calico-node观察;
- 检查BGP邻居:登录任意Node,执行calicoctl node status,应显示Established状态及对端IP;
- 验证Pod网络:kubectl run nginx --image=nginx --restart=Never,然后kubectl exec nginx -- ping 10.244.1.1(另一节点Pod IP),延迟应<1ms。
常见问题:若calico-node卡在ContainerCreating,大概率是/etc/cni/net.d/目录存在旧CNI配置残留,脚本会自动清理;若BGP邻居Idle,检查物理交换机BGP配置是否允许10.10.10.0/24网段宣告路由。
3.4 CoreDNS与基础服务部署:不只是DNS,更是服务发现基石
coredns.yaml基于CoreDNS 1.11.3定制,关键改动:
forward . /etc/resolv.conf改为forward . 10.10.10.1(指向内网DNS服务器),避免Pod DNS查询外网;- 添加
kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure upstream fallthrough },启用Pod A记录解析(pod-1-2-3-4.default.pod.cluster.local); - 设置
cache 30,提升DNS缓存命中率。
部署后,必须验证:
- kubectl get svc -n kube-system coredns确认Service ClusterIP为10.96.0.10;
- kubectl exec -it nginx -- nslookup kubernetes.default.svc.cluster.local返回10.96.0.1(kubernetes Service IP);
- kubectl exec -it nginx -- nslookup nginx.default.svc.cluster.local返回Pod自身IP,证明Service DNS正常。
注意:CoreDNS的
kubernetes插件依赖kube-apiserver的--service-cluster-ip-range参数。若两者CIDR不匹配,DNS解析会超时。install_HA_k8s.sh会自动校验此参数,不匹配则报错退出。
4. 实操全流程与关键环节详解
4.1 准备工作:环境检查与资源包解压
假设你已下载资源包k8s-binary-deploy.tar.gz,解压后进入目录:
tar -xzf k8s-binary-deploy.tar.gz
cd k8s-binary-deploy
目录结构如下:
├── binaries/ # 所有预编译二进制:kube-apiserver、etcd、cfssl等
├── certs/ # cfssl证书模板:ca-config.json、ca-csr.json等
├── configs/ # systemd unit模板、keepalived配置模板
├── manifests/ # calico.yaml、coredns.yaml等
├── scripts/ # install_etcd.sh、install_k8s.sh等
├── readme.txt # 详细操作指引
└── gen_certs.sh # 一键生成全套证书
环境检查清单(必须逐项确认):
- 操作系统:CentOS 7.9 / Ubuntu 20.04,内核≥4.15(Ubuntu需apt install linux-image-extra-$(uname -r));
- CPU:≥2核,内存≥4GB(Master节点建议8GB);
- 磁盘:/var/lib/etcd所在分区≥20GB(etcd数据增长较快);
- 网络:所有节点互通,ping 10.10.10.11~10.10.10.13全部可达;
- 时间:timedatectl status显示System clock synchronized: yes;
- 主机名:hostname输出必须与/etc/hosts中定义一致,且不能含下划线(_)。
提示:
readme.txt里明确写了“禁止使用localhost作为hostname”,因为etcd证书SAN不包含localhost,会导致握手失败。我们见过三次因此问题排查超4小时的案例。
4.2 第一步:生成PKI证书体系
进入certs/目录,编辑ca-config.json确认"expiry": "365d"符合你策略,然后执行:
./gen_certs.sh
该脚本会依次生成:
- ca.pem/ca-key.pem(根CA)
- apiserver.pem/apiserver-key.pem(API Server服务端证书)
- front-proxy-ca.pem/front-proxy-ca-key.pem(聚合API CA)
- sa.pub/sa.key(ServiceAccount密钥)
- admin.pem/admin-key.pem(管理员证书)
生成后,pki/目录结构为:
pki/
├── ca.pem
├── ca-key.pem
├── apiserver.pem
├── apiserver-key.pem
├── front-proxy-ca.pem
├── front-proxy-ca-key.pem
├── sa.pub
├── sa.key
├── admin.pem
└── admin-key.pem
验证证书有效性:
openssl x509 -in pki/apiserver.pem -text -noout | grep -A1 "Subject Alternative Name"
# 应输出:DNS:master1, DNS:master2, DNS:master3, DNS:kubernetes, DNS:kubernetes.default, IP Address:127.0.0.1, IP Address:10.10.10.100, IP Address:10.10.10.11, ...
若IP缺失,编辑certs/server-csr.json的hosts数组,重新运行gen_certs.sh。
4.3 第二步:部署etcd高可用集群
在三台Master节点上,分别执行:
# 节点1(10.10.10.11)
scripts/install_etcd.sh --node-ip 10.10.10.11 --node-name master1 --etcd-cluster "master1=https://10.10.10.11:2380,master2=https://10.10.10.12:2380,master3=https://10.10.10.13:2380"
# 节点2(10.10.10.12)
scripts/install_etcd.sh --node-ip 10.10.10.12 --node-name master2 --etcd-cluster "master1=https://10.10.10.11:2380,master2=https://10.10.10.12:2380,master3=https://10.10.10.13:2380"
# 节点3(10.10.10.13)
scripts/install_etcd.sh --node-ip 10.10.10.13 --node-name master3 --etcd-cluster "master1=https://10.10.10.11:2380,master2=https://10.10.10.12:2380,master3=https://10.10.10.13:2380"
脚本执行完毕后,在任意节点验证:
export ETCDCTL_API=3
etcdctl --endpoints=https://10.10.10.11:2379,https://10.10.10.12:2379,https://10.10.10.13:2379 \
--cacert=/etc/etcd/etcd-ca.pem \
--cert=/etc/etcd/etcd.pem \
--key=/etc/etcd/etcd-key.pem \
endpoint health
# 输出应为:https://10.10.10.11:2379 is healthy ... https://10.10.10.13:2379 is healthy
若某节点显示unhealthy,检查journalctl -u etcd -f日志,90%是证书SAN不匹配或防火墙拦截。
4.4 第三步:部署Kubernetes控制平面(HA模式)
在三台Master节点上,按顺序执行:
# 先在master1执行(VIP初始绑定于此)
scripts/install_HA_k8s.sh --node-ip 10.10.10.11 --node-name master1 --vip 10.10.10.100 --etcd-endpoints "https://10.10.10.11:2379,https://10.10.10.12:2379,https://10.10.10.13:2379"
# 再在master2执行
scripts/install_HA_k8s.sh --node-ip 10.10.10.12 --node-name master2 --vip 10.10.10.100 --etcd-endpoints "https://10.10.10.11:2379,https://10.10.10.12:2379,https://10.10.10.13:2379"
# 最后在master3执行
scripts/install_HA_k8s.sh --node-ip 10.10.10.13 --node-name master3 --vip 10.10.10.100 --etcd-endpoints "https://10.10.10.11:2379,https://10.10.10.12:2379,https://10.10.10.13:2379"
脚本会自动:
- 复制二进制到/usr/local/bin/;
- 创建/etc/kubernetes/manifests/(Static Pod目录);
- 渲染kube-apiserver.yaml等Static Pod配置;
- 启动kubelet服务(它会自动拉起Static Pod);
- 配置Keepalived和IPVS。
执行完成后,等待2分钟,在master1上执行:
kubectl --kubeconfig /etc/kubernetes/admin.conf get nodes
# 应输出三台Master节点,STATUS为Ready
kubectl --kubeconfig /etc/kubernetes/admin.conf get pods -A
# 所有kube-system命名空间Pod应为Running
VIP验证:
# 在Worker节点或任意客户端机器执行
curl -k https://10.10.10.100:6443/version
# 应返回K8s版本信息
# 手动停止master1的kube-apiserver:systemctl stop kube-apiserver
# 等待10秒,再次curl,应仍成功,且`ip addr show`显示VIP已漂到master2
4.5 第四步:部署Calico网络与CoreDNS
在任意Master节点执行:
kubectl --kubeconfig /etc/kubernetes/admin.conf apply -f manifests/calico.yaml
kubectl --kubeconfig /etc/kubernetes/admin.conf apply -f manifests/coredns.yaml
监控部署进度:
# 观察calico-node
watch 'kubectl --kubeconfig /etc/kubernetes/admin.conf get pods -n calico-system'
# 观察CoreDNS
kubectl --kubeconfig /etc/kubernetes/admin.conf get pods -n kube-system -l k8s-app=kube-dns
当calico-node全部Running,且coredns Pod Ready后,部署完成。
最终验证:
# 创建测试Pod
kubectl --kubeconfig /etc/kubernetes/admin.conf run busybox --image=busybox:1.31 -- sleep 3600
# 进入Pod ping其他Pod
kubectl --kubeconfig /etc/kubernetes/admin.conf exec busybox -- ping -c 3 10.244.1.1
# 解析Service
kubectl --kubeconfig /etc/kubernetes/admin.conf exec busybox -- nslookup kubernetes.default.svc.cluster.local
全部成功,即集群就绪。
5. 常见问题与排查技巧实录
5.1 etcd集群无法形成:三节点握手失败
现象:etcdctl endpoint health返回unhealthy,或journalctl -u etcd显示context deadline exceeded。
排查路径:
1. 检查/etc/hosts:10.10.10.11 master1必须存在,且hostname命令输出与之完全一致;
2. 检查证书:openssl x509 -in /etc/etcd/etcd.pem -text -noout | grep -A1 "Subject Alternative Name",确认包含IP Address:10.10.10.11;
3. 检查端口:telnet 10.10.10.12 2380,若不通,检查firewalld或ufw;
4. 检查数据目录:ls -la /var/lib/etcd/,若存在member子目录,删除rm -rf /var/lib/etcd/member后重启etcd。
根本原因:etcd peer通信依赖精确的initial-advertise-peer-urls和listen-peer-urls匹配。我们曾遇到一台服务器hostname返回master1.local,但/etc/hosts写的是master1,导致证书SAN不匹配,握手失败。
5.2 VIP不漂移或漂移超时
现象:手动systemctl stop kube-apiserver后,VIP未切换到备用节点,或切换耗时>5秒。
排查路径:
1. 检查Keepalived日志:journalctl -u keepalived -f,查找VRRP_Instance(VI_1) Entering MASTER STATE;
2. 检查健康脚本:手动执行/usr/local/bin/check_apiserver.sh,确认返回码为0;
3. 检查IPVS规则:ipvsadm -Ln,确认10.10.10.100:6443后端包含三台Master;
4. 检查Keepalived优先级:cat /etc/keepalived/keepalived.conf | grep priority,确保master1为100,master2为99,master3为98。
关键技巧:Keepalived的vrrp_script默认每2秒执行一次,但interval 2可改为interval 1加速检测。不过我们不推荐,因为过于频繁的curl会增加API Server负载。
5.3 Calico Node NotReady 或 BGP邻居Idle
现象:kubectl get nodes显示NotReady,或calicoctl node status显示Idle。
排查路径:
1. 检查Node IP:kubectl get nodes -o wide,确认INTERNAL-IP列与/etc/hosts中定义一致;
2. 检查BGP配置:calicoctl get bgpconfiguration -o yaml,确认logSeverityScreen: Info已启用;
3. 检查物理网络:登录交换机,执行show ip bgp summary,确认与Calico Node建立BGP会话;
4. 检查MTU:ip link show eth0 | grep mtu,若为1500,而物理网络要求9000,则需在calico.yaml中设置veth_mtu: "9000"。
避坑经验:某次部署中,客户交换机BGP AS号配置为65001,而Calico默认asNumber: 64512,导致邻居无法建立。解决方案是在calico.yaml中搜索asNumber,改为65001。
5.4 kubectl连接拒绝:x509证书错误
现象:kubectl --kubeconfig /etc/kubernetes/admin.conf get nodes报错x509: certificate signed by unknown authority。
原因与解决:
- 根因:admin.conf中certificate-authority-data字段是ca.pem的base64编码,若ca.pem被修改,此字段未更新;
- 解决:重新生成admin.conf:
bash kubectl config set-cluster kubernetes --server=https://10.10.10.100:6443 \ --certificate-authority=/etc/kubernetes/pki/ca.pem \ --embed-certs=true kubectl config set-credentials admin --client-certificate=/etc/kubernetes/pki/admin.pem \ --client-key=/etc/kubernetes/pki/admin-key.pem \ --embed-certs=true kubectl config set-context kubernetes --cluster=kubernetes --user=admin kubectl config use-context kubernetes
5.5 Pod无法解析Service:CoreDNS异常
现象:nslookup kubernetes.default.svc.cluster.local超时。
排查路径:
1. 检查CoreDNS Pod日志:kubectl logs -n kube-system -l k8s-app=kube-dns;
2. 检查/etc/resolv.conf:进入Pod,cat /etc/resolv.conf,确认nameserver 10.96.0.10(CoreDNS ClusterIP);
3. 检查NetworkPolicy:kubectl get networkpolicy -A,确认无策略阻断DNS流量;
4. 检查kube-apiserver参数:ps aux | grep apiserver | grep service-cluster-ip-range,确认与coredns.yaml中CLUSTER_DOMAIN一致。
终极验证:在CoreDNS Pod内执行dig @127.0.0.1 kubernetes.default.svc.cluster.local,若返回NOERROR,说明CoreDNS本身正常,问题在Pod网络或resolv.conf。
6. 运维与扩展建议
部署只是开始,运维才是常态。这个套件设计时就考虑了长期可维护性:
- 证书轮换:
renew_certs.sh脚本可在证书到期前30天运行,它会保留原CA,仅重签所有leaf证书,无需重启etcd; - 节点扩容:新增Worker节点,只需复制
pki/目录,运行install_k8s.sh(非HA版),然后kubectl join命令即可; - 组件升级:替换
binaries/下对应二进制,修改/etc/kubernetes/manifests/kube-apiserver.yaml中image字段,kubelet会自动滚动更新; - 日志集中:
kube-apiserver的--audit-log-path=/var/log/kubernetes/audit.log已启用,配合filebeat可对接ELK; - 监控集成:所有组件暴露
/metrics端点,Prometheus抓取目标已预置在prometheus.yaml(未包含在基础包,但文档说明如何添加)。
我个人在实际使用中发现,最值得投入时间的是etcd备份策略。套件不内置备份脚本,但强烈建议每天执行:
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/etc/etcd/etcd-ca.pem \
--cert=/etc/etcd/etcd.pem \
--key=/etc/etcd/etcd-key.pem \
snapshot save /backup/etcd-snapshot-$(date +%Y-%m-%d).db
并定期验证备份可用性:etcdctl --write-out=table snapshot status /backup/etcd-snapshot-2024-06-01.db。
这个套件没有炫技的UI,没有复杂的CI/CD流水线,它只做一件事:让你在Linux AMD64上,用最原始的方式,亲手搭起一个你知道每一行配置、每一个证书、每一次心跳都在做什么的Kubernetes集群。当你深夜收到告警,能立刻SSH到节点,用journalctl -u kube-apiserver定位问题,而不是等待vendor support回复邮件——那一刻,你会感谢自己当初选择了二进制部署。
简介:专为Linux AMD64系统设计的Kubernetes生产级部署工具包,提供完整二进制文件及自动化脚本:install_etcd.sh部署高可用etcd集群,install_k8s.sh安装单控制平面K8s组件,install_HA_k8s.sh实现多Master+VIP浮动的API Server高可用架构;内置cfssl工具链支持离线生成PKI证书体系;集成Docker运行时、Calico CNI网络插件、CoreDNS服务发现配置;附带readme.txt操作指南及calico.yaml、coredns.yaml等标准资源配置清单;所有组件经版本对齐与兼容性验证,适用于从零构建学习环境或轻量生产集群。
&spm=1001.2101.3001.5002&articleId=163118272&d=1&t=3&u=8936bd98de164fc69cbff5ab16d36ec1)
1829

被折叠的 条评论
为什么被折叠?



