
To avoid buffer bloat in long running processes, we try to use buffer pools where possible. This is meant to address shim memory usage issues, but may not be the root cause. Signed-off-by: Stephen J Day <stephen.day@docker.com>
137 lines
3.8 KiB
Go
137 lines
3.8 KiB
Go
// +build linux
|
|
|
|
package linux
|
|
|
|
import (
|
|
"context"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/containerd/containerd/events/exchange"
|
|
"github.com/containerd/containerd/linux/runctypes"
|
|
"github.com/containerd/containerd/linux/shim"
|
|
"github.com/containerd/containerd/linux/shim/client"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// loadBundle loads an existing bundle from disk
|
|
func loadBundle(id, path, workdir string) *bundle {
|
|
return &bundle{
|
|
id: id,
|
|
path: path,
|
|
workDir: workdir,
|
|
}
|
|
}
|
|
|
|
// newBundle creates a new bundle on disk at the provided path for the given id
|
|
func newBundle(id, path, workDir string, spec []byte) (b *bundle, err error) {
|
|
if err := os.MkdirAll(path, 0711); err != nil {
|
|
return nil, err
|
|
}
|
|
path = filepath.Join(path, id)
|
|
defer func() {
|
|
if err != nil {
|
|
os.RemoveAll(path)
|
|
}
|
|
}()
|
|
workDir = filepath.Join(workDir, id)
|
|
if err := os.MkdirAll(workDir, 0711); err != nil {
|
|
return nil, err
|
|
}
|
|
defer func() {
|
|
if err != nil {
|
|
os.RemoveAll(workDir)
|
|
}
|
|
}()
|
|
|
|
if err := os.Mkdir(path, 0711); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := os.Mkdir(filepath.Join(path, "rootfs"), 0711); err != nil {
|
|
return nil, err
|
|
}
|
|
err = ioutil.WriteFile(filepath.Join(path, configFilename), spec, 0666)
|
|
return &bundle{
|
|
id: id,
|
|
path: path,
|
|
workDir: workDir,
|
|
}, err
|
|
}
|
|
|
|
type bundle struct {
|
|
id string
|
|
path string
|
|
workDir string
|
|
}
|
|
|
|
// ShimOpt specifies shim options for initialization and connection
|
|
type ShimOpt func(*bundle, string, *runctypes.RuncOptions) (shim.Config, client.Opt)
|
|
|
|
// ShimRemote is a ShimOpt for connecting and starting a remote shim
|
|
func ShimRemote(shimBinary, daemonAddress, cgroup string, debug bool, exitHandler func()) ShimOpt {
|
|
return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) {
|
|
return b.shimConfig(ns, ropts),
|
|
client.WithStart(shimBinary, b.shimAddress(ns), daemonAddress, cgroup, debug, exitHandler)
|
|
}
|
|
}
|
|
|
|
// ShimLocal is a ShimOpt for using an in process shim implementation
|
|
func ShimLocal(exchange *exchange.Exchange) ShimOpt {
|
|
return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) {
|
|
return b.shimConfig(ns, ropts), client.WithLocal(exchange)
|
|
}
|
|
}
|
|
|
|
// ShimConnect is a ShimOpt for connecting to an existing remote shim
|
|
func ShimConnect() ShimOpt {
|
|
return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) {
|
|
return b.shimConfig(ns, ropts), client.WithConnect(b.shimAddress(ns))
|
|
}
|
|
}
|
|
|
|
// NewShimClient connects to the shim managing the bundle and tasks creating it if needed
|
|
func (b *bundle) NewShimClient(ctx context.Context, namespace string, getClientOpts ShimOpt, runcOpts *runctypes.RuncOptions) (*client.Client, error) {
|
|
cfg, opt := getClientOpts(b, namespace, runcOpts)
|
|
return client.New(ctx, cfg, opt)
|
|
}
|
|
|
|
// Delete deletes the bundle from disk
|
|
func (b *bundle) Delete() error {
|
|
err := os.RemoveAll(b.path)
|
|
if err == nil {
|
|
return os.RemoveAll(b.workDir)
|
|
}
|
|
// error removing the bundle path; still attempt removing work dir
|
|
err2 := os.RemoveAll(b.workDir)
|
|
if err2 == nil {
|
|
return err
|
|
}
|
|
return errors.Wrapf(err, "Failed to remove both bundle and workdir locations: %v", err2)
|
|
}
|
|
|
|
func (b *bundle) shimAddress(namespace string) string {
|
|
return filepath.Join(string(filepath.Separator), "containerd-shim", namespace, b.id, "shim.sock")
|
|
}
|
|
|
|
func (b *bundle) shimConfig(namespace string, runcOptions *runctypes.RuncOptions) shim.Config {
|
|
var (
|
|
criuPath string
|
|
runtimeRoot string
|
|
systemdCgroup bool
|
|
)
|
|
if runcOptions != nil {
|
|
criuPath = runcOptions.CriuPath
|
|
systemdCgroup = runcOptions.SystemdCgroup
|
|
runtimeRoot = runcOptions.RuntimeRoot
|
|
}
|
|
return shim.Config{
|
|
Path: b.path,
|
|
WorkDir: b.workDir,
|
|
Namespace: namespace,
|
|
Criu: criuPath,
|
|
RuntimeRoot: runtimeRoot,
|
|
SystemdCgroup: systemdCgroup,
|
|
}
|
|
}
|