From 17eb92bb79650cdc3edb690a9a7289c36eab8e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Fri, 30 Aug 2019 21:41:36 +0300 Subject: [PATCH] Implement hostPort support with CNI --- pkg/network/cni/cni.go | 49 +++++++++++++++++++++++++++--------- pkg/network/docker/docker.go | 3 ++- pkg/network/types.go | 3 ++- pkg/operations/remove.go | 2 +- pkg/operations/start.go | 2 +- 5 files changed, 43 insertions(+), 16 deletions(-) diff --git a/pkg/network/cni/cni.go b/pkg/network/cni/cni.go index 2bc2fa6a5..bec788b2c 100644 --- a/pkg/network/cni/cni.go +++ b/pkg/network/cni/cni.go @@ -10,6 +10,7 @@ import ( gocni "github.com/containerd/go-cni" log "github.com/sirupsen/logrus" + meta "github.com/weaveworks/ignite/pkg/apis/meta/v1alpha1" "github.com/weaveworks/ignite/pkg/constants" "github.com/weaveworks/ignite/pkg/network" "github.com/weaveworks/ignite/pkg/runtime" @@ -31,18 +32,28 @@ const ( // igniteCNIConf is a base CNI configuration that will enable VMs to access the internet connection (docker-bridge style) var igniteCNIConf = `{ - "cniVersion": "0.4.0", - "name": "ignite-containerd-default", - "type": "bridge", - "bridge": "cni0", - "isGateway": true, - "isDefaultGateway": true, - "promiscMode": true, - "ipMasq": true, - "ipam": { + "cniVersion": "0.4.0", + "name": "ignite-containerd-bridge", + "plugins": [ + { + "type": "bridge", + "bridge": "cni0", + "isGateway": true, + "isDefaultGateway": true, + "promiscMode": true, + "ipMasq": true, + "ipam": { "type": "host-local", "subnet": "172.18.0.0/16" - } + } + }, + { + "type": "portmap", + "capabilities": { + "portMappings": true + } + } + ] } ` @@ -85,7 +96,7 @@ func (plugin *cniNetworkPlugin) PrepareContainerSpec(container *runtime.Containe return nil } -func (plugin *cniNetworkPlugin) SetupContainerNetwork(containerid string) (*network.Result, error) { +func (plugin *cniNetworkPlugin) SetupContainerNetwork(containerid string, portMappings ...meta.PortMapping) (*network.Result, error) { if err := plugin.initialize(); err != nil { return nil, err } @@ -95,8 +106,22 @@ func (plugin *cniNetworkPlugin) SetupContainerNetwork(containerid string) (*netw return nil, fmt.Errorf("CNI failed to retrieve network namespace path: %v", err) } + pms := []gocni.PortMapping{} + for _, pm := range portMappings { + hostIP := "" + if pm.BindAddress != nil { + hostIP = pm.BindAddress.String() + } + pms = append(pms, gocni.PortMapping{ + HostPort: int32(pm.HostPort), + ContainerPort: int32(pm.VMPort), + Protocol: pm.Protocol.String(), + HostIP: hostIP, + }) + } + netnsPath := fmt.Sprintf(netNSPathFmt, c.PID) - result, err := plugin.cni.Setup(context.Background(), containerid, netnsPath) + result, err := plugin.cni.Setup(context.Background(), containerid, netnsPath, gocni.WithCapabilityPortMap(pms)) if err != nil { log.Errorf("failed to setup network for namespace %q: %v", containerid, err) return nil, err diff --git a/pkg/network/docker/docker.go b/pkg/network/docker/docker.go index d321f477f..4d4192672 100644 --- a/pkg/network/docker/docker.go +++ b/pkg/network/docker/docker.go @@ -4,6 +4,7 @@ import ( "fmt" "net" + meta "github.com/weaveworks/ignite/pkg/apis/meta/v1alpha1" "github.com/weaveworks/ignite/pkg/network" "github.com/weaveworks/ignite/pkg/runtime" ) @@ -25,7 +26,7 @@ func (*dockerNetworkPlugin) PrepareContainerSpec(_ *runtime.ContainerConfig) err return nil } -func (plugin *dockerNetworkPlugin) SetupContainerNetwork(containerID string) (*network.Result, error) { +func (plugin *dockerNetworkPlugin) SetupContainerNetwork(containerID string, _ ...meta.PortMapping) (*network.Result, error) { // This is used to fetch the IP address the runtime gives to the VM container result, err := plugin.runtime.InspectContainer(containerID) if err != nil { diff --git a/pkg/network/types.go b/pkg/network/types.go index bfc157529..f91ce053c 100644 --- a/pkg/network/types.go +++ b/pkg/network/types.go @@ -4,6 +4,7 @@ import ( "fmt" "net" + meta "github.com/weaveworks/ignite/pkg/apis/meta/v1alpha1" "github.com/weaveworks/ignite/pkg/runtime" ) @@ -17,7 +18,7 @@ type Plugin interface { // SetupContainerNetwork sets up the networking for a container // This is ran _after_ the container has been started - SetupContainerNetwork(containerID string) (*Result, error) + SetupContainerNetwork(containerID string, portmappings ...meta.PortMapping) (*Result, error) // RemoveContainerNetwork is the method called before a container using the network plugin can be deleted RemoveContainerNetwork(containerID string) error diff --git a/pkg/operations/remove.go b/pkg/operations/remove.go index b447b9343..3dc449269 100644 --- a/pkg/operations/remove.go +++ b/pkg/operations/remove.go @@ -98,6 +98,6 @@ func StopVM(vm *api.VM, kill, silent bool) error { } func removeNetworking(containerID string) error { - log.Debugf("Removing the container with ID %q from the %q network", containerID, providers.NetworkPlugin.Name()) + log.Infof("Removing the container with ID %q from the %q network", containerID, providers.NetworkPlugin.Name()) return providers.NetworkPlugin.RemoveContainerNetwork(containerID) } diff --git a/pkg/operations/start.go b/pkg/operations/start.go index 61b7f6f72..d26cc232e 100644 --- a/pkg/operations/start.go +++ b/pkg/operations/start.go @@ -108,7 +108,7 @@ func StartVM(vm *api.VM, debug bool) error { } // Set up the networking - result, err := providers.NetworkPlugin.SetupContainerNetwork(containerID) + result, err := providers.NetworkPlugin.SetupContainerNetwork(containerID, vm.Spec.Network.Ports...) if err != nil { return err }