1 - Kubelet Checkpoint API

特性状态: Kubernetes v1.30 (Beta; (默认启用))

为容器生成检查点这个功能可以为一个正在运行的容器创建有状态的拷贝。 一旦容器有一个有状态的拷贝,你就可以将其移动到其他计算机进行调试或类似用途。

如果你将通过检查点操作生成的容器数据移动到能够恢复该容器的一台计算机, 所恢复的容器将从之前检查点操作执行的时间点继续运行。 你也可以检视所保存的数据,前提是你拥有这类操作的合适工具。

创建容器的检查点可能会产生安全隐患。 通常,一个检查点包含执行检查点操作时容器中所有进程的所有内存页。 这意味着以前存在于内存中的一切内容现在都在本地磁盘上获得。 这里的内容包括一切私密数据和可能用于加密的密钥。 底层 CRI 实现(该节点上的容器运行时)应创建只有 root 用户可以访问的检查点存档。 另外重要的是记住:如果检查点存档被转移到另一个系统,该检查点存档的所有者将可以读取所有内存页。

操作

post 对指定的容器执行检查点操作

告知 kubelet 对指定 Pod 中的特定容器执行检查点操作。

查阅 Kubelet 身份验证/鉴权参考了解如何控制对 kubelet 检查点接口的访问。

Kubelet 将对底层 CRI 实现请求执行检查点操作。 在该检查点请求中,Kubelet 将检查点存档的名称设置为 checkpoint-<pod 全称>-<容器名称>-<时间戳>.tar, 还会请求将该检查点存档存储到其根目录(由 --root-dir 定义)下的 checkpoints 子目录中。 这个目录默认为 /var/lib/kubelet/checkpoints

检查点存档的格式为 tar,可以使用 tar 的一种实现来读取。存档文件的内容取决于底层 CRI 实现(该节点的容器运行时)。

HTTP 请求

POST /checkpoint/{namespace}/{pod}/{container}

参数

  • namespace (路径参数):string,必需

    名字空间(Namespace)
  • pod (路径参数):string,必需

    Pod
  • container (路径参数):string,必需

    容器(Container)
  • timeout (查询参数):integer

    等待检查点创建完成的超时时间(单位为秒)。 如果超时值为零或未设定,将使用默认的 CRI 超时时间值。 生成检查点所需的时长直接取决于容器所用的内存。容器使用的内存越多,创建相应检查点所需的时间越长。

响应

200: OK

401: Unauthorized

404: Not Found(如果 ContainerCheckpoint 特性门控被禁用)

404: Not Found(如果指定的 namespacepodcontainer 无法被找到)

500: Internal Server Error(如果执行检查点操作期间 CRI 实现遇到一个错误(参阅错误消息了解更多细节))

500: Internal Server Error(如果 CRI 实现未实现检查点 CRI API(参阅错误消息了解更多细节))

2 - Linux 内核版本要求

许多特性依赖于特定的内核功能,并且有最低的内核版本要求。 然而,单纯依赖内核版本号可能不足以满足某些操作系统发行版, 因为像 RHEL、Ubuntu 和 SUSE 等发行版的维护者们通常会将选定的特性反向移植到较旧的内核版本(保留较旧的内核版本)。

Pod sysctl

在 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.tcp_rmem(自 Kubernetes 1.32,需要内核 4.15+)。
  • net.ipv4.tcp_wmem(自 Kubernetes 1.32,需要内核 4.15+)。
  • net.ipv4.vs.conn_reuse_mode(用于 ipvs 代理模式,需要内核 4.1+)。

kube proxy nftables 代理模式

对于 Kubernetes 1.35,kube-proxy 的 nftables 模式要求 nft 命令行工具为 v1.0.1 或更高版本,要求内核为 v5.13 或更高版本。

出于测试/开发目的,你可以使用较旧的内核,如果你在 kube-proxy 配置中设置 nftables.skipKernelVersionCheck 选项, 最老可以回溯到 v5.4。但在生产环境中不推荐这样做,因为这可能会导致系统上其他 nftables 用户出现问题。

v2 控制组

Kubernetes 对 CGroup v1 的支持从 v1.31 开始处于维护模式;推荐使用 CGroup v2。 在 Linux 5.8 中,为了方便使用,系统层面的 cpu.stat 文件被添加到根 CGroup。

在 runc 文档中,不推荐使用低于 5.2 的内核,因为其缺少冻结特性。

压力阻塞信息(PSI)

Linux 内核 v4.20 及更高版本支持压力阻塞信息, 但需要以下配置:

  • 内核必须使用 CONFIG_PSI=y 选项进行编译(大多数现代发行版默认启用此选项)。 你可以通过运行 zgrep CONFIG_PSI /proc/config.gz 来检查内核的配置。
  • 某些 Linux 发行版可能会将 PSI 编译进内核,但默认情况下是禁用的。 如果是这样,你需要在启动时通过向内核命令行添加 psi=1 参数来启用它。

其他内核要求

某些特性可能依赖于新的内核功能并具有特定的内核要求:

  1. 递归只读挂载: 这是通过应用 MOUNT_ATTR_RDONLY 属性和 AT_RECURSIVE 标志来实现的,使用的是在 Linux 内核 v5.12 中添加的 mount_setattr(2)。
  2. Pod 用户命名空间支持需要最低内核版本 6.5+,参阅 KEP-127
  3. 对于节点系统交换, 直到内核 6.3 才支持将 tmpfs 设置为 noswap

Linux 内核长期维护

你可以在 kernel.org 找到活动的内核版本。

通常会提供多个长期维护内核版本,用于将 Bug 修复反向移植到较旧的内核树。 特别是对于较旧的树,只有重要的 Bug 修复才会被应用到此类内核,这些内核通常不会频繁发布新版本。 请参阅 Linux 内核网站,了解 Longterm 类别中的发布列表

接下来

3 - 关于 dockershim 移除和使用兼容 CRI 运行时的文章

这是关于 Kubernetes 弃用和移除 dockershim 或使用兼容 CRI 的容器运行时相关的文章和其他页面的列表。

Kubernetes 项目

