Skip to content

Commit

Permalink
VMCache: the new function that creates VMs as caches before using it
Browse files Browse the repository at this point in the history
VM cache helps speeding up new container creation.
To use it,  need set option "enable_vm_cache" to true and use
"kata-runtime cache" command start the VM cache server that created
some VMs as VM cache.  Then each kata-runtime will request VM from
VM cache server.

Currently, VM cache still cannot work with VM templating and vsock.
And just support qemu.

Fixes: kata-containers#52

Signed-off-by: Hui Zhu <[email protected]>
  • Loading branch information
teawater committed Jan 29, 2019
1 parent 6f2c036 commit 8260c2e
Show file tree
Hide file tree
Showing 28 changed files with 1,075 additions and 154 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
/cli/config/configuration-fc.toml
/cli/config/configuration-qemu.toml
/cli/config-generated.go
/cli/kata-vmcache/config-generated.go
/cli/coverage.html
/containerd-shim-kata-v2
/data/kata-collect-data.sh
/kata-netmon
/kata-runtime
/kata-vmcache
/virtcontainers/hack/virtc/virtc
/virtcontainers/hook/mock/hook
/virtcontainers/profile.cov
Expand Down
20 changes: 17 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ SHIMV2 = containerd-shim-kata-v2
SHIMV2_OUTPUT = $(CURDIR)/$(SHIMV2)
SHIMV2_DIR = $(CLI_DIR)/$(SHIMV2)

VMCACHE = kata-vmcache
VMCACHE_OUTPUT = $(CURDIR)/$(VMCACHE)
VMCACHE_DIR = $(CLI_DIR)/$(VMCACHE)

SOURCES := $(shell find . 2>&1 | grep -E '.*\.(c|h|go)$$')
VERSION := ${shell cat ./VERSION}
COMMIT_NO := $(shell git rev-parse HEAD 2> /dev/null || true)
Expand Down Expand Up @@ -351,7 +355,7 @@ define SHOW_ARCH
$(shell printf "\\t%s%s\\\n" "$(1)" $(if $(filter $(ARCH),$(1))," (default)",""))
endef

all: runtime containerd-shim-v2 netmon
all: runtime containerd-shim-v2 netmon $(VMCACHE)

containerd-shim-v2: $(SHIMV2_OUTPUT)

Expand All @@ -360,6 +364,11 @@ netmon: $(NETMON_TARGET_OUTPUT)
$(NETMON_TARGET_OUTPUT): $(SOURCES)
$(QUIET_BUILD)(cd $(NETMON_DIR) && go build $(BUILDFLAGS) -o $@ -ldflags "-X main.version=$(VERSION)")

$(VMCACHE): $(VMCACHE_OUTPUT)

$(VMCACHE_OUTPUT): $(TARGET_OUTPUT)
$(QUIET_BUILD)(cd $(VMCACHE_DIR)/ && go build -i -o $@ .)

runtime: $(TARGET_OUTPUT) $(CONFIGS)
.DEFAULT: default

Expand Down Expand Up @@ -437,11 +446,13 @@ $(if $(findstring uncompressed,$1),vmlinux.container,vmlinuz.container)
endef

GENERATED_CONFIG = $(CLI_DIR)/config-generated.go
VMCACHE_GENERATED_CONFIG = $(VMCACHE_DIR)/config-generated.go

GENERATED_GO_FILES += $(GENERATED_CONFIG)

$(GENERATED_CONFIG): Makefile VERSION
$(QUIET_GENERATE)echo "$$GENERATED_CODE" >$@
@cp $@ $(VMCACHE_GENERATED_CONFIG)

$(TARGET_OUTPUT): $(EXTRA_DEPS) $(SOURCES) $(GENERATED_GO_FILES) $(GENERATED_FILES) Makefile | show-summary
$(QUIET_BUILD)(cd $(CLI_DIR) && go build $(BUILDFLAGS) -o $@ .)
Expand Down Expand Up @@ -533,14 +544,17 @@ check-go-static:
coverage:
$(QUIET_TEST).ci/go-test.sh html-coverage

install: default runtime install-scripts install-completions install-configs install-bin install-containerd-shim-v2 install-bin-libexec
install: default runtime install-scripts install-completions install-configs install-bin install-containerd-shim-v2 install-kata-vmcache install-bin-libexec

install-bin: $(BINLIST)
$(QUIET_INST)$(foreach f,$(BINLIST),$(call INSTALL_EXEC,$f,$(BINDIR)))

install-containerd-shim-v2: $(SHIMV2)
$(QUIET_INST)$(call INSTALL_EXEC,$<,$(BINDIR))

