From ffa02c35b1a43ba2fc35ba3e3e75d3864ef17d41 Mon Sep 17 00:00:00 2001 From: "yuchen.cc" Date: Fri, 5 Jan 2024 16:46:51 +0800 Subject: [PATCH] convertor: support setting virtual block device size Signed-off-by: yuchen.cc --- cmd/convertor/builder/builder.go | 2 ++ cmd/convertor/builder/builder_engine.go | 1 + cmd/convertor/builder/overlaybd_builder.go | 8 ++++-- cmd/convertor/builder/turboOCI_builder.go | 7 +++++- cmd/convertor/main.go | 4 ++- cmd/ctr/overlaybd_conv.go | 10 +++++++- docs/IMAGE_CONVERTOR.md | 29 ++++++++++++++++++++++ docs/USERSPACE_CONVERTOR.md | 5 ++++ pkg/convertor/convertor.go | 15 +++++++++-- pkg/label/label.go | 3 +++ pkg/snapshot/storage.go | 11 ++++++-- 11 files changed, 86 insertions(+), 9 deletions(-) diff --git a/cmd/convertor/builder/builder.go b/cmd/convertor/builder/builder.go index f39cf477..7cb651ed 100644 --- a/cmd/convertor/builder/builder.go +++ b/cmd/convertor/builder/builder.go @@ -50,6 +50,7 @@ type BuilderOptions struct { WorkDir string OCI bool Mkfs bool + Vsize int DB database.ConversionDatabase Engine BuilderEngineType CertOption @@ -101,6 +102,7 @@ func NewOverlayBDBuilder(ctx context.Context, opt BuilderOptions) (Builder, erro engineBase.workDir = opt.WorkDir engineBase.oci = opt.OCI engineBase.mkfs = opt.Mkfs + engineBase.vsize = opt.Vsize engineBase.db = opt.DB refspec, err := reference.Parse(opt.Ref) diff --git a/cmd/convertor/builder/builder_engine.go b/cmd/convertor/builder/builder_engine.go index 85cf520a..81f74e91 100644 --- a/cmd/convertor/builder/builder_engine.go +++ b/cmd/convertor/builder/builder_engine.go @@ -73,6 +73,7 @@ type builderEngineBase struct { workDir string oci bool mkfs bool + vsize int db database.ConversionDatabase host string repository string diff --git a/cmd/convertor/builder/overlaybd_builder.go b/cmd/convertor/builder/overlaybd_builder.go index 2dc931cb..28aa35e5 100644 --- a/cmd/convertor/builder/overlaybd_builder.go +++ b/cmd/convertor/builder/overlaybd_builder.go @@ -102,7 +102,11 @@ func (e *overlaybdBuilderEngine) BuildLayer(ctx context.Context, idx int) error mkfs := e.mkfs && (idx == 0) vsizeGB := 0 if idx == 0 { - vsizeGB = 64 + if mkfs { + vsizeGB = e.vsize + } else { + vsizeGB = 64 // in case that using default baselayer + } } if err := e.create(ctx, layerDir, mkfs, vsizeGB); err != nil { return err @@ -310,7 +314,7 @@ func (e *overlaybdBuilderEngine) create(ctx context.Context, dir string, mkfs bo opts := []string{"-s", fmt.Sprintf("%d", vsizeGB)} if mkfs { opts = append(opts, "--mkfs") - logrus.Infof("mkfs for baselayer") + logrus.Infof("mkfs for baselayer, vsize: %d GB", vsizeGB) } return utils.Create(ctx, dir, opts...) } diff --git a/cmd/convertor/builder/turboOCI_builder.go b/cmd/convertor/builder/turboOCI_builder.go index 1724a1a9..984b442d 100644 --- a/cmd/convertor/builder/turboOCI_builder.go +++ b/cmd/convertor/builder/turboOCI_builder.go @@ -233,9 +233,14 @@ func (e *turboOCIBuilderEngine) createIdentifier(idx int) error { } func (e *turboOCIBuilderEngine) create(ctx context.Context, dir string, mkfs bool) error { - opts := []string{"-s", "64", "--turboOCI"} + vsizeGB := 64 + if mkfs { + vsizeGB = e.vsize + } + opts := []string{"-s", fmt.Sprintf("%d", vsizeGB), "--turboOCI"} if mkfs { opts = append(opts, "--mkfs") + logrus.Infof("mkfs for baselayer, vsize: %d GB", vsizeGB) } return utils.Create(ctx, dir, opts...) } diff --git a/cmd/convertor/main.go b/cmd/convertor/main.go index 7f5be3b0..1d491c0f 100644 --- a/cmd/convertor/main.go +++ b/cmd/convertor/main.go @@ -40,6 +40,7 @@ var ( oci bool mkfs bool verbose bool + vsize int fastoci string turboOCI string overlaybd string @@ -87,6 +88,7 @@ var ( WorkDir: dir, OCI: oci, Mkfs: mkfs, + Vsize: vsize, CertOption: builder.CertOption{ CertDirs: certDirs, RootCAs: rootCAs, @@ -160,8 +162,8 @@ func init() { rootCmd.Flags().StringVarP(&dir, "dir", "d", "tmp_conv", "directory used for temporary data") rootCmd.Flags().BoolVarP(&oci, "oci", "", false, "export image with oci spec") rootCmd.Flags().BoolVarP(&mkfs, "mkfs", "", true, "make ext4 fs in bottom layer") + rootCmd.Flags().IntVarP(&vsize, "vsize", "", 64, "virtual block device size (GB)") rootCmd.Flags().StringVar(&fastoci, "fastoci", "", "build 'Overlaybd-Turbo OCIv1' format (old name of turboOCIv1. deprecated)") - rootCmd.Flags().StringVar(&turboOCI, "turboOCI", "", "build 'Overlaybd-Turbo OCIv1' format") rootCmd.Flags().StringVar(&overlaybd, "overlaybd", "", "build overlaybd format") rootCmd.Flags().StringVar(&dbstr, "db-str", "", "db str for overlaybd conversion") diff --git a/cmd/ctr/overlaybd_conv.go b/cmd/ctr/overlaybd_conv.go index 70c50249..993502e2 100644 --- a/cmd/ctr/overlaybd_conv.go +++ b/cmd/ctr/overlaybd_conv.go @@ -52,9 +52,14 @@ var convertCommand = cli.Command{ }, cli.IntFlag{ Name: "bs", - Usage: "The size of a compressed data block in KB. Must be a power of two between 4K~64K [4/8/16/32/64])", + Usage: "The size of a compressed data block in KB. Must be a power of two between 4K~64K [4/8/16/32/64]", Value: 0, }, + cli.IntFlag{ + Name: "vsize", + Usage: "virtual block device size (GB)", + Value: 64, + }, ), Action: func(context *cli.Context) error { var ( @@ -98,6 +103,9 @@ var convertCommand = cli.Command{ obdOpts = append(obdOpts, obdconv.WithAlgorithm(algorithm)) blockSize := context.Int("bs") obdOpts = append(obdOpts, obdconv.WithBlockSize(blockSize)) + vsize := context.Int("vsize") + fmt.Printf("vsize: %d GB\n", vsize) + obdOpts = append(obdOpts, obdconv.WithVsize(vsize)) resolver, err := commands.GetResolver(ctx, context) if err != nil { diff --git a/docs/IMAGE_CONVERTOR.md b/docs/IMAGE_CONVERTOR.md index 3454ecd2..c497b444 100644 --- a/docs/IMAGE_CONVERTOR.md +++ b/docs/IMAGE_CONVERTOR.md @@ -3,7 +3,36 @@ We provide a ctr command tool to convert OCIv1 images into overlaybd format, which is stored in `bin` after `make` or downloading the release package. # Basic Usage +```bash +# usage +$ bin/ctr obdconv --help + +NAME: + ctr obdconv - convert image layer into overlaybd format type + +USAGE: + ctr obdconv [command options] +DESCRIPTION: + Export images to an OCI tar[.gz] into zfile format + +OPTIONS: + --skip-verify, -k skip SSL certificate validation + --plain-http allow connections using plain HTTP + --user value, -u value user[:password] Registry user and password + --refresh value refresh token for authorization server + --hosts-dir value Custom hosts configuration directory + --tlscacert value path to TLS root CA + --tlscert value path to TLS client certificate + --tlskey value path to TLS client key + --http-dump dump all HTTP request/responses when interacting with container registry + --http-trace enable HTTP tracing for registry interactions + --fstype value filesystem type(required), used to mount block device, support specifying mount options and mkfs options, separate fs type and options by ';', separate mount options by ',', separate mkfs options by ' ' (default: "ext4") + --dbstr value data base config string used for layer deduplication + --algorithm value compress algorithm uses in zfile, [lz4|zstd] + --bs value The size of a compressed data block in KB. Must be a power of two between 4K~64K [4/8/16/32/64] (default: 0) + --vsize value virtual block device size (GB) (default: 64) +``` ```bash # pull the source image sudo ctr i pull registry.hub.docker.com/library/redis:6.2.1 diff --git a/docs/USERSPACE_CONVERTOR.md b/docs/USERSPACE_CONVERTOR.md index 5ad3cfcc..06cb4815 100644 --- a/docs/USERSPACE_CONVERTOR.md +++ b/docs/USERSPACE_CONVERTOR.md @@ -43,6 +43,7 @@ Flags: -d, --dir string directory used for temporary data (default "tmp_conv") --oci export image with oci spec --mkfs make ext4 fs in bottom layer (default true) + --vsize int virtual block device size (GB) (default 64) --fastoci string build 'Overlaybd-Turbo OCIv1' format (old name of turboOCIv1. deprecated) --turboOCI string build 'Overlaybd-Turbo OCIv1' format --overlaybd string build overlaybd format @@ -52,11 +53,15 @@ Flags: --root-ca stringArray root CA certificates --client-cert stringArray client cert certificates, should form in ${cert-file}:${key-file} --insecure don't verify the server's certificate chain and host name + --reserve reserve tmp data + --no-upload don't upload layer and manifest + --dump-manifest dump manifest -h, --help help for convertor # examples $ bin/convertor -r docker.io/overlaybd/redis -u user:pass -i 6.2.6 -o 6.2.6_obd $ bin/convertor -r docker.io/overlaybd/redis -u user:pass -i 6.2.6 --overlaybd 6.2.6_obd --fastoci 6.2.6_foci +$ bin/convertor -r docker.io/overlaybd/redis -u user:pass -i 6.2.6 -o 6.2.6_obd --vsize 256 ``` diff --git a/pkg/convertor/convertor.go b/pkg/convertor/convertor.go index 5e3122f7..f875927a 100644 --- a/pkg/convertor/convertor.go +++ b/pkg/convertor/convertor.go @@ -226,14 +226,16 @@ type overlaybdConvertor struct { host string repo string zfileCfg ZFileConfig + vsize int } -func NewOverlaybdConvertor(ctx context.Context, cs content.Store, sn snapshots.Snapshotter, resolver remotes.Resolver, ref string, dbstr string, zfileCfg ZFileConfig) (ImageConvertor, error) { +func NewOverlaybdConvertor(ctx context.Context, cs content.Store, sn snapshots.Snapshotter, resolver remotes.Resolver, ref string, dbstr string, zfileCfg ZFileConfig, vsize int) (ImageConvertor, error) { c := &overlaybdConvertor{ cs: cs, sn: sn, remote: false, zfileCfg: zfileCfg, + vsize: vsize, } var err error if dbstr != "" { @@ -535,6 +537,7 @@ func (c *overlaybdConvertor) convertLayers(ctx context.Context, srcDescs []ocisp snapshots.WithLabels(map[string]string{ label.SupportReadWriteMode: "dir", label.OverlayBDBlobFsType: fsType, + label.OverlayBDVsize: fmt.Sprintf("%d", c.vsize), }), } cfgStr, err := json.Marshal(c.zfileCfg) @@ -682,6 +685,7 @@ type options struct { imgRef string algorithm string blockSize int + vsize int resolver remotes.Resolver client *containerd.Client } @@ -723,6 +727,13 @@ func WithBlockSize(blockSize int) Option { } } +func WithVsize(vsize int) Option { + return func(o *options) error { + o.vsize = vsize + return nil + } +} + func WithResolver(resolver remotes.Resolver) Option { return func(o *options) error { o.resolver = resolver @@ -762,7 +773,7 @@ func IndexConvertFunc(opts ...Option) converter.ConvertFunc { Algorithm: copts.algorithm, BlockSize: copts.blockSize, } - c, err := NewOverlaybdConvertor(ctx, cs, sn, copts.resolver, imgRef, copts.dbstr, zfileCfg) + c, err := NewOverlaybdConvertor(ctx, cs, sn, copts.resolver, imgRef, copts.dbstr, zfileCfg, copts.vsize) if err != nil { return nil, err } diff --git a/pkg/label/label.go b/pkg/label/label.go index 5589c4b0..dda6abb6 100644 --- a/pkg/label/label.go +++ b/pkg/label/label.go @@ -70,6 +70,9 @@ const ( // ZFileConfig is the config of ZFile ZFileConfig = "containerd.io/snapshot/overlaybd/zfile-config" + // OverlayBD virtual block device size + OverlayBDVsize = "containerd.io/snapshot/overlaybd/vsize" + // CRIImageRef is the image-ref from cri CRIImageRef = "containerd.io/snapshot/cri.image-ref" diff --git a/pkg/snapshot/storage.go b/pkg/snapshot/storage.go index 4616905f..d900092b 100644 --- a/pkg/snapshot/storage.go +++ b/pkg/snapshot/storage.go @@ -551,11 +551,18 @@ func (o *snapshotter) constructOverlayBDSpec(ctx context.Context, key string, wr if !writable { return errors.Errorf("unexpect storage %v of snapshot %v during construct overlaybd spec(writable=%v, parent=%s)", stype, key, writable, info.Parent) } - log.G(ctx).Infof("prepare writable layer. (sn: %s)", id) vsizeGB := 0 if info.Parent == "" { - vsizeGB = 64 + if vsize, ok := info.Labels[label.OverlayBDVsize]; ok { + vsizeGB, err = strconv.Atoi(vsize) + if err != nil { + vsizeGB = 64 + } + } else { + vsizeGB = 64 + } } + log.G(ctx).Infof("prepare writable layer. (sn: %s, vsize: %d GB)", id, vsizeGB) if err := o.prepareWritableOverlaybd(ctx, id, vsizeGB); err != nil { return err }