Skip to content

Commit

Permalink
agent: add support for loading kernel modules
Browse files Browse the repository at this point in the history
Some containers may require HW devices to improve its performance. In Kata
containers these devices can be passed though VFIO and used in the container
only if the guest kernel has the drivers built-in for them. When kernel
fragment support landed (kata-containers/packaging#646), kata lost support
for several HW devices like Intel GPUs, this was expected since one of the
goals of this change was to have a minimal kernel in order to improve boot
time, memory footprint and reduce the attack surface by enabling just the
features required to run kata containers.
Currently if the users want to use a HW device in kata container, He/She has
to build a custom kernel and create a custom image that includes the modules
that will be loaded by systemd. From user's perspective this is a pain, since
not all users know how to create a custom image or configure/build a custom
kernel.
Same as the `debug_console` feature (kata-containers/agent#547), the goal of
this change is to facilitate the things to the final user and *do not* depend
on systemd.
The list of kernel modules and their parameters are set through gRPC when the
sandbox is created.

fixes kata-containers#615

see kata-containers/osbuilder#77

Signed-off-by: Julio Montes <julio.montes@intel.com>
  • Loading branch information
Julio Montes committed Aug 1, 2019
1 parent d6d8514 commit ad72fe8
Show file tree
Hide file tree
Showing 4 changed files with 517 additions and 198 deletions.
37 changes: 37 additions & 0 deletions grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ var (

// set when StopTracing() is called.
stopTracingCalled = false

modprobePath = "/sbin/modprobe"
)

type onlineResource struct {
Expand Down Expand Up @@ -1399,6 +1401,35 @@ func (a *agentGRPC) TtyWinResize(ctx context.Context, req *pb.TtyWinResizeReques
return emptyResp, nil
}

func loadKernelModule(module *pb.KernelModule) error {
if module == nil {
return fmt.Errorf("Kernel module is nil")
}

if module.Name == "" {
return fmt.Errorf("Kernel module name is empty")
}

log := agentLog.WithFields(logrus.Fields{
"module-name": module.Name,
"module-params": module.Parameters,
})

log.Debug("loading module")
cmd := exec.Command(modprobePath, "-v", module.Name)

if len(module.Parameters) > 0 {
cmd.Args = append(cmd.Args, module.Parameters...)
}

output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("could not load module: %v: %v", err, string(output))
}

return nil
}

func (a *agentGRPC) CreateSandbox(ctx context.Context, req *pb.CreateSandboxRequest) (*gpb.Empty, error) {
if a.sandbox.running {
return emptyResp, grpcStatus.Error(codes.AlreadyExists, "Sandbox already started, impossible to start again")
Expand All @@ -1414,6 +1445,12 @@ func (a *agentGRPC) CreateSandbox(ctx context.Context, req *pb.CreateSandboxRequ
a.sandbox.guestHooks = &specs.Hooks{}
a.sandbox.guestHooksPresent = false

for _, m := range req.KernelModules {
if err := loadKernelModule(m); err != nil {
return emptyResp, err
}
}

if req.GuestHookPath != "" {
a.sandbox.scanGuestHooks(req.GuestHookPath)
}
Expand Down
19 changes: 19 additions & 0 deletions grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1754,3 +1754,22 @@ func TestTtyWinResize(t *testing.T) {
_, err := a.TtyWinResize(context.Background(), req)
assert.Error(err)
}

func TestLoadKernelModule(t *testing.T) {
assert := assert.New(t)

err := loadKernelModule(nil)
assert.Error(err)

m := &pb.KernelModule{
Name: "",
Parameters: []string{"opt"},
}
err = loadKernelModule(m)
assert.Error(err)

modprobePath = "/bin/echo"
m.Name = "fake"
err = loadKernelModule(m)
assert.NoError(err)
}
Loading

0 comments on commit ad72fe8

Please sign in to comment.