pkg/config: add new default_subnet_pools field

Add a new field to set the default subnet pools. They can be used to
change the subnet which is automatically allocated by podman network
create.

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger 2022-02-14 18:53:19 +01:00
parent 4ae6102976
commit b76062811b
6 changed files with 146 additions and 7 deletions

View File

@ -307,6 +307,25 @@ The network name of the default network to attach pods to.
The subnet to use for the default network (named above in **default_network**).
If the default network does not exist, it will be automatically created the first time a tool is run using this subnet.
**default_subnet_pools**=[]
DefaultSubnetPools is a list of subnets and size which are used to
allocate subnets automatically for podman network create.
It will iterate through the list and will pick the first free subnet
with the given size. This is only used for ipv4 subnets, ipv6 subnets
are always assigned randomly.
The default list is (10.89.0.0-10.255.255.0/24):
```
default_subnet_pools = [
{"base" = "10.89.0.0/16", "size" = 24},
{"base" = "10.90.0.0/15", "size" = 24},
{"base" = "10.92.0.0/14", "size" = 24},
{"base" = "10.96.0.0/11", "size" = 24},
{"base" = "10.128.0.0/9", "size" = 24},
]
```
**network_config_dir**="/etc/cni/net.d/"
Path to the directory where network configuration files are located.

View File

@ -10,6 +10,7 @@ import (
"sync"
"github.com/BurntSushi/toml"
"github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/capabilities"
"github.com/containers/storage/pkg/unshare"
units "github.com/docker/go-units"
@ -486,20 +487,36 @@ type NetworkConfig struct {
// CNIPluginDirs is where CNI plugin binaries are stored.
CNIPluginDirs []string `toml:"cni_plugin_dirs,omitempty"`
// DefaultNetwork is the network name of the default CNI network
// DefaultNetwork is the network name of the default network
// to attach pods to.
DefaultNetwork string `toml:"default_network,omitempty"`
// DefaultSubnet is the subnet to be used for the default CNI network.
// DefaultSubnet is the subnet to be used for the default network.
// If a network with the name given in DefaultNetwork is not present
// then a new network using this subnet will be created.
// Must be a valid IPv4 CIDR block.
DefaultSubnet string `toml:"default_subnet,omitempty"`
// NetworkConfigDir is where CNI network configuration files are stored.
// DefaultSubnetPools is a list of subnets and size which are used to
// allocate subnets automatically for podman network create.
// It will iterate through the list and will pick the first free subnet
// with the given size. This is only used for ipv4 subnets, ipv6 subnets
// are always assigned randomly.
DefaultSubnetPools []SubnetPool `toml:"default_subnet_pools,omitempty"`
// NetworkConfigDir is where network configuration files are stored.
NetworkConfigDir string `toml:"network_config_dir,omitempty"`
}
type SubnetPool struct {
// Base is a bigger subnet which will be used to allocate a subnet with
// the given size.
Base *types.IPNet `toml:"base,omitempty"`
// Size is the CIDR for the new subnet. It must be equal or small
// than the CIDR from the base subnet.
Size int `toml:"size,omitempty"`
}
// SecretConfig represents the "secret" TOML config table
type SecretConfig struct {
// Driver specifies the secret driver to use.
@ -830,6 +847,21 @@ func (c *ContainersConfig) Validate() error {
// execution checks. It returns an `error` on validation failure, otherwise
// `nil`.
func (c *NetworkConfig) Validate() error {
if &c.DefaultSubnetPools != &DefaultSubnetPools {
for _, pool := range c.DefaultSubnetPools {
if pool.Base.IP.To4() == nil {
return errors.Errorf("invalid subnet pool ip %q", pool.Base.IP)
}
ones, _ := pool.Base.IPNet.Mask.Size()
if ones > pool.Size {
return errors.Errorf("invalid subnet pool, size is bigger than subnet %q", &pool.Base.IPNet)
}
if pool.Size > 32 {
return errors.New("invalid subnet pool size, must be between 0-32")
}
}
}
if stringsEq(c.CNIPluginDirs, DefaultCNIPluginDirs) {
return nil
}

View File

@ -8,6 +8,7 @@ import (
"path"
"strings"
"github.com/containers/common/libnetwork/types"
. "github.com/onsi/ginkgo"
"github.com/onsi/gomega"
)
@ -83,6 +84,56 @@ var _ = Describe("Config Local", func() {
gomega.Expect(err).NotTo(gomega.BeNil())
})
It("should fail on invalid subnet pool", func() {
validDirPath, err := ioutil.TempDir("", "config-empty")
if err != nil {
panic(err)
}
defer os.RemoveAll(validDirPath)
// Given
sut.Network.NetworkConfigDir = validDirPath
sut.Network.CNIPluginDirs = []string{validDirPath}
net, _ := types.ParseCIDR("10.0.0.0/24")
sut.Network.DefaultSubnetPools = []SubnetPool{
{Base: &net, Size: 16},
}
// When
err = sut.Network.Validate()
// Then
gomega.Expect(err).NotTo(gomega.BeNil())
sut.Network.DefaultSubnetPools = []SubnetPool{
{Base: &net, Size: 33},
}
// When
err = sut.Network.Validate()
// Then
gomega.Expect(err).NotTo(gomega.BeNil())
})
It("parse network subnet pool", func() {
config, err := NewConfig("testdata/containers_default.conf")
// Then
gomega.Expect(err).To(gomega.BeNil())
net1, _ := types.ParseCIDR("10.89.0.0/16")
net2, _ := types.ParseCIDR("10.90.0.0/15")
gomega.Expect(config.Network.DefaultSubnetPools).To(gomega.Equal(
[]SubnetPool{{
Base: &net1,
Size: 24,
}, {
Base: &net2,
Size: 24,
}},
))
})
It("should fail during runtime", func() {
validDirPath, err := ioutil.TempDir("", "config-empty")
if err != nil {

View File

@ -284,6 +284,20 @@ default_sysctls = [
#
#default_subnet = "10.88.0.0/16"
# DefaultSubnetPools is a list of subnets and size which are used to
# allocate subnets automatically for podman network create.
# It will iterate through the list and will pick the first free subnet
# with the given size. This is only used for ipv4 subnets, ipv6 subnets
# are always assigned randomly.
#
#default_subnet_pools = [
# {"base" = "10.89.0.0/16", "size" = 24},
# {"base" = "10.90.0.0/15", "size" = 24},
# {"base" = "10.92.0.0/14", "size" = 24},
# {"base" = "10.96.0.0/11", "size" = 24},
# {"base" = "10.128.0.0/9", "size" = 24},
#]
# Path to the directory where network configuration files are located.
# For the CNI backend the default is "/etc/cni/net.d" as root
# and "$HOME/.config/cni/net.d" as rootless.

View File

@ -3,12 +3,14 @@ package config
import (
"bytes"
"fmt"
"net"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
nettypes "github.com/containers/common/libnetwork/types"
"github.com/containers/common/pkg/apparmor"
"github.com/containers/common/pkg/cgroupv2"
"github.com/containers/common/pkg/util"
@ -85,8 +87,26 @@ var (
"/usr/lib/cni",
"/opt/cni/bin",
}
DefaultSubnetPools = []SubnetPool{
// 10.89.0.0/24-10.255.255.0/24
parseSubnetPool("10.89.0.0/16", 24),
parseSubnetPool("10.90.0.0/15", 24),
parseSubnetPool("10.92.0.0/14", 24),
parseSubnetPool("10.96.0.0/11", 24),
parseSubnetPool("10.128.0.0/9", 24),
}
)
// nolint:unparam
func parseSubnetPool(subnet string, size int) SubnetPool {
_, n, _ := net.ParseCIDR(subnet)
return SubnetPool{
Base: &nettypes.IPNet{IPNet: *n},
Size: size,
}
}
const (
// _etcDir is the sysconfdir where podman should look for system config files.
// It can be overridden at build time.
@ -111,7 +131,7 @@ const (
// DefaultSignaturePolicyPath is the default value for the
// policy.json file.
DefaultSignaturePolicyPath = "/etc/containers/policy.json"
// DefaultSubnet is the subnet that will be used for the default CNI
// DefaultSubnet is the subnet that will be used for the default
// network.
DefaultSubnet = "10.88.0.0/16"
// DefaultRootlessSignaturePolicyPath is the location within
@ -195,9 +215,10 @@ func DefaultConfig() (*Config, error) {
UserNSSize: DefaultUserNSSize,
},
Network: NetworkConfig{
DefaultNetwork: "podman",
DefaultSubnet: DefaultSubnet,
CNIPluginDirs: DefaultCNIPluginDirs,
DefaultNetwork: "podman",
DefaultSubnet: DefaultSubnet,
DefaultSubnetPools: DefaultSubnetPools,
CNIPluginDirs: DefaultCNIPluginDirs,
},
Engine: *defaultEngineConfig,
Secrets: defaultSecretConfig(),

View File

@ -103,6 +103,8 @@ cni_plugin_dirs = [
# Path to the directory where CNI configuration files are located.
network_config_dir = "/etc/cni/net.d/"
default_subnet_pools = [{"base" = "10.89.0.0/16", "size" = 24}, {"base" = "10.90.0.0/15", "size" = 24}]
[engine]
# Cgroup management implementation used for the runtime.