diff --git a/cmd/soci-snapshotter-grpc/main.go b/cmd/soci-snapshotter-grpc/main.go index 6ce2ff2a8..f62f62b69 100644 --- a/cmd/soci-snapshotter-grpc/main.go +++ b/cmd/soci-snapshotter-grpc/main.go @@ -34,6 +34,7 @@ package main import ( "context" + "errors" "flag" "fmt" "io" @@ -43,6 +44,7 @@ import ( "os" "os/signal" "path/filepath" + "strings" "time" _ "net/http/pprof" @@ -66,6 +68,7 @@ import ( "github.com/containerd/containerd/snapshots" runtime_alpha "github.com/containerd/containerd/third_party/k8s.io/cri-api/pkg/apis/runtime/v1alpha2" "github.com/containerd/log" + "github.com/coreos/go-systemd/v22/activation" sddaemon "github.com/coreos/go-systemd/v22/daemon" metrics "github.com/docker/go-metrics" "github.com/sirupsen/logrus" @@ -252,7 +255,7 @@ func serve(ctx context.Context, rpc *grpc.Server, addr string, rs snapshots.Snap } // Listen and serve - l, err := net.Listen("unix", addr) + l, err := getListener(ctx, addr) if err != nil { return false, fmt.Errorf("error on listen socket %q: %w", addr, err) } @@ -337,3 +340,37 @@ func getCriConn(criAddr string) (*grpc.ClientConn, error) { } return grpc.Dial(dialer.DialAddress(criAddr), gopts...) } + +func getListener(ctx context.Context, address string) (net.Listener, error) { + protocol, addr, found := strings.Cut(address, "://") + if !found { + // The address doesn't start with a protocol, assume it's a path to a unix socket + return net.Listen("unix", address) + } + switch protocol { + case "unix": + return net.Listen(protocol, addr) + case "fd": + return listenFd(ctx) + default: + return nil, fmt.Errorf("unkown protocol for address %s", address) + } +} + +func listenFd(ctx context.Context) (net.Listener, error) { + listeners, err := activation.Listeners() + if err != nil { + return nil, err + } + if len(listeners) == 0 { + log.G(ctx).Info("Address was set to listen on a file descriptor, but no file descriptors were passed. Perhaps soci was launched directly without using systemd socket activation? Using the default address.") + return net.Listen("unix", defaultAddress) + } + if len(listeners) > 1 { + for _, socket := range listeners { + socket.Close() + } + return nil, errors.New("soci only supports a single systemd socket on activation") + } + return listeners[0], nil +} diff --git a/soci-snapshotter.service b/soci-snapshotter.service index 4a80f9b4d..961375c2e 100644 --- a/soci-snapshotter.service +++ b/soci-snapshotter.service @@ -34,7 +34,7 @@ Before=containerd.service [Service] Type=notify -ExecStart=/usr/local/bin/soci-snapshotter-grpc +ExecStart=/usr/local/bin/soci-snapshotter-grpc --address fd:// Restart=always RestartSec=5 diff --git a/soci-snapshotter.socket b/soci-snapshotter.socket new file mode 100644 index 000000000..e05d1c4d6 --- /dev/null +++ b/soci-snapshotter.socket @@ -0,0 +1,10 @@ +[Unit] +Description=soci snapshotter containerd plugin (socket) +Documentation=https://github.com/awslabs/soci-snapshotter + +[Socket] +ListenStream=/run/soci-snapshotter-grpc/soci-snapshotter-grpc.sock +SocketMode=0660 + +[Install] +WantedBy=sockets.target \ No newline at end of file