install-kata-vmcache: $(VMCACHE)
$(QUIET_INST)$(call INSTALL_EXEC,$<,$(BINDIR))

install-bin-libexec: $(BINLIBEXECLIST)
$(QUIET_INST)$(foreach f,$(BINLIBEXECLIST),$(call INSTALL_EXEC,$f,$(PKGLIBEXECDIR)))

Expand All @@ -555,7 +569,7 @@ install-completions:
$(QUIET_INST)install --mode 0644 -D $(BASH_COMPLETIONS) $(DESTDIR)/$(BASH_COMPLETIONSDIR)/$(notdir $(BASH_COMPLETIONS));

clean:
$(QUIET_CLEAN)rm -f $(TARGET) $(SHIMV2) $(NETMON_TARGET) $(CONFIGS) $(GENERATED_GO_FILES) $(GENERATED_FILES) $(COLLECT_SCRIPT)
$(QUIET_CLEAN)rm -f $(TARGET) $(SHIMV2) $(VMCACHE_OUTPUT) $(NETMON_TARGET) $(CONFIGS) $(GENERATED_GO_FILES) $(GENERATED_FILES) $(COLLECT_SCRIPT)

show-usage: show-header
@printf "• Overview:\n"
Expand Down
15 changes: 15 additions & 0 deletions cli/config/configuration-qemu.toml.in
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,21 @@ enable_iothreads = @DEFENABLEIOTHREADS@
# Default false
#enable_template = true

# VM cache support. Once enabled, need use "kata-vmcache" command start
# the VM cache server that created some VMs (number is set by option number)
# as VM cache. Each kata-runtime will request VM from VM cache server
# through vm_cache_endpoint.
# It helps speeding up new container creation.
#
# Default false
#enable_vm_cache = true

# Specify the endpoint of transport VM from the VM cache server to runtime.
# "kata-vmcache" will start a gRPC server in this endpoint.
# Each kata-runtime will request VM through gRPC protocol.
# Default /var/run/kata-containers/cache.sock
#vm_cache_endpoint = "/var/run/kata-containers/cache.sock"

[proxy.@PROJECT_TYPE@]
path = "@PROXYPATH@"

Expand Down
205 changes: 205 additions & 0 deletions cli/kata-vmcache/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
// Copyright (c) 2019 HyperHQ Inc.
//
// SPDX-License-Identifier: Apache-2.0
//

package main

import (
"context"
"fmt"
"net"
"os"
"os/signal"
"path/filepath"
rDebug "runtime/debug"

google_protobuf "github.com/golang/protobuf/ptypes/empty"
"github.com/kata-containers/runtime/pkg/katautils"
pb "github.com/kata-containers/runtime/protocols/cache"
vc "github.com/kata-containers/runtime/virtcontainers"
vf "github.com/kata-containers/runtime/virtcontainers/factory"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"golang.org/x/sys/unix"
"google.golang.org/grpc"
)

const vmCacheName = "kata-vmcache"

var usage = fmt.Sprintf(`%s kata VM cache server
When enable_vm_cache enabled, %s start the VM cache server
that created some VMs (number is set by option number) as
VM cache.
Each kata-runtime will request VM from VM cache server
through vm_cache_endpoint.
It helps speeding up new container creation.`, vmCacheName, vmCacheName)

var kataLog = logrus.New()

type cacheServer struct {
rpc *grpc.Server
factory vc.Factory
}

var jsonVMConfig *pb.GrpcVMConfig

// Config requests base factory config and convert it to gRPC protocol.
func (s *cacheServer) Config(ctx context.Context, empty *google_protobuf.Empty) (*pb.GrpcVMConfig, error) {
if jsonVMConfig == nil {
config := s.factory.Config()

var err error
jsonVMConfig, err = config.ToGrpc()
if err != nil {
return nil, err
}
}

return jsonVMConfig, nil
}

// GetBaseVM requests a paused VM and convert it to gRPC protocol.
func (s *cacheServer) GetBaseVM(ctx context.Context, empty *google_protobuf.Empty) (*pb.GrpcVM, error) {
config := s.factory.Config()

vm, err := s.factory.GetBaseVM(ctx, config)
if err != nil {
return nil, errors.Wrapf(err, "failed to GetBaseVM")
}

return vm.ToGrpc(config)
}

func getUnixListener(path string) (net.Listener, error) {
err := os.MkdirAll(filepath.Dir(path), 0755)
if err != nil {
return nil, err
}
if err = unix.Unlink(path); err != nil && !os.IsNotExist(err) {
return nil, err
}
l, err := net.Listen("unix", path)
if err != nil {
return nil, err
}
if err = os.Chmod(path, 0660); err != nil {
l.Close()
return nil, err
}
return l, nil
}

var handledSignals = []os.Signal{
unix.SIGTERM,
unix.SIGINT,
unix.SIGUSR1,
unix.SIGPIPE,
}

func handleSignals(s *cacheServer, signals chan os.Signal) chan struct{} {
done := make(chan struct{}, 1)
go func() {
for {
sig := <-signals
kataLog.WithField("signal", sig).Debug("received signal")
switch sig {
case unix.SIGUSR1:
kataLog.WithField("stack", rDebug.Stack()).Debug("dump stack")
case unix.SIGPIPE:
continue
default:
s.rpc.GracefulStop()
close(done)
return
}
}
}()
return done
}

func main() {
app := cli.NewApp()
app.Name = vmCacheName
app.Usage = usage
app.Writer = os.Stdout
app.Version = katautils.MakeVersionString(version, commit, specs.Version)
app.Flags = []cli.Flag{
cli.StringFlag{
Name: configFilePathOption,
Usage: project + " config file path",
},
cli.UintFlag{
Name: "number, n",
Value: 1,
Usage: "number of cache",
},
}
app.Action = func(c *cli.Context) error {
cacheNum := c.Uint("number")
if cacheNum == 0 {
return errors.New("cache number must be greater than zero")
}
ctx := context.Background()
fmt.Println(c.GlobalString(configFilePathOption))
_, runtimeConfig, err := katautils.LoadConfiguration(c.GlobalString(configFilePathOption), false, false)
if err != nil {
return errors.Wrap(err, "invalid runtime config")
}
if !runtimeConfig.FactoryConfig.VMCache {
return errors.New("vm cache not enabled")
}

factoryConfig := vf.Config{
Template: runtimeConfig.FactoryConfig.Template,
Cache: cacheNum,
VMCache: true,
VMConfig: vc.VMConfig{
HypervisorType: runtimeConfig.HypervisorType,
HypervisorConfig: runtimeConfig.HypervisorConfig,
AgentType: runtimeConfig.AgentType,
AgentConfig: runtimeConfig.AgentConfig,
ProxyType: runtimeConfig.ProxyType,
ProxyConfig: runtimeConfig.ProxyConfig,
},
}
f, err := vf.NewFactory(ctx, factoryConfig, false)
if err != nil {
return err
}
defer f.CloseFactory(ctx)

s := &cacheServer{
rpc: grpc.NewServer(),
factory: f,
}
pb.RegisterCacheServiceServer(s.rpc, s)

l, err := getUnixListener(runtimeConfig.FactoryConfig.VMCacheEndpoint)
if err != nil {
return err
}
defer l.Close()

signals := make(chan os.Signal, 2048)
done := handleSignals(s, signals)
signal.Notify(signals, handledSignals...)

kataLog.WithField("endpoint", runtimeConfig.FactoryConfig.VMCacheEndpoint).Info("VM cache server start")
s.rpc.Serve(l)

<-done

kataLog.WithField("endpoint", runtimeConfig.FactoryConfig.VMCacheEndpoint).Info("VM cache server stop")

return nil
}

err := app.Run(os.Args)
if err != nil {
kataLog.Fatal(err)
}
}
25 changes: 1 addition & 24 deletions cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,30 +409,7 @@ func commandNotFound(c *cli.Context, command string) {
// makeVersionString returns a multi-line string describing the runtime
// version along with the version of the OCI specification it supports.
func makeVersionString() string {
v := make([]string, 0, 3)

versionStr := version
if versionStr == "" {
versionStr = unknown
}

v = append(v, name+" : "+versionStr)

commitStr := commit
if commitStr == "" {
commitStr = unknown
}

v = append(v, " commit : "+commitStr)

specVersionStr := specs.Version
if specVersionStr == "" {
specVersionStr = unknown
}

v = append(v, " OCI specs: "+specVersionStr)

return strings.Join(v, "\n")
return katautils.MakeVersionString(version, commit, specs.Version)
}

// setCLIGlobals modifies various cli package global variables
Expand Down
2 changes: 2 additions & 0 deletions pkg/katautils/config-settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ const defaultHotplugVFIOOnRootBus bool = false
const defaultEntropySource = "/dev/urandom"
const defaultGuestHookPath string = ""

const defaultVMCacheEndpoint string = "/var/run/kata-containers/cache.sock"

// Default config file used by stateless systems.
var defaultRuntimeConfiguration = "/usr/share/defaults/kata-containers/configuration.toml"

Expand Down
Loading

0 comments on commit 8260c2e

Please sign in to comment.