你可以通过 GitHub 问题 Dockershim 移除反馈和问题 提供反馈。 (k/kubernetes/#106917)

外部来源

4 - 由 kubelet 填充的节点标签

Kubernetes 节点预先填充了一组标准 标签

你还可以通过 kubelet 配置或使用 Kubernetes API 在节点上设置自己的标签。

预设标签

Kubernetes 在节点上设置的预设标签有:

接下来

5 - kubelet 所使用的本地文件和路径

kubelet 是一个运行在 Kubernetes 节点上的无状态进程。本文简要介绍了 kubelet 读写的文件。

kubelet 通常使用控制面作为需要在 Node 上运行的事物的真实来源,并使用容器运行时获取容器的当前状态。 只要你向 kubelet 提供 kubeconfig(API 客户端配置),kubelet 就会连接到你的控制面; 否则,节点将以**独立(Standalone)**模式运行。

在 Linux 节点上,kubelet 还需要读取 cgroups 和各种系统文件来收集指标。

在 Windows 节点上,kubelet 不依赖于路径,而是通过其他机制来收集指标。

kubelet 所使用的还有其他文件,包括其使用本地 Unix 域套接字进行通信的文件。 有些文件是 kubelet 要监听的套接字,而其他套接字则是 kubelet 先发现后作为客户端连接的。

配置

kubelet 配置文件

你可以使用命令行参数 --config 指定 kubelet 配置文件的路径。kubelet 还支持插件(Drop-in)配置文件来增强配置。

证书

证书和私钥通常位于 /var/lib/kubelet/pki,但你可以使用 --cert-dir kubelet 命令行参数进行配置。 证书文件的名称也是可以配置的。

清单

静态 Pod 的清单通常位于 /etc/kubernetes/manifests。 你可以使用 staticPodPath kubelet 配置选项进行配置。

systemd 单元设置

当 kubelet 作为 systemd 单元运行时,一些 kubelet 配置可以在 systemd 单元设置文件中声明。 这些配置通常包括:

状态

资源管理器的检查点文件

所有资源管理器将 Pod 与已分配资源之间的映射保存在状态文件中。 状态文件位于 kubelet 的基础目录,也称为根目录(但与节点根目录 / 不同)之下。 你可以使用 kubelet 命令行参数 --root-dir 来配置 kubelet 的基础目录。

文件名称:

设备管理器的检查点文件

设备管理器在与套接字文件相同的目录(/var/lib/kubelet/device-plugins/)中创建检查点。 对于设备管理器, 检查点文件的名称为 kubelet_internal_checkpoint

Pod 状态检查点

特性状态: Kubernetes v1.35 (GA)
More information about this feature

This is a stable feature in Kubernetes, and has been since version 1.35. It was first available in the v1.27 release.

如果某个节点已启用了 InPlacePodVerticalScaling 特性门控, 则 kubelet 存储有关 Pod 资源已分配已应用状态的本地记录。
有关如何使用这些记录的更多细节, 请参阅调整分配给容器的 CPU 和内存资源

文件名称如下:

  • allocated_pods_state:记录分配给该节点上每个 Pod 的资源。
  • actuated_pods_state:记录运行时已接受并应用于该节点上每个 Pod 的资源。

这些文件位于 kubelet 的基础目录中(在 Linux 系统中默认是 /var/lib/kubelet; 也可以通过 --root-dir 参数进行配置)。

容器运行时

kubelet 使用通过配置参数所配置的套接字与容器运行时进行通信:

  • containerRuntimeEndpoint 用于运行时操作
  • imageServiceEndpoint 用于镜像管理操作

这些端点的实际值取决于所使用的容器运行时。

设备插件

kubelet 在路径 /var/lib/kubelet/device-plugins/kubelet.sock 为各个要注册的设备插件公开一个套接字。

当设备插件注册自己时,它会为提供其套接字路径供 kubelet 连接使用。

设备插件套接字应位于 kubelet 基础目录中的 device-plugins 目录内。 在典型的 Linux 节点上,这意味着 /var/lib/kubelet/device-plugins

Pod Resources API

Pod Resources API 将在路径 /var/lib/kubelet/pod-resources 上被公开。

DRA、CSI 和设备插件

kubelet 会查找通过 DRA 设备管理器或存储插件所管理的设备插件所创建的套接字文件,然后尝试连接到这些套接字。 kubelet 查找的目录是 kubelet 基础目录下的 plugins_registry, 因此在典型的 Linux 节点上这意味着 /var/lib/kubelet/plugins_registry

请注意,对于设备插件,有两种备选的注册机制。每个给定的插件只能使用其中一种注册机制。

可以将套接字文件放入该目录的插件类型包括:

  • CSI 插件
  • DRA 插件
  • 设备管理器插件

(通常是 /var/lib/kubelet/plugins_registry)。

节点体面关闭

特性状态: Kubernetes v1.21 (Beta; (默认启用))

节点体面关闭将状态存储在本地目录 /var/lib/kubelet/graceful_node_shutdown_state

镜像拉取记录

特性状态: Kubernetes v1.35 (Beta; (默认启用))

kubelet 存储镜像拉取的尝试记录和成功记录,并使用这些记录来验证镜像是否曾使用相同的凭据被成功拉取过。

这些记录作为文件缓存在 kubelet 基础目录下的 image_registry 目录中。 在典型的 Linux 节点上,这个路径通常为 /var/lib/kubelet/image_manager
image_manager 目录下包含两个子目录:

  • pulling:存储 kubelet 正在尝试拉取的镜像的相关记录。
  • pulled:存储 kubelet 成功拉取的镜像记录,以及与拉取所用凭据相关的元数据。

更多细节请参阅确保镜像拉取凭据验证

安全配置文件和配置

Seccomp

被 Pod 引用的 Seccomp 配置文件应放置在 /var/lib/kubelet/seccomp。 有关细节请参见 Seccomp 参考

AppArmor

kubelet 不会通过特定于 Kubernetes 的路径加载或引用 AppArmor 配置文件。 AppArmor 配置文件通过节点操作系统被加载,而不是通过其路径被引用。

加锁

特性状态: Kubernetes v1.2 (Alpha)

kubelet 的锁文件;通常为 /var/run/kubelet.lock。 kubelet 使用此文件确保尝试运行两个不同的、彼此冲突的 kubelet。 你可以使用 --lock-file kubelet 命令行参数来配置这个锁文件的路径。

如果同一节点上的两个 kubelet 使用不同的锁文件路径值,则这两个 kubelet 在同时运行时将不会检测到冲突。

接下来

6 - kubelet 配置目录合并

当使用 kubelet 的 --config-dir 标志来指定存放配置的目录时,不同类型的配置会有一些特定的行为。

以下是在配置合并过程中不同数据类型的一些行为示例:

结构字段

在 YAML 结构中有两种结构字段:独立(标量类型)和嵌入式(此结构包含标量类型)。 配置合并过程将处理独立构造字段和嵌入式构造字段的重载,以创建最终的 kubelet 配置。

例如,你可能想要为所有节点设置一个基准 kubelet 配置,但希望自定义 addressauthorization 字段。 这种情况下,你可以按以下方式完成:

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 类型来说,与特定字段关联的整个列表都将被重载。 让我们通过一个例子更好地理解这一点,特别是 featureGatesstaticPodURLHeader 这类字段:

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"

7 - Kubelet 设备管理器 API 版本

本页详述了 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)都能工作。

