{"id":17999415,"url":"https://github.com/ehazlett/circuit","last_synced_at":"2025-03-26T06:31:42.775Z","repository":{"id":57522153,"uuid":"70663455","full_name":"ehazlett/circuit","owner":"ehazlett","description":"Container Network Management","archived":false,"fork":false,"pushed_at":"2020-04-17T20:03:13.000Z","size":14636,"stargazers_count":44,"open_issues_count":0,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-24T12:54:25.870Z","etag":null,"topics":["cni","containerd","containers","grpc","networking"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ehazlett.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-10-12T04:42:17.000Z","updated_at":"2024-11-02T01:26:50.000Z","dependencies_parsed_at":"2022-08-26T23:41:29.189Z","dependency_job_id":null,"html_url":"https://github.com/ehazlett/circuit","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehazlett%2Fcircuit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehazlett%2Fcircuit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehazlett%2Fcircuit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehazlett%2Fcircuit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ehazlett","download_url":"https://codeload.github.com/ehazlett/circuit/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245603813,"owners_count":20642882,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cni","containerd","containers","grpc","networking"],"created_at":"2024-10-29T22:12:45.723Z","updated_at":"2025-03-26T06:31:37.762Z","avatar_url":"https://github.com/ehazlett.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"```\n      _                _ _\n     (_)              (_) |\n  ___ _ _ __ ___ _   _ _| |_\n / __| | '__/ __| | | | | __|\n| (__| | | | (__| |_| | | |_\n \\___|_|_|  \\___|\\__,_|_|\\__|\n\n```\n\n![CI](https://github.com/ehazlett/circuit/workflows/CI/badge.svg)\n\n# Circuit\nCircuit is a container management application for [containerd](https://github.com/containerd/containerd).\n\nIt can be used imperitively to connect/disconnect containers to/from networks and also run as a daemon to\nlisten for containerd events and connect/disconnect containers automatically.\n\nCircuit can also provide basic restart capabilities for containers.  By adding the `io.circuit.restart` label,\nthe daemon will monitor containers and restart if they exit.\n\nCircuit can be used with a [CoreDNS](https://coredns.io/) [Plugin](https://github.com/ehazlett/circuit-coredns)\nto provide DNS responses for containers.  This is most useful with the [macvlan](https://github.com/containernetworking/plugins/tree/master/plugins/main/macvlan)\nCNI plugin.  Circuit uses [Redis](https://redis.io/) to provide basic clustering to enable container IP resolution\nacross a fleet of Circuit nodes.\n\n# Usage\nThe daemon and cli is combined in a single binary.\n\n## Daemon\nTo run the daemon, use the `server` subcommand:\n\n```\n$\u003e circuit server\n```\n\nThis will start the GRPC server on port `8080` by default.\n\n## CLI\nTo use the CLI start the server and then use the various subcommands:\n\nCircuit network definitions are simply CNI specs.  To create a network for use with Circuit, use the `create` command.\n\nAs an example, you can create a bridge network using the following config as `bridge.json`:\n\n```\n{\n    \"cniVersion\": \"0.3.1\",\n    \"name\": \"ctr0\",\n    \"plugins\": [\n        {\n            \"type\": \"bridge\",\n            \"bridge\": \"ctr0\",\n            \"isDefaultGateway\": true,\n            \"forceAddress\": false,\n            \"ipMasq\": true,\n            \"hairpinMode\": true,\n            \"ipam\": {\n                \"type\": \"host-local\",\n                \"subnet\": \"10.255.0.0/16\"\n            }\n        }\n    ]\n}\n```\n\nCreate the network in Circuit:\n\n```\n$\u003e circuit network create ctr0 bridge.json\n```\n\nYou can then list networks:\n\n```\n$\u003e circuit network ls\nNAME      TYPE\nctr0      bridge\n```\n\nRun a container with no external networking:\n\n```\n$\u003e ctr run -t docker.io/library/alpine:latest shell sh\n/ # ip a s\n1: lo: \u003cLOOPBACK,UP,LOWER_UP\u003e mtu 65536 qdisc noqueue state UNKNOWN qlen 1000\n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n    inet 127.0.0.1/8 scope host lo\n       valid_lft forever preferred_lft forever\n    inet6 ::1/128 scope host\n       valid_lft forever preferred_lft forever\n```\n\nNow connect the `shell` container to the `ctr0` network:\n\nNote: make sure to have the CNI plugins [installed](https://github.com/containernetworking/plugins/releases) to `/opt/containerd/bin` (can be changed with `--cni-path`).\n\n```\n$\u003e circuit network connect shell ctr0\nconnected shell to ctr0 with ip=10.255.0.2\n```\n\nConfirm that the container has the interface:\n\n```\n/ # ip a s\n1: lo: \u003cLOOPBACK,UP,LOWER_UP\u003e mtu 65536 qdisc noqueue state UNKNOWN qlen 1000\n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n    inet 127.0.0.1/8 scope host lo\n       valid_lft forever preferred_lft forever\n    inet6 ::1/128 scope host\n       valid_lft forever preferred_lft forever\n3: eth0@if45: \u003cBROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN\u003e mtu 1500 qdisc noqueue state UP\n    link/ether 22:e0:21:33:ec:18 brd ff:ff:ff:ff:ff:ff\n    inet 10.255.0.3/16 brd 10.255.255.255 scope global eth0\n       valid_lft forever preferred_lft forever\n    inet6 fe80::20e0:21ff:fe33:ec18/64 scope link\n       valid_lft forever preferred_lft forever\n```\n\nYou can also see all of the container IPs:\n\n```\n$\u003e circuit network ips shell\nNETWORK   IP              INTERFACE\nctr0      10.255.0.3      eth0\n```\n\n## Automatic Networking\nCircuit can run as a daemon and use containerd events to automatically connect and disconnect\ncontainers.\n\nNote: currently automatic connection is limited to a single network.\n\nTo enable automatic connecting, use the `io.circuit.network` label when creating the container:\n\n```\n$\u003e ctr run -t --label io.circuit.network=ctr0 docker.io/library/alpine:latest shell sh\n```\n\nThere should already be an additional interface in the container:\n\n```\n/ # ip a s\n1: lo: \u003cLOOPBACK,UP,LOWER_UP\u003e mtu 65536 qdisc noqueue state UNKNOWN qlen 1000\n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n    inet 127.0.0.1/8 scope host lo\n       valid_lft forever preferred_lft forever\n    inet6 ::1/128 scope host\n       valid_lft forever preferred_lft forever\n3: eth0@if46: \u003cBROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN\u003e mtu 1500 qdisc noqueue state UP\n    link/ether de:6a:45:37:7a:5d brd ff:ff:ff:ff:ff:ff\n    inet 10.255.0.4/16 brd 10.255.255.255 scope global eth0\n       valid_lft forever preferred_lft forever\n    inet6 fe80::dc6a:45ff:fe37:7a5d/64 scope link tentative\n       valid_lft forever preferred_lft forever\n```\n\nYou should also see a log message for the connect event:\n```\nDEBU[0004] task start: container=shell pid=23217\nINFO[0005] connected shell to ctr0 with ip 10.255.0.5\n```\n\n# Clustering\nCircuit can be configured to use [Redis](https://redis.io/) so that when querying for the container IP\n(i.e `circuit network ips \u003cname\u003e`) the Circuit nodes will query each other internally and return\nall known IPs of containers with that name.  Note: you will need to setup a Redis host separately.\n\nTo form a Circuit cluster, simply configure the Circuit server to connect to Redis:\n\n```\n$\u003e circuit server --redis-url redis://1.2.3.4:6379\n```\n\nYou can then list all available nodes:\n\n```\n$\u003e circuit cluster nodes\nNAME\nwhite-rabbit\n```\n\nYou can then query for container IPs across all Circuit nodes:\n\n```\n$\u003e circuit network ips shell\nNETWORK   IP             INTERFACE\nctr0      10.10.214.28   eth0\n```\n\nThis will query the Circuit cluster for all available IPs of containers with the name `shell`.\n\n# API\nThere is a GRPC API that the CLI uses for management.  This can also be used in third party applications for more control\nover container network management.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehazlett%2Fcircuit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fehazlett%2Fcircuit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehazlett%2Fcircuit/lists"}