Skip to content
This repository was archived by the owner on May 12, 2021. It is now read-only.

network: Move OCI hooks and network namespace creation out of virtcontainers#623

Merged
bergwolf merged 5 commits intokata-containers:masterfrom
sboeuf:move_hooks
Aug 31, 2018
Merged

network: Move OCI hooks and network namespace creation out of virtcontainers#623
bergwolf merged 5 commits intokata-containers:masterfrom
sboeuf:move_hooks

Conversation

@sboeuf
Copy link

@sboeuf sboeuf commented Aug 22, 2018

Before we decide to move to a fully hotpluggable network model, we want to go step by step by making sure we can still support the network being coldplugged in case of kata-runtime, but also letting the possibility to consumer of the API (such as frakti) to hotplug the network interfaces, without having virtcontainers doing some prework there.

This PR introduces a few rework and fixes, but the most important part is about the creation of the network namespace and the execution of the OCI hooks being handled directly from the CLI. This allows the Kata API to be OCI agnostic.

Fixes #599

@egernst egernst added the review label Aug 22, 2018
@sboeuf sboeuf requested a review from amshinde August 22, 2018 07:48
@sboeuf
Copy link
Author

sboeuf commented Aug 22, 2018

@egernst @WeiZhang555 @bergwolf @amshinde @caoruidong PTAL

FYI, this PR does not supersede #600, but shares part of the commits. The approach here is less aggressive as we're not dropping the network coldplug, but we let the possibility for the network not to be created if we don't want to (frakti case with the factory).

We need to discuss if we want eventually to move to a fully hopluggable model, but this is beyond this PR scope.

@katacontainersbot
Copy link
Contributor

PSS Measurement:
Qemu: 169182 KB
Proxy: 4151 KB
Shim: 8884 KB

Memory inside container:
Total Memory: 2043464 KB
Free Memory: 2003588 KB

@opendev-zuul
Copy link

opendev-zuul bot commented Aug 22, 2018

Build failed (third-party-check pipeline) integration testing with
OpenStack. For information on how to proceed, see
http://docs.openstack.org/infra/manual/developers.html#automated-testing

@jodh-intel
Copy link

This is going to conflict with #617, so please could folk take a look at that one :)

cli/create.go Outdated
}

// Execute prestart OCI hooks
if err := enterNetNS(sandboxConfig.NetworkConfig.NetNSPath, func() error {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit of a mind-bender :) I think it would be clearer if you assigned to err and then checked err on a separate line.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok fair enough ;)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

"github.com/kata-containers/runtime/virtcontainers/device/api"
)

type noopResourceStorage struct{}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Since you've added this though, how about splitting filesystem.go into:

  • resource_storage.go (type resourceStorage interface only).
  • resource_storage_filesystem.go

And renaming filesystem_test.go to resource_storage_filesystem_test.go ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this makes sense, let me take care of this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in other PR (already merged)

cli/hook.go Outdated
return nil
}

func postStartHooks(spec oci.CompatOCISpec, cid, bundlePath string) error {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function and postStopHooks() are almost identical to preStartHooks(), so how about having them all call a generic function. Something like:

func runHooks(cid, bundlePath string, hooks []Hook, name string) error { }

func preStartHooks(spec oci.CompatOCISpec, cid, bundlePath string) error {
    if spec.Hooks == nil {
        return nil
    }

    return runHooks(cid, bundlePath, spec.Hooks.Prestart, "pre-start")
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I can work on this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

cli/start.go Outdated

if err := enterNetNS(s.GetNetNs(), func() error {
return postStartHooks(ociSpec, sandboxID, status.Annotations[vcAnnot.BundlePathKey])
}); err != nil {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above - this is compact, but rather difficult to understand ;)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

type defNetwork struct {
}

func defNetworkLogger() *logrus.Entry {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not?:

func (n *defNetwork) logger() *logrus.Entry

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, that works !

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return endpoint, nil
}

func generateInterfacesAndRoutes(networkNS NetworkNamespace) ([]*grpc.Interface, []*grpc.Route, error) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty surprised the linters don't complain about the length/complexity of this function ;)

@codecov
Copy link

codecov bot commented Aug 22, 2018

Codecov Report

❗ No coverage uploaded for pull request base (master@cc29b8d). Click here to learn what that means.
The diff coverage is 77.98%.

@@            Coverage Diff            @@
##             master     #623   +/-   ##
=========================================
  Coverage          ?   64.92%           
=========================================
  Files             ?       85           
  Lines             ?     9589           
  Branches          ?        0           
=========================================
  Hits              ?     6226           
  Misses            ?     2717           
  Partials          ?      646

@katacontainersbot
Copy link
Contributor

PSS Measurement:
Qemu: 165401 KB
Proxy: 4238 KB
Shim: 8920 KB

Memory inside container:
Total Memory: 2043464 KB
Free Memory: 2003564 KB

@opendev-zuul
Copy link

opendev-zuul bot commented Aug 22, 2018

Build failed (third-party-check pipeline) integration testing with
OpenStack. For information on how to proceed, see
http://docs.openstack.org/infra/manual/developers.html#automated-testing

// CNMNetworkModel is the CNM network.
CNMNetworkModel NetworkModel = "CNM"
// DefaultNetworkModel is the default network.
DefaultNetworkModel NetworkModel = "default"
Copy link
Member

@egernst egernst Aug 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a defaultNetworkModel and just a Noop model seems a bit awkward now? Really we're either having a network or not at this point, from what I can see? Maybe just a better name than 'default?'

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah tell me which name I could use, but I agree "default" is definitely not great...
A bit more background here, initially I wanted to remove the interface since it was not really needed as we now have only one real implementation, but I realized that our unit testing would be way more complicated/impossible? if we decide to remove the noop implementation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@egernst I think naming the network to Default is a bit awkward, lets rework this in a separate PR if required.

@egernst
Copy link
Member

egernst commented Aug 22, 2018

This is a big PR - nice work. I feel like some of the commits would be better off in a seperate PR? In particular:
virtcontainers: qemu: Don't shutdown QMP from hotplug

And probably:
virtcontainers: kata_agent: Move out a generic function
virtcontainers: storage: Add a noop version of filesystem

@caoruidong
Copy link
Member

Most of changes are code movement, generally good

Copy link
Member

@bergwolf bergwolf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I see this is mostly moving codes from virtcontainers to cli, there are a couple of issues that we should address IMHO.

cli/create.go Outdated

// Execute prestart OCI hooks
if err := enterNetNS(sandboxConfig.NetworkConfig.NetNSPath, func() error {
return preStartHooks(ociSpec, containerID, bundlePath)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes that only the very first container of a sandbox has prestart hooks. However, OCI hooks are part of the OCI spec that every container can include. So IMO we should call these hooks for every container instead of just on the first container of a sandbox.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense, even if I don't expect any hook for containers following the sandbox container.

cli/delete.go Outdated

switch containerType {
case vc.PodSandbox:
if err := postStopHooks(ociSpec, sandboxID, status.Annotations[vcAnnot.BundlePathKey]); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. It only runs the post stop hooks of the last container of a sandbox.

Also post stop hooks are supposed to run after a container is stopped. However, here we might have called them before the container is stopped.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes good point, I have to move this slightly further in the code.


var stdout, stderr bytes.Buffer
cmd := &exec.Cmd{
Path: hook.Path,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we must validate the hook commands (e.g., with a configurable command binary whitelist) before really executing any of them. For example, imagine a public container cloud provider that runs kata containers inside, and then here comes a user who creates a container with rm -rf / in the OCI spec hook. BOOM!

It looks like runc does not handle it either. But kata is supposed to be more secure than runc. :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am trying not to introduce too much new code, simply doing a clean move from virtcontainers to the CLI. I think your proposal should go through a follow up PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sboeuf Please open an issue to track this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return endpoint, nil
}

func generateInterfacesAndRoutes(networkNS NetworkNamespace) ([]*grpc.Interface, []*grpc.Route, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is very Kata agent specific since it deals with grpc and not applicable for other agents. So I think it should be it in kata agent.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, but if you look at the Kata API, we're using both grpc.Interface and grpc.Route structures as the generic structures to add interfaces or routes.
I think moving this function out of kata_agent.go is the first step, and the second logical step would be to move those very generic structure definitions out of kata-containers/agent/protocols/grpc. It'd might be better to have them in a separate package so that they don't get associated with the kata-agent.


var stdout, stderr bytes.Buffer
cmd := &exec.Cmd{
Path: hook.Path,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sboeuf Please open an issue to track this.

@sboeuf
Copy link
Author

sboeuf commented Aug 24, 2018

Rebased! I'll address the comments now.

Sebastien Boeuf added 3 commits August 24, 2018 14:12
Since we removed the CNI implementation and that we agreed the network
should only be handled in a single way from virtcontainers, this patch
logically replace the "CNM" naming with "Default".

Signed-off-by: Sebastien Boeuf <[email protected]>
This commit moves the network namespace creation out of virtcontainers
in order to anticipate the move of the OCI hooks to the CLI through a
follow up commit.

Signed-off-by: Sebastien Boeuf <[email protected]>
As we want to call the OCI hook from the CLI, we need a way for the
CLI to figure out what is the network namespace used by the sandbox.
This is needed particularly because virtcontainers creates the netns
if none was provided.

Signed-off-by: Sebastien Boeuf <[email protected]>
@sboeuf sboeuf force-pushed the move_hooks branch 2 times, most recently from 03d731a to 39cfbba Compare August 24, 2018 21:30
@sboeuf
Copy link
Author

sboeuf commented Aug 24, 2018

@jodh-intel all your comments addressed. The rebase on top of the opentracing was trickier than I thought it'd be :)

Sebastien Boeuf added 2 commits August 24, 2018 15:07
The CLI being the implementation of the OCI specification, and the
hooks being OCI specific, it makes sense to move the handling of any
OCI hooks to the CLI level. This changes allows the Kata API to
become OCI agnostic.

Fixes kata-containers#599

Signed-off-by: Sebastien Boeuf <[email protected]>
If the sandbox has been initialized with a factory, this means the
caller should be in charge of adding any network to the VM, and
virtcontainers library cannot make any assumptions about adding
the default underlying network.

Signed-off-by: Sebastien Boeuf <[email protected]>
@sboeuf
Copy link
Author

sboeuf commented Aug 24, 2018

@bergwolf I have addressed your comments, PTAL

@opendev-zuul
Copy link

opendev-zuul bot commented Aug 24, 2018

Build failed (third-party-check pipeline) integration testing with
OpenStack. For information on how to proceed, see
http://docs.openstack.org/infra/manual/developers.html#automated-testing

@katacontainersbot
Copy link
Contributor

PSS Measurement:
Qemu: 169727 KB
Proxy: 4267 KB
Shim: 8816 KB

Memory inside container:
Total Memory: 2043464 KB
Free Memory: 2003564 KB

Copy link
Member

@bergwolf bergwolf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall. Just have one comment about the place to call prestart hooks.


// Run pre-start OCI hooks.
err = enterNetNS(sandboxConfig.NetworkConfig.NetNSPath, func() error {
return preStartHooks(ctx, ociSpec, containerID, bundlePath)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it can work, I wonder why we are not calling it in start.go? After all, they are preStart hooks not preCreate hooks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bergwolf This is what the OCI spec calls them. We have simply chosen to call it in create as we need the network hook to be called. @sboeuf and I had a discussion about moving to a hotplug model, but lets address that in a separate PR.

I also believe we need to evaluate if there are certain hooks that need to be run inside the VM.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth pointing out that both the current code, and this PR are somewhat abusing the standard:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amshinde @sboeuf I think we will need to move it to start.go otherwise vm factory will still be lacking network configurations. But I agree with you that it can be handled in a following up PR.

Copy link
Member

@amshinde amshinde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@amshinde
Copy link
Member

@egernst Can you take a look at this? I would like to get this merged if it looks good to you.

@egernst
Copy link
Member

egernst commented Aug 29, 2018

change is fine with me, I'll want to get @bergwolf 's ACK. I'd prefer a less awkward naming scheme (defaultNetwork when we only have one network is a bit odd), but don't want to delay this too much longer when I'm not providing a better alternative...

@amshinde
Copy link
Member

@bergwolf Can you take another look at this? Are you ok with merging this as is and address the hooks issue in a separate PR. Else we can wait for @sboeuf when he is back next week.


// Run pre-start OCI hooks.
err = enterNetNS(sandboxConfig.NetworkConfig.NetNSPath, func() error {
return preStartHooks(ctx, ociSpec, containerID, bundlePath)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amshinde @sboeuf I think we will need to move it to start.go otherwise vm factory will still be lacking network configurations. But I agree with you that it can be handled in a following up PR.

@bergwolf
Copy link
Member

Well, it looks like pullapprove really dislikes my approval and just keeps ignoring it. I'm going to ignore it as well, again.

@bergwolf bergwolf merged commit b982373 into kata-containers:master Aug 31, 2018
@egernst egernst removed the review label Aug 31, 2018
@sboeuf
Copy link
Author

sboeuf commented Sep 4, 2018

Thanks for merging this ;)

@sboeuf sboeuf added the enhancement Improvement to an existing feature label Sep 12, 2018
egernst pushed a commit to egernst/runtime that referenced this pull request Feb 9, 2021
Routes with proto kernel are automatically added by the kernel
when an interface is added with ip assigned as a subnet address.
With github.com/kata-containers#1936, these routes will no
longer be sent from the runtime.

Depends-on: github.com/kata-containers#1936

Fixes: kata-containers#623

Signed-off-by: Archana Shinde <[email protected]>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

enhancement Improvement to an existing feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cli: Move OCI hooks handling from virtcontainers to the CLI

7 participants