circuit
circuit copied to clipboard
Container Network Management
_ _ _
(_) (_) |
___ _ _ __ ___ _ _ _| |_
/ __| | '__/ __| | | | | __|
| (__| | | | (__| |_| | | |_
\___|_|_| \___|\__,_|_|\__|
Circuit
Circuit is a container management application for containerd.
It can be used imperitively to connect/disconnect containers to/from networks and also run as a daemon to listen for containerd events and connect/disconnect containers automatically.
Circuit can also provide basic restart capabilities for containers. By adding the io.circuit.restart
label,
the daemon will monitor containers and restart if they exit.
Circuit can be used with a CoreDNS Plugin to provide DNS responses for containers. This is most useful with the macvlan CNI plugin. Circuit uses Redis to provide basic clustering to enable container IP resolution across a fleet of Circuit nodes.
Usage
The daemon and cli is combined in a single binary.
Daemon
To run the daemon, use the server
subcommand:
$> circuit server
This will start the GRPC server on port 8080
by default.
CLI
To use the CLI start the server and then use the various subcommands:
Circuit network definitions are simply CNI specs. To create a network for use with Circuit, use the create
command.
As an example, you can create a bridge network using the following config as bridge.json
:
{
"cniVersion": "0.3.1",
"name": "ctr0",
"plugins": [
{
"type": "bridge",
"bridge": "ctr0",
"isDefaultGateway": true,
"forceAddress": false,
"ipMasq": true,
"hairpinMode": true,
"ipam": {
"type": "host-local",
"subnet": "10.255.0.0/16"
}
}
]
}
Create the network in Circuit:
$> circuit network create ctr0 bridge.json
You can then list networks:
$> circuit network ls
NAME TYPE
ctr0 bridge
Run a container with no external networking:
$> ctr run -t docker.io/library/alpine:latest shell sh
/ # ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
Now connect the shell
container to the ctr0
network:
Note: make sure to have the CNI plugins installed to /opt/containerd/bin
(can be changed with --cni-path
).
$> circuit network connect shell ctr0
connected shell to ctr0 with ip=10.255.0.2
Confirm that the container has the interface:
/ # ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: eth0@if45: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 22:e0:21:33:ec:18 brd ff:ff:ff:ff:ff:ff
inet 10.255.0.3/16 brd 10.255.255.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::20e0:21ff:fe33:ec18/64 scope link
valid_lft forever preferred_lft forever
You can also see all of the container IPs:
$> circuit network ips shell
NETWORK IP INTERFACE
ctr0 10.255.0.3 eth0
Automatic Networking
Circuit can run as a daemon and use containerd events to automatically connect and disconnect containers.
Note: currently automatic connection is limited to a single network.
To enable automatic connecting, use the io.circuit.network
label when creating the container:
$> ctr run -t --label io.circuit.network=ctr0 docker.io/library/alpine:latest shell sh
There should already be an additional interface in the container:
/ # ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: eth0@if46: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether de:6a:45:37:7a:5d brd ff:ff:ff:ff:ff:ff
inet 10.255.0.4/16 brd 10.255.255.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::dc6a:45ff:fe37:7a5d/64 scope link tentative
valid_lft forever preferred_lft forever
You should also see a log message for the connect event:
DEBU[0004] task start: container=shell pid=23217
INFO[0005] connected shell to ctr0 with ip 10.255.0.5
Clustering
Circuit can be configured to use Redis so that when querying for the container IP
(i.e circuit network ips <name>
) the Circuit nodes will query each other internally and return
all known IPs of containers with that name. Note: you will need to setup a Redis host separately.
To form a Circuit cluster, simply configure the Circuit server to connect to Redis:
$> circuit server --redis-url redis://1.2.3.4:6379
You can then list all available nodes:
$> circuit cluster nodes
NAME
white-rabbit
You can then query for container IPs across all Circuit nodes:
$> circuit network ips shell
NETWORK IP INTERFACE
ctr0 10.10.214.28 eth0
This will query the Circuit cluster for all available IPs of containers with the name shell
.
API
There is a GRPC API that the CLI uses for management. This can also be used in third party applications for more control over container network management.