k8s的进阶-01
Posted 王佐的运维笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了k8s的进阶-01相关的知识,希望对你有一定的参考价值。
至此,k8s的基础已经结束了,下边开始新的里程碑,k8s进阶。
首先从架构上来说,什么是节点,怎么查看节点,节点的状态呢?
Kubernetes中节点(node)指的是一个工作机器,曾经叫做 minion。不同的集群中,节点可能是虚拟机也可能是物理机。每个节点都由 master 组件管理,并包含了运行 Pod(容器组)所需的服务。这些服务包括:
容器引擎(上一篇提到的)
kubelet
kube-proxy
那如何查看节点的状态,节点的状态信息又包括哪些?
Addresses
Conditions
Capacity and Allocatable
Info
执行以下命令可查看所有节点的列表:
kubectl get nodes -o wide
执行以下命令可查看节点状态以及节点的其他详细信息:
kubectl describe node <your-node-name>
例如: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
node02=node02
Annotations: node.alpha.kubernetes.io/ttl: 0
projectcalico.org/IPv4Address: 10.244.1.1/24
projectcalico.org/IPv4IPIPTunnelAddr: 10.100.166.128
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Thu, 18 Mar 2021 14:08:24 +0800
Taints: <none>
Unschedulable: false
Lease:
HolderIdentity: node1
AcquireTime: <unset>
RenewTime: Thu, 18 Mar 2021 17:10:29 +0800
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
NetworkUnavailable False Thu, 18 Mar 2021 15:02:07 +0800 Thu, 18 Mar 2021 15:02:07 +0800 CalicoIsUp Calico is running on this node
MemoryPressure False Thu, 18 Mar 2021 17:06:35 +0800 Thu, 18 Mar 2021 14:08:24 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False Thu, 18 Mar 2021 17:06:35 +0800 Thu, 18 Mar 2021 14:08:24 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure
PIDPressure False Thu, 18 Mar 2021 17:06:35 +0800 Thu, 18 Mar 2021 14:08:24 +0800 KubeletHasSufficientPID kubelet has sufficient PID available
Ready True Thu, 18 Mar 2021 17:06:35 +0800 Thu, 18 Mar 2021 14:08:34 +0800 KubeletReady kubelet is posting ready status
Addresses:
InternalIP: 192.168.0.131
Hostname: node1
Capacity:
cpu: 4
ephemeral-storage: 49250820Ki
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 4045080Ki
pods: 110
Allocatable:
cpu: 4
ephemeral-storage: 45389555637
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 3942680Ki
pods: 110
System Info:
Machine ID: 41381d3178bd478ab9e52d1743c438f8
System UUID: C6081F42-8094-35D2-BB92-45202EBA7170
Boot ID: 190a64d4-7bf5-4cfc-b606-32e94c076629
Kernel Version: 3.10.0-1127.13.1.el7.x86_64
OS Image: CentOS Linux 7 (Core)
Operating System: linux
Architecture: amd64
Container Runtime Version: docker://19.3.11
Kubelet Version: v1.20.2
Kube-Proxy Version: v1.20.2
PodCIDR: 10.100.2.0/24
PodCIDRs: 10.100.2.0/24
Non-terminated Pods: (3 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
kube-system calico-node-m58ts 250m (6%) 0 (0%) 0 (0%) 0 (0%) 3h2m
kube-system kube-proxy-qrphw 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3h2m
nginx-ingress nginx-ingress-hvjn7 0 (0%) 0 (0%) 0 (0%) 0 (0%) 3h2m
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 250m (6%) 0 (0%)
memory 0 (0%) 0 (0%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-1Gi 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)
Events: <none>
下边就详细说下节点状态的主要内容:
Addresses
依据你集群部署的方式(在哪个云供应商部署,或是在物理机上部署),Addesses 字段可能有所不同。
HostName:在节点命令行界面上执行 hostname 命令所获得的值。启动 kubelet 时,可以通过参数 --hostname-override 覆盖
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 |
Node Condition 以一个 JSON 对象的形式存在。例如,下面的yaml 描述了一个健康状态下节点的 Condition,如下所示:
"conditions": [
{
"type": "Ready",
"status": "True",
"reason": "KubeletReady",
"message": "kubelet is posting ready status",
"lastHeartbeatTime": "2021-03-17T22:38:35Z",
"lastTransitionTime": "2021-03-17T21:24:27Z"
}
]
如果 Ready 类型Condition 的 status 持续为 Unkown 或者 False 超过 pod-eviction-timeout(kube-controller-manage (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 的资源总数。
Info
描述了节点的基本信息,例如:
Linux 内核版本
Kubernetes 版本(kubelet 和 kube-proxy 的版本)
Docker 版本
操作系统名称
这些信息是由节点(node)上的kubelet收集。
节点管理:
与 Pod 和 Service 不一样,节点并不是由 Kubernetes 创建的,节点由云供应商(例如,Google Compute Engine、阿里云等)创建,或者节点已经存在于您的物理机/虚拟机的资源池。向 Kubernetes 中创建节点时,仅仅是创建了一个描述该节点的 API 对象。节点 API 对象创建成功后,Kubernetes将检查该节点是否有效。例如,假设您创建如下节点信息:
kind: Node
apiVersion: v1
metadata:
name: "10.240.79.157"
labels:
name: "node01"
Kubernetes 在 APIServer 上创建一个节点 API 对象(节点的描述),并且基于 metadata.name 字段对节点进行健康检查。如果节点有效(节点组件正在运行),则可以向该节点调度 Pod;否则,该节点 API 对象将被忽略,直到节点变为有效状态。
TIP
Kubernetes 将保留无效的节点 API 对象,并不断地检查该节点是否有效。除非您使用 kubectl delete node node01 命令删除该节点。
节点控制器(Node Controller)
节点控制器是一个负责管理节点的 Kubernetes master 组件。在节点的生命周期中,节点控制器起到了许多作用。
第二,节点控制器通过云供应商(cloud-controller-manager)接口检查节点列表中每一个节点对象对应的虚拟机是否可用。在云环境中,只要节点状态异常,节点控制器检查其虚拟机在云供应商的状态,如果虚拟机不可用,自动将节点对象从 APIServer 中删除。
节点控制器监控节点的健康状况。当节点变得不可触达时(例如,由于节点已停机,节点控制器不再收到来自节点的心跳信号),节点控制器将节点API对象的 NodeStatus Condition 取值从 NodeReady 更新为 Unknown;然后在等待 pod-eviction-timeout 时间后,将节点上的所有 Pod 从节点驱逐。
tips:
默认40秒未收到心跳,修改 NodeStatus Condition 为 Unknown;
默认 pod-eviction-timeout 为 5分钟
节点控制器每隔 --node-monitor-period 秒检查一次节点的状态
节点自注册(Self-Registration)
如果 kubelet 的启动参数 --register-node为 true(默认为 true),kubelet 会尝试将自己注册到 API Server。kubelet自行注册时,将使用如下选项:
--kubeconfig:向 apiserver 进行认证时所用身份信息的路径
--cloud-provider:向云供应商读取节点自身元数据
--register-node:自动向 API Server 注册节点
--register-with-taints:注册节点时,为节点添加污点(逗号分隔,格式为 <key>=<value>:<effect>
--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
TIP
DaemonSet Controller 创建的 Pod 将绕过 Kubernetes 调度器,并且忽略节点的 unschedulable 属性。因为我们假设 Daemons 守护进程属于节点,尽管该节点在准备重启前,已经排空了上面所有的应用程序。
节点容量(Node Capacity)
节点API对象中描述了节点的容量(Capacity),例如,CPU数量、内存大小等信息。通常,节点在向 APIServer 注册的同时,在节点API对象里汇报了其容量(Capacity)。如果您 手动管理节点,您需要在添加节点时自己设置节点的容量。
Kubernetes 调度器在调度 Pod 到节点上时,将确保节点上有足够的资源。具体来说,调度器检查节点上所有容器的资源请求之和不大于节点的容量。此时,只能检查由 kubelet 启动的容器,不包括直接由容器引擎启动的容器,更不包括不在容器里运行的进程。
以上是关于k8s的进阶-01的主要内容,如果未能解决你的问题,请参考以下文章
我的Android进阶之旅NDK开发之在C++代码中使用Android Log打印日志,打印出C++的函数耗时以及代码片段耗时详情