@@ -20,43 +20,32 @@ import (
20
20
"context"
21
21
"flag"
22
22
"fmt"
23
- "io"
24
23
golog "log"
25
24
"math/rand"
26
25
"net"
27
26
"net/http"
28
27
"os"
28
+ "os/exec"
29
29
"os/signal"
30
30
"path/filepath"
31
31
"time"
32
32
33
33
snapshotsapi "github.com/containerd/containerd/api/services/snapshots/v1"
34
34
"github.com/containerd/containerd/v2/contrib/snapshotservice"
35
35
"github.com/containerd/containerd/v2/core/snapshots"
36
- "github.com/containerd/containerd/v2/defaults"
37
- "github.com/containerd/containerd/v2/pkg/dialer"
38
36
"github.com/containerd/containerd/v2/pkg/sys"
39
37
"github.com/containerd/log"
40
- dbmetadata "github.com/containerd/stargz-snapshotter/cmd/containerd-stargz-grpc/db"
41
- ipfs "github.com/containerd/stargz-snapshotter/cmd/containerd-stargz-grpc/ipfs"
42
- "github.com/containerd/stargz-snapshotter/fs"
43
- "github.com/containerd/stargz-snapshotter/metadata"
44
- memorymetadata "github.com/containerd/stargz-snapshotter/metadata/memory"
38
+ "github.com/containerd/stargz-snapshotter/cmd/containerd-stargz-grpc/fsopts"
39
+ "github.com/containerd/stargz-snapshotter/fusemanager"
45
40
"github.com/containerd/stargz-snapshotter/service"
46
- "github.com/containerd/stargz-snapshotter/service/keychain/cri"
47
- "github.com/containerd/stargz-snapshotter/service/keychain/dockerconfig"
48
- "github.com/containerd/stargz-snapshotter/service/keychain/kubeconfig"
49
- "github.com/containerd/stargz-snapshotter/service/resolver"
41
+ "github.com/containerd/stargz-snapshotter/service/keychain/keychainconfig"
42
+ snbase "github.com/containerd/stargz-snapshotter/snapshot"
50
43
"github.com/containerd/stargz-snapshotter/version"
51
44
sddaemon "github.com/coreos/go-systemd/v22/daemon"
52
45
metrics "github.com/docker/go-metrics"
53
46
"github.com/pelletier/go-toml"
54
- bolt "go.etcd.io/bbolt"
55
47
"golang.org/x/sys/unix"
56
48
"google.golang.org/grpc"
57
- "google.golang.org/grpc/backoff"
58
- "google.golang.org/grpc/credentials/insecure"
59
- runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
60
49
)
61
50
62
51
const (
@@ -65,14 +54,19 @@ const (
65
54
defaultLogLevel = log .InfoLevel
66
55
defaultRootDir = "/var/lib/containerd-stargz-grpc"
67
56
defaultImageServiceAddress = "/run/containerd/containerd.sock"
57
+ defaultFuseManagerAddress = "/run/containerd-stargz-grpc/fuse-manager.sock"
58
+
59
+ fuseManagerBin = "stargz-fuse-manager"
60
+ fuseManagerAddress = "fuse-manager.sock"
68
61
)
69
62
70
63
var (
71
- address = flag .String ("address" , defaultAddress , "address for the snapshotter's GRPC server" )
72
- configPath = flag .String ("config" , defaultConfigPath , "path to the configuration file" )
73
- logLevel = flag .String ("log-level" , defaultLogLevel .String (), "set the logging level [trace, debug, info, warn, error, fatal, panic]" )
74
- rootDir = flag .String ("root" , defaultRootDir , "path to the root directory for this snapshotter" )
75
- printVersion = flag .Bool ("version" , false , "print the version" )
64
+ address = flag .String ("address" , defaultAddress , "address for the snapshotter's GRPC server" )
65
+ configPath = flag .String ("config" , defaultConfigPath , "path to the configuration file" )
66
+ logLevel = flag .String ("log-level" , defaultLogLevel .String (), "set the logging level [trace, debug, info, warn, error, fatal, panic]" )
67
+ rootDir = flag .String ("root" , defaultRootDir , "path to the root directory for this snapshotter" )
68
+ detachFuseManager = flag .Bool ("detach-fuse-manager" , false , "whether detach fusemanager or not" )
69
+ printVersion = flag .Bool ("version" , false , "print the version" )
76
70
)
77
71
78
72
type snapshotterConfig struct {
@@ -92,6 +86,11 @@ type snapshotterConfig struct {
92
86
93
87
// MetadataStore is the type of the metadata store to use.
94
88
MetadataStore string `toml:"metadata_store" default:"memory"`
89
+ // FuseManagerAddress is address for the fusemanager's GRPC server
90
+ FuseManagerAddress string `toml:"fusemanager_address"`
91
+
92
+ // FuseManagerPath is path to the fusemanager's executable
93
+ FuseManagerPath string `toml:"fusemanager_path"`
95
94
}
96
95
97
96
func main () {
@@ -140,51 +139,84 @@ func main() {
140
139
}
141
140
142
141
// Configure keychain
143
- credsFuncs := []resolver.Credential {dockerconfig .NewDockerconfigKeychain (ctx )}
144
- if config .Config .KubeconfigKeychainConfig .EnableKeychain {
145
- var opts []kubeconfig.Option
146
- if kcp := config .Config .KubeconfigKeychainConfig .KubeconfigPath ; kcp != "" {
147
- opts = append (opts , kubeconfig .WithKubeconfigPath (kcp ))
148
- }
149
- credsFuncs = append (credsFuncs , kubeconfig .NewKubeconfigKeychain (ctx , opts ... ))
142
+ keyChainConfig := keychainconfig.Config {
143
+ EnableKubeKeychain : config .Config .KubeconfigKeychainConfig .EnableKeychain ,
144
+ EnableCRIKeychain : config .Config .CRIKeychainConfig .EnableKeychain ,
145
+ KubeconfigPath : config .Config .KubeconfigKeychainConfig .KubeconfigPath ,
146
+ DefaultImageServiceAddress : defaultImageServiceAddress ,
147
+ ImageServicePath : config .CRIKeychainConfig .ImageServicePath ,
150
148
}
151
- if config .Config .CRIKeychainConfig .EnableKeychain {
152
- // connects to the backend CRI service (defaults to containerd socket)
153
- criAddr := defaultImageServiceAddress
154
- if cp := config .CRIKeychainConfig .ImageServicePath ; cp != "" {
155
- criAddr = cp
156
- }
157
- connectCRI := func () (runtime.ImageServiceClient , error ) {
158
- conn , err := newCRIConn (criAddr )
149
+
150
+ var rs snapshots.Snapshotter
151
+ if * detachFuseManager {
152
+ fmPath := config .FuseManagerPath
153
+ if fmPath == "" {
154
+ var err error
155
+ fmPath , err = exec .LookPath (fuseManagerBin )
159
156
if err != nil {
160
- return nil , err
157
+ log . G ( ctx ). WithError ( err ). Fatalf ( "failed to find fusemanager bin" )
161
158
}
162
- return runtime .NewImageServiceClient (conn ), nil
163
159
}
164
- f , criServer := cri .NewCRIKeychain (ctx , connectCRI )
165
- runtime .RegisterImageServiceServer (rpc , criServer )
166
- credsFuncs = append (credsFuncs , f )
167
- }
168
- fsOpts := []fs.Option {fs .WithMetricsLogLevel (log .InfoLevel )}
169
- if config .IPFS {
170
- fsOpts = append (fsOpts , fs .WithResolveHandler ("ipfs" , new (ipfs.ResolveHandler )))
171
- }
172
- mt , err := getMetadataStore (* rootDir , config )
173
- if err != nil {
174
- log .G (ctx ).WithError (err ).Fatalf ("failed to configure metadata store" )
175
- }
176
- fsOpts = append (fsOpts , fs .WithMetadataStore (mt ))
177
- rs , err := service .NewStargzSnapshotterService (ctx , * rootDir , & config .Config ,
178
- service .WithCredsFuncs (credsFuncs ... ), service .WithFilesystemOptions (fsOpts ... ))
179
- if err != nil {
180
- log .G (ctx ).WithError (err ).Fatalf ("failed to configure snapshotter" )
160
+ fmAddr := config .FuseManagerAddress
161
+ if fmAddr == "" {
162
+ fmAddr = defaultFuseManagerAddress
163
+ }
164
+
165
+ if ! filepath .IsAbs (fmAddr ) {
166
+ log .G (ctx ).WithError (err ).Fatalf ("fuse manager address must be an absolute path: %s" , fmAddr )
167
+ }
168
+ err := fusemanager .StartFuseManager (ctx , fmPath , fmAddr , filepath .Join (* rootDir , "fusestore.db" ), * logLevel , filepath .Join (* rootDir , "stargz-fuse-manager.log" ))
169
+ if err != nil {
170
+ log .G (ctx ).WithError (err ).Fatalf ("failed to start fusemanager" )
171
+ }
172
+
173
+ fuseManagerConfig := fusemanager.Config {
174
+ Config : & config .Config ,
175
+ IPFS : config .IPFS ,
176
+ MetadataStore : config .MetadataStore ,
177
+ DefaultImageServiceAddress : defaultImageServiceAddress ,
178
+ }
179
+
180
+ fs , err := fusemanager .NewManagerClient (ctx , * rootDir , fmAddr , & fuseManagerConfig )
181
+ if err != nil {
182
+ log .G (ctx ).WithError (err ).Fatalf ("failed to configure fusemanager" )
183
+ }
184
+ rs , err = snbase .NewSnapshotter (ctx , filepath .Join (* rootDir , "snapshotter" ), fs , snbase .AsynchronousRemove )
185
+ if err != nil {
186
+ log .G (ctx ).WithError (err ).Fatalf ("failed to configure snapshotter" )
187
+ }
188
+ log .G (ctx ).Infof ("Start snapshotter with fusemanager mode" )
189
+ } else {
190
+ credsFuncs , err := keychainconfig .ConfigKeychain (ctx , rpc , & keyChainConfig )
191
+ if err != nil {
192
+ log .G (ctx ).WithError (err ).Fatalf ("failed to configure keychain" )
193
+ }
194
+
195
+ fsConfig := fsopts.Config {
196
+ EnableIpfs : config .IPFS ,
197
+ MetadataStore : config .MetadataStore ,
198
+ }
199
+ fsOpts , err := fsopts .ConfigFsOpts (ctx , * rootDir , & fsConfig )
200
+ if err != nil {
201
+ log .G (ctx ).WithError (err ).Fatalf ("failed to configure fs config" )
202
+ }
203
+
204
+ rs , err = service .NewStargzSnapshotterService (ctx , * rootDir , & config .Config ,
205
+ service .WithCredsFuncs (credsFuncs ... ), service .WithFilesystemOptions (fsOpts ... ))
206
+ if err != nil {
207
+ log .G (ctx ).WithError (err ).Fatalf ("failed to configure snapshotter" )
208
+ }
181
209
}
182
210
183
211
cleanup , err := serve (ctx , rpc , * address , rs , config )
184
212
if err != nil {
185
213
log .G (ctx ).WithError (err ).Fatalf ("failed to serve snapshotter" )
186
214
}
187
215
216
+ // TODO: In detach mode, rs is taken over by fusemanager,
217
+ // but client will send unmount request to fusemanager,
218
+ // and fusemanager need get mount info from local db to
219
+ // determine its behavior
188
220
if cleanup {
189
221
log .G (ctx ).Debug ("Closing the snapshotter" )
190
222
rs .Close ()
@@ -275,48 +307,3 @@ func serve(ctx context.Context, rpc *grpc.Server, addr string, rs snapshots.Snap
275
307
}
276
308
return false , nil
277
309
}
278
-
279
- const (
280
- memoryMetadataType = "memory"
281
- dbMetadataType = "db"
282
- )
283
-
284
- func getMetadataStore (rootDir string , config snapshotterConfig ) (metadata.Store , error ) {
285
- switch config .MetadataStore {
286
- case "" , memoryMetadataType :
287
- return memorymetadata .NewReader , nil
288
- case dbMetadataType :
289
- bOpts := bolt.Options {
290
- NoFreelistSync : true ,
291
- InitialMmapSize : 64 * 1024 * 1024 ,
292
- FreelistType : bolt .FreelistMapType ,
293
- }
294
- db , err := bolt .Open (filepath .Join (rootDir , "metadata.db" ), 0600 , & bOpts )
295
- if err != nil {
296
- return nil , err
297
- }
298
- return func (sr * io.SectionReader , opts ... metadata.Option ) (metadata.Reader , error ) {
299
- return dbmetadata .NewReader (db , sr , opts ... )
300
- }, nil
301
- default :
302
- return nil , fmt .Errorf ("unknown metadata store type: %v; must be %v or %v" ,
303
- config .MetadataStore , memoryMetadataType , dbMetadataType )
304
- }
305
- }
306
-
307
- func newCRIConn (criAddr string ) (* grpc.ClientConn , error ) {
308
- // TODO: make gRPC options configurable from config.toml
309
- backoffConfig := backoff .DefaultConfig
310
- backoffConfig .MaxDelay = 3 * time .Second
311
- connParams := grpc.ConnectParams {
312
- Backoff : backoffConfig ,
313
- }
314
- gopts := []grpc.DialOption {
315
- grpc .WithTransportCredentials (insecure .NewCredentials ()),
316
- grpc .WithConnectParams (connParams ),
317
- grpc .WithContextDialer (dialer .ContextDialer ),
318
- grpc .WithDefaultCallOptions (grpc .MaxCallRecvMsgSize (defaults .DefaultMaxRecvMsgSize )),
319
- grpc .WithDefaultCallOptions (grpc .MaxCallSendMsgSize (defaults .DefaultMaxSendMsgSize )),
320
- }
321
- return grpc .NewClient (dialer .DialAddress (criAddr ), gopts ... )
322
- }
0 commit comments