8 - kubelet systemd 看门狗

特性状态: Kubernetes v1.32 (Beta; (默认启用))

在 Linux 节点上,Kubernetes 1.35 支持与 systemd 集成,以允许操作系统监视程序恢复失败的 kubelet。 这种集成默认并未被启用。它可以作为一个替代方案,通过定期请求 kubelet 的 /healthz 端点进行健康检查。 如果 kubelet 在设定的超时时限内未对看门狗做出响应,看门狗将杀死 kubelet。

systemd 看门狗的工作原理是要求服务定期向 systemd 进程发送一个保持活跃的信号。 如果 systemd 进程在指定的超时时限内未接收到某服务发出的信号,则对应的服务被视为无响应并被终止。 之后 systemd 进程可以基于配置重启该服务。

配置

使用 systemd 看门狗需要在 kubelet 服务单元文件的 [Service] 部分配置 WatchdogSec 参数:

[Service]
WatchdogSec=30s

设置 WatchdogSec=30s 表示服务看门狗超时时限为 30 秒。 在 kubelet 内,sd_notify() 函数被调用,以 \( WatchdogSec \div 2\) 的时间间隔, 发送 WATCHDOG=1(保持活跃的消息)。如果在超时时限内看门狗未被“投喂”此信号,kubelet 将被杀死。 将 Restart 设置为 "always"、"on-failure"、"on-watchdog" 或 "on-abnormal" 将确保服务被自动重启。

systemd 配置相关的一些细节:

  1. 如果你将 systemd 的 WatchdogSec 值设置为 0,或省略不设置,则对应的单元上不启用 systemd 看门狗。
  2. kubelet 支持设置的最小看门狗超时时限为 1.0 秒;这是为了防止 kubelet 被意外杀死。 你可以在 systemd 单元定义中将 WatchdogSec 的值设置为短于 1 秒的超时时限, 但 Kubernetes 不支持任何更短的时间间隔。超时时限不必是整数的秒数。
  3. Kubernetes 项目建议将 WatchdogSec 时限设置为大约 15 秒。 系统支持超过 10 分钟的时限设置,但明确推荐这样做。

示例配置

