Skip to content

Instantly share code, notes, and snippets.

@JapuDCret
Last active March 23, 2023 12:58
Show Gist options
  • Save JapuDCret/74e2fa1d6da937df5ba88ad76c70f258 to your computer and use it in GitHub Desktop.
Save JapuDCret/74e2fa1d6da937df5ba88ad76c70f258 to your computer and use it in GitHub Desktop.
Kubernetes forwards via dedicated docker container
cp ~/.kube/config .kube-config
docker build -t "forward-tool" .
FROM debian:stable-slim
RUN apt-get update && apt-get -y install --no-install-recommends \
gnupg \
curl \
wget \
git \
apt-transport-https \
ca-certificates \
zsh \
&& rm -rf /var/lib/apt/lists/*
# Install kubectl
RUN curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.list && \
apt-get update && apt-get -y install --no-install-recommends kubectl
ENV container_port=""
ENV local_port=""
ENV identifier=""
ENV KUBE_CONFIG_FILE=./.kube-config
ENV CONTEXT=kube-context-001
ENV NAMESPACE=default
WORKDIR /root
# Copy Kubernetes config
COPY $KUBE_CONFIG_FILE /root/.kube/config
# Copy forward script
COPY ./start-forward.sh start-forward.sh
CMD bash -c ./start-forward.sh
image_name="forward-tool"
kill_forwards () {
echo "stopping portforwarding.."
kill_service "service1"
kill_service "service2"
echo "portforwarding stopped."
}
kill_service() {
name=$1
container_name="forward-$name"
echo "($name) killing and removing container $container_name"
docker kill $container_name
docker rm $container_name
}
do_forwards () {
echo "portforwarding.."
forward_service "service1" "25565" ${PORT_SERICE1:-25565} "deployment/service1"
forward_service "service2" "3306" ${PORT_SERICE2:-3306} "statefulset/service2"
echo "portforwarding completed."
}
forward_service() {
name=$1
container_port=$2
local_port=$3
identifier=$4
container_name="forward-$name"
if [ "$(docker ps -a -f name=$container_name | grep -w $container_name)" ] ; then
if [ "$(docker ps -a -f status=exited -f name=$container_name | grep -w $container_name)" ]; then
# cleanup
kill_service $name
else
echo "($name) container $container_name already running"
return
fi
fi
echo "($name) starting $container_name to forward $identifier at $local_port"
docker run -d --rm --name $container_name --network host \
-e container_port=$container_port \
-e local_port=$local_port \
-e identifier=$identifier \
$image_name
}
if [ $1 = "kill" ] ; then
kill_forwards
else
do_forwards
fi
if [[ -z $container_port ]] ; then
echo "($identifier) container_port is undefined"
exit 1
fi
echo "($identifier) using container_port = $container_port"
if [[ -z $local_port ]] ; then
echo "($identifier) local_port is undefined"
exit 1
fi
echo "($identifier) using local_port = $local_port"
if [[ -z $identifier ]] ; then
echo "($identifier) identifier is undefined"
exit 1
fi
echo "($identifier) using identifier = $identifier"
context="${CONTEXT}"
echo "($identifier) using context = $context"
kubectl config use-context $context
namespace="${NAMESPACE}"
echo "($identifier) using namespace = $namespace"
echo "($identifier) trying to forward $identifier to $local_port"
while : ; do kubectl port-forward --namespace=$namespace $identifier $local_port:$container_port || true ; done
@JapuDCret
Copy link
Author

JapuDCret commented Mar 23, 2023

forward.sh

A tool that keeps a Kubernetes port forward open and encapsulates it in a dedicated docker container to not interfere with the host machine.

Prerequisites

  • Inside Dockerfile: Update the kube context, namespace and maybe the kube config file

Usage

Build

./build.sh

Edit forward.sh to fit your needs

Execute

./forward.sh

Kill and remove the containers

./forward.sh kill

How it works

  • Creates a Docker image with your kube config and kubectl
  • On startup runs a kubectl port-forward .. loop with your provided values (container_port, local_port, identifier)
  • Due to the container running within your host network, the local port will also be available on your machine

Why?

Kubectl's port-forward is notoriously unreliable. One can rely on higher level tools that solve the problem, but I wanted an understandable and hassle-free way of having reliable port-forwards.

At first this script was supposed to run on a host machine, but due to the fact that we have to manage sub-processes I thought it'd be much easier if we put the magic into a Docker container.

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