Skip to content

Commit

Permalink
Merge pull request containerd#6019 from klihub/pr/proto/nri
Browse files Browse the repository at this point in the history
NRI: add support for NRI with extended scope.
  • Loading branch information
dmcgowan committed Nov 30, 2022
2 parents 9c9f564 + a0daf1c commit c469f67
Show file tree
Hide file tree
Showing 143 changed files with 16,056 additions and 10,203 deletions.
1 change: 1 addition & 0 deletions cmd/containerd/builtins/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
_ "github.com/containerd/containerd/gc/scheduler"
_ "github.com/containerd/containerd/leases/plugin"
_ "github.com/containerd/containerd/metadata/plugin"
_ "github.com/containerd/containerd/pkg/nri/plugin"
_ "github.com/containerd/containerd/runtime/restart/monitor"
_ "github.com/containerd/containerd/runtime/v2"
_ "github.com/containerd/containerd/services/containers"
Expand Down
2 changes: 1 addition & 1 deletion contrib/fuzz/cri_server_fuzzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func FuzzCRIServer(data []byte) int {
}
defer client.Close()

c, err := server.NewCRIService(criconfig.Config{}, client)
c, err := server.NewCRIService(criconfig.Config{}, client, nil)
if err != nil {
panic(err)
}
Expand Down
141 changes: 141 additions & 0 deletions docs/NRI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# NRI Support In Containerd

## Node Resource Interface

NRI, the Node Resource Interface, is a common framework for plugging
extensions into OCI-compatible container runtimes. It provides basic
mechanisms for plugins to track the state of containers and to make
limited changes to their configuration.

NRI itself is agnostic to the internal implementation details of any
container runtime. It provides an adaptation library which runtimes
use to integrate to and interact with NRI and plugins. In principle
any NRI plugin should be able to work with NRI-enabled runtimes.

For a detailed description of NRI and its capabilities please take a
look at the [NRI respository](https://github.com/containerd/nri).

## Containerd NRI Integration

<details>
<summary>see the containerd/NRI integration diagram</summary>
<img src="./containerd-nri-integration.png" title="Containerd/NRI Integration">
</details>

NRI support in containerd is split into two parts both logically and
physically. These parts are a common plugin (/nri/*) to integrate to
NRI and CRI-specific bits (/pkg/cri/server/nri-api) which convert
data between the runtime-agnostic NRI representation and the internal
representation of the CRI plugin.

### Containerd NRI Plugin

The containerd common NRI plugin implements the core logic of integrating
to and interacting with NRI. However, it does this without any knowledge
about the internal representation of containers or pods within containerd.
It defines an additional interface, Domain, which is used whenever the
internal representation of a container or pod needs to be translated to
the runtime agnostic NRI one, or when a configuration change requested by
an external NRI plugin needs to be applied to a container within containerd. `Domain` can be considered as a short-cut name for Domain-Namespace as Domain implements the functions the generic NRI interface needs to deal with pods and containers from a particular containerd namespace. As a reminder, containerd namespaces isolate state between clients of containerd. E.g. "k8s.io" for the kubernetes CRI clients, "moby" for docker clients, ... and "containerd" as the default for containerd/ctr.

### NRI Support for CRI Containers

The containerd CRI plugin registers itself as an above mentioned NRI
Domain for the "k8s.io" namespace, to allow container configuration to be customized by external
NRI plugins. Currently this Domain interface is only implemented for
the original CRI `pkg/cri/server` implementation. Implementing it for
the more recent experimental `pkg/cri/sbserver` implementation is on
the TODO list.

### NRI Support for Other Container 'Domains'

The main reason for this split of functionality is to allow
NRI plugins for other types of sandboxes and for other container clients other than just for CRI containers in the "k8s.io" namespace.

## Enabling NRI Support in Containerd

Enabling and disabling NRI support in containerd happens by enabling or
disabling the common containerd NRI plugin. The plugin, and consequently
NRI functionality, is disabled by default. It can be enabled by editing
the `[plugins."io.containerd.nri.v1.nri"]` section in the containerd
configuration file, which by default is `/etc/containerd/config.toml`,
and changing `disable = true` to `disable = false`. Once enabled, the
NRI section should look something like this:

```toml
[plugins."io.containerd.nri.v1.nri"]
config_file = "/etc/nri/nri.conf"
disable = false
plugin_path = "/opt/nri/plugins"
socket_path = "/var/run/nri.sock"
```

In addition to this, you need to put a runtime agnostic NRI configuration
file in place, to let NRI itself know that it is enabled. You can do this
by creating `/etc/nri/nri.conf` with the following content:

```yaml
disableConnections: false
```

This enables externally launched NRI plugins to connect and register
themselves.

There are two ways how an NRI plugin can be started. Plugins can be
pre-registered in which case they are automatically started when the NRI
adaptation is instantiated (or in our case when containerd is started).
Plugins can also be started by external means, for instance by systemd.

Pre-registering a plugin happens by placing a symbolic link to the plugin
executable into a well-known NRI-specific directory, `/opt/nri/plugins`
by default. A pre-registered plugin is started with a socket pre-connected
to NRI. Externally launched plugins connect to a well-known NRI-specific
socket, `/var/run/nri.sock` by default, to register themselves. The only
difference between pre-registered and externally launched plugins is how
they get started and connected to NRI. Once a connection is established
all plugins are identical.

NRI can be configured to disable connections from externally launched
plugins, in which case the well-known socket is not created at all. The
configuration fragment shown above ensures that external connections are
enabled regardless of the built-in NRI defaults. This is convenient for
testing as it allows one to connect, disconnect and reconnect plugins at
any time.

For more details about pre-registered and externally launched plugins

## Testing NRI Support in Containerd

You can verify that NRI integration is properly enabled and functional by
configuring containerd and NRI as described above, taking the NRI
logger plugin either from the NRI repository or
[this fork](https://github.com/klihub/nri/tree/pr/proto/draft/plugins/logger)
on github, compiling it and starting it up.

```bash
git clone https://github.com/klihub/nri
cd nri
git checkout pr/proto/draft
make
./build/bin/logger -idx 00
```

You should see the logger plugin receiving receiving a list of existing pods
and containers. If you then create or remove further pods and containers
using crictl or kubectl you should see detailed logs of the corresponding NRI
events printed by the logger.

## NRI Compatibility With v0.1.0 Plugins

You can enable backward compatibility with NRI v0.1.0 plugins using the
[v010-adapter plugin](https://github.com/klihub/nri/tree/pr/proto/draft/plugins/v010-adapter).

```bash
git clone https://github.com/klihub/nri
cd nri
git checkout pr/proto/draft
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
```
Binary file added docs/containerd-nri-integration.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 14 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ require (
github.com/containerd/go-cni v1.1.6
github.com/containerd/go-runc v1.0.0
github.com/containerd/imgcrypt v1.1.5-0.20220421044638-8ba028dca028
github.com/containerd/nri v0.1.0
// We need an NRI with the updated interface. We use a replace to
// divert it until the corresponding PR lands in the NRI repo.
github.com/containerd/nri v0.2.0
github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3
github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67
github.com/containerd/zfs v1.0.0
Expand Down Expand Up @@ -47,7 +49,10 @@ require (
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
github.com/opencontainers/runc v1.1.4
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417
github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb
// ATM the runtime-tools commit we need are beyond the latest tag.
// We use a replace to handle that until a new version is tagged.
github.com/opencontainers/runtime-tools v0.9.0
github.com/opencontainers/selinux v1.10.2
github.com/pelletier/go-toml v1.9.3
github.com/prometheus/client_golang v1.12.1
Expand Down Expand Up @@ -82,7 +87,6 @@ require (
require (
cloud.google.com/go/compute/metadata v0.2.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
Expand All @@ -106,7 +110,6 @@ require (
github.com/moby/spdystream v0.2.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/opencontainers/runtime-tools v0.0.0-20190417131837-cd1349b7c47e // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
Expand All @@ -117,9 +120,6 @@ require (
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect
go.opencensus.io v0.23.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.11.1 // indirect
Expand All @@ -131,7 +131,7 @@ require (
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
golang.org/x/tools v0.1.13-0.20221007141809-02bef08ac854 // indirect
golang.org/x/tools v0.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
Expand All @@ -141,3 +141,9 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

replace (
// Temporarily divert repo for updated/extended NRI.
github.com/containerd/nri => github.com/klihub/nri v0.0.0-20221122201439-2b09b4ad5cf3
github.com/opencontainers/runtime-tools => github.com/opencontainers/runtime-tools v0.0.0-20221026201742-946c877fa809
)

0 comments on commit c469f67

Please sign in to comment.