failed=0 只是开始 — 逐层检查 Kubespray 集群
一句话总结
用 kubespray 搭建的集群,外表与 kubeadm 集群相同,但 etcd、DNS、证书这三处的放置方式不同,所以验证也必须把这三处分别检查。
为什么需要它
安装结束后,人们看一行 kubectl get nodes,只要是 Ready 就算完事。然而节点 Ready 只表示 kubelet 向 API 服务器报告了状态,并且存在 CNI 配置文件。Pod 能否下载镜像、请求能否通过 Service IP 到达、名称能否解析、一年之后什么会停止,这一行里都没有。而且 kubespray 会做出几项与 kubeadm 默认值不同的选择。如果不了解这些差异,照搬 kubeadm 文档中的检查流程,反而会跳过真正重要的地方。
工作原理
节点与污点。 kubeadm 会给控制平面节点加上 node-role.kubernetes.io/control-plane:NoSchedule 污点。如果该节点在 inventory 中同时位于 kube_node,kubespray 会用 “Remove taint for control plane node with node role” 任务清除这个污点。所以只有一个节点的 kubespray 集群,无需另行处理就能接收普通 Pod。这相当于 inventory 中的组布局就是调度策略。
etcd 不是 Pod。 group_vars/all/etcd.yml 中 etcd_deployment_type 的默认值是 host,所以 etcd 是用 kubespray 下载的二进制文件,作为主机上的 etcd.service 运行的。无论怎么查看 kube-system,都没有 etcd Pod,状态要在 systemctl status etcd 和 /etc/etcd.env 中查看。API 服务器把这个 etcd 作为“外部 etcd”来连接。
证书分为两支。 kubeadm 创建的证书(API 服务器、controller 和 scheduler 的 kubeconfig 等)在 kubespray 中位于 /etc/kubernetes/ssl,叶子证书一年、CA 十年。在这台 VM 上,kubeadm certs check-expiration 显示叶子证书 364 天、CA 9 年,而列表中没有 etcd——因为它是外部 etcd。etcd 证书由 kubespray 的 make-ssl-etcd.sh 用 openssl 创建,有效期是 certificates_duration(默认 36500 天,约 100 年)。看一看哪一边先到期,就能清楚地知道一年之内要做的事是 kubeadm 一侧的续期。
DNS 有两级。 kubespray 默认会打开 nodelocaldns。每个节点上的 DaemonSet 在链路本地地址(默认 169.254.25.10)上运行缓存 DNS,kubelet 的 clusterDNS 把这个地址告知 Pod。只有缓存不认识的名称才会转交给 CoreDNS。所以要确认“DNS 可用”,必须同时向 CoreDNS Service 地址和 nodelocaldns 地址发出查询,而 Pod 实际使用的是后者。正如 Kubernetes 文档对 NodeLocal DNSCache 的说明,这种部署是为了减少 conntrack 竞争和 CoreDNS 的负载。
安装的记录。 kubespray 会把调用 kubeadm 时使用的 /etc/kubernetes/kubeadm-config.yaml、etcd 的 /etc/etcd.env、下载的二进制文件缓存 /tmp/releases(local_release_dir)留在节点上。三个月之后,想知道“这个集群是用什么值搭建的”,它们是继 inventory 之后要看的第一手资料。
在现场相遇的样子
在本课程的实测集群(1.35.8,calico)中,kube-system 里运行了 calico-kube-controllers、calico-node、coredns、dns-autoscaler、kube-apiserver、kube-controller-manager、kube-proxy、kube-scheduler、nodelocaldns。CoreDNS 只有一个,是因为副本数由 dns-autoscaler 根据节点和核数来决定。节点增加时,CoreDNS 也会增加。
现场最常见的错觉是证书。如果监控只抓取 kubeadm certs check-expiration 的结果,etcd 证书就永远不会被监控到。这次部署中 etcd 一侧是 100 年,所以没有问题,但如果有人缩短了 certificates_duration,或者把 etcd 改成了 kubeadm 部署,情况就不同了。检查清单中,首先要写的是“哪个工具创建了哪个证书”。
最后的证据是工作负载。向一个有两个 Pod 的 Deployment 和一个 Service 发送请求,如果两个 Pod 的名称都返回了,就一次性确认了注册表出口、调度、Pod 网络和 kube-proxy。一次请求,比好几个绿灯说明得更多。
下一项实验要做什么
搭建集群之后,读取节点的角色和污点,并在 systemd 中确认核心 Pod 列表中为什么没有 etcd。分别向 nodelocaldns 和 CoreDNS 查询名称,确认两级 DNS,并用 openssl 读取 kubeadm 证书和 etcd 证书的到期日。确认 kubespray 留下的配置文件之后,向一个小型工作负载发送真实请求来收尾。