-
Notifications
You must be signed in to change notification settings - Fork 886
Description
Proposal
There have been many requests from end-users about having some control of the ip address assignment for containers. In order to satisfy this requirement in a common way across the different network drivers, we need to make some changes to the way ip addresses are managed today in the CNM model.
We think the address management should be deferred to a new component in libnetwork separate from the network drivers. CNM would interact with this component via a well known API during the network/endpoint creation/deletion based on the input received from user.
We are proposing to add an infrastructure and API for a new pluggable IPAM driver decoupled from the network driver.
CNM will ship with a default IPAM component, which database is strongly consistent across the cluster. User will be able to plug their own IPAM implementation and instruct CNM to use that instead of or along to the default one. CNM will provide a plugin mechanism for IPAMs similarly to the one offered for remote network drivers.
During the Network/Endpoint life cycle, libnetwork will interact with the ipam driver and allocate the minimally (for now) necessary address pool and addresses based on the user directives, if passed, or on some preallocated info otherwise. When libnetwork will invoke CreateNetwork() on network driver, it will also pass the network's ipam operational data (see IpamData below)
Initial definition of the IPAM API/contract will favor simplicity over comprehensiveness. A rough definition can be found below.
package ipam
type Config interface {
RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (string, *net.IPNet, map[string]string, error)
ReleasePool(poolID string) error
}
type Allocator interface {
RequestAddress(poolID string, preferredAddress net.IP, options map[string]string) (net.IP, map[string]string, error)
ReleaseAddress(poolID string, address net.IP) error
}
An address space is a set of non-overlapping address pools.
The subPool may or may not be supported by the driver, but idea is that it is a way to split a pool in smaller non-overlapping pools (think of the docker `FixedCIDR` use case). If subPool is specified, the poolID returned by `RequestPool() identifies the subPool`
The options passed to `RequestAddress()` may contain, for example, the endpoint's mac address.
// IPData represents the per-network or per-endpoint ipam operational
// information libnetwork will send to the network driver during
// CreateNetwork() and CreateEndpoint() calls
type IPData struct {
Pool *net.IPNet
Meta map[string]string
}
The CNM/IPAM flow follows (some behaviour listed may be specfic to the default IPAM driver):
- NewNetwork() is called. CNM will associate one or more subnet and gateway address to the new network. The subnet and gateway are optional parameters and can be specified by the caller of NewNetwork(). In case the subnet is not passed, its upto the ipam driver implementation to handle the case appropriately. The default/in-built IPAM driver will return the first un-allocated subnet from a predefined list along with a self designated address as gw. ipam plugin should return an id for the allocated subnet which will be associated with the network.
(The above sequence will repeat for as many subnets as the user passes for the network creation). - CNM invoke the CreateNetwork() on the network driver and passes along the subnet and gateway address.
- CreateEndpoint() is called. CNM will request ipam an address and store it in the endpoint.
The address is an optional parameter and can be specified by the caller of CreateEndpoint().
CNM will try to allocate an (or the preferred) address with ipam on the subnet id for this network.
(In case of multiple subnets configured per Network, user is expected to also pass the subnet during endpoint creation call, otherwise libnetwork will request from each stored subnet until succeds) - CNM invokes the CreateEndpoint() on the network driver and passes along the interface address.
- On endpoint Delete() CNM will release the address from the subnet id
- On network Delete() CNM will release the subnet id
Open items
- Regarding multiple interfaces for Endpoint: can this requirement be removed ? Otherwise CNM would need to query the network driver to find out how many interfaces are needed per endpoint.
- At this point we are not clear yet if CNM should work with only one global IPAM driver or with a per-network driver. Current thought is to allow a per-network IPAM driver.
[Updated on 9/3] As per @tomdee suggestion, added options (labels) support in API and made it more explicit that multiple subnets per network is allowed ()
[Updated on 9/14] As per @lxpollitt and @tomdee comments, replaced "subnet" with "address pool" and have request address api return a CIDR (*net.IPNet) instead of a simple ip (net.IP).
Also replaced default gateway (net.IP) with ipam metadata (map[string]string) where, for example, and ipam driver can return a default gateway in form of a (key,value) pair at time of pool request or at the time of address request.
This metadata should be useful to address the case where ipam driver is backed by a DHCP.