Skip to content

Commit

Permalink
add a doc for prefetch-nri-plugin
Browse files Browse the repository at this point in the history
1. specify the prefetch value with an URL
2. modified some Syntax errors
3. Modify the reading mode of configuration file
4. modify ci.yml and k8s-e2e.yml
  • Loading branch information
billie60 committed Oct 24, 2023
1 parent 2cc7d81 commit d585766
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 38 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ jobs:
- name: Build
run: |
# Download nydus components
NYDUS_VER=v$(curl --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' -s "https://api.github.com/repos/dragonflyoss/image-service/releases/latest" | jq -r .tag_name | sed 's/^v//')
# NYDUS_VER=v$(curl --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' -s "https://api.github.com/repos/dragonflyoss/image-service/releases/latest" | jq -r .tag_name | sed 's/^v//')
NYDUS_VER=v$(curl --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' -s "https://api.github.com/repos/dragonflyoss/nydus/releases/latest" | jq -r .tag_name | sed 's/^v//')
wget https://github.com/dragonflyoss/image-service/releases/download/$NYDUS_VER/nydus-static-$NYDUS_VER-linux-amd64.tgz
tar xzvf nydus-static-$NYDUS_VER-linux-amd64.tgz
mkdir -p /usr/bin
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/k8s-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
cp bin/containerd-nydus-grpc ./
cp misc/snapshotter/* ./
ls -tl ./
NYDUS_VER=v$(curl --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' -s "https://api.github.com/repos/dragonflyoss/image-service/releases/latest" | jq -r .tag_name | sed 's/^v//')
NYDUS_VER=v$(curl --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' -s "https://api.github.com/repos/dragonflyoss/nydus/releases/latest" | jq -r .tag_name | sed 's/^v//')
docker build --build-arg NYDUS_VER=${NYDUS_VER} -t local-dev:e2e .
## load local test image into kind node
Expand Down Expand Up @@ -97,7 +97,7 @@ jobs:
docker exec kind-control-plane systemctl restart containerd
- name: Install Nydus binaries and convert nydus image
run: |
NYDUS_VER=v$(curl --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' -s "https://api.github.com/repos/dragonflyoss/image-service/releases/latest" | jq -r .tag_name | sed 's/^v//')
NYDUS_VER=v$(curl --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' -s "https://api.github.com/repos/dragonflyoss/nydus/releases/latest" | jq -r .tag_name | sed 's/^v//')
wget -q https://github.com/dragonflyoss/image-service/releases/download/$NYDUS_VER/nydus-static-$NYDUS_VER-linux-amd64.tgz
tar xzf nydus-static-$NYDUS_VER-linux-amd64.tgz
sudo cp nydus-static/nydusify nydus-static/nydus-image /usr/local/bin/
Expand Down
60 changes: 36 additions & 24 deletions cmd/prefetchfiles-nri-plugin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"net"
"net/http"
"os"
"path/filepath"
"strings"

"github.com/containerd/nri/pkg/api"
Expand All @@ -32,14 +31,17 @@ const (
endpointPrefetch = "/api/v1/prefetch"
defaultEvents = "RunPodSandbox"
defaultSystemControllerAddress = "/run/containerd-nydus/system.sock"
defaultPrefetchConfigDir = "/etc/nydus"
nydusPrefetchAnnotation = "containerd.io/nydus-prefetch"
)

type PluginConfig struct {
SocketAddr string `toml:"socket_address"`
}

type PluginArgs struct {
PluginName string
PluginIdx string
SocketAddress string
PluginName string
PluginIdx string
Config PluginConfig
}

type Flags struct {
Expand All @@ -62,8 +64,8 @@ func buildFlags(args *PluginArgs) []cli.Flag {
&cli.StringFlag{
Name: "socket-addr",
Value: defaultSystemControllerAddress,
Usage: "unix domain socket address. If defined in the configuration file, there is no need to add ",
Destination: &args.SocketAddress,
Usage: "unix domain socket address.",
Destination: &args.Config.SocketAddr,
},
}
}
Expand Down Expand Up @@ -129,6 +131,30 @@ func (p *plugin) RunPodSandbox(pod *api.PodSandbox) error {

return nil
}
func (p *plugin) Configure(config, runtime, version string) (stub.EventMask, error) {
var cfg PluginConfig
log.Infof("got configuration data: %q from runtime %s %s", config, runtime, version)
if config == "" {
return p.mask, nil
}

tree, err := toml.Load(config)
if err != nil {
return 0, err
}
if err := tree.Unmarshal(&cfg); err != nil {
return 0, err
}
p.mask, err = api.ParseEventMask(defaultEvents)
if err != nil {
return 0, errors.Wrap(err, "parse events in configuration")
}

log.Infof("configuration: %#v", cfg)
globalSocket = cfg.SocketAddr

return p.mask, nil
}

func main() {

Expand All @@ -148,24 +174,10 @@ func main() {

log = logrus.StandardLogger()

configFileName := "prefetchConfig.toml"
configDir := defaultPrefetchConfigDir
configFilePath := filepath.Join(configDir, configFileName)

config, err := toml.LoadFile(configFilePath)
if err != nil {
log.Warnf("failed to read config file: %v", err)
}

configSocketAddrRaw := config.Get("file_prefetch.socket_address")
if configSocketAddrRaw != nil {
if configSocketAddr, ok := configSocketAddrRaw.(string); ok {
globalSocket = configSocketAddr
} else {
log.Warnf("failed to read config: 'file_prefetch.socket_address' is not a string")
}
if flags.Args.Config.SocketAddr != "" {
globalSocket = flags.Args.Config.SocketAddr
} else {
globalSocket = flags.Args.SocketAddress
globalSocket = defaultSystemControllerAddress
}

log.SetFormatter(&logrus.TextFormatter{
Expand Down
160 changes: 160 additions & 0 deletions docs/prefetchfiles-nri-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# User self-defined nydus image files prefetch
To improve the flexibility of nydus image files prefetch, for the k8s scenario, we can specify a prefetch files list when create a nydus daemon. The prefetch files list is user self-defined. Nydus-snapshotter has implemented a containerd NRI plugin to transmit the path of prefetch files list to nydus-snapshotter. The prefetch plugin requires NRI 2.0, which is available in containerd (>=v1.7.0). The prefetch plugin subscribes pod creation event, obtains the URL address containing the content of the files need to be prefetched, and forwards it to `nydus-snapshotter`. The `nydus-snapshotter` reads the data through the URL and stores it locally. Then when `nydusd` starts, it will pull the files defined in the prefetch files list through lazy loading. This allows the pull of the prefetch files to be done during container creation rather than image convert, improving the flexibility of file prefetching.

## Requirements

- [NRI 2.0](https://github.com/containerd/nri): Which has been integrated into containerd since [v1.7.0](https://github.com/containerd/containerd/tree/v1.7.0-beta.1).

## Workflow

1. Add information such as image reference and URL address containing prefetch files to annotations in pod configuration file.
2. Run the prefetch plugin to monitor RunPodSandbox events.
3. The prefetch plugin fetches image reference and URL and forwards them to nydus-snapshotter.
4. Nydus-snapshotter specifies the prefetch list when starting nydus daemon.
5. Nydusd completes the mounting of the nydus image.





## Modify configuration file

Modify containerd's toml configuration file to enable NRI.
```console
sudo tee -a /etc/containerd/config.toml <<- EOF
[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"
EOF
```
Containerd will load all NRI plugins in the `plugin_path` directory on startup. If you want to start an NRI plugin manually, please add the following configuration to allow other NRI plugins to connect via `socket_path`.

```console
sudo tee /etc/nri/nri.conf <<- EOF
disableConnections: false
EOF
```

Restart the containerd service.

```console
sudo systemctl restart containerd
```
If you want to start the plugin using `pre-connection` mode, that is, `disableConnections: true`. You need to write a configuration file and place the plugin's binary file and configuration file in the correct directories. Here is an example of configuration file:
```console
sudo tee prefetchConfig.conf <<- EOF
# unix domain socket address
socket_address = "/run/containerd-nydus/system.sock"
EOF
```
Then move the files to the correct directories and set permissions.
```console
go build
sudo install -D -m 755 ./prefetchfiles-nri-plugin /opt/nri/plugins/03-prefetchfiles-nri-plugin
sudo install -D -m 755 ./prefetchfiles-nri-plugin.conf /etc/nri/conf.d/03-prefetchfiles-nri-plugin.conf
```
When manually starting the prefetch NRI plugin, the socket address can be modified through the command line parameter `socket-addr`.



After start the prefetch plugin, it will monitor pod creation events. Note that NRI plugin can only be called from containerd/CRI. So creation a pod using crictl as below.
```console
sudo tee pod.yaml <<- EOF
kind: pod
metadata:
name: wordpress-sandbox
namespace: default
attempt: 1
uid: hdishd83djaidwnduwk28bcsb
log_directory: /tmp
annotations:
containerd.io/nydus-prefetch: |
[
{"image": "dockerhub.kubekey.local/dfns/wordpress:nydus_latest", "prefetch": "http://example.com/api/v1/resource/wordpress"}
]

linux: {}

EOF

crictl runp pod.yaml
```
The files that require prefetching are written in a URL, and `nydus-snapshoter` will read the prefetch list based on the URL address and transfer it to a local text file. The specific content of the prefetch files can be customized by the user.
`http://example.com/api/v1/resource/wordpress` is just an example of URL address, which needs to be replaced with a real URL during actual operation. The following is an example of some prefetch files in URL:
```console
/usr/bin/env
/lib/x86_64-linux-gnu/ld-2.31.so
/etc/ld.so.cache
/lib/x86_64-linux-gnu/libc-2.31.so
/bin/bash
/lib/x86_64-linux-gnu/libtinfo.so.6.2
/lib/x86_64-linux-gnu/libdl-2.31.so
/etc/nsswitch.conf
```

The prefetching NRI plugin also supports the case where the pod configuration file contains multiple containers. In this case, the definition of pod-mutlicontainers.yaml is as follows:


```console
sudo tee pod-mutlicontainers.yaml <<- EOF
apiVersion: v1
kind: Pod
metadata:
name: multi-containers-pod
namespace: default
attempt: 1
uid: hdishd83djaidwnduwk28bcsb
log_directory: /tmp
annotations:
containerd.io/nydus-prefetch: |
[
{"image": "dockerhub.kubekey.local/dfns/busybox:nydus_latest", "prefetch": "http://example.com/api/v1/resource/busybox"},
{"image": "dockerhub.kubekey.local/dfns/ubuntu:nydus_latest", "prefetch": "http://example.com/api/v1/resource/ubuntu"},
{"image": "dockerhub.kubekey.local/dfns/wordpress:nydus_latest", "prefetch": "http://example.com/api/v1/resource/wordpress"}
]

linux: {}

spec:
containers:
- name: container-1
image: dockerhub.kubekey.local/dfns/busybox:nydus_latest
command: ["ls"]
- name: container-2
image: dockerhub.kubekey.local/dfns/ubuntu:nydus_latest
command: ["ls"]
- name: container-3
image: dockerhub.kubekey.local/dfns/wordpress:nydus_latest
command: ["ls"]
EOF
```



Note that the naming of keys in annotations is fixed, and the values in annotations are user self-defined.
After creating a pod, `nydus-snapshotter` will store the image references and paths of the prefetch list.

## Nydus-snapshotter starts nydusd
Nydusd daemon will start when the container is created. We start a container like below.
```console
sudo tee wordpress.yaml <<- EOF
metadata:
name: wordpress
image:
image: dockerhub.kubekey.local/dfns/wordpress:nydus_latest
log_path: wordpress.0.log
linux: {}
EOF

crictl pull dockerhub.kubekey.local/dfns/wordpress:nydus_latest
crictl create <pod_id> wordpress.yaml pod.yaml
```

Then nydus-snapshotter will start a daemon by command as follows.
```editorconfig
/usr/local/bin/nydusd fuse --thread-num 4 --config /var/lib/containerd-nydus/config/cjmnum3c3al8js5p3740/config.json --bootstrap /var/lib/containerd-nydus/snapshots/22/fs/image/image.boot --mountpoint /var/lib/containerd-nydus/snapshots/22/mnt --apisock /var/lib/containerd-nydus/socket/cjmnum3c3al8js5p3740/api.sock --log-level info --log-rotation-size 100 --prefetch-files /etc/nydus/PrefetchFiles/dockerhub.kubekey.local@dfns@wordpress:nydus_latest
```

According to the parameter `--prefetch-files`, we have implemented file prefetching through lazy loading.
10 changes: 6 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,20 @@ require (
k8s.io/apimachinery v0.26.2
k8s.io/client-go v0.26.2
k8s.io/cri-api v0.27.0-alpha.3
)

require github.com/freddierice/go-losetup v0.0.0-20220711213114-2a14873012db // indirect
)

require (
github.com/cilium/ebpf v0.9.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/frankban/quicktest v1.14.4 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
)

require github.com/freddierice/go-losetup v0.0.0-20220711213114-2a14873012db

require github.com/frankban/quicktest v1.14.4 // indirect

require (
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
Expand Down Expand Up @@ -155,7 +157,7 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.90.1 // indirect
k8s.io/kube-openapi v0.0.0-20230308215209-15aac26d736a // indirect
k8s.io/utils v0.0.0-20230308161112-d77c459e9343 // indirect
k8s.io/utils v0.0.0-20230308161112-d77c459e9343
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,6 @@ github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/freddierice/go-losetup v0.0.0-20220711213114-2a14873012db h1:StM6A9LvaVrFS2chAGcfRVDoBB6rHYPIGJ3GknpB25c=
github.com/freddierice/go-losetup v0.0.0-20220711213114-2a14873012db/go.mod h1:pwuQfHWn6j2Fpl2AWw/bPLlKfojHxIIEa5TeKIgDFW4=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
Expand Down
3 changes: 3 additions & 0 deletions misc/example/prefetchfiles-nri-plugin.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# unix domain socket address
socket_address = "/run/containerd-nydus/system.sock"

3 changes: 0 additions & 3 deletions misc/nri-prefetch/prefetchConfig.toml

This file was deleted.

2 changes: 1 addition & 1 deletion pkg/filesystem/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import (
"os"
"path"

snpkg "github.com/containerd/containerd/pkg/snapshotters"
"github.com/mohae/deepcopy"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"

"github.com/containerd/containerd/log"
snpkg "github.com/containerd/containerd/pkg/snapshotters"
"github.com/containerd/containerd/snapshots"
"github.com/containerd/containerd/snapshots/storage"

Expand Down
Loading

0 comments on commit d585766

Please sign in to comment.