本部分包含以下有关节点的参考主题:
Kubelet 的 Checkpoint API
你还可以从 Kubernetes 文档的其他地方阅读节点的详细参考信息,包括:
Kubernetes v1.30 [beta]
(enabled by default: true)为容器生成检查点这个功能可以为一个正在运行的容器创建有状态的拷贝。 一旦容器有一个有状态的拷贝,你就可以将其移动到其他计算机进行调试或类似用途。
如果你将通过检查点操作生成的容器数据移动到能够恢复该容器的一台计算机, 所恢复的容器将从之前检查点操作执行的时间点继续运行。 你也可以检视所保存的数据,前提是你拥有这类操作的合适工具。
创建容器的检查点可能会产生安全隐患。
通常,一个检查点包含执行检查点操作时容器中所有进程的所有内存页。
这意味着以前存在于内存中的一切内容现在都在本地磁盘上获得。
这里的内容包括一切私密数据和可能用于加密的密钥。
底层 CRI 实现(该节点上的容器运行时)应创建只有 root
用户可以访问的检查点存档。
另外重要的是记住:如果检查点存档被转移到另一个系统,该检查点存档的所有者将可以读取所有内存页。
post
对指定的容器执行检查点操作告知 kubelet 对指定 Pod 中的特定容器执行检查点操作。
查阅 Kubelet 身份验证/鉴权参考了解如何控制对 kubelet 检查点接口的访问。
Kubelet 将对底层 CRI 实现请求执行检查点操作。
在该检查点请求中,Kubelet 将检查点存档的名称设置为 checkpoint-<pod 全称>-<容器名称>-<时间戳>.tar
,
还会请求将该检查点存档存储到其根目录(由 --root-dir
定义)下的 checkpoints
子目录中。
这个目录默认为 /var/lib/kubelet/checkpoints
。
检查点存档的格式为 tar,可以使用 tar
的一种实现来读取。存档文件的内容取决于底层 CRI 实现(该节点的容器运行时)。
POST /checkpoint/{namespace}/{pod}/{container}
namespace (路径参数):string,必需
名字空间(Namespace)pod (路径参数):string,必需
Podcontainer (路径参数):string,必需
容器(Container)timeout (查询参数):integer
等待检查点创建完成的超时时间(单位为秒)。 如果超时值为零或未设定,将使用默认的 CRI 超时时间值。 生成检查点所需的时长直接取决于容器所用的内存。容器使用的内存越多,创建相应检查点所需的时间越长。
200: OK
401: Unauthorized
404: Not Found(如果 ContainerCheckpoint
特性门控被禁用)
404: Not Found(如果指定的 namespace
、pod
或 container
无法被找到)
500: Internal Server Error(如果执行检查点操作期间 CRI 实现遇到一个错误(参阅错误消息了解更多细节))
500: Internal Server Error(如果 CRI 实现未实现检查点 CRI API(参阅错误消息了解更多细节))
许多特性依赖于特定的内核功能,并且有最低的内核版本要求。 然而,单纯依赖内核版本号可能不足以满足某些操作系统发行版, 因为像 RHEL、Ubuntu 和 SUSE 等发行版的维护者们通常会将选定的特性反向移植到较旧的内核版本(保留较旧的内核版本)。
在 Linux 中,sysctl()
系统调用在运行时配置内核参数。
你可以使用名为 sysctl
的命令行工具来配置这些参数,许多参数通过 proc
文件系统暴露。
某些 sysctl 仅可用于足够新的内核上。
以下 sysctl 具有最低的内核版本要求, 并在安全集中得到了支持:
net.ipv4.ip_local_reserved_ports
(自 Kubernetes 1.27 起,需要内核 3.16+);net.ipv4.tcp_keepalive_time
(自 Kubernetes 1.29 起,需要内核 4.5+);net.ipv4.tcp_fin_timeout
(自 Kubernetes 1.29 起,需要内核 4.6+);net.ipv4.tcp_keepalive_intvl
(自 Kubernetes 1.29 起,需要内核 4.5+);net.ipv4.tcp_keepalive_probes
(自 Kubernetes 1.29 起,需要内核 4.5+);net.ipv4.tcp_syncookies
(自内核 4.6+ 添加了命名空间作用域)。net.ipv4.vs.conn_reuse_mode
(用于 ipvs
代理模式,需要内核 4.1+);nftables
代理模式对于 Kubernetes 1.31,kube-proxy 的
nftables
模式要求
nft 命令行工具为 v1.0.1 或更高版本,要求内核为 v5.13 或更高版本。
出于测试/开发目的,你可以使用较旧的内核,如果你在 kube-proxy 配置中设置 nftables.skipKernelVersionCheck
选项,
最老可以回溯到 v5.4。但在生产环境中不推荐这样做,因为这可能会导致系统上其他 nftables 用户出现问题。
Kubernetes 对 cgroup v1 的支持从 v1.31 开始处于维护模式;推荐使用 cgroup v2。
在 Linux 5.8
中,为了方便使用,系统层面的 cpu.stat
文件被添加到根 cgroup。
在 runc 文档中,不推荐使用低于 5.2 的内核,因为其缺少冻结特性。
某些特性可能依赖于新的内核功能并具有特定的内核要求:
MOUNT_ATTR_RDONLY
属性和 AT_RECURSIVE
标志来实现的,使用的是在 Linux
内核 v5.12 中添加的 mount_setattr
(2)。noswap
。你可以在 kernel.org 找到活动的内核版本。
通常会提供多个 长期维护 内核版本,用于将 Bug 修复反向移植到较旧的内核树。 特别是对于较旧的树,只有重要的 Bug 修复才会被应用到此类内核,这些内核通常不会频繁发布新版本。 请参阅 Linux 内核网站,了解 Longterm 类别中的发布列表。
这是关于 Kubernetes 弃用和移除 dockershim 或使用兼容 CRI 的容器运行时相关的文章和其他页面的列表。
Kubernetes 博客:Dockershim 移除常见问题解答(最初发表于 2020/12/02)
Kubernetes 博客:更新:Dockershim 移除常见问题解答(更新发表于 2020/12/02)
Kubernetes 博客:Kubernetes 即将移除 Dockershim:承诺和下一步(发表于 2022/01/07)
Kubernetes 博客:移除 Dockershim 即将到来。你准备好了吗?(发表于 2021/11/12)
Kubernetes 文档:从 dockershim 迁移
Kubernetes 文档:容器运行时
Kubernetes 增强建议:KEP-2221: 从 kubelet 中移除 dockershim
Kubernetes 增强提问:从 kubelet 中移除 dockershim (k/enhancements#2221)
你可以通过 GitHub 问题 Dockershim 移除反馈和问题 提供反馈。 (k/kubernetes/#106917)
Amazon Web Services EKS 文档:Amazon EKS 将终止对 Dockershim 的支持
CNCF 会议视频:将 Kubernetes 从 Docker 迁移到 containerd 运行时的经验教训(Ana Caylin,在 KubeCon Europe 2019)
Docker.com 博客:开发人员需要了解的关于 Docker、Docker Engine 和 Kubernetes v1.20 的哪些知识(发表于 2020/12/04)
YouTube 上的 “Google Open Source” 频道:与 Google 一起学习 Kubernetes - 从 Dockershim 迁移到 Containerd
Azure 博客上的 Microsoft 应用:Dockershim 弃用和 AKS(发表于 2022/01/21)
Mirantis 博客:Dockershim 的未来是 cri-dockerd(发表于 2021/04/21)
Mirantis: Mirantis/cri-dockerd 官方文档
Tripwire:Dockershim 即将弃用如何影响你的 Kubernetes (发表于 2021/07/01)
你还可以通过 kubelet 配置或使用 Kubernetes API 在节点上设置自己的标签。
Kubernetes 在节点上设置的预设标签有:
kubernetes.io/arch
kubernetes.io/hostname
kubernetes.io/os
node.kubernetes.io/instance-type
(如果 kubelet 知道此信息 – Kubernetes 可能没有这些信息来设置标签)topology.kubernetes.io/region
(如果 kubelet 知道此信息 – Kubernetes 可能没有这些信息来设置标签)topology.kubernetes.io/zone
(如果 kubelet 知道此信息 – Kubernetes 可能没有这些信息来设置标签)这些标签的值是特定于云提供商的,并且不保证其可靠性。
例如,kubernetes.io/hostname
的值在某些环境中可能与节点名称相同,
而在其他环境中可能与节点名称不同。
当使用 kubelet 的 --config-dir
标志来指定存放配置的目录时,不同类型的配置会有一些特定的行为。
以下是在配置合并过程中不同数据类型的一些行为示例:
在 YAML 结构中有两种结构字段:独立(标量类型)和嵌入式(此结构包含标量类型)。 配置合并过程将处理独立构造字段和嵌入式构造字段的重载,以创建最终的 kubelet 配置。
例如,你可能想要为所有节点设置一个基准 kubelet 配置,但希望自定义 address
和 authorization
字段。
这种情况下,你可以按以下方式完成:
kubelet 主配置文件内容:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
port: 20250
authorization:
mode: Webhook
webhook:
cacheAuthorizedTTL: "5m"
cacheUnauthorizedTTL: "30s"
serializeImagePulls: false
address: "192.168.0.1"
--config-dir
目录中文件的内容:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authorization:
mode: AlwaysAllow
webhook:
cacheAuthorizedTTL: "8m"
cacheUnauthorizedTTL: "45s"
address: "192.168.0.8"
生成的配置如下所示:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
port: 20250
serializeImagePulls: false
authorization:
mode: AlwaysAllow
webhook:
cacheAuthorizedTTL: "8m"
cacheUnauthorizedTTL: "45s"
address: "192.168.0.8"
你可以重载 kubelet 配置的切片/列表值。
但在合并过程中整个列表将被重载。
例如,你可以按以下方式重载 clusterDNS
列表:
kubelet 主配置文件的内容:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
port: 20250
serializeImagePulls: false
clusterDNS:
- "192.168.0.9"
- "192.168.0.8"
--config-dir
目录中文件的内容:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
clusterDNS:
- "192.168.0.2"
- "192.168.0.3"
- "192.168.0.5"
生成的配置如下所示:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
port: 20250
serializeImagePulls: false
clusterDNS:
- "192.168.0.2"
- "192.168.0.3"
- "192.168.0.5"
映射中的各个字段(无论其值类型是布尔值、字符串等)都可以被选择性地重载。
但对于 map[string][]string
类型来说,与特定字段关联的整个列表都将被重载。
让我们通过一个例子更好地理解这一点,特别是 featureGates
和 staticPodURLHeader
这类字段:
kubelet 主配置文件的内容:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
port: 20250
serializeImagePulls: false
featureGates:
AllAlpha: false
MemoryQoS: true
staticPodURLHeader:
kubelet-api-support:
- "Authorization: 234APSDFA"
- "X-Custom-Header: 123"
custom-static-pod:
- "Authorization: 223EWRWER"
- "X-Custom-Header: 456"
--config-dir
目录中文件的内容:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
MemoryQoS: false
KubeletTracing: true
DynamicResourceAllocation: true
staticPodURLHeader:
custom-static-pod:
- "Authorization: 223EWRWER"
- "X-Custom-Header: 345"
生成的配置如下所示:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
port: 20250
serializeImagePulls: false
featureGates:
AllAlpha: false
MemoryQoS: false
KubeletTracing: true
DynamicResourceAllocation: true
staticPodURLHeader:
kubelet-api-support:
- "Authorization: 234APSDFA"
- "X-Custom-Header: 123"
custom-static-pod:
- "Authorization: 223EWRWER"
- "X-Custom-Header: 345"
本页详述了 Kubernetes 设备插件 API 与不同版本的 Kubernetes 本身之间的版本兼容性。
v1alpha1 | v1beta1 | |
---|---|---|
Kubernetes 1.21 | - | ✓ |
Kubernetes 1.22 | - | ✓ |
Kubernetes 1.23 | - | ✓ |
Kubernetes 1.24 | - | ✓ |
Kubernetes 1.25 | - | ✓ |
Kubernetes 1.26 | - | ✓ |
简要说明:
✓
设备插件 API 和 Kubernetes 版本中的特性或 API 对象完全相同。+
设备插件 API 具有 Kubernetes 集群中可能不存在的特性或 API 对象,
不是因为设备插件 API 添加了额外的新 API 调用,就是因为服务器移除了旧的 API 调用。
但它们的共同点是(大多数其他 API)都能工作。
请注意,Alpha API 可能会在次要版本的迭代过程中消失或出现重大变更。-
Kubernetes 集群具有设备插件 API 无法使用的特性,不是因为服务器添加了额外的 API 调用,
就是因为设备插件 API 移除了旧的 API 调用。但它们的共同点是(大多数 API)都能工作。Seccomp 表示安全计算(Secure Computing)模式,自 2.6.12 版本以来,一直是 Linux 内核的一个特性。 它可以用来沙箱化进程的权限,限制进程从用户态到内核态的调用。 Kubernetes 能使你自动将加载到节点上的 seccomp 配置文件应用到你的 Pod 和容器。
Kubernetes v1.19 [stable]
有四种方式可以为 Pod 指定 seccomp 配置文件:
spec.securityContext.seccompProfile
spec.containers[*].securityContext.seccompProfile
spec.initContainers[*].securityContext.seccompProfile
spec.ephemeralContainers[*].securityContext.seccompProfile
apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
securityContext:
seccompProfile:
type: Unconfined
ephemeralContainers:
- name: ephemeral-container
image: debian
securityContext:
seccompProfile:
type: RuntimeDefault
initContainers:
- name: init-container
image: debian
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: container
image: docker.io/library/debian:stable
securityContext:
seccompProfile:
type: Localhost
localhostProfile: my-profile.json
上面的示例中的 Pod 以 Unconfined
运行,而 ephemeral-container
和
init-container
独立设置了 RuntimeDefault
。
如果临时容器或 Init 容器没有明确设置 securityContext.seccompProfile
字段,
则此值将从 Pod 继承。同样的机制也适用于运行 Localhost
配置文件 my-profile.json
的容器。
一般来说,(临时)容器的字段优先级高于 Pod 层级的值,而未设置 seccomp 字段的容器则从 Pod 继承配置。
你不可以将 seccomp 配置文件应用到在容器的 securityContext
中设置了 privileged: true
的
Pod 或容器。特权容器始终以 Unconfined
运行。
对于 seccompProfile.type
,可以使用以下值:
Unconfined
RuntimeDefault
Localhost
localhostProfile
将被应用,这一配置必须位于节点磁盘上(在 Linux 上是 /var/lib/kubelet/seccomp
)。
在创建容器时,容器运行时会验证 seccomp
配置文件的可用性。如果此配置文件不存在,则容器创建将失败,并报错 CreateContainerError
。Localhost
配置文件Seccomp 配置文件是遵循 OCI 运行时规范定义的 JSON 文件。配置文件主要根据所匹配的系统调用来定义操作,但也允许将特定值作为参数传递给系统调用。例如:
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38,
"syscalls": [
{
"names": [
"adjtimex",
"alarm",
"bind",
"waitid",
"waitpid",
"write",
"writev"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
上述配置文件中的 defaultAction
被定义为 SCMP_ACT_ERRNO
,并可回退至 syscalls
中所定义的操作。
此错误通过 defaultErrnoRet
字段被定义为代码 38
。
通常可以使用以下操作:
SCMP_ACT_ERRNO
SCMP_ACT_ALLOW
SCMP_ACT_KILL_PROCESS
SCMP_ACT_KILL_THREAD
和 SCMP_ACT_KILL
SCMP_ACT_TRAP
SIGSYS
信号。SCMP_ACT_NOTIFY
和 SECCOMP_RET_USER_NOTIF
SCMP_ACT_TRACE
SCMP_ACT_LOG
SCMP_ACT_NOTIFY
或 SECCOMP_RET_USER_NOTIF
这类操作可能不被支持,
具体取决于所使用的容器运行时、OCI 运行时或 Linux 内核版本。也可能存在其他限制,
例如 SCMP_ACT_NOTIFY
不能用作 defaultAction
或用于某些系统调用(如 write
)。
所有这些限制由 OCI 运行时
(runc、crun)
或 libseccomp 所定义。
syscalls
JSON 数组包含对象列表,每个对象通过系统调用的 names
引用系统调用。
例如,SCMP_ACT_ALLOW
操作可用于创建包含如上例所示的系统调用的白名单。
也可以使用 SCMP_ACT_ERRNO
操作定义另一个列表,但会有不同的返回值(errnoRet
)。
你还可以指定传递给某些系统调用的参数(args
)。有关这些高级用例的细节,请参见
OCI 运行时规范
和 Seccomp Linux 内核文档。
在 Kubernetes 中,节点的状态是管理 Kubernetes 集群的一个关键方面。在本文中,我们将简要介绍如何监控和维护节点状态以确保集群的健康和稳定。
一个节点的状态包含以下信息:
你可以使用 kubectl
来查看节点状态和其他细节信息:
kubectl describe node <节点名称>
下面对输出的每个部分进行详细描述。
这些字段的用法取决于你的云服务商或者物理机配置。
--hostname-override
参数覆盖。conditions
字段描述了所有 Running
节点的状况。状况的示例包括:
节点状况 | 描述 |
---|---|
Ready | 如节点是健康的并已经准备好接收 Pod 则为 True ;False 表示节点不健康而且不能接收 Pod;Unknown 表示节点控制器在最近 node-monitor-grace-period 期间(默认 40 秒)没有收到节点的消息 |
DiskPressure | True 表示节点存在磁盘空间压力,即磁盘可用量低,否则为 False |
MemoryPressure | True 表示节点存在内存压力,即节点内存可用量低,否则为 False |
PIDPressure | True 表示节点存在进程压力,即节点上进程过多;否则为 False |
NetworkUnavailable | True 表示节点网络配置不正确;否则为 False |
如果使用命令行工具来打印已保护(Cordoned)节点的细节,其中的 Condition 字段可能包括
SchedulingDisabled
。SchedulingDisabled
不是 Kubernetes API 中定义的
Condition,被保护起来的节点在其规约中被标记为不可调度(Unschedulable)。
在 Kubernetes API 中,节点的状况表示节点资源中 .status
的一部分。
例如,以下 JSON 结构描述了一个健康节点:
"conditions": [
{
"type": "Ready",
"status": "True",
"reason": "KubeletReady",
"message": "kubelet is posting ready status",
"lastHeartbeatTime": "2019-06-05T18:38:35Z",
"lastTransitionTime": "2019-06-05T11:41:27Z"
}
]
当节点上出现问题时,Kubernetes 控制面会自动创建与影响节点的状况对应的
污点。
例如当 Ready 状况的 status
保持 Unknown
或 False
的时间长于
kube-controller-manager 的 NodeMonitorGracePeriod
(默认为 40 秒)时,
会造成 Unknown
状态下为节点添加 node.kubernetes.io/unreachable
污点或在
False
状态下为节点添加 node.kubernetes.io/not-ready
污点。
这些污点会影响悬决的 Pod,因为调度器在将 Pod 分配到节点时会考虑节点的污点。
已调度到节点的当前 Pod 可能会由于施加的 NoExecute
污点被驱逐。
Pod 还可以设置容忍度,
使得这些 Pod 仍然能够调度到且继续运行在设置了特定污点的节点上。
进一步的细节可参阅基于污点的驱逐 和根据状况为节点设置污点。
这两个值描述节点上的可用资源:CPU、内存和可以调度到节点上的 Pod 的个数上限。
capacity
块中的字段标示节点拥有的资源总量。
allocatable
块指示节点上可供普通 Pod 使用的资源量。
你可以通过学习如何在节点上预留计算资源 来进一步了解有关容量和可分配资源的信息。
Info 指的是节点的一般信息,如内核版本、Kubernetes 版本(kubelet
和 kube-proxy
版本)、
容器运行时详细信息,以及节点使用的操作系统。
kubelet
从节点收集这些信息并将其发布到 Kubernetes API。
Kubernetes 节点发送的心跳帮助你的集群确定每个节点的可用性,并在检测到故障时采取行动。
对于节点,有两种形式的心跳:
与节点的 .status
更新相比,Lease 是一种轻量级资源。
使用 Lease 来表达心跳在大型集群中可以减少这些更新对性能的影响。
kubelet 负责创建和更新节点的 .status
,以及更新它们对应的 Lease。
.status
。
.status
更新的默认间隔为 5 分钟(比节点不可达事件的 40 秒默认超时时间长很多)。kubelet
会创建并每 10 秒(默认更新间隔时间)更新 Lease 对象。
Lease 的更新独立于节点的 .status
更新而发生。
如果 Lease 的更新操作失败,kubelet 会采用指数回退机制,从 200 毫秒开始重试,
最长重试间隔为 7 秒钟。