How to setup Coil
May 29, 2026 ยท View on GitHub
This document describes step-by-step instructions for installing Coil to Kubernetes.
All the instructions should be done under the v2/ directory.
The YAML manifests of Coil can be generated using kustomize.
You can tweak optional parameters by editing kustomization.yaml file.
- Install
kustomize - TLS certificates
- Edit
kustomization.yaml - Edit
netconf.json - Compile and apply the manifest
- Define the default address pool
- (Option) Configure BIRD
- Note on CRI runtime compatibility
- Standalone egress
Install kustomize
Follow the instructions: https://kubectl.docs.kubernetes.io/installation/kustomize/
kustomize 4.1.3 is verified to work for Coil.
TLS certificates
Coil runs admission webhook servers, and each one needs a self-signed certificate. You can either generate certificates manually or have Coil create them when it starts up.
Generate certificates manually
Run make certs under v2/ directory to generate the certificates.
$ make certs
This should generate the following PEM files:
$ ls config/default/*.pem
config/default/cert.pem config/default/egress-key.pem config/default/ipam-key.pem
config/default/egress-cert.pem config/default/ipam-cert.pem config/default/key.pem
Enable automatic certs rotation
Run make enable-certs-rotation under v2/ directory to enable automatic certificate generation in coil.
$ make enable-certs-rotation
This will configure the kustomization files that will can be later used by make install-coil target.
Edit kustomization.yaml
kustomization.yaml under v2/ directory contains some commented option settings.
Uncomment if you want to enable them.
If all the nodes are connected in a flat L2 network, enabling coil-router is recommended.
$ vi kustomization.yaml
Edit netconf.json
netconf.json under v2/ directory is just an example CNI network configuration
(actually, the example is a network configuration list).
You may edit the file to, say, add Cilium for network policies or to tune MTU.
Note that coil must be the first in the plugin list if IPAM is enabled.
vi netconf.json
These documents help you to edit the configuration.
The following example adds tuning and bandwidth plugins.
{
"cniVersion": "0.4.0",
"name": "k8s-pod-network",
"plugins": [
{
"type": "coil",
"socket": "/run/coild.sock",
},
{
"type": "tuning",
"mtu": 1400
},
{
"type": "bandwidth",
"capabilities": {
"bandwidth": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
Compile and apply the manifest
Now you can compile the manifest with kustomize and apply it to your cluster.
$ kustomize build . > coil.yaml
$ kubectl apply -f coil.yaml
Define the default address pool
There should be the default address pool for Pods. Create a YAML manifest like this and apply it.
apiVersion: coil.cybozu.com/v2
kind: AddressPool
metadata:
name: default
spec:
blockSizeBits: 5
subnets:
- ipv4: 10.100.0.0/16
blockSizeBits: 5 means that blocks of 32 (= ) addresses will be carved out.subnets: a list of IP subnets in this pool.
IPv6 pool
To define an IPv6 address pool, change the spec as follows:
spec:
blockSizeBits: 8
subnets:
- ipv6: fd02::/96
IPv4/v6 dual stack pool
To define an IPv4/v6 dual stack pool, change the spec as follows:
spec:
blockSizeBits: 5
subnets:
- ipv4: 10.100.0.0/16
ipv6: fd02::/112
Note that IPv4 and IPv6 subnet must be the same size. In the above example, their sizes are 16 bits.
(Option) Configure BIRD
If your nodes are not connected each other within a flat L2 network, or
if you did not enable coil-router in kustomization.yaml, you need to
configure some routing software to advertise routes.
Coil exports routing information in an unused kernel routing table. By default, the routing table ID is 119.
Routing software should import routes from the table. Following is a configuration snippet for BIRD.
# export4 is a table to be used for routing protocol such as BGP
ipv4 table export4;
# Import Coil routes into export4
protocol kernel 'coil' {
kernel table 119; # the routing table coild exports routes.
learn;
scan time 1;
ipv4 {
table export4;
import all;
export none;
};
}
# Import routes from external routers into master4, the main table for IPv4 routes
protocol pipe {
table master4;
peer table export4;
import filter {
if proto = "coil" then reject;
accept;
};
export none;
}
# Reflect routes in master4 into the Linux kernel
protocol kernel {
ipv4 {
export all;
};
}
# This is merely an example of using BGP to exchange routes between external routers
protocol bgp {
local as __ASN__;
neighbor __PEER_ADDRESS__ as __PEER_ASN__;
ipv4 {
table export4;
import all;
export all;
next hop self;
};
}
Note on CRI runtime compatibility
coild needs to see the network namespace (netns) files on the host.
Such files are usually created under /proc.
coild shares the PID namespace to see netns files under /proc, so
if your CRI runtime passes file path under /proc to CNI plugins,
there is no problem.
Some CRI runtimes are known to bind mount netns files under /var/run/netns.
The default manifest of coild mounts that host directory, so if your CRI
runtime passes file path under /var/run/netns, there is also no problem.
Otherwise, coild might not work with your CRI runtime.
In such cases, you need to edit config/pod/coild.yaml to mount the right
host directory.
Standalone egress
Coil can be run as standalone egress NAT controller, using CNI chaining with another CNI providing base connectivity. This chapter will guide you on how to achieve this.
Configuration
To deploy Coil with only egress feature enabled the following changes are required in the configuration files:
-
Comment all IPAM related pieces in the following
kustomization.yamlfiles:v2/config/crd/kustomization.yamlv2/config/default/kustomization.yamlv2/config/pod/kustomization.yamlv2/config/rbac/kustomization.yaml
-
Comment unnecessary resources in
config/crd/patches/remove_status.yaml. -
Add following arguments to the
coildcontianer executable inconfig/pod/coild.yamlcontainers: - name: coild image: coil:dev command: ["coild"] args: - --zap-stacktrace-level=panic - --enable-ipam=false - --enable-egress=true - --pod-table-id=0 # 255 if IPv6 is being used - --protocol-id=2 -
Set CNI config filename using environment variable for init contianer
coil-installerinconfig/pod/coild.yaml:env: - name: CNI_CONF_NAME value: "01-coil.conflist" -
Add configuration of your chosen CNI to
v2/netconf.jsonbeforecoilrelated configuration. -
Deploy
coilto existing cluster as described in Compile and apply the manifest.
Testing standalone egress
Testing with Kindnet using IPv4
- Generate certificates using
v2/Makefile.cd v2 && make certs - Go to
v2/e2ecd e2e - Export the scenario environment (egress-only IPv4):
export WITH_IPAM=false TEST_IPV4=true TEST_IPV6=false - Create IPv4 based Kind cluster with Kindnet CNI deployed:
make start - Install Coil on the cluster:
make install-coil - Run egress-only IPv4 tests:
make test
Testing with Kindnet using IPv6
- Generate certificates using
v2/Makefile.cd v2 && make certs - Go to
v2/e2ecd e2e - Export the scenario environment (egress-only IPv6):
export WITH_IPAM=false TEST_IPV4=false TEST_IPV6=true - Create IPv6 based Kind cluster with Kindnet CNI deployed:
make start - Install Coil on the cluster:
make install-coil - Run egress-only IPv6 tests:
make test