How to open a tunnel to a Kubernetes pod or container with tcpserver and netcat

Note: translation.: This practical note from the creator of LayerCI is an excellent illustration of the so-called tips & tricks for Kubernetes (and beyond). The solution proposed here is just one of the few and perhaps not the most obvious ones (for some cases, the 'native' for K8s mentioned in the comments might suffice). kubectl port-forward). However, it at least allows you to look at the problem from the perspective of applying classic utilities and their further combination — simultaneously simple, flexible, and powerful (see 'other ideas' at the end for inspiration).

How to open a tunnel to a Kubernetes pod or container with tcpserver and netcat

Imagine a typical situation: you want a port on your local computer to magically redirect traffic to a pod/container (or vice versa).

Possible use cases

  1. Check what an HTTP endpoint returns /healthz of the pod in the production cluster.
  2. Connect a TCP debugger to the pod on your local machine.
  3. Access the production database from local database management tools without having to deal with authentication (usually, localhost has root permissions).
  4. Run a one-off migration script for data in the staging cluster without needing to create a container for it.
  5. Connect a VNC session to the pod running a virtual desktop (see XVFB).

A few words about necessary tools

Tcpserver — An open-source utility available in most Linux package repositories. It allows you to open a local port and redirect traffic received via stdin/stdout from any specified command:

colin@colin-work:~$ tcpserver 127.0.0.1 8080 echo -e 'HTTP/1.0 200 OK\nContent-Length: 19\n\n<body>hello!</body>'&amp;\n[1] 17377\ncolin@colin-work:~$ curl localhost:8080
<body>hello!</body>colin@colin-work:~$

(asciinema.org)

Netcat does the opposite. It allows you to connect to an open port and send the input/output received from it to stdin/stdout:

colin@colin-work:~$ nc -C httpstat.us 80
GET /200 HTTP/1.0
Host: httpstat.us
HTTP/1.1 200 OK
Cache-Control: private
Server: Microsoft-IIS/10.0
X-AspNetMvc-Version: 5.1
Access-Control-Allow-Origin: *
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=93fdbab9d364704de8ef77182b4d13811344b7dd1ec45d3a9682bbd6fa154ead;Path=/;HttpOnly;Domain=httpstat.us
Date: Fri, 01 Nov 2019 17:53:04 GMT
Connection: close
Content-Length: 0

^C
colin@colin-work:~$

(asciinema.org)

In the example above, netcat requests the page via HTTP. The flag -C causes it to append CRLF at the end of the line.

Combining with kubectl: listen on the host and connect to the pod

If we combine the tools presented above with kubectl, we would get a command like this:

tcpserver 127.0.0.1 8000 kubectl exec -i web-pod nc 127.0.0.1 8080

Similarly, to access port 80 inside the pod, you just need to do curl "127.0.0.1:80":

colin@colin-work:~$ sanic kubectl exec -it web-54dfb667b6-28n85 bash
root@web-54dfb667b6-28n85:/web# apt-get -y install netcat-openbsd
Reading package lists... Done
Building dependency tree
Reading state information... Done
netcat-openbsd is already the newest version (1.195-2).
0 upgraded, 0 newly installed, 0 to remove and 10 not upgraded.
root@web-54dfb667b6-28n85:/web# exit
colin@colin-work:~$ tcpserver 127.0.0.1 8000 sanic kubectl exec -i web-54dfb667b6-28n85 nc 127.0.0.1 8080&
[1] 3232
colin@colin-work:~$ curl localhost:8000/healthz
{"status":"ok"}colin@colin-work:~$ exit

(asciinema.org)

How to open a tunnel to a Kubernetes pod or container with tcpserver and netcat
Utility Interaction Diagram

In the opposite direction: listen in the pod and connect to the host

nc 127.0.0.1 8000 | kubectl exec -i web-pod tcpserver 127.0.0.1 8080 cat

This command allows the pod to access port 8000 on the local machine.

Bash Script

I wrote a special Bash script to manage the production Kubernetes cluster. LayerCI, using the method described above:

kubetunnel() {
    POD="$1"
    DESTPORT="$2"
    if [ -z "$POD" -o -z "$DESTPORT" ]; then
        echo "Usage: kubetunnel [pod name] [destination port]"
        return 1
    fi
    pkill -f 'tcpserver 127.0.0.1 6666'
    tcpserver 127.0.0.1 6666 kubectl exec -i "$POD" nc 127.0.0.1 "$DESTPORT"&
    echo "Connect to 127.0.0.1:6666 to access $POD:$DESTPORT"
}

If you add this function to ~/ .bashrc, you can easily open a tunnel to the pod with the command kubetunnel web-pod 8080 and execute curl localhost:6666.

  • For the tunnel in Docker you can replace the main line with:
    tcpserver 127.0.0.1 6666 docker exec -i "$CONTAINER" nc 127.0.0.1 "$DESTPORT"
  • for the tunnel in K3s — change it to:
    tcpserver 127.0.0.1 6666 k3s kubectl exec …
  • etc.

Other Ideas

  • Redirecting UDP traffic can be done with commands netcat -l -u -c instead of tcpserver and netcat -u instead of netcat respectively.
  • View input/output through pipe viewer:

    nc 127.0.0.1 8000 | pv --progress | kubectl exec -i web-pod tcpserver 127.0.0.1 8080 cat

  • Traffic can be compressed and decompressed on both ends using gzip.
  • Connect via SSH to another computer with the appropriate file kubeconfig:

    tcpserver ssh workcomputer "kubectl exec -i my-pod nc 127.0.0.1 80"

  • You can connect two pods in different clusters using mkfifo and run two separate commands kubectl.

The possibilities are endless!

P.S. from the translator

Also read in our blog:

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster