From 2a0b2ee9ebc11dc8d707064749564b666e10fe7a Mon Sep 17 00:00:00 2001 From: songjiang han Date: Fri, 11 Mar 2022 23:50:20 +0800 Subject: [PATCH] fix: ctr run --cni get failed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit when user executes ctr run --cni to start a container,it will call cni plugin to create network .But when user kills it,the network won’t be removed. if we run a container with same namespace and name again will trigger a bug. we should remove the network when user kills task if it enables cni plugin. Fix:#6604 Signed-off-by: SongJiang Han --- cmd/ctr/commands/cni.go | 51 ++++++++++++++++++++++++++++++++ cmd/ctr/commands/run/run.go | 15 ++-------- cmd/ctr/commands/run/run_unix.go | 4 +++ cmd/ctr/commands/tasks/kill.go | 38 ++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 13 deletions(-) create mode 100644 cmd/ctr/commands/cni.go diff --git a/cmd/ctr/commands/cni.go b/cmd/ctr/commands/cni.go new file mode 100644 index 000000000..c7e20b3bc --- /dev/null +++ b/cmd/ctr/commands/cni.go @@ -0,0 +1,51 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package commands + +import ( + "context" + "fmt" + + "github.com/containerd/containerd" + "github.com/containerd/containerd/namespaces" + "github.com/containerd/typeurl" +) + +func init() { + typeurl.Register(&NetworkMetaData{}, + "github.com/containerd/containerd/cmd/ctr/commands", "NetworkMetaData") +} + +const ( + + // CtrCniMetadataExtension is an extension name that identify metadata of container in CreateContainerRequest + CtrCniMetadataExtension = "ctr.cni-containerd.metadata" +) + +//ctr pass cni network metadata to containerd if ctr run use option of --cni +type NetworkMetaData struct { + EnableCni bool +} + +func FullID(ctx context.Context, c containerd.Container) string { + id := c.ID() + ns, ok := namespaces.Namespace(ctx) + if !ok { + return id + } + return fmt.Sprintf("%s-%s", ns, id) +} diff --git a/cmd/ctr/commands/run/run.go b/cmd/ctr/commands/run/run.go index bf0ebfe5c..77414b1ab 100644 --- a/cmd/ctr/commands/run/run.go +++ b/cmd/ctr/commands/run/run.go @@ -17,7 +17,6 @@ package run import ( - "context" gocontext "context" "encoding/csv" "errors" @@ -31,7 +30,6 @@ import ( "github.com/containerd/containerd/cmd/ctr/commands/tasks" "github.com/containerd/containerd/containers" clabels "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/oci" gocni "github.com/containerd/go-cni" specs "github.com/opencontainers/runtime-spec/specs-go" @@ -196,7 +194,7 @@ var Command = cli.Command{ if !detach { defer func() { if enableCNI { - if err := network.Remove(ctx, fullID(ctx, container), ""); err != nil { + if err := network.Remove(ctx, commands.FullID(ctx, container), ""); err != nil { logrus.WithError(err).Error("network review") } } @@ -218,7 +216,7 @@ var Command = cli.Command{ return err } - if _, err := network.Setup(ctx, fullID(ctx, container), netNsPath); err != nil { + if _, err := network.Setup(ctx, commands.FullID(ctx, container), netNsPath); err != nil { return err } } @@ -251,15 +249,6 @@ var Command = cli.Command{ }, } -func fullID(ctx context.Context, c containerd.Container) string { - id := c.ID() - ns, ok := namespaces.Namespace(ctx) - if !ok { - return id - } - return fmt.Sprintf("%s-%s", ns, id) -} - // buildLabel builds the labels from command line labels and the image labels func buildLabels(cmdLabels, imageLabels map[string]string) map[string]string { labels := make(map[string]string) diff --git a/cmd/ctr/commands/run/run_unix.go b/cmd/ctr/commands/run/run_unix.go index 69283e111..f20437a80 100644 --- a/cmd/ctr/commands/run/run_unix.go +++ b/cmd/ctr/commands/run/run_unix.go @@ -214,6 +214,10 @@ func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli ) } + if context.Bool("cni") { + cniMeta := &commands.NetworkMetaData{EnableCni: true} + cOpts = append(cOpts, containerd.WithContainerExtension(commands.CtrCniMetadataExtension, cniMeta)) + } if caps := context.StringSlice("cap-add"); len(caps) > 0 { for _, cap := range caps { if !strings.HasPrefix(cap, "CAP_") { diff --git a/cmd/ctr/commands/tasks/kill.go b/cmd/ctr/commands/tasks/kill.go index 3aef2c9f7..bdbfaab8b 100644 --- a/cmd/ctr/commands/tasks/kill.go +++ b/cmd/ctr/commands/tasks/kill.go @@ -17,16 +17,50 @@ package tasks import ( + "context" "errors" + "fmt" "github.com/containerd/containerd" "github.com/containerd/containerd/cmd/ctr/commands" + gocni "github.com/containerd/go-cni" + "github.com/containerd/typeurl" "github.com/moby/sys/signal" + "github.com/sirupsen/logrus" "github.com/urfave/cli" ) const defaultSignal = "SIGTERM" +func RemoveCniNetworkIfExist(ctx context.Context, container containerd.Container) error { + exts, err := container.Extensions(ctx) + if err != nil { + return err + } + networkMeta, ok := exts[commands.CtrCniMetadataExtension] + if !ok { + return nil + } + + data, err := typeurl.UnmarshalAny(&networkMeta) + if err != nil { + return fmt.Errorf("failed to unmarshal cni metadata extension %s", commands.CtrCniMetadataExtension) + } + networkMetaData := data.(*commands.NetworkMetaData) + + var network gocni.CNI + if networkMetaData.EnableCni { + if network, err = gocni.New(gocni.WithDefaultConf); err != nil { + return err + } + if err := network.Remove(ctx, commands.FullID(ctx, container), ""); err != nil { + logrus.WithError(err).Error("network remove error") + return err + } + } + return nil +} + var killCommand = cli.Command{ Name: "kill", Usage: "signal a container (default: SIGTERM)", @@ -93,6 +127,10 @@ var killCommand = cli.Command{ if err != nil { return err } + err = RemoveCniNetworkIfExist(ctx, container) + if err != nil { + return err + } return task.Kill(ctx, sig, opts...) }, }