Skip to content

Instantly share code, notes, and snippets.

@aojea
Created August 17, 2020 20:47
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aojea/603e88ba709aac874bd7611752261772 to your computer and use it in GitHub Desktop.
Save aojea/603e88ba709aac874bd7611752261772 to your computer and use it in GitHub Desktop.
Emulate network connection on KIND clusters

KIND network emulation

Configuration parameters

  • Network bandwidth rate
  • Network latency
  • Packet loss rate

Requirements

  • iproute2
  • sch_netem kernel module

How to use it

Assuming you have already created your cluster with KIND https://kind.sigs.k8s.io/docs/user/quick-start/

and you want to emulate a network rate limited to 120mbps, with 10 ms of latency and 10% of packet loss

 ./netem.sh -r=120mbps -d=10ms -l=10
CLUSTER = 
RATE    = 120mbps
DELAY   = 10ms
LOSS    = 10
Cluster network configured correctly

if you want to remove all the network constraints, just reset the status:

./netem.sh --reset
#!/usr/bin/env bash
set -e
# Get params
for i in "$@"
do
case $i in
-n=*|--name=*)
KIND_CLUSTER="${i#*=}"
shift
;;
-r=*|--rate=*)
RATE="${i#*=}"
shift
;;
-d=*|--delay=*)
DELAY="${i#*=}"
shift
;;
-l=*|--loss=*)
LOSS="${i#*=}"
shift
;;
--reset)
RESET="true"
shift
;;
esac
done
echo "CLUSTER = ${KIND_CLUSTER}"
echo "RATE = ${RATE}"
echo "DELAY = ${DELAY}"
echo "LOSS = ${LOSS}"
# Check requirements
if ! command -v kind &> /dev/null ; then
echo "KIND is not present!"
exit 1
fi
# If we want to configure the outer interface of the
# container we need this available in the host
# if ! command -v tc &> /dev/null ; then
# echo "traffic control command is not present!"
# exit 1
#fi
if ! lsmod | grep sch_netem &> /dev/null ; then
echo "sch_netem kernel module is not loaded!"
exit 1
fi
# Get kind nodes
NODES=$(kind get nodes --name ${KIND_CLUSTER:-"kind"})
if [[ -z $NODES ]]; then
echo "no nodes found"
exit 1
fi
# Configure network for each node in the cluster:
# - htb for rate limiting
# - netem for delay and packet loss
# Use the container internal interface
# so it can work in Mac and Windows.
# In Linux we can find the outer veth interface
# and configure it instead, to be more realistic
INTERFACE="eth0"
for n in $NODES; do
CMD="docker exec -it ${n}"
# delete any previous configuration (if exist)
$CMD tc qdisc del dev ${INTERFACE} root || true
if [[ ! -z $RESET ]]; then
continue
fi
# set the parent for the netem configuration
# use root if the rate is not enabled, otherwise
# the parent will be the traffic class with the rate limit
PARENT="root"
if [[ ! -z $RATE ]]; then
# set the root qdisc using HTB for rate limit
$CMD tc qdisc add dev ${INTERFACE} root handle 1: htb
# create a class to apply the rate limit
$CMD tc class add dev ${INTERFACE} parent 1:1 classid 1:10 htb ${RATE:+rate $RATE}
# set the class as parent of the netem qdisc
PARENT="parent 1:10"
fi
# set the delay and the packet loss
if [[ ! -z $DELAY ]] || [[ ! -z $LOSS ]]; then
$CMD tc qdisc add dev ${INTERFACE} ${PARENT} netem ${DELAY:+delay $DELAY} ${LOSS:+loss $LOSS}
fi
done
echo "Cluster network configured correctly"
exit 0
@chevalsumo
Copy link

Thanks for the implementation, I have a silly question. Can this work between two gateway nodes of two clusters (connected using submariner) ? I want to emulate the networking constraints between two clusters and not within the cluster

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment