K8s-节点

K8s的node(节点)是一个工作机器。每个节点都是归属master组件管理。

节点的状态

  • Addresses
  • Conditions
  • Capacity and Allocatable
  • Info

Addresses

  • HostName: 在节点命令行界面上执行 hostname 命令所获得的值。启动 kubelet 时,可以通过参数 --hostname-override 覆盖
  • ExternalIP:通常是节点的外部IP(可以从集群外访问的内网IP地址;上面的例子中,此字段为空)
  • InternalIP:通常是从节点内部可以访问的 IP 地址

Conditions

Conditions 描述了节点的状态。

Condition的例子有:

Node Condition 描述
OutOfDisk 如果节点上的空白磁盘空间不够,不能够再添加新的节点时,该字段为 True,其他情况为 False
Ready 如果节点是健康的且已经就绪可以接受新的 Pod。则节点Ready字段为 TrueFalse表明了该节点不健康,不能够接受新的 Pod。
MemoryPressure 如果节点内存紧张,则该字段为 True,否则为False
PIDPressure 如果节点上进程过多,则该字段为 True,否则为 False
DiskPressure 如果节点磁盘空间紧张,则该字段为 True,否则为 False
NetworkUnvailable 如果节点的网络配置有问题,则该字段为 True,否则为 False

如果 Ready 类型Condition 的 status 持续为 Unkown 或者 False 超过 pod-eviction-timeoutkube-controller-manager (opens new window)的参数)所指定的时间,节点控制器(node controller)将对该节点上的所有 Pod 执行删除的调度动作

默认的 pod-eviction-timeout 时间是 5 分钟。某些情况下(例如,节点网络故障),apiserver 不能够与节点上的 kubelet 通信,删除 Pod 的指令不能下达到该节点的 kubelet 上,直到 apiserver 与节点的通信重新建立,指令才下达到节点。这意味着,虽然对 Pod 执行了删除的调度指令,但是这些Pod 可能仍然在失联的节点上运行

在 kubernetes v1.5 以前,节点控制器将从 apiserver 强制删除这些失联节点上的 Pod。在 v1.5 及以后的版本中,节点控制器将不会强制删除这些 Pod,直到已经确认他们已经停止运行为止。您可能会发现失联节点上的 Pod 仍然在运行(在该节点上执行 docker ps 命令可查看容器的运行状态),然而 apiserver 中,他们的状态已经变为 Terminating 或者 Unknown。如果 Kubernetes 不能通过 cloud-controller-manager 判断失联节点是否已经永久从集群中移除(例如,在虚拟机或物理机上自己部署 Kubernetes 的情况),集群管理员需要手工(通过 kubectl delete node your-node-name 命令)删除 apiserver 中的节点对象。此时,Kubernetes 将删除该节点上的所有 Pod

在 Kubernetes v1.12 中,TaintNodesByCondition 特性进入 beta 阶段,此时 node lifecycle controller 将自动创建该 Condition 对应的 污点。相应地,调度器在选择合适的节点时,不再关注节点的 Condition,而是检查节点的污点和 Pod 的容忍。

Capacity and Allocatable(容量和可分配量)

容量和可分配量(Capacity and Allocatable)描述了节点上的可用资源的情况:

  • CPU
  • 内存
  • 该节点可调度的最大 pod 数量

Capacity 中的字段表示节点上的资源总数,Allocatable 中的字段表示该节点上可分配给普通 Pod 的资源总数。

参考 reserve compute resources (opens new window)可以了解更多关于容量和可分配量的内容

节点管理

节点控制器

  • 节点控制器,在注册节点的时候分配CIDR地址块

  • 通过cloud-controller-manager 检查节点的虚拟机是否可用

  • 节点控制器会监控节点的监控状态。节点控制器将节点API对象的 NodeStatus Condition 取值从 NodeReady 更新为 Unknown;然后在等待 pod-eviction-timeout 时间后,将节点上的所有 Pod 从节点驱逐

    默认40秒未收到心跳,修改 NodeStatus Condition 为 Unknown

    默认 pod-eviction-timeout 为 5分钟

    节点控制器每隔 --node-monitor-period 秒检查一次节点的状态

大多数情况下,节点控制器限制了驱逐 Pod 的速率为 --node-eviction-rate (默认值是0.1)每秒,即节点控制器每 10 秒驱逐 1 个 Pod。

当节点所在的高可用区出现故障时,节点控制器驱逐 Pod 的方式将不一样。节点控制器驱逐Pod前,将检查高可用区里故障节点的百分比(NodeReady Condition 的值为 UnknownFalse):

  • 如果故障节点的比例不低于--unhealthy-zone-threshold(默认为 0.55),则降低驱逐 Pod 的速率
    • 如果集群规模较小(少于等于 --large-cluster-size-threshold 个节点,默认值为 50),则停止驱逐 Pod
    • 如果集群规模大于 --large-cluster-size-threshold 个节点,则驱逐 Pod 的速率降低到 --secondary-node-eviction-rate (默认值为 0.01)每秒

节点自注册(Self-Registration)

如果 kubelet 的启动参数 --register-node为 true(默认为 true),kubelet 会尝试将自己注册到 API Server。kubelet自行注册时,将使用如下选项:

  • --kubeconfig:向 apiserver 进行认证时所用身份信息的路径
  • --cloud-provider:向云供应商读取节点自身元数据
  • --register-node:自动向 API Server 注册节点
  • --register-with-taints:注册节点时,为节点添加污点(逗号分隔,格式为 =:
  • --node-ip:节点的 IP 地址
  • --node-labels:注册节点时,为节点添加标签
  • --node-status-update-frequency:向 master 节点发送心跳信息的时间间

手动管理节点

集群管理员可以创建和修改节点API对象。

如果管理员想要手工创建节点API对象,可以将 kubelet 的启动参数 --register-node 设置为 false。

管理员可以修改节点API对象(不管是否设置了 --register-node 参数)。可以修改的内容有:

  • 增加/减少标签
  • 标记节点为不可调度(unschedulable)

节点的标签与 Pod 上的节点选择器(node selector)配合,可以控制调度方式,例如,限定 Pod 只能在某一组节点上运行。请参考 将容器组调度到指定的节点

执行如下命令可将节点标记为不可调度(unschedulable),此时将阻止新的 Pod 被调度到该节点上,但是不影响任何已经在该节点上运行的 Pod。这在准备重启节点之前非常有用。

kubectl cordon $NODENAME