Kubernetes Kubernetes

Kubernetes 集群如何工作:控制平面与节点

让集群运转的各个组件,以及从 kubectl apply 到运行中的容器之间发生了什么。

12 min 初级

Kubernetes 集群是一组相互协作的进程。了解每个进程做什么,会让其他一切,从调度到排障,都更容易推理。本指南先点出各个组件的名称,然后跟随一个请求一路走到运行中的容器。

控制平面与工作节点

控制平面负责对集群做出决策。工作节点运行你的工作负载。在 minikube 这样的本地集群中,一个节点同时扮演两种角色。生产集群通常有多个控制平面节点以保证可用性:如果你失去了唯一的一个,你就无法再更改集群中的任何东西,尽管已在运行的工作负载通常会继续运行一段时间。控制平面节点通常带有污点(taint),这样你的应用 Pod 就不会被调度到它们上面。

控制平面组件

  • kube-apiserver 是前门。每个客户端(kubectl、仪表板、脚本以及其他组件)都通过 HTTP API 与它通信。它负责认证和授权请求、验证对象,并且是唯一读写 etcd 的组件。
  • etcd 是一个一致性的键值存储,保存集群的所有状态:存在哪些节点、应该运行哪些 Pod、它们的当前状态。把它视作集群的记忆。请备份它,因为失去它意味着失去对一切的跟踪。
  • kube-scheduler 为每个尚未分配节点的 Pod 选择一个节点,依据的是资源请求、约束和可用容量。
  • kube-controller-manager 运行各个控制器,即比较期望状态与实际状态并对差异采取行动的控制循环。Deployment、ReplicaSet 和 Node 控制器都在这里。
  • cloud-controller-manager(仅在云服务商上)与服务商集成,处理负载均衡器和节点生命周期之类的事情。

节点组件

  • kubelet 是每个节点上的代理。它监视分配到其节点的 Pod,确保它们的容器正在运行且健康,并把状态汇报回去。
  • 容器运行时(container runtime) 实际运行容器。它通常是 containerd 或 CRI-O,通过容器运行时接口连接。Kubernetes 不再直接与 Docker Engine 通信(dockershim 已在 1.24 中被移除),但用 Docker 构建的镜像仍能运行,因为镜像遵循开放的 OCI 标准。
  • kube-proxy 在每个节点上维护网络规则,使 Service 地址能够到达正确的 Pod。
  • 网络插件(CNI) 为 Pod 提供 IP 地址以及跨节点的连通性。

跟随一个请求从 kubectl apply 到运行中的容器

假设你应用了一个 Deployment 清单。接下来会发生:

  1. kubectl 读取你的 kubeconfig,并通过 HTTPS 将清单发送给 API 服务器。
  2. API 服务器对你进行认证和授权,验证对象,将其存入 etcd,并作出响应。
  3. Deployment 控制器注意到新的 Deployment 并创建一个 ReplicaSet,ReplicaSet 控制器随后创建 Pod 对象。此时 Pod 已经存在,但尚未分配到节点。
  4. 调度器注意到没有节点的 Pod,为每个 Pod 选择一个节点,并通过 API 服务器记录这一决定。
  5. 被选中节点上的 kubelet 看到分配给它的 Pod,并告诉容器运行时拉取镜像并启动容器。
  6. kubelet 将进展汇报回 API 服务器,后者将其存入 etcd。这正是 kubectl get pods 读取的内容。

注意这些组件从不直接相互调用。每个组件都监视 API 服务器上它所关心的对象并做出反应。这种松耦合正是你可以重启大多数组件而不丢失任何东西的原因:它们所需要的状态都在 etcd 中。

你可以在 Kubernetes 记录的事件中看到这个序列:

kubectl create deployment demo --image=nginx:1.25
kubectl get events --sort-by=.metadata.creationTimestamp

查找 Scheduled、Pulling、Pulled、Created 和 Started。这些是调度器和 kubelet 在各自履行职责。

查看你自己集群中的组件

kubectl get nodes -o wide
kubectl get pods -n kube-system

在 minikube 和 kubeadm 构建的集群上,你会看到控制平面组件作为 Pod 运行在 kube-system 命名空间中,旁边还有 kube-proxy 和网络插件。在托管服务(EKS、GKE、AKS)上,服务商为你运行控制平面,你只会看到你的工作节点。

这种设计在实践中意味着什么

  • API 服务器是咽喉要道。 一切都经过它,所以保护它并为它合理定容很重要。
  • etcd 的健康就是集群的健康。 备份它,并在生产环境中冗余运行它。
  • 失败是预料之中的。 宕机的节点、崩溃的组件或被删除的 Pod,只是期望状态与实际状态之间的一个差异,某个控制器最终会修复它。

热门指南