[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=https://kubernetes.io/docs/home/
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/bin/kubelet
# 配置看门狗的超时时限
WatchdogSec=30s
Restart=on-failure
StartLimitInterval=0
RestartSec=10

[Install]
WantedBy=multi-user.target

接下来

有关 systemd 配置的细节,请参阅 systemd 文档

9 - Seccomp 和 Kubernetes

Seccomp 表示安全计算(Secure Computing)模式,自 2.6.12 版本以来,一直是 Linux 内核的一个特性。 它可以用来沙箱化进程的权限,限制进程从用户态到内核态的调用。 Kubernetes 能使你自动将加载到节点上的 seccomp 配置文件应用到你的 Pod 和容器。

Seccomp 字段

特性状态: Kubernetes v1.19 (GA)

有四种方式可以为 Pod 指定 seccomp 配置文件:

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-containerinit-container 独立设置了 RuntimeDefault。 如果临时容器或 Init 容器没有明确设置 securityContext.seccompProfile 字段, 则此值将从 Pod 继承。同样的机制也适用于运行 Localhost 配置文件 my-profile.json 的容器。

一般来说,(临时)容器的字段优先级高于 Pod 层级的值,而未设置 seccomp 字段的容器则从 Pod 继承配置。

对于 seccompProfile.type,可以使用以下值:

Unconfined
工作负载在没有任何 seccomp 限制的情况下运行。
RuntimeDefault
容器运行时定义的默认 seccomp 配置文件被应用。这个默认的配置文件旨在提供一套强大的安全默认值,同时保持工作负载的功能不受影响。 不同的容器运行时及其版本之间的默认配置文件可能会有所不同, 例如在比较 CRI-Ocontainerd 的默认配置文件时就会发现不同。
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_THREADSCMP_ACT_KILL
仅杀死线程。
SCMP_ACT_TRAP
发送 SIGSYS 信号。
SCMP_ACT_NOTIFYSECCOMP_RET_USER_NOTIF
通知用户空间。
SCMP_ACT_TRACE
使用指定的值通知跟踪进程。
SCMP_ACT_LOG
在将操作记录到 syslog 或 auditd 之后,允许执行系统调用。

SCMP_ACT_NOTIFYSECCOMP_RET_USER_NOTIF 这类操作可能不被支持, 具体取决于所使用的容器运行时、OCI 运行时或 Linux 内核版本。也可能存在其他限制, 例如 SCMP_ACT_NOTIFY 不能用作 defaultAction 或用于某些系统调用(如 write)。 所有这些限制由 OCI 运行时 (runccrun) 或 libseccomp 所定义。

syscalls JSON 数组包含对象列表,每个对象通过系统调用的 names 引用系统调用。 例如,SCMP_ACT_ALLOW 操作可用于创建包含如上例所示的系统调用的白名单。 也可以使用 SCMP_ACT_ERRNO 操作定义另一个列表,但会有不同的返回值(errnoRet)。

你还可以指定传递给某些系统调用的参数(args)。有关这些高级用例的细节,请参见 OCI 运行时规范Seccomp Linux 内核文档

进一步阅读

10 - 节点状态

在 Kubernetes 中,节点的状态是管理 Kubernetes 集群的一个关键方面。在本文中,我们将简要介绍如何监控和维护节点状态以确保集群的健康和稳定。

节点状态字段

一个节点的状态包含以下信息:

你可以使用 kubectl 来查看节点状态和其他细节信息:

kubectl describe node <节点名称>

下面对输出的每个部分进行详细描述。

地址

这些字段的用法取决于你的云服务商或者物理机配置。

  • HostName:由节点的内核报告。可以通过 kubelet 的 --hostname-override 参数覆盖。
  • ExternalIP:通常是节点的可外部路由(从集群外可访问)的 IP 地址。
  • InternalIP:通常是节点的仅可在集群内部路由的 IP 地址。

状况

conditions 字段描述了所有 Running 节点的状况。状况的示例包括:

节点状况及每种状况适用场景的描述
节点状况 描述
Ready 如节点是健康的并已经准备好接收 Pod 则为 TrueFalse 表示节点不健康而且不能接收 Pod;Unknown 表示节点控制器在最近 node-monitor-grace-period 期间(默认 50 秒)没有收到节点的消息
DiskPressure True 表示节点存在磁盘空间压力,即磁盘可用量低,否则为 False
MemoryPressure True 表示节点存在内存压力,即节点内存可用量低,否则为 False
PIDPressure True 表示节点存在进程压力,即节点上进程过多;否则为 False
NetworkUnavailable True 表示节点网络配置不正确;否则为 False

在 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 保持 UnknownFalse 的时间长于 kube-controller-manager 的 NodeMonitorGracePeriod(默认为 50 秒)时, 会造成 Unknown 状态下为节点添加 node.kubernetes.io/unreachable 污点或在 False 状态下为节点添加 node.kubernetes.io/not-ready 污点。

这些污点会影响悬决的 Pod,因为调度器在将 Pod 分配到节点时会考虑节点的污点。 已调度到节点的当前 Pod 可能会由于施加的 NoExecute 污点被驱逐。 Pod 还可以设置容忍度, 使得这些 Pod 仍然能够调度到且继续运行在设置了特定污点的节点上。

进一步的细节可参阅基于污点的驱逐根据状况为节点设置污点

容量(Capacity)与可分配(Allocatable)

这两个值描述节点上的可用资源:CPU、内存和可以调度到节点上的 Pod 的个数上限。

capacity 块中的字段标示节点拥有的资源总量。 allocatable 块指示节点上可供普通 Pod 使用的资源量。

你可以通过学习如何在节点上预留计算资源 来进一步了解有关容量和可分配资源的信息。

信息(Info)

Info 指的是节点的一般信息,如内核版本、Kubernetes 版本(kubeletkube-proxy 版本)、 容器运行时详细信息,以及节点使用的操作系统。 kubelet 从节点收集这些信息并将其发布到 Kubernetes API。

声明式特性

特性状态: Kubernetes v1.35 (Alpha; (默认禁用))
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the NodeDeclaredFeatures feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

此字段列出了通过特性门控在节点的 kubelet 上当前已启用的特定 Kubernetes 特性。 kubelet 会将这些特性以字符串列表的形式报告到 Node 对象的 .status.declaredFeatures 字段中。

此字段用于记录正在积极开发的新特性; 已完成且不再需要特性门控的功能被视为基线功能,无需在此字段中声明。 这反映的是 Kubernetes 特性的启用情况,而非节点底层操作系统或内核的特性。

有关更多详细信息,请参阅节点声明特性

心跳

Kubernetes 节点发送的心跳帮助你的集群确定每个节点的可用性,并在检测到故障时采取行动。

对于节点,有两种形式的心跳:

与节点的 .status 更新相比,Lease 是一种轻量级资源。 使用 Lease 来表达心跳在大型集群中可以减少这些更新对性能的影响。

kubelet 负责创建和更新节点的 .status,以及更新它们对应的 Lease。

  • 当节点状态发生变化时,或者在配置的时间间隔内没有更新事件时,kubelet 会更新 .status.status 更新的默认间隔为 5 分钟(比节点不可达事件的 40 秒默认超时时间长很多)。
  • kubelet 会创建并每 10 秒(默认更新间隔时间)更新 Lease 对象。 Lease 的更新独立于节点的 .status 更新而发生。 如果 Lease 的更新操作失败,kubelet 会采用指数回退机制,从 200 毫秒开始重试, 最长重试间隔为 7 秒钟。

11 - Linux 节点的交换(Swap)行为

要允许 Kubernetes 工作负载在 Linux 节点上使用交换分区, 你必须禁用 kubelet 在检测到交换分区时失败的默认行为, 并指定内存交换行为为 LimitedSwap

可用的交换行为选项有:

NoSwap
(默认)在此节点上作为 Pod 运行的工作负载不会也不能使用交换分区。 然而,系统守护进程(包括 kubelet 本身!)等这类 Kubernetes 范围之外的进程可以利用交换分区。 这种行为有助于保护节点免受系统级别的内存峰值影响, 但这不能保护工作负载本身不受此类峰值的影响。
LimitedSwap
Kubernetes 工作负载可以使用交换内存,Pod 可用的交换量是自动确定的。

要了解更多,请阅读交换内存管理