The provided code is a Python script that implements a Container Network Interface (CNI) project for Kubernetes. It leverages the etcd3 Python library to interact with an etcd key-value store to manage network configuration for Kubernetes pods.
The code relies on several Python libraries, which need to be installed for the script to work correctly:
etcd3: This library provides the necessary functionality to interact with an etcd key-value store.socket: Thegethostnameandgethostbynamefunctions from this library are used to retrieve the hostname and IP address of the current host.ipaddress: Theip_networkfunction from this library is used to manipulate IP subnets.itertools: Theislicefunction from this library is used to iterate over a subset of elements.subprocess: Therunfunction from this library is used to execute shell commands.json: Thedumpfunction from this library is used to write JSON data to a file.os: Thechmodandenvironfunctions from this library are used to set file permissions and access environment variables, respectively.jinja2: This library provides a templating engine to generate dynamic configuration files.
The script relies on several environment variables to configure its behavior. These variables are:
ETCD_HOST: The address of the etcd server.CNI_VERSION: The version of the CNI specification.CNI_NAME: The name of the CNI plugin.CNI_TYPE: The type of the CNI plugin.BRIDGE_NAME: The name of the bridge network interface.IP_SUBNET: The base IP subnet for the pod network.IP_SUBNET_MARGIN: The number of subnets to allocate from the base IP subnet.ETCD_PREFIX: The prefix used for keys in the etcd store.ETCD_COUNTER_KEY: The key in the etcd store used to store the subnet counter.CNI_CONFIG_LOCATION: The file path where the CNI configuration will be written.CNI_PLUGIN_LOCATION: The file path where the CNI plugin will be written.
This function retrieves the current value of a counter stored in the etcd store. It takes a client_obj (an etcd3 client object) and a key as arguments. It sets the value associated with the key to an empty string if it doesn't exist. It then retrieves the metadata for the key and returns the version of the metadata.
This function retrieves all hosts from the etcd store. It takes a client_obj (an etcd3 client object) as an argument. It retrieves all key-value pairs with the specified ETCD_PREFIX and returns a dictionary mapping hostnames to their corresponding IP addresses.
This function creates routes for the specified hosts using the ip route add command. It takes hosts (a dictionary of hostnames and IP addresses) and bridge_subnet (the current host's subnet) as arguments. It iterates over each host and its IP address and executes the ip route add command to add a route to the host via the current host's IP address.
This function retrieves the IP subnet associated with the current host from the etcd store. It takes a client_obj (an etcd3 client object) and a key as arguments. If the subnet doesn't exist, it retrieves the current value of the subnet counter and increments it. It then stores the new subnet in the etcd store and returns it.
This function creates a bridge network interface using the brctl addbr and ip commands. It takes bridge_subnet (the current host's subnet) as an argument. It executes the brctl addbr command to create a bridge with the specified BRIDGE_NAME. It then brings up the bridge interface using the ip link set command and assigns the bridge_subnet to the bridge interface using the ip addr add command.
This function writes the CNI configuration to a file. It takes bridge_subnet (the current host's subnet) as an argument. It creates a JSON object representing the CNI configuration and writes it to the file specified by CNI_CONFIG_LOCATION. It also sets the file permissions to 0o600 (read and write permissions for the owner).
This function writes the CNI plugin script to a file. It takes bridge_subnet (the current host's subnet) as an argument. It uses the jinja2 templating engine togenerate the content of the CNI plugin script based on a template file. The template file (templates/plugin.j2) is loaded using the Environment object from the jinja2 library. The template variables CNI_VERSION, BRIDGE_NAME, and bridge_subnet are passed to the template rendering process. The rendered content is then written to the file specified by CNI_PLUGIN_LOCATION. The file permissions are set to 0o700 (read, write, and execute permissions for the owner).
The main execution of the script starts by retrieving the current host's subnet using the get_host_subnet function. It then calls the create_bridge function to create the bridge network interface. Next, it retrieves all hosts from the etcd store using the get_hosts function and calls the create_routes function to create routes to those hosts. After that, it calls the write_config function to generate and write the CNI configuration file. Finally, it calls the write_plugin function to generate and write the CNI plugin script.
The script enters an infinite loop where it watches for events in the etcd store using the etcd_client.watch_prefix function. Whenever an event occurs, it retrieves the key and value of the event and calls the create_routes function to create a route to the corresponding host.
This code implements a CNI project for Kubernetes using Python and interacts with an etcd key-value store for network configuration management. It creates a bridge network interface, assigns subnets to hosts, creates routes, and generates the necessary CNI configuration and plugin files.