Skip to content

Commit 0a10755

Browse files
authored
Merge pull request #178 from chrishenzie/revert-pr-154
Revert "move packages related to v0.1.0 to the plugins/v010-adapter"
2 parents f837b36 + e5b126b commit 0a10755

File tree

10 files changed

+426
-39
lines changed

10 files changed

+426
-39
lines changed

README-v0.1.0.md

Lines changed: 110 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,110 @@
1-
original v0.1.0 CLI invoke style version of NRI has been moved
2-
[v0.1.0 docs](/plugins/v010-adapter/0.1.0/README.md)
1+
# nri - Node Resource Interface
2+
3+
*This version of NRI is supported through the included v010-adapter plugin.*
4+
5+
This project is a WIP for a new, CNI like, interface for managing resources on a node for Pods and Containers.
6+
7+
## Documentation
8+
9+
The basic interface, concepts and plugin design of the Container Network Interface (CNI) is an elegant way to handle multiple implementations of the network stack for containers.
10+
This concept can be used for additional interfaces to customize a container's runtime environment.
11+
This proposal covers a new interface for resource management on a node with a structured API and plugin design for containers.
12+
13+
## Lifecycle
14+
15+
The big selling point for CNI is that it has a structured interface for modifying the network namespace for a container.
16+
This is different from generic hooks as they lack a type safe API injected into the lifecycle of a container.
17+
The lifecycle point that CNI and NRI plugins will be injected into is the point between `Create` and `Start` of the container's init process.
18+
19+
`Create->NRI->Start`
20+
21+
## Configuration
22+
23+
Configuration is split into two parts. One is the payload that is specific to a plugin invocation while the second is the host level configuration and options that specify what plugins to run and provide additional configuration to a plugin.
24+
25+
### Filepath and Binaries
26+
27+
Plugin binary paths can be configured via the consumer but will default to `/opt/nri/bin`.
28+
Binaries are named with their type as the binary name, same as the CNI plugin naming scheme.
29+
30+
### Host Level Config
31+
32+
The config's default location will be `/etc/nri/resource.d/*.conf`.
33+
34+
```json
35+
{
36+
"version": "0.1",
37+
"plugins": [
38+
{
39+
"type": "konfine",
40+
"conf": {
41+
"systemReserved": [0, 1]
42+
}
43+
},
44+
{
45+
"type": "clearcfs"
46+
}
47+
]
48+
}
49+
```
50+
51+
### Input
52+
53+
Input to a plugin is provided via `STDIN` as a `json` payload.
54+
55+
```json
56+
{
57+
"version": "0.1",
58+
"state": "create",
59+
"id": "redis",
60+
"pid": 1234,
61+
"spec": {
62+
"resources": {},
63+
"cgroupsPath": "default/redis",
64+
"namespaces": {
65+
"pid": "/proc/44/ns/pid",
66+
"mount": "/proc/44/ns/mnt",
67+
"net": "/proc/44/ns/net"
68+
},
69+
"annotations": {
70+
"qos.class": "ls"
71+
}
72+
}
73+
}
74+
```
75+
76+
### Output
77+
78+
```json
79+
{
80+
"version": "0.1",
81+
"state": "create",
82+
"id": "redis",
83+
"pid": 1234,
84+
"cgroupsPath": "qos-ls/default/redis"
85+
}
86+
```
87+
88+
## Commands
89+
90+
* Invoke - provides invocations into different lifecycle changes of a container
91+
- states: `setup|pause|resume|update|delete`
92+
93+
## Packages
94+
95+
A Go based API and client package will be created for both producers of plugins and consumers, commonly being the container runtime (containerd).
96+
97+
### Sample Plugin
98+
99+
* [clearcfs](examples/clearcfs/main.go)
100+
101+
## Project details
102+
103+
nri is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
104+
As a containerd sub-project, you will find the:
105+
106+
* [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md),
107+
* [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS),
108+
* and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md)
109+
110+
information in our [`containerd/project`](https://github.com/containerd/project) repository.

README.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,25 @@ The goal is to enable NRI support in the most commonly used OCI runtimes,
2323
[containerd](https://github.com/containerd/containerd) and
2424
[CRI-O](https://github.com/cri-o/cri-o).
2525

26-
### Plugins
27-
Plugins in NRI are daemon-like entities. A single instance of a plugin is
28-
responsible for handling the full stream of NRI events and requests.
29-
A unix-domain socket is used as the transport for communication.
26+
## Background
27+
28+
The revisited API is a major rewrite of NRI. It changes the scope of NRI
29+
and how it gets integrated into runtimes. It reworks how plugins are
30+
implemented, how they communicate with the runtime, and what kind of
31+
changes they can make to containers.
3032

31-
NRI is defined as a formal, protobuf-based 'NRI plugin protocol' which is
32-
compiled into ttRPC bindings. This should result in improved communication
33-
efficiency with lower per-message overhead, and enable straightforward
34-
implementation of stateful NRI plugins.
33+
[NRI v0.1.0](README-v0.1.0.md) used an OCI hook-like one-shot plugin invocation
34+
mechanism where a separate instance of a plugin was spawned for every NRI
35+
event. This instance then used its standard input and output to receive a
36+
request and provide a response, both as JSON data.
37+
38+
Plugins in NRI are daemon-like entities. A single instance of a plugin is
39+
now responsible for handling the full stream of NRI events and requests. A
40+
unix-domain socket is used as the transport for communication. Instead of
41+
JSON requests and responses NRI is defined as a formal, protobuf-based
42+
'NRI plugin protocol' which is compiled into ttRPC bindings. This should
43+
result in improved communication efficiency with lower per-message overhead,
44+
and enable straightforward implementation of stateful NRI plugins.
3545

3646
## Components
3747

plugins/v010-adapter/0.1.0/client.go renamed to client.go

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525
"os/exec"
2626
"sync"
2727

28-
types "github.com/containerd/nri/plugins/v010-adapter/0.1.0/types/v1"
28+
types "github.com/containerd/nri/types/v1"
2929

3030
oci "github.com/opencontainers/runtime-spec/specs-go"
3131
)
@@ -42,6 +42,8 @@ const (
4242
var appendPathOnce sync.Once
4343

4444
// New nri client
45+
//
46+
// Deprecated: NRI 0.1.0-style plugins should only be used through the v010-adapter plugin
4547
func New() (*Client, error) {
4648
conf, err := loadConfig(DefaultConfPath)
4749
if err != nil {
@@ -60,12 +62,28 @@ func New() (*Client, error) {
6062
}, nil
6163
}
6264

65+
// Plugins returns a slice of the configured plugin names. This can be used by
66+
// the runtime to detect which plugins are configured.
67+
//
68+
// Deprecated: NRI 0.1.0-style plugins should only be used through the v010-adapter plugin
69+
func (c *Client) Plugins() []string {
70+
names := make([]string, 0)
71+
for _, p := range c.conf.Plugins {
72+
names = append(names, p.Type)
73+
}
74+
return names
75+
}
76+
6377
// Client for calling nri plugins
78+
//
79+
// Deprecated: NRI 0.1.0-style plugins should only be used through the v010-adapter plugin
6480
type Client struct {
6581
conf *types.ConfigList
6682
}
6783

6884
// Sandbox information
85+
//
86+
// Deprecated: NRI 0.1.0-style plugins should only be used through the v010-adapter plugin
6987
type Sandbox struct {
7088
// ID of the sandbox
7189
ID string
@@ -82,6 +100,8 @@ type process interface {
82100
}
83101

84102
// Task is a subset of containerd's Task interface.
103+
//
104+
// Deprecated: NRI 0.1.0-style plugins should only be used through the v010-adapter plugin
85105
type Task interface {
86106
process
87107

@@ -90,11 +110,15 @@ type Task interface {
90110
}
91111

92112
// Invoke the ConfList of nri plugins
113+
//
114+
// Deprecated: NRI 0.1.0-style plugins should only be used through the v010-adapter plugin
93115
func (c *Client) Invoke(ctx context.Context, task Task, state types.State) ([]*types.Result, error) {
94116
return c.InvokeWithSandbox(ctx, task, state, nil)
95117
}
96118

97119
// InvokeWithSandbox invokes the ConfList of nri plugins
120+
//
121+
// Deprecated: NRI 0.1.0-style plugins should only be used through the v010-adapter plugin
98122
func (c *Client) InvokeWithSandbox(ctx context.Context, task Task, state types.State, sandbox *Sandbox) ([]*types.Result, error) {
99123
if len(c.conf.Plugins) == 0 {
100124
return nil, nil
@@ -129,7 +153,7 @@ func (c *Client) InvokeWithSandbox(ctx context.Context, task Task, state types.S
129153
return r.Results, nil
130154
}
131155

132-
func (c *Client) invokePlugin(ctx context.Context, name string, r *types.Request) (*types.Result, error) {
156+
func (c *Client) invokePlugin(ctx context.Context, name string, r *types.Request) (*types.Result, error) { //nolint:staticcheck
133157
payload, err := json.Marshal(r)
134158
if err != nil {
135159
return nil, err
@@ -154,28 +178,28 @@ func (c *Client) invokePlugin(ctx context.Context, name string, r *types.Request
154178
return nil, err
155179
}
156180
}
157-
var result types.Result
181+
var result types.Result //nolint:staticcheck
158182
if err := json.Unmarshal(out, &result); err != nil {
159183
return nil, fmt.Errorf("failed to unmarshal plugin output %s: %w", msg, err)
160184
}
161-
if result.Err() != nil {
162-
return nil, result.Err()
185+
if result.Err() != nil { //nolint:staticcheck
186+
return nil, result.Err() //nolint:staticcheck
163187
}
164188
return &result, nil
165189
}
166190

167-
func loadConfig(path string) (*types.ConfigList, error) {
191+
func loadConfig(path string) (*types.ConfigList, error) { //nolint:staticcheck
168192
f, err := os.Open(path)
169193
if err != nil {
170194
// if we don't have a config list on disk, create a new one for use
171195
if os.IsNotExist(err) {
172-
return &types.ConfigList{
196+
return &types.ConfigList{ //nolint:staticcheck
173197
Version: Version,
174198
}, nil
175199
}
176200
return nil, err
177201
}
178-
var c types.ConfigList
202+
var c types.ConfigList //nolint:staticcheck
179203
err = json.NewDecoder(f).Decode(&c)
180204
f.Close()
181205
if err != nil {
@@ -184,8 +208,8 @@ func loadConfig(path string) (*types.ConfigList, error) {
184208
return &c, nil
185209
}
186210

187-
func createSpec(spec *oci.Spec) (*types.Spec, error) {
188-
s := types.Spec{
211+
func createSpec(spec *oci.Spec) (*types.Spec, error) { //nolint:staticcheck
212+
s := types.Spec{ //nolint:staticcheck
189213
Namespaces: make(map[string]string),
190214
Annotations: spec.Annotations,
191215
}

examples/clearcfs/main.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"os"
23+
24+
"github.com/containerd/cgroups"
25+
"github.com/containerd/nri/skel"
26+
types "github.com/containerd/nri/types/v1"
27+
"github.com/opencontainers/runtime-spec/specs-go"
28+
"github.com/sirupsen/logrus"
29+
)
30+
31+
// clearCFS clears any cfs quotas for the containers
32+
type clearCFS struct {
33+
}
34+
35+
func (c *clearCFS) Type() string {
36+
return "clearcfs"
37+
}
38+
39+
func (c *clearCFS) Invoke(ctx context.Context, r *types.Request) (*types.Result, error) {
40+
result := r.NewResult(c.Type())
41+
42+
if r.State != types.Create {
43+
return result, nil
44+
}
45+
46+
switch r.Spec.Annotations["qos.class"] {
47+
case "ls":
48+
logrus.Debugf("clearing cfs for %s", r.ID)
49+
control, err := cgroups.Load(cgroups.V1, cgroups.StaticPath(r.Spec.CgroupsPath))
50+
if err != nil {
51+
return nil, err
52+
}
53+
54+
quota := int64(-1)
55+
return result, control.Update(&specs.LinuxResources{
56+
CPU: &specs.LinuxCPU{
57+
Quota: &quota,
58+
},
59+
})
60+
}
61+
return result, nil
62+
}
63+
64+
func main() {
65+
ctx := context.Background()
66+
if err := skel.Run(ctx, &clearCFS{}); err != nil {
67+
fmt.Fprintf(os.Stderr, "%s", err)
68+
os.Exit(1)
69+
}
70+
}

examples/go.mod

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module github.com/containerd/nri/examples
2+
3+
go 1.22.0
4+
5+
require (
6+
github.com/containerd/cgroups v1.0.3
7+
github.com/containerd/nri v0.1.0
8+
github.com/opencontainers/runtime-spec v1.1.0
9+
github.com/sirupsen/logrus v1.9.3
10+
)
11+
12+
require (
13+
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
14+
github.com/docker/go-units v0.4.0 // indirect
15+
github.com/godbus/dbus/v5 v5.0.4 // indirect
16+
github.com/gogo/protobuf v1.3.2 // indirect
17+
golang.org/x/sys v0.21.0 // indirect
18+
)
19+
20+
replace github.com/containerd/nri => ../

0 commit comments

Comments
 (0)