diff --git a/docs/cri/config.md b/docs/cri/config.md index 63041db75..163679aed 100644 --- a/docs/cri/config.md +++ b/docs/cri/config.md @@ -432,6 +432,8 @@ version = 2 # * ipv6 - select the first ipv6 address # * cni - use the order returned by the CNI plugins, returning the first IP address from the results ip_pref = "ipv4" + # use_internal_loopback specifies if we use the CNI loopback plugin or internal mechanism to set lo to up + use_internal_loopback = false # 'plugins."io.containerd.grpc.v1.cri".image_decryption' contains config related # to handling decryption of encrypted container images. diff --git a/internal/cri/config/config.go b/internal/cri/config/config.go index 1d1c7fc63..dec569809 100644 --- a/internal/cri/config/config.go +++ b/internal/cri/config/config.go @@ -185,6 +185,8 @@ type CniConfig struct { // * ipv6 - select the first ipv6 address // * cni - use the order returned by the CNI plugins, returning the first IP address from the results IPPreference string `toml:"ip_pref" json:"ipPref"` + // UseInternalLoopback specifies if we use the CNI loopback plugin or internal mechanism to set lo to up + UseInternalLoopback bool `toml:"use_internal_loopback" json:"useInternalLoopback"` } // Mirror contains the config related to the registry mirror diff --git a/internal/cri/config/config_unix.go b/internal/cri/config/config_unix.go index d31b090a1..7322700b4 100644 --- a/internal/cri/config/config_unix.go +++ b/internal/cri/config/config_unix.go @@ -77,6 +77,7 @@ func DefaultRuntimeConfig() RuntimeConfig { NetworkPluginMaxConfNum: 1, // only one CNI plugin config file will be loaded NetworkPluginSetupSerially: false, NetworkPluginConfTemplate: "", + UseInternalLoopback: false, }, ContainerdConfig: ContainerdConfig{ DefaultRuntimeName: "runc", diff --git a/internal/cri/config/config_windows.go b/internal/cri/config/config_windows.go index a1d4b072c..17ef08e52 100644 --- a/internal/cri/config/config_windows.go +++ b/internal/cri/config/config_windows.go @@ -47,6 +47,7 @@ func DefaultRuntimeConfig() RuntimeConfig { NetworkPluginMaxConfNum: 1, NetworkPluginSetupSerially: false, NetworkPluginConfTemplate: "", + UseInternalLoopback: false, }, ContainerdConfig: ContainerdConfig{ DefaultRuntimeName: "runhcs-wcow-process", diff --git a/internal/cri/server/sandbox_run.go b/internal/cri/server/sandbox_run.go index 0157d4b7d..8c0cb2a5e 100644 --- a/internal/cri/server/sandbox_run.go +++ b/internal/cri/server/sandbox_run.go @@ -455,7 +455,12 @@ func (c *criService) setupPodNetwork(ctx context.Context, sandbox *sandboxstore. if netPlugin == nil { return errors.New("cni config not initialized") } - + if c.config.UseInternalLoopback { + err := c.bringUpLoopback(path) + if err != nil { + return fmt.Errorf("unable to set lo to up: %w", err) + } + } opts, err := cniNamespaceOpts(id, config) if err != nil { return fmt.Errorf("get cni namespace options: %w", err) diff --git a/internal/cri/server/sandbox_run_linux.go b/internal/cri/server/sandbox_run_linux.go new file mode 100644 index 000000000..810bcc7d3 --- /dev/null +++ b/internal/cri/server/sandbox_run_linux.go @@ -0,0 +1,37 @@ +/* + 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 server + +import ( + "fmt" + + "github.com/containernetworking/plugins/pkg/ns" + "github.com/vishvananda/netlink" +) + +func (c *criService) bringUpLoopback(netns string) error { + if err := ns.WithNetNSPath(netns, func(_ ns.NetNS) error { + link, err := netlink.LinkByName("lo") + if err != nil { + return err + } + return netlink.LinkSetUp(link) + }); err != nil { + return fmt.Errorf("error setting loopback interface up: %w", err) + } + return nil +} diff --git a/internal/cri/server/sandbox_run_other.go b/internal/cri/server/sandbox_run_other.go new file mode 100644 index 000000000..8f1a2b209 --- /dev/null +++ b/internal/cri/server/sandbox_run_other.go @@ -0,0 +1,23 @@ +//go:build !windows && !linux + +/* + 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 server + +func (c *criService) bringUpLoopback(string) error { + return nil +} diff --git a/internal/cri/server/sandbox_run_windows.go b/internal/cri/server/sandbox_run_windows.go new file mode 100644 index 000000000..99ec7b2fd --- /dev/null +++ b/internal/cri/server/sandbox_run_windows.go @@ -0,0 +1,21 @@ +/* + 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 server + +func (c *criService) bringUpLoopback(string) error { + return nil +} diff --git a/internal/cri/server/service_linux.go b/internal/cri/server/service_linux.go index d9f5f3c87..55994d52e 100644 --- a/internal/cri/server/service_linux.go +++ b/internal/cri/server/service_linux.go @@ -37,10 +37,6 @@ func init() { } } -// networkAttachCount is the minimum number of networks the PodSandbox -// attaches to -const networkAttachCount = 2 - // initPlatform handles linux specific initialization for the CRI service. func (c *criService) initPlatform() (err error) { if userns.RunningInUserNS() { @@ -69,6 +65,12 @@ func (c *criService) initPlatform() (err error) { } } + networkAttachCount := 2 + + if c.Config().UseInternalLoopback { + networkAttachCount = 1 + } + c.netPlugin = make(map[string]cni.CNI) for name, dir := range pluginDirs { max := c.config.NetworkPluginMaxConfNum @@ -78,9 +80,10 @@ func (c *criService) initPlatform() (err error) { } } // Pod needs to attach to at least loopback network and a non host network, - // hence networkAttachCount is 2. If there are more network configs the - // pod will be attached to all the networks but we will only use the ip - // of the default network interface as the pod IP. + // hence networkAttachCount is 2 if the CNI plugin is used and + // 1 if the internal mechanism for setting lo to up is used. + // If there are more network configs the pod will be attached to all the networks + // but we will only use the ip of the default network interface as the pod IP. i, err := cni.New(cni.WithMinNetworkCount(networkAttachCount), cni.WithPluginConfDir(dir), cni.WithPluginMaxConfNum(max), @@ -110,5 +113,9 @@ func (c *criService) initPlatform() (err error) { // cniLoadOptions returns cni load options for the linux. func (c *criService) cniLoadOptions() []cni.Opt { + if c.config.UseInternalLoopback { + return []cni.Opt{cni.WithDefaultConf} + } + return []cni.Opt{cni.WithLoNetwork, cni.WithDefaultConf} }