Skip to content

Commit e2bae7f

Browse files
committed
Support auto cleanup overlaybdX
1. support auto cleanup overlaybd after container removed by config option 'autoRemoveDev' 2. rename mode tag of rootfs as 'overlayfs/dir/dev' Signed-off-by: Yifan Yuan <tuji.yyf@alibaba-inc.com>
1 parent fd022b9 commit e2bae7f

File tree

4 files changed

+220
-53
lines changed

4 files changed

+220
-53
lines changed

cmd/overlaybd-snapshotter/main.go

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,14 @@ import (
3838

3939
const defaultConfigPath = "/etc/overlaybd-snapshotter/config.json"
4040

41-
type pluginConfig struct {
42-
Address string `json:"address"`
43-
Root string `json:"root"`
44-
LogLevel string `json:"verbose"`
45-
Mode string `json:"mode"` // fs, dir or dev
46-
}
47-
48-
var pconfig pluginConfig
41+
var pconfig *overlaybd.BootConfig
4942

5043
func parseConfig(fpath string) error {
5144
data, err := os.ReadFile(fpath)
5245
if err != nil {
5346
return errors.Wrapf(err, "failed to read plugin config from %s", fpath)
5447
}
55-
56-
if err := json.Unmarshal(data, &pconfig); err != nil {
48+
if err := json.Unmarshal(data, pconfig); err != nil {
5749
return errors.Wrapf(err, "failed to parse plugin config from %s", string(data))
5850
}
5951
return nil
@@ -62,26 +54,23 @@ func parseConfig(fpath string) error {
6254
// TODO: use github.com/urfave/cli
6355
func main() {
6456

57+
pconfig = overlaybd.DefaultBootConfig()
6558
if err := parseConfig(defaultConfigPath); err != nil {
6659
logrus.Error(err)
6760
os.Exit(1)
6861
}
69-
70-
if pconfig.Mode == "" {
71-
pconfig.Mode = "fs"
62+
if pconfig.LogReportCaller {
63+
logrus.SetReportCaller(true)
7264
}
73-
logrus.Infof("set mode: %s", pconfig.Mode)
65+
logrus.Infof("%+v", *pconfig)
7466

75-
if pconfig.LogLevel == "" {
76-
pconfig.LogLevel = "info"
77-
}
7867
if err := setLogLevel(pconfig.LogLevel); err != nil {
7968
logrus.Errorf("failed to set log level: %v", err)
8069
} else {
8170
logrus.Infof("set log level: %s", pconfig.LogLevel)
8271
}
8372

84-
sn, err := overlaybd.NewSnapshotter(pconfig.Root, pconfig.Mode)
73+
sn, err := overlaybd.NewSnapshotter(pconfig)
8574
if err != nil {
8675
logrus.Errorf("failed to init overlaybd snapshotter: %v", err)
8776
os.Exit(1)

pkg/snapshot/overlay.go

Lines changed: 94 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/containerd/containerd/snapshots"
3232
"github.com/containerd/containerd/snapshots/storage"
3333
"github.com/containerd/continuity/fs"
34+
"github.com/moby/locker"
3435
"github.com/pkg/errors"
3536
)
3637

@@ -136,11 +137,29 @@ const (
136137
)
137138

138139
const (
139-
roDir = iota // overlayfs as rootfs. upper + lower (overlaybd)
140-
rwDir // mount overlaybd as rootfs
141-
rwDev // use overlaybd directly
140+
roDir = "overlayfs" // overlayfs as rootfs. upper + lower (overlaybd)
141+
rwDir = "dir" // mount overlaybd as rootfs
142+
rwDev = "dev" // use overlaybd directly
142143
)
143144

145+
type BootConfig struct {
146+
Address string `json:"address"`
147+
Root string `json:"root"`
148+
LogLevel string `json:"verbose"`
149+
LogReportCaller bool `json:"logReportCaller"`
150+
Mode string `json:"mode"` // fs, dir or dev
151+
AutoRemoveDev bool `json:"autoRemoveDev"`
152+
}
153+
154+
func DefaultBootConfig() *BootConfig {
155+
return &BootConfig{
156+
LogLevel: "info",
157+
Mode: "overlayfs",
158+
LogReportCaller: false,
159+
AutoRemoveDev: false,
160+
}
161+
}
162+
144163
// SnapshotterConfig is used to configure the snapshotter instance
145164
type SnapshotterConfig struct {
146165
// OverlayBDUtilBinDir contains overlaybd-create/overlaybd-commit tools
@@ -189,47 +208,59 @@ type Opt func(config *SnapshotterConfig) error
189208
// #
190209
// - metadata.db
191210
type snapshotter struct {
192-
root string
193-
mode string
194-
config SnapshotterConfig
195-
ms *storage.MetaStore
196-
indexOff bool
211+
root string
212+
mode string
213+
config SnapshotterConfig
214+
metacopyOption string
215+
ms *storage.MetaStore
216+
indexOff bool
217+
autoRemoveDev bool
218+
219+
locker *locker.Locker
197220
}
198221

199222
// NewSnapshotter returns a Snapshotter which uses block device based on overlayFS.
200-
func NewSnapshotter(root string, mode string, opts ...Opt) (snapshots.Snapshotter, error) {
223+
func NewSnapshotter(bootConfig *BootConfig, opts ...Opt) (snapshots.Snapshotter, error) {
201224
config := defaultConfig
202225
for _, opt := range opts {
203226
if err := opt(&config); err != nil {
204227
return nil, err
205228
}
206229
}
207230

208-
if err := os.MkdirAll(root, 0700); err != nil {
231+
if err := os.MkdirAll(bootConfig.Root, 0700); err != nil {
209232
return nil, err
210233
}
211234

212-
ms, err := storage.NewMetaStore(filepath.Join(root, "metadata.db"))
235+
ms, err := storage.NewMetaStore(filepath.Join(bootConfig.Root, "metadata.db"))
213236
if err != nil {
214237
return nil, err
215238
}
216239

217-
if err := os.Mkdir(filepath.Join(root, "snapshots"), 0700); err != nil && !os.IsExist(err) {
240+
if err := os.Mkdir(filepath.Join(bootConfig.Root, "snapshots"), 0700); err != nil && !os.IsExist(err) {
218241
return nil, err
219242
}
220243

244+
metacopyOption := ""
245+
if _, err := os.Stat("/sys/module/overlay/parameters/metacopy"); err == nil {
246+
metacopyOption = "metacopy=on"
247+
}
248+
221249
// figure out whether "index=off" option is recognized by the kernel
222250
var indexOff bool
223251
if _, err = os.Stat("/sys/module/overlay/parameters/index"); err == nil {
224252
indexOff = true
225253
}
226254

227255
return &snapshotter{
228-
root: root,
229-
mode: mode,
230-
ms: ms,
231-
indexOff: indexOff,
232-
config: config,
256+
root: bootConfig.Root,
257+
mode: bootConfig.Mode,
258+
ms: ms,
259+
indexOff: indexOff,
260+
config: config,
261+
metacopyOption: metacopyOption,
262+
autoRemoveDev: bootConfig.AutoRemoveDev,
263+
locker: locker.New(),
233264
}, nil
234265
}
235266

@@ -301,9 +332,9 @@ func (o *snapshotter) Usage(ctx context.Context, key string) (snapshots.Usage, e
301332
return usage, nil
302333
}
303334

304-
func (o *snapshotter) getWritableType(ctx context.Context, id string, info snapshots.Info) (mode int) {
335+
func (o *snapshotter) getWritableType(ctx context.Context, id string, info snapshots.Info) (mode string) {
305336
defer func() {
306-
log.G(ctx).Infof("snapshot R/W label: %d", mode)
337+
log.G(ctx).Infof("snapshot R/W label: %s", mode)
307338
}()
308339
// check image type (OCIv1 or overlaybd)
309340
if id != "" {
@@ -315,7 +346,7 @@ func (o *snapshotter) getWritableType(ctx context.Context, id string, info snaps
315346
log.G(ctx).Debugf("empty snID get. It should be an initial layer.")
316347
}
317348
// overlaybd
318-
rwMode := func(m string) int {
349+
rwMode := func(m string) string {
319350
if m == "dir" {
320351
return rwDir
321352
}
@@ -431,11 +462,14 @@ func (o *snapshotter) createMountPoint(ctx context.Context, kind snapshots.Kind,
431462

432463
stype := storageTypeNormal
433464
writeType := o.getWritableType(ctx, parentID, info)
465+
434466
// If Preparing for rootfs, find metadata from its parent (top layer), launch and mount backstore device.
435467
if _, ok := info.Labels[labelKeyTargetSnapshotRef]; !ok {
468+
log.G(ctx).Infof("Preparing rootfs. writeType: %s", writeType)
436469
if writeType != roDir {
437470
stype = storageTypeLocalBlock
438471
if err := o.constructOverlayBDSpec(ctx, key, true); err != nil {
472+
log.G(ctx).Errorln(err.Error())
439473
return nil, err
440474
}
441475
} else if parent != "" {
@@ -486,7 +520,7 @@ func (o *snapshotter) createMountPoint(ctx context.Context, kind snapshots.Kind,
486520
log.G(ctx).Warnf("cannot get fs type from label, %v", obdInfo.Labels)
487521
fsType = "ext4"
488522
}
489-
log.G(ctx).Debugf("attachAndMountBlockDevice (obdID: %s, writeType: %d, fsType %s, targetPath: %s)",
523+
log.G(ctx).Debugf("attachAndMountBlockDevice (obdID: %s, writeType: %s, fsType %s, targetPath: %s)",
490524
obdID, writeType, fsType, o.overlaybdTargetPath(obdID))
491525
if err = o.attachAndMountBlockDevice(ctx, obdID, writeType, fsType, parent == ""); err != nil {
492526
log.G(ctx).Errorf("%v", err)
@@ -514,7 +548,7 @@ func (o *snapshotter) createMountPoint(ctx context.Context, kind snapshots.Kind,
514548
switch stype {
515549
case storageTypeNormal:
516550
m = o.normalOverlayMount(s)
517-
log.G(ctx).Debugf("return mount point(R/W mode: %d): %v", writeType, m)
551+
log.G(ctx).Debugf("return mount point(R/W mode: %s): %v", writeType, m)
518552
case storageTypeLocalBlock, storageTypeRemoteBlock:
519553
m, err = o.basedOnBlockDeviceMount(ctx, s, writeType)
520554
if err != nil {
@@ -559,6 +593,11 @@ func (o *snapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, er
559593
log.G(ctx).Debugf("Mounts (key: %s, id: %s, parentID: %s, kind: %d)", key, s.ID, s.ParentIDs, s.Kind)
560594

561595
if len(s.ParentIDs) > 0 {
596+
o.locker.Lock(s.ID)
597+
defer o.locker.Unlock(s.ID)
598+
o.locker.Lock(s.ParentIDs[0])
599+
defer o.locker.Unlock(s.ParentIDs[0])
600+
562601
_, info, _, err := storage.GetInfo(ctx, key)
563602
if err != nil {
564603
return nil, errors.Wrap(err, "failed to get info")
@@ -732,6 +771,24 @@ func (o *snapshotter) Remove(ctx context.Context, key string) (err error) {
732771
}
733772
}
734773

774+
// for TypeNormal, verify its(parent) meets the condition of overlaybd format
775+
if o.autoRemoveDev {
776+
if s, err := storage.GetSnapshot(ctx, key); err == nil && s.Kind == snapshots.KindActive && len(s.ParentIDs) > 0 {
777+
o.locker.Lock(s.ID)
778+
defer o.locker.Unlock(s.ID)
779+
o.locker.Lock(s.ParentIDs[0])
780+
defer o.locker.Unlock(s.ParentIDs[0])
781+
782+
log.G(ctx).Debugf("try to verify parent snapshots format.")
783+
if st, err := o.identifySnapshotStorageType(ctx, s.ParentIDs[0], info); err == nil && st != storageTypeNormal {
784+
err = o.unmountAndDetachBlockDevice(ctx, s.ParentIDs[0], "")
785+
if err != nil {
786+
return errors.Wrapf(err, "failed to destroy target device for snapshot %s", key)
787+
}
788+
}
789+
}
790+
}
791+
735792
defer func() {
736793
if err != nil && rollback {
737794
if rerr := t.Rollback(); rerr != nil {
@@ -797,10 +854,10 @@ func (o *snapshotter) prepareDirectory(ctx context.Context, snapshotDir string,
797854
return td, nil
798855
}
799856

800-
func (o *snapshotter) basedOnBlockDeviceMount(ctx context.Context, s storage.Snapshot, writeType int) (m []mount.Mount, err error) {
857+
func (o *snapshotter) basedOnBlockDeviceMount(ctx context.Context, s storage.Snapshot, writeType string) (m []mount.Mount, err error) {
801858
defer func() {
802859
if err == nil {
803-
log.G(ctx).Infof("return mount point(R/W mode: %d): %v", writeType, m)
860+
log.G(ctx).Infof("return mount point(R/W mode: %s): %v", writeType, m)
804861
} else {
805862
log.G(ctx).Errorf("basedOnBlockDeviceMount return error: %v", err)
806863
}
@@ -1017,9 +1074,21 @@ func (o *snapshotter) identifySnapshotStorageType(ctx context.Context, id string
10171074
// check writable data file
10181075
filePath = o.overlaybdWritableDataPath(id)
10191076
st, err = o.identifyLocalStorageType(filePath)
1020-
if err != nil && os.IsNotExist(err) {
1077+
if err == nil {
1078+
return st, nil
1079+
}
1080+
if os.IsNotExist(err) {
1081+
// check config.v1.json
1082+
log.G(ctx).Debugf("failed to identify by writable_data(sn: %s), try to identify by config.v1.json", id)
1083+
filePath = o.overlaybdConfPath(id)
1084+
if _, err := os.Stat(filePath); err == nil {
1085+
log.G(ctx).Debugf("%s/config.v1.json found, return storageTypeRemoteBlock", id)
1086+
return storageTypeRemoteBlock, nil
1087+
}
10211088
return storageTypeNormal, nil
10221089
}
1090+
log.G(ctx).Debugf("storageType(sn: %s): %d", id, st)
1091+
10231092
return st, err
10241093
}
10251094

pkg/snapshot/overlay_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ import (
2727

2828
func newSnapshotterWithOpts(opts ...Opt) testsuite.SnapshotterFunc {
2929
return func(ctx context.Context, root string) (snapshots.Snapshotter, func() error, error) {
30-
snapshotter, err := NewSnapshotter(root, "fs", opts...)
30+
cfg := DefaultBootConfig()
31+
snapshotter, err := NewSnapshotter(cfg, opts...)
3132
if err != nil {
3233
return nil, nil, err
3334
}

0 commit comments

Comments
 (0)