Skip to content

Commit

Permalink
nri-plugin: file prefetching
Browse files Browse the repository at this point in the history
1. move prefetchfiles out of States struct
2. use go-toml package to read configuration file
3. make sure every container can get correct prefetchfiles
  • Loading branch information
billie60 committed Aug 15, 2023
1 parent a6f4457 commit ea50514
Show file tree
Hide file tree
Showing 12 changed files with 906 additions and 24 deletions.
222 changes: 222 additions & 0 deletions cmd/prefetchfiles-nri-plugin/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
/*
* Copyright (c) 2023. Nydus Developers. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/

package main

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"log/syslog"
"net"
"net/http"
"os"
"path/filepath"

"github.com/containerd/nri/pkg/api"
"github.com/containerd/nri/pkg/stub"
"github.com/pelletier/go-toml"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"

"github.com/containerd/nydus-snapshotter/pkg/errdefs"
"github.com/containerd/nydus-snapshotter/pkg/prefetch"
"github.com/containerd/nydus-snapshotter/version"
)

const (
endpointPrefetch = "/api/v1/prefetch"
defaultEvents = "RunPodSandbox"
defaultSystemControllerAddress = "/run/containerd-nydus/system.sock"
nydusPrefetchAnnotation = "containerd.io/nydus-prefetch"
imageAddressAnnotation = "containerd.io/nydus-image-reference"
)

type PluginArgs struct {
PluginName string
PluginIdx string
SocketAddress string
}

type Flags struct {
Args *PluginArgs
Flag []cli.Flag
}

func buildFlags(args *PluginArgs) []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "name",
Usage: "plugin name to register to NRI",
Destination: &args.PluginName,
},
&cli.StringFlag{
Name: "idx",
Usage: "plugin index to register to NRI",
Destination: &args.PluginIdx,
},
&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,
},
}
}

func NewPluginFlags() *Flags {
var args PluginArgs
return &Flags{
Args: &args,
Flag: buildFlags(&args),
}
}

type plugin struct {
stub stub.Stub
mask stub.EventMask
}

var (
globalSocket string
log *logrus.Logger
logWriter *syslog.Writer
)

// sendDataOverHTTP sends the prefetch data to the specified endpoint over HTTP using a Unix socket.
func sendDataOverHTTP(data prefetch.MessagePrefetch, endpoint, sock string) error {
url := fmt.Sprintf("http://unix%s", endpoint)

body, err := json.Marshal(data)
if err != nil {
return err
}

req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(body))
if err != nil {
return err
}

client := &http.Client{
Transport: &http.Transport{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", sock)
},
},
}
resp, err := client.Do(req)
if err != nil {
return err
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to send data, status code: %d", resp.StatusCode)
}
resp.Body.Close()

return nil
}

func (p *plugin) RunPodSandbox(pod *api.PodSandbox) error {
prefetchList, ok := pod.Annotations[nydusPrefetchAnnotation]
if !ok {
return nil
}

imageAddress, ok := pod.Annotations[imageAddressAnnotation]
if !ok {
return nil
}
msg := prefetch.MessagePrefetch{
ImageReference: imageAddress,
PrefetchFiles: prefetchList,
}

err := sendDataOverHTTP(msg, endpointPrefetch, globalSocket)
if err != nil {
log.Errorf("failed to send data: %v\n", err)
return err
}

return nil
}

func main() {

flags := NewPluginFlags()

app := &cli.App{
Name: "prefetch-nri-plugin",
Usage: "NRI plugin for obtaining and transmitting prefetch files path",
Version: version.Version,
Flags: flags.Flag,
HideVersion: true,
Action: func(c *cli.Context) error {
var (
opts []stub.Option
err error
)

log = logrus.StandardLogger()

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

config, err := toml.LoadFile(configFilePath)
if err != nil {
log.Warnf("failed to read config file: %v", err)
}
if configSocketAddr := config.Get("file_prefetch.socket_address").(string); configSocketAddr != "" {
globalSocket = configSocketAddr
} else {
globalSocket = flags.Args.SocketAddress
}

log.SetFormatter(&logrus.TextFormatter{
PadLevelText: true,
})
logWriter, err = syslog.New(syslog.LOG_INFO, "prefetch-nri-plugin")

if err == nil {
log.SetOutput(io.MultiWriter(os.Stdout, logWriter))
}

if flags.Args.PluginName != "" {
opts = append(opts, stub.WithPluginName(flags.Args.PluginName))
}
if flags.Args.PluginIdx != "" {
opts = append(opts, stub.WithPluginIdx(flags.Args.PluginIdx))
}

p := &plugin{}

if p.mask, err = api.ParseEventMask(defaultEvents); err != nil {
log.Fatalf("failed to parse events: %v", err)
}

if p.stub, err = stub.New(p, opts...); err != nil {
log.Fatalf("failed to create plugin stub: %v", err)
}

err = p.stub.Run(context.Background())
if err != nil {
return errors.Wrap(err, "plugin exited")
}
return nil
},
}
if err := app.Run(os.Args); err != nil {

if errdefs.IsConnectionClosed(err) {
log.Info("prefetch NRI plugin exited")
} else {
log.WithError(err).Fatal("failed to start prefetch NRI plugin")
}
}
}
3 changes: 3 additions & 0 deletions cmd/prefetchfiles-nri-plugin/prefetchConfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[file_prefetch]
# This is used to configure the socket address for the file prefetch.
socket_address = "/run/containerd-nydus/system.sock"
3 changes: 2 additions & 1 deletion config/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import (
"time"

"github.com/containerd/containerd/log"
"github.com/pkg/errors"

"github.com/containerd/nydus-snapshotter/internal/logging"
"github.com/containerd/nydus-snapshotter/pkg/utils/mount"
"github.com/pkg/errors"
)

var (
Expand Down
71 changes: 57 additions & 14 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ require (
github.com/containerd/nri v0.3.0
github.com/containerd/stargz-snapshotter v0.14.3
github.com/containerd/stargz-snapshotter/estargz v0.14.3
github.com/containers/ocicrypt v1.1.7
github.com/docker/cli v23.0.1+incompatible
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
github.com/google/go-containerregistry v0.13.0
Expand All @@ -32,21 +33,63 @@ require (
github.com/prometheus/client_model v0.3.0
github.com/rs/xid v1.4.0
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.2
github.com/stretchr/testify v1.8.3
github.com/urfave/cli/v2 v2.25.0
go.etcd.io/bbolt v1.3.7
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
golang.org/x/net v0.8.0
golang.org/x/net v0.10.0
golang.org/x/sync v0.1.0
golang.org/x/sys v0.6.0
google.golang.org/grpc v1.53.0
golang.org/x/sys v0.10.0
google.golang.org/grpc v1.55.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gotest.tools v2.2.0+incompatible
k8s.io/api v0.26.2
k8s.io/apimachinery v0.26.2
k8s.io/client-go v0.26.2
k8s.io/cri-api v0.27.0-alpha.3
github.com/containers/ocicrypt v1.1.7
)

require (
cloud.google.com/go v0.110.0 // indirect
cloud.google.com/go/compute v1.19.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/firestore v1.9.0 // indirect
cloud.google.com/go/longrunning v0.4.1 // indirect
github.com/armon/go-metrics v0.4.0 // indirect
github.com/cilium/ebpf v0.9.1 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/google/s2a-go v0.1.3 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/googleapis/gax-go/v2 v2.8.0 // indirect
github.com/hashicorp/consul/api v1.20.0 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/serf v0.10.1 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/sagikazarmark/crypt v0.10.0 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/viper v1.16.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
go.etcd.io/etcd/api/v3 v3.5.9 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect
go.etcd.io/etcd/client/v2 v2.305.7 // indirect
go.etcd.io/etcd/client/v3 v3.5.9 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.122.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)

require (
Expand Down Expand Up @@ -112,6 +155,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/moby/locker v1.0.1
github.com/moby/sys/mountinfo v0.6.2 // indirect
Expand All @@ -128,21 +172,25 @@ require (
github.com/prometheus/procfs v0.9.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
github.com/vbatts/tar-split v0.11.2 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/mod v0.9.0
golang.org/x/oauth2 v0.6.0 // indirect
golang.org/x/term v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/term v0.10.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.90.1 // indirect
Expand All @@ -151,11 +199,6 @@ require (
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
github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 // indirect
golang.org/x/crypto v0.1.0 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
)

retract (
Expand Down
Loading

0 comments on commit ea50514

Please sign in to comment.