NRI 是节点资源接口(Node Resource Interface),它是一个通用框架,用于将扩展功能插入兼容 OCI 的容器运行时。它提供了插件跟踪容器状态并对其配置进行有限的更改改的基本机制。
NRI 本身与任何容器运行时的内部实现细节无关。它提供了一个适配库,运行时用来集成 NRI 和插件并与之交互。原则上任何 NRI 插件都应能与支持 NRI 的运行时协同工作。
有关 NRI 及其功能的详细说明,请参阅NRI 存储库。
containerd 中的 NRI 支持分为逻辑和物理两部分。这些部分是用于集成 NRI 和 CRI 特定位(/pkg/cri/server/nri-api)的通用插件 (/nri/*)。CRI 特定位/pkg/cri/server/nri-api)。用于运行时间无关的 NRI 表示法和 CRI 插件的内部表示之间的数据转换。
containerd 通用 NRI 插件实现了与 NRI 集成和与之交互的核心逻辑。不过,它是完全不了解容器或 pod 的内部表示。它定义了一个额外的接口 Domain,当容器或 pod 的内部表示需要转换为运行时不可知的 NRI 表示时,或者当外部 NRI 插件请求更改配置时、外部 NRI 插件所要求的配置更改需要应用到 containerd 中的容器时,就会用到这个接口。Domain
可以看作是 "Domain-Namespace "的快捷方式,因为 Domain 实现了通用 NRI 接口处理来自特定 containerd 命名空间的pod和容器所需的功能。需要提醒的是,containerd 命名空间隔离了containerd 客户端之间的状态。例如,kubernetes CRI 客户端使用 “k8s.io”,docker 客户端使用 “moby”,…而 containerd/ctr 默认使用 “containerd”。
containerd CRI 插件会将自己注册为上述 NRIDomain,以便容器配置可由外部NRI 插件来定义。目前,只有为最初的 CRI pkg/cri/server
完成了实现。对最新的CRI pkg/cri/server
的实现在TODO LIST上。
这种功能拆分的主要原因是为了允许 NRI 插件用于其他类型的沙箱和其他容器客户端,而不仅仅是用于 "k8s.io "命名空间中的 CRI 容器。
在 containerd 中启用和禁用 NRI 支持是通过启用或禁用启用或禁用通用的 containerd NRI 插件。该插件以及NRI 功能默认是禁用的。可以通过编辑配置文件中的"[plugins. “io.containerd.nri.v1.nri”]"部分来启用它。配置文件(默认配置文件为 /etc/containerd/config.toml
)中的并将 disable = true
更改为 disable = false
。启用后,
NRI 部分应该如下所示:
[plugins."io.containerd.nri.v1.nri"]
# 在 containerd 中启用 NRI 支持
disable = false
# 允许来自外部启动的 NRI 插件的连接。
disable_connections = false
# plugin_config_path 是搜索特定插件配置的目录.
plugin_config_path = "/etc/nri/conf.d"
# plugin_path 是在启动时搜索插件的目录。
plugin_path = "/opt/nri/plugins"
# plugin_registration_timeout 是连接后插件注册的超时时间。
plugin_registration_timeout = "5s"
# plugin_requst_timeout 是插件处理事件/请求的超时时间。
plugin_request_timeout = "2s"
# socket_path 是要创建供插件连接的 NRI 套接字的路径。
socket_path = "/var/run/nri/nri.sock"
启动 NRI 插件有两种方式。插件可以预先注册好在这种情况下,它们会在 NRI适配器实例化时(或者在我们的例子中,启动 containerd 时)自动启动。插件也可以通过外部方式启动,例如由 systemd 启动。
预注册插件的方法是防止一个可执行文件的符号链接到一个众所周知的 NRI 特定目录中,默认情况下是 /opt/nri/plugins
目录。预先注册的插件伴随着一个预先连接到NRI的套接字一起启动。外部启动的插件会连接到 NRI 专用的套接字(默认为 /var/run/nri/nri.sock
)来注册自己。预注册和外部启动插件的唯一区别在于它们是如何启动并连接到 NRI 的。一旦建立连接所有插件都是一样的。
可以对 NRI 进行配置,禁用来自外部启动的插件的连接。在这种情况下,根本不会创建众所周知的套接字。上图所示的配置片段可确保启用外部连接而与默认无关。这对于测试非常便利因为这样可以随时连接、断开和重新连接插件。
请注意,您不能在一个节点上运行两个启用了 NRI 的运行时,并使用相同的默认套接字配置。您需要禁用 NRI 或更改其中一个运行时中的NRI 套接字路径。
您可以通过以下方式验证 NRI 集成是否已正确启用并正常运行配置 containerd 和 NRI,并从 NRI 资源库获取 NRI日志记录器插件,编译并启动它。
git clone https://github.com/containerd/nri
cd nri
make
./build/bin/logger -idx 00
您应该会看到日志记录器插件正在接收现有 pod和容器的列表。如果使用 crictl 或 kubectl 创建或移除更多 pod 和容器,你就会看到日志记录器打印的相应 NRI事件的详细日志。
您可以使用v010-adapter 插件启用与 NRI v0.1.0 插件的向后兼容性。
git clone https://github.com/containerd/nri
cd nri
make
sudo cp build/bin/v010-adapter /usr/local/bin
sudo mkdir -p /opt/nri/plugins
sudo ln -s /usr/local/bin/v010-adapter /opt/nri/plugins/00-v010-adapter