A system component in databox managing container-to-container and container-to-external communications
- CM, arbiter, core-network will be put on a network
databox-system-net
- CM calls on core-network to identify itself as a privileged entity, then CM is authorized to resolve all the other components that core-network knows of and make connections with them
- A dedicated network is created, core-network then gets attached to it, and by default external access is disallowed on this network
- After parsing SLA, CM gathers all the entities that this component would like to communicate with (arbiter, and its dependent stores, datasources etc.), and call on core-network to enable these, which includes being able to resolve host names and make connections with previously resolved IP addresses
- When CM starts the app/driver and its dependent stores, their DNS servers will be pointed to core-network
- CM calls on core-network to disable all the communications, giving the being removed service name and its IP address. This mainly helps core-network to recollect resources and delete un-usuful states
- CM checks if this is the last component on its dedicated network, if so, remove the network, if not, this network will be kept and reusued when a user possibly wants to reinstall a related service
core-network oprates on IP packet, for all the other L4 traffic, it only concerns itself with DNS queries.
All the control policies are stored within two data structures:
transport: Set of (src_ip, dst_ip')
resolve: Map from src_ip to (host name, dst_ip') list
When a packet comes in from an interface, its (src_ip, dst_ip') pair is checked against transport
, only existed pairs are allowed to move on, otherwise the packet will get dropped. And when a DNS query comes in, the src_ip of the query and the name it wants to resolve are extracted, then it tries to find a dst_ip' from resolve
.
Another point worth mentioning is that all the src_ip
s are the IP addresses that currently used by containers, and almost all the dst_ip'
s are spoofed by core-network on each interface within the same subnet as with associated src_ip
s.
When CM calls on core-network to enable communication for a pair of host names, core-network firstly tries to resolve those to (src_ip, dst_ip). If they are coming from the same subnet, like driver and its dependent store, only resolve
will be updated to contain these new infomation. Since core-network serves as the DNS server for them, when driver wants to talk to its store, a DNS query will be expected to come up in core-network, and core-network could lookup resolve
to return the IP of the store. When src_ip and dst_ip are from different subnets, like app and one of its datasources, core-network will spoof dst_ip' and src_ip' on both of those two networks, and transport
will be updated with (src_ip, dst_ip') and also (dst_ip, src_ip'), so that traffic could come back and forth from both sides. resolve
will also be updated accrodingly, DNS requires from both sides will be replied with spoofed addresses within their same subnets. This also implies that there is a NAT-like module which is in charge of translating from (src_ip, dst_ip') to (src_ip', dst_ip) before sending the packet out.
So a container can't communicate with an entity which it doesn't declare explicitly in the manifest, cause no such infomation reside in resolve
and NXDOMAIN
will be returned. It can't use an IP directly either, cause everything is constraint to happen locally, and all the contactable IPs on the local subnet are either its dependent stores, or are spoofed and controlled by core-network.
All of the following calls are intended to be invoked only by core-container-manager, and caller is authenticated by a key.
POST /privileged
input: {"src_ip": <string>}
src_ip
is a privileged source IP. Any DNS queries or communications from this IP will be served. CM calls on this when it starts up.
POST /connect
input: {"name":<string>, "peers":[<string>]}
name
is the service's host name which CM wants to enable communications for, peers
is an array of peer host names that this service may want connmunicate with.
POST /disconnect
intput: {"name":<string>, "ip":<string>}
name
is the service about to be removed, and ip
is its IP address. core-container uses these to delete related states.
POST /restart
intput: {"name":<string>, "old_ip":<string>, "new_ip":<string>}
name
is the restarted service, and old_ip
is its IP address before restart, new_ip
is the new IP address after retart. core-network updates the policies accroding to this change.
GET /status
This returns a string 'active'
.