节点
节点介绍
Kubernetes 通过将容器放入在节点(Node)上运行的 Pod 中来执行你的工作负载。 节点可以是一个虚拟机或者物理机器,取决于所在的集群配置。 每个节点包含运行 Pod 所需的服务; 这些节点由 master 组件负责管理。
节点上的组件包括 :
- kubelet
- 容器运行时 CRI
- kube-proxy
节点状态
节点的状态包含如下信息:
- Addresses
- Conditions
Conditions
描述了节点的状态。Condition的例子有:
Node Condition | 描述 |
---|---|
OutOfDisk | 如果节点上的空白磁盘空间不够,不能够再添加新的节点时,该字段为 True ,其他情况为 False |
Ready | 如果节点是健康的且已经就绪可以接受新的 Pod。则节点Ready字段为 True 。False 表明了该节点不健康,不能够接受新的 Pod。 |
MemoryPressure | 如果节点内存紧张,则该字段为 True ,否则为False |
PIDPressure | 如果节点上进程过多,则该字段为 True ,否则为 False |
DiskPressure | 如果节点磁盘空间紧张,则该字段为 True ,否则为 False |
NetworkUnvailable | 如果节点的网络配置有问题,则该字段为 True ,否则为 False |
- Capacity and Allocatable
- System Info
执行以下命令可查看所有节点的列表:
root@master:/# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master Ready control-plane 35d v1.25.0 192.168.3.153 <none> Ubuntu 18.04.5 LTS 5.4.0-126-generic docker://20.10.8
node1 Ready <none> 35d v1.25.0 192.168.3.190 <none> Ubuntu 16.04.6 LTS 4.4.0-142-generic docker://20.10.7
执行以下命令可查看节点状态以及节点的其他详细信息:
root@master:/# kubectl describe node node1
Name: node1
Roles: <none>
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=node1
kubernetes.io/os=linux
Annotations: flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"46:05:07:4c:77:02"}
flannel.alpha.coreos.com/backend-type: vxlan
flannel.alpha.coreos.com/kube-subnet-manager: true
flannel.alpha.coreos.com/public-ip: 192.168.3.190
kubeadm.alpha.kubernetes.io/cri-socket: /var/run/cri-dockerd.sock
node.alpha.kubernetes.io/ttl: 0
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Mon, 05 Sep 2022 18:39:04 +0800
Taints: <none>
Unschedulable: false
Lease:
HolderIdentity: node1
AcquireTime: <unset>
RenewTime: Tue, 11 Oct 2022 17:10:52 +0800
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
NetworkUnavailable False Sun, 09 Oct 2022 10:18:19 +0800 Sun, 09 Oct 2022 10:18:19 +0800 FlannelIsUp Flannel is running on this node
MemoryPressure False Tue, 11 Oct 2022 17:09:38 +0800 Mon, 05 Sep 2022 18:39:04 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False Tue, 11 Oct 2022 17:09:38 +0800 Mon, 05 Sep 2022 18:39:04 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure
PIDPressure False Tue, 11 Oct 2022 17:09:38 +0800 Mon, 05 Sep 2022 18:39:04 +0800 KubeletHasSufficientPID kubelet has sufficient PID available
Ready True Tue, 11 Oct 2022 17:09:38 +0800 Mon, 05 Sep 2022 19:23:33 +0800 KubeletReady kubelet is posting ready status. AppArmor enabled
Addresses:
InternalIP: 192.168.3.190 #通常是从节点内部可以访问的 IP 地址
Hostname: node1 #在节点命令行界面上执行 hostname 命令所获得的值
Capacity: # 容量:节点上的资源总数
cpu: 4
ephemeral-storage: 959061464Ki
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 49299724Ki
pods: 110 # 该节点可调度的最大 pod 数量
Allocatable: # 可分配量:该节点上可分配给普通 Pod 的资源总数
cpu: 4
ephemeral-storage: 883871043759
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 49197324Ki
pods: 110 # 该节点可调度的最大 pod 数量
System Info: # 描述了节点的基本信息
Machine ID: 959acb4bc3df3086d845d40960702460
System UUID: 4C4C4544-0044-3510-805A-C8C04F384233
Boot ID: 35d07f76-4238-4db8-a0cb-2d96d61e52b2
Kernel Version: 4.4.0-142-generic # Linux 内核版本
OS Image: Ubuntu 16.04.6 LTS # 系统镜像
Operating System: linux # 操作系统名称
Architecture: amd64
Container Runtime Version: docker://20.10.7 # Docker 版本
Kubelet Version: v1.25.0 # Kubernetes 版本
Kube-Proxy Version: v1.25.0
PodCIDR: 10.244.1.0/24
PodCIDRs: 10.244.1.0/24
Non-terminated Pods: (26 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits Age
--------- ---- ------------ ---------- --------------- ------------- ---
default sc-deployment-78f5b66dd6-sqxkg 0 (0%) 0 (0%) 0 (0%) 0 (0%) 34d
ingress-nginx ingress-nginx-controller-54f8f88b77-hscfl 100m (2%) 0 (0%) 90Mi (0%) 0 (0%) 35d
kube-flannel kube-flannel-ds-qzd7k 100m (2%) 100m (2%) 50Mi (0%) 50Mi (0%) 35d
kube-system coredns-658fdc5f4b-t6s6w 100m (2%) 0 (0%) 70Mi (0%) 170Mi (0%) 35d
kube-system coredns-658fdc5f4b-tbpb2 100m (2%) 0 (0%) 70Mi (0%) 170Mi (0%) 35d
kube-system kube-proxy-t6nbm 0 (0%) 0 (0%) 0 (0%) 0 (0%) 35d
kube-system metrics-server-6c4b958989-hwmd4 100m (2%) 0 (0%) 200Mi (0%) 0 (0%) 35d
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 500m (12%) 100m (2%)
memory 680Mi (1%) 2438Mi (5%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-1Gi 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)
Events: <none>
节点管理
与 Pod 和 Service 不一样,节点并不是由 Kubernetes 创建的,节点由云供应商(例如,Google Compute Engine、阿里云等)创建,或者节点已经存在于您的物理机/虚拟机的资源池。向 Kubernetes 中创建节点时,仅仅是创建了一个描述该节点的 API 对象。节点 API 对象创建成功后,Kubernetes将检查该节点是否有效。例如,假设您创建如下节点信息:
kind: Node
apiVersion: v1
metadata:
name: "10.240.79.157"
labels:
name: "my-first-k8s-node"
Kubernetes 在 APIServer 上创建一个节点 API 对象(节点的描述),并且基于 metadata.name
字段对节点进行健康检查。如果节点有效(节点组件正在运行),则可以向该节点调度 Pod;否则,该节点 API 对象将被忽略,直到节点变为有效状态。
Kubernetes 将保留无效的节点 API 对象,并不断地检查该节点是否有效。除非您使用
kubectl delete node my-first-k8s-node
命令删除该节点。
有三个组件与Kubernetes节点接口进行交互:节点控制器(node controller)、kubelet和kubectl。
节点名称唯一性
节点的名称用来标识 Node 对象。 没有两个 Node 可以同时使用相同的名称。 Kubernetes 还假定名字相同的资源是同一个对象。 就 Node 而言,隐式假定使用相同名称的实例会具有相同的状态(例如网络配置、根磁盘内容) 和类似节点标签这类属性。这可能在节点被更改但其名称未变时导致系统状态不一致。 如果某个 Node 需要被替换或者大量变更,需要从 API 服务器移除现有的 Node 对象, 之后再在更新之后重新将其加入
节点控制器(Node Controller)
节点控制器是一个负责管理节点的 Kubernetes master 组件。在节点的生命周期中,节点控制器起到了许多作用。
-
在注册时将CIDR块分配给节点。
-
使节点控制器的内部列表与云提供商的可用机器列表保持最新。当在云环境中运行时,每当节点不健康时,节点控制器将询问云提供程序是否该节点的VM仍然可用,如果不可用,节点控制器会从其节点列表中删除该节点。
-
监测节点的健康状况。当节点变为不可访问时,节点控制器负责将NodeStatus的NodeReady条件更新为ConditionUnknown,随后从节点中卸载所有pod ,如果节点继续无法访问,(默认超时时间为40 --node-monitor-period秒,开始报告ConditionUnknown,之后为5m开始卸载)。节点控制器按每秒来检查每个节点的状态。
在Kubernetes 1.4中,我们更新了节点控制器的逻辑,以更好地处理大量节点到达主节点的一些问题(例如,主节某些网络问题)。从1.4开始,节点控制器将在决定关于pod卸载的过程中会查看集群中所有节点的状态。
在大多数情况下,节点控制器将逐出速率限制为 --node-eviction-rate(默认为0.1)/秒,这意味着它不会每10秒从多于1个节点驱逐Pod。
当给定可用性的区域中的节点变得不健康时,节点逐出行为发生变化,节点控制器同时检查区域中节点的不健康百分比(NodeReady条件为ConditionUnknown或ConditionFalse)。如果不健康节点的比例为 --unhealthy-zone-threshold(默认为0.55),那么驱逐速度就会降低:如果集群很小(即小于或等于–large-cluster-size-threshold节点 - 默认值为50),则停止驱逐,否则, --secondary-node-eviction-rate(默认为0.01)每秒。这些策略在可用性区域内实现的原因是,一个可用性区域可能会从主分区中被分区,而其他可用区域则保持连接。如果集群没有跨多个云提供商可用性区域,那么只有一个可用区域(整个集群)。
在可用区域之间传播节点的一个主要原因是,当整个区域停止时,工作负载可以转移到健康区域。因此,如果区域中的所有节点都不健康,则节点控制器以正常速率逐出–node-eviction-rate。如所有的区域都是完全不健康的(即群集中没有健康的节点),在这种情况下,节点控制器会假设主连接有一些问题,并停止所有驱逐,直到某些连接恢复。
自 Kubernetes v1.6 开始,节点控制器同时也负责为带有 NoExecute 污点的节点驱逐其上的 Pod。此外,节点控制器还负责根据节点的状态(例如,节点不可用,节点未就绪等)为节点添加污点。参考 NoExecute) 获取更多信息。
自 Kubernetes v1.8 开始,节点控制器可以根据节点的 Condition 为节点添加污点,此特性处于 alpha 阶段
节点自注册(Self-Registration)
当kubelet flag --register-node为true(默认值)时,kubelet将向API服务器注册自身。这是大多数发行版使用的首选模式。
对于self-registration,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
DaemonSet Controller 创建的 Pod 将绕过 Kubernetes 调度器,并且忽略节点的 unschedulable 属性。因为我们假设 Daemons 守护进程属于节点,尽管该节点在准备重启前,已经排空了上面所有的应用程序。
节点容量(Node Capacity)
节点API对象中描述了节点的容量(Capacity),例如,CPU数量、内存大小等信息。通常,节点在向 APIServer 注册的同时,在节点API对象里汇报了其容量(Capacity)。
Kubernetes 调度器在调度 Pod 到节点上时,将确保节点上有足够的资源。具体来说,调度器检查节点上所有容器的资源请求之和不大于节点的容量。此时,只能检查由 kubelet 启动的容器,不包括直接由容器引擎启动的容器,更不包括不在容器里运行的进程。
如果要明确保留非pod过程的资源,可以创建一个占位符pod。使用以下模板:
apiVersion: v1
kind: Pod
metadata:
name: resource-reserver
spec:
containers:
- name: sleep-forever
image: gcr.io/google_containers/pause:0.8.0
resources:
requests:
cpu: 100m
memory: 100Mi
将cpu和内存值设置为你想要保留的资源量,将文件放置在manifest目录中(--config=DIR
flag of kubelet)。在要预留资源的每个kubelet上执行此操作。