Last active
July 18, 2024 08:39
-
-
Save jb-alvarado/2ef1645e06859f7d04e2b2258b02689d to your computer and use it in GitHub Desktop.
Add poddman container to existing host bridge
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/bash | |
# This script manages network interfaces for Podman containers. Podman is a daemonless container engine | |
# for developing, managing, and running OCI Containers on your Linux System. | |
# | |
# The script takes three arguments: an operation (either "start" or "stop"), a container name, and an IPv4 | |
# address for the container. If any of these arguments are missing, the script will exit with an error message. | |
# | |
# The script first checks if it's being run as root. If not, it prepends `sudo` to certain commands to ensure | |
# they have the necessary permissions. | |
# | |
# The script then sets up some variables, including the bridge interface name (`br0`), the IPv4 address with | |
# a subnet mask (`ipv4`), the virtual Ethernet device ID (`veth_id`), the virtual Ethernet device name | |
# (`veth_dev`), the gateway IP address (`gate`), and the container interface name (`cont_iface`). | |
# | |
# The script then retrieves the full container ID using the `podman inspect` command and constructs a network | |
# namespace name from it. | |
# | |
# If the operation is "start", the script starts the container, creates a directory for network namespaces | |
# if it doesn't exist, retrieves the container's PID, and creates a symlink from the container's network | |
# namespace to a file in the `/var/run/netns` directory. It then creates a virtual Ethernet device, attaches | |
# it to the bridge, moves the peer interface to the container's network namespace, renames the peer interface, | |
# brings up both interfaces, assigns the IPv4 address to the container's interface, and adds a default route | |
# in the container's network namespace. | |
# | |
# If the operation is "stop", the script removes the default route in the container's network namespace, | |
# removes the IPv4 address from the container's interface, brings down both interfaces, stops the container, | |
# and removes the symlink to the container's network namespace. | |
# | |
# This script is a example of how to manually manage network interfaces for containers when you need more | |
# control than the default networking provided by container runtimes. | |
# | |
# The idea to this script comes from podman network documentation: | |
# https://github.com/containers/podman/blob/main/docs/tutorials/performance.md#network-performance-for-rootless-podman | |
# and a podman list post from Rudolf Vesely: | |
# https://lists.podman.io/archives/list/[email protected]/thread/W6MCYO6RY5YFRTSUDAOEZA7SC2EFXRZE/ | |
# start / stop | |
operation=$1 | |
# container name | |
container=$2 | |
# container ip v4 | |
cont_ip4=$3 | |
SUDO="" | |
if [[ -z "$operation" ]] || [[ -z "$container" ]] || [[ -z "$cont_ip4" ]]; then | |
echo "Run command with 'start/stop' 'container name' 'IP'!" | |
exit 1 | |
fi | |
# when not runniing as root, for rootful containers, | |
# run system commands with sudo, for footless container. | |
if (( $EUID != 0 )); then | |
SUDO="sudo" | |
fi | |
bridge="br0" | |
ipv4="${cont_ip4}/24" | |
veth_id="$(echo -n "$cont_ip4" | tail -c 2 | sed 's/.//g')" | |
veth_id="$(printf "%02d" $veth_id)" | |
veth_dev="veth3${veth_id}" | |
gate="10.10.0.1" | |
cont_iface="eth0" | |
# container need to be created with no network interface: | |
# podman run --net=none ... | |
# get full container ID | |
cont_id=$(podman inspect -f '{{.Id}}' $container) | |
net_ns_name="cont-${cont_id}" | |
if [[ $operation == "start" ]]; then | |
podman start $container | |
# create folder if not exists | |
[[ ! -d /var/run/netns ]] && $SUDO mkdir -v /var/run/netns | |
# get container pid, works only on running containers | |
cont_pc_id=$(podman inspect -f '{{.State.Pid}}' "${cont_id}") | |
# symlink container pid to container name id | |
$SUDO ln -sfT "/proc/${cont_pc_id}/ns/net" "/var/run/netns/${net_ns_name}" | |
# create virtual interface on existing bridge interface | |
# start interface and add default route | |
$SUDO ip link add $veth_dev type veth peer name veth300p | |
$SUDO ip link set dev $veth_dev master $bridge | |
$SUDO ip link set veth300p netns "$net_ns_name" | |
$SUDO ip -netns "$net_ns_name" link set veth300p name "$cont_iface" | |
$SUDO ip link set dev $veth_dev up | |
$SUDO ip -netns "$net_ns_name" link set dev "$cont_iface" up | |
$SUDO ip -netns "$net_ns_name" address add "$ipv4" dev "$cont_iface" | |
$SUDO ip -netns "$net_ns_name" route add default via "$gate" | |
elif [[ $operation == "stop" ]]; then | |
# remove route and virtual interface | |
$SUDO ip -netns "$net_ns_name" route del default via "$gate" | |
$SUDO ip -netns "$net_ns_name" address del "$ipv4" dev "$cont_iface" | |
$SUDO ip -netns "$net_ns_name" link set dev "$cont_iface" down | |
$SUDO ip link set dev $veth_dev down | |
podman stop $container | |
$SUDO rm -f "/var/run/netns/$net_ns_name" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment