diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container.go | 12 | ||||
-rw-r--r-- | libpod/kube.go | 22 | ||||
-rw-r--r-- | libpod/network/config.go | 5 | ||||
-rw-r--r-- | libpod/network/create.go | 31 | ||||
-rw-r--r-- | libpod/network/netconflist.go | 22 | ||||
-rw-r--r-- | libpod/network/network.go | 12 | ||||
-rw-r--r-- | libpod/options.go | 29 | ||||
-rw-r--r-- | libpod/pod.go | 1 | ||||
-rw-r--r-- | libpod/runtime_pod_infra_linux.go | 14 |
9 files changed, 122 insertions, 26 deletions
diff --git a/libpod/container.go b/libpod/container.go index 58bf95470..ed7535bc8 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -1073,6 +1073,18 @@ func networkDisabled(c *Container) (bool, error) { return false, nil } +func (c *Container) HostNetwork() bool { + if c.config.CreateNetNS || c.config.NetNsCtr != "" { + return false + } + for _, ns := range c.config.Spec.Linux.Namespaces { + if ns.Type == spec.NetworkNamespace { + return false + } + } + return true +} + // ContainerState returns containerstate struct func (c *Container) ContainerState() (*ContainerState, error) { if !c.batched { diff --git a/libpod/kube.go b/libpod/kube.go index b5197293e..bf314b9a3 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -49,6 +49,7 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) { } extraHost := make([]v1.HostAlias, 0) + hostNetwork := false if p.HasInfraContainer() { infraContainer, err := p.getInfraContainer() if err != nil { @@ -69,9 +70,9 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) { return nil, servicePorts, err } servicePorts = containerPortsToServicePorts(ports) - + hostNetwork = p.config.InfraContainer.HostNetwork } - pod, err := p.podWithContainers(allContainers, ports) + pod, err := p.podWithContainers(allContainers, ports, hostNetwork) if err != nil { return nil, servicePorts, err } @@ -167,7 +168,7 @@ func containersToServicePorts(containers []v1.Container) []v1.ServicePort { return sps } -func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPort) (*v1.Pod, error) { +func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPort, hostNetwork bool) (*v1.Pod, error) { deDupPodVolumes := make(map[string]*v1.Volume) first := true podContainers := make([]v1.Container, 0, len(containers)) @@ -220,10 +221,10 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor podVolumes = append(podVolumes, *vol) } - return addContainersAndVolumesToPodObject(podContainers, podVolumes, p.Name(), &dnsInfo), nil + return addContainersAndVolumesToPodObject(podContainers, podVolumes, p.Name(), &dnsInfo, hostNetwork), nil } -func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1.Volume, podName string, dnsOptions *v1.PodDNSConfig) *v1.Pod { +func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1.Volume, podName string, dnsOptions *v1.PodDNSConfig, hostNetwork bool) *v1.Pod { tm := v12.TypeMeta{ Kind: "Pod", APIVersion: "v1", @@ -242,8 +243,9 @@ func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1. CreationTimestamp: v12.Now(), } ps := v1.PodSpec{ - Containers: containers, - Volumes: volumes, + Containers: containers, + Volumes: volumes, + HostNetwork: hostNetwork, } if dnsOptions != nil { ps.DNSConfig = dnsOptions @@ -261,8 +263,12 @@ func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1. func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) { kubeCtrs := make([]v1.Container, 0, len(ctrs)) kubeVolumes := make([]v1.Volume, 0) + hostNetwork := true podDNS := v1.PodDNSConfig{} for _, ctr := range ctrs { + if !ctr.HostNetwork() { + hostNetwork = false + } kubeCtr, kubeVols, ctrDNS, err := containerToV1Container(ctr) if err != nil { return nil, err @@ -303,7 +309,7 @@ func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) { } } // end if ctrDNS } - return addContainersAndVolumesToPodObject(kubeCtrs, kubeVolumes, strings.ReplaceAll(ctrs[0].Name(), "_", ""), &podDNS), nil + return addContainersAndVolumesToPodObject(kubeCtrs, kubeVolumes, strings.ReplaceAll(ctrs[0].Name(), "_", ""), &podDNS, hostNetwork), nil } // containerToV1Container converts information we know about a libpod container diff --git a/libpod/network/config.go b/libpod/network/config.go index ce351129e..294e23509 100644 --- a/libpod/network/config.go +++ b/libpod/network/config.go @@ -103,7 +103,9 @@ func (p PortMapConfig) Bytes() ([]byte, error) { // IPAMDHCP describes the ipamdhcp config type IPAMDHCP struct { - DHCP string `json:"type"` + DHCP string `json:"type"` + Routes []IPAMRoute `json:"routes,omitempty"` + Ranges [][]IPAMLocalHostRangeConf `json:"ranges,omitempty"` } // MacVLANConfig describes the macvlan config @@ -111,6 +113,7 @@ type MacVLANConfig struct { PluginType string `json:"type"` Master string `json:"master"` IPAM IPAMDHCP `json:"ipam"` + MTU int `json:"mtu,omitempty"` } // Bytes outputs the configuration as []byte diff --git a/libpod/network/create.go b/libpod/network/create.go index a8f985af9..deacf487a 100644 --- a/libpod/network/create.go +++ b/libpod/network/create.go @@ -29,7 +29,7 @@ func Create(name string, options entities.NetworkCreateOptions, runtimeConfig *c return nil, err } defer l.releaseCNILock() - if len(options.MacVLAN) > 0 { + if len(options.MacVLAN) > 0 || options.Driver == MacVLANNetworkDriver { fileName, err = createMacVLAN(name, options, runtimeConfig) } else { fileName, err = createBridge(name, options, runtimeConfig) @@ -249,6 +249,7 @@ func createBridge(name string, options entities.NetworkCreateOptions, runtimeCon func createMacVLAN(name string, options entities.NetworkCreateOptions, runtimeConfig *config.Config) (string, error) { var ( + mtu int plugins []CNIPlugins ) liveNetNames, err := GetLiveNetworkNames() @@ -256,9 +257,17 @@ func createMacVLAN(name string, options entities.NetworkCreateOptions, runtimeCo return "", err } - // Make sure the host-device exists - if !util.StringInSlice(options.MacVLAN, liveNetNames) { - return "", errors.Errorf("failed to find network interface %q", options.MacVLAN) + // The parent can be defined with --macvlan or as an option (-o parent:device) + parentNetworkDevice := options.MacVLAN + if len(parentNetworkDevice) < 1 { + if parent, ok := options.Options["parent"]; ok { + parentNetworkDevice = parent + } + } + + // Make sure the host-device exists if provided + if len(parentNetworkDevice) > 0 && !util.StringInSlice(parentNetworkDevice, liveNetNames) { + return "", errors.Errorf("failed to find network interface %q", parentNetworkDevice) } if len(name) > 0 { netNames, err := GetNetworkNamesFromFileSystem(runtimeConfig) @@ -275,7 +284,19 @@ func createMacVLAN(name string, options entities.NetworkCreateOptions, runtimeCo } } ncList := NewNcList(name, version.Current(), options.Labels) - macvlan := NewMacVLANPlugin(options.MacVLAN) + if val, ok := options.Options["mtu"]; ok { + intVal, err := strconv.Atoi(val) + if err != nil { + return "", err + } + if intVal > 0 { + mtu = intVal + } + } + macvlan, err := NewMacVLANPlugin(parentNetworkDevice, options.Gateway, &options.Range, &options.Subnet, mtu) + if err != nil { + return "", err + } plugins = append(plugins, macvlan) ncList["plugins"] = plugins b, err := json.MarshalIndent(ncList, "", " ") diff --git a/libpod/network/netconflist.go b/libpod/network/netconflist.go index 165a9067b..9be98e78f 100644 --- a/libpod/network/netconflist.go +++ b/libpod/network/netconflist.go @@ -172,15 +172,31 @@ func HasDNSNamePlugin(paths []string) bool { } // NewMacVLANPlugin creates a macvlanconfig with a given device name -func NewMacVLANPlugin(device string) MacVLANConfig { +func NewMacVLANPlugin(device string, gateway net.IP, ipRange *net.IPNet, subnet *net.IPNet, mtu int) (MacVLANConfig, error) { i := IPAMDHCP{DHCP: "dhcp"} + if gateway != nil || ipRange != nil || subnet != nil { + ipam, err := NewIPAMLocalHostRange(subnet, ipRange, gateway) + if err != nil { + return MacVLANConfig{}, err + } + ranges := make([][]IPAMLocalHostRangeConf, 0) + ranges = append(ranges, ipam) + i.Ranges = ranges + } m := MacVLANConfig{ PluginType: "macvlan", - Master: device, IPAM: i, } - return m + if mtu > 0 { + m.MTU = mtu + } + // CNI is supposed to use the default route if a + // parent device is not provided + if len(device) > 0 { + m.Master = device + } + return m, nil } // IfPassesFilter filters NetworkListReport and returns true if the filter match the given config diff --git a/libpod/network/network.go b/libpod/network/network.go index 0fb878b18..0ff14c1f7 100644 --- a/libpod/network/network.go +++ b/libpod/network/network.go @@ -17,11 +17,17 @@ import ( "github.com/sirupsen/logrus" ) -// DefaultNetworkDriver is the default network type used -var DefaultNetworkDriver = "bridge" +var ( + // BridgeNetworkDriver defines the bridge cni driver + BridgeNetworkDriver = "bridge" + // DefaultNetworkDriver is the default network type used + DefaultNetworkDriver = BridgeNetworkDriver + // MacVLANNetworkDriver defines the macvlan cni driver + MacVLANNetworkDriver = "macvlan" +) // SupportedNetworkDrivers describes the list of supported drivers -var SupportedNetworkDrivers = []string{DefaultNetworkDriver} +var SupportedNetworkDrivers = []string{BridgeNetworkDriver, MacVLANNetworkDriver} // isSupportedDriver checks if the user provided driver is supported func isSupportedDriver(driver string) error { diff --git a/libpod/options.go b/libpod/options.go index c7bac7e1f..20f62ee37 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -2190,13 +2190,37 @@ func WithPodNetworks(networks []string) PodCreateOption { } } +// WithPodNoNetwork tells the pod to disable external networking. +func WithPodNoNetwork() PodCreateOption { + return func(pod *Pod) error { + if pod.valid { + return define.ErrPodFinalized + } + + if !pod.config.InfraContainer.HasInfraContainer { + return errors.Wrapf(define.ErrInvalidArg, "cannot disable pod networking as no infra container is being created") + } + + if len(pod.config.InfraContainer.PortBindings) > 0 || + pod.config.InfraContainer.StaticIP != nil || + pod.config.InfraContainer.StaticMAC != nil || + len(pod.config.InfraContainer.Networks) > 0 || + pod.config.InfraContainer.HostNetwork { + return errors.Wrapf(define.ErrInvalidArg, "cannot disable pod network if network-related configuration is specified") + } + + pod.config.InfraContainer.NoNetwork = true + + return nil + } +} + // WithPodHostNetwork tells the pod to use the host's network namespace. func WithPodHostNetwork() PodCreateOption { return func(pod *Pod) error { if pod.valid { return define.ErrPodFinalized } - if !pod.config.InfraContainer.HasInfraContainer { return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod host networking as no infra container is being created") } @@ -2204,7 +2228,8 @@ func WithPodHostNetwork() PodCreateOption { if len(pod.config.InfraContainer.PortBindings) > 0 || pod.config.InfraContainer.StaticIP != nil || pod.config.InfraContainer.StaticMAC != nil || - len(pod.config.InfraContainer.Networks) > 0 { + len(pod.config.InfraContainer.Networks) > 0 || + pod.config.InfraContainer.NoNetwork { return errors.Wrapf(define.ErrInvalidArg, "cannot set host network if network-related configuration is specified") } diff --git a/libpod/pod.go b/libpod/pod.go index c8f62ca18..784c2cf5e 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -93,6 +93,7 @@ type podState struct { type InfraContainerConfig struct { ConmonPidFile string `json:"conmonPidFile"` HasInfraContainer bool `json:"makeInfraContainer"` + NoNetwork bool `json:"noNetwork,omitempty"` HostNetwork bool `json:"infraHostNetwork,omitempty"` PortBindings []ocicni.PortMapping `json:"infraPortBindings"` StaticIP net.IP `json:"staticIP,omitempty"` diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go index dd957527d..564851f4e 100644 --- a/libpod/runtime_pod_infra_linux.go +++ b/libpod/runtime_pod_infra_linux.go @@ -94,8 +94,16 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm } } - // Since user namespace sharing is not implemented, we only need to check if it's rootless - if !p.config.InfraContainer.HostNetwork { + switch { + case p.config.InfraContainer.HostNetwork: + if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil { + return nil, errors.Wrapf(err, "error removing network namespace from pod %s infra container", p.ID()) + } + case p.config.InfraContainer.NoNetwork: + // Do nothing - we have a network namespace by default, + // but should not configure slirp. + default: + // Since user namespace sharing is not implemented, we only need to check if it's rootless netmode := "bridge" if isRootless || p.config.InfraContainer.Slirp4netns { netmode = "slirp4netns" @@ -106,8 +114,6 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm // PostConfigureNetNS should not be set since user namespace sharing is not implemented // and rootless networking no longer supports post configuration setup options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, false, netmode, p.config.InfraContainer.Networks)) - } else if err := g.RemoveLinuxNamespace(string(spec.NetworkNamespace)); err != nil { - return nil, errors.Wrapf(err, "error removing network namespace from pod %s infra container", p.ID()) } // For each option in InfraContainerConfig - if set, pass into |