Double port forwarding kubernetes + docker
Summary:
I have a docker container which is running kubectl port-forward, forwarding the port (5432) of a postgres service running as a k8s service to a local port (2223).
In the Dockerfile, I have exposed the relevant port 2223. Then I ran the container by publishing the said port (-p 2223:2223
)
Now when I am trying to access the postgres through psql -h localhost -p 2223
, I am getting the following error:
psql: server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
However, when I do docker exec -ti
to the said container and run the above psql command, I am able to connect to postgres.
Dockerfile CMD:
EXPOSE 2223
CMD ["bash", "-c", "kubectl -n namespace_test port-forward service/postgres-11-2 2223:5432"]
Docker Run command:
docker run -it --name=k8s-conn-12 -p 2223:2223 my_image_name:latest
Output of the docker run command:
Forwarding from 127.0.0.1:2223 -> 5432
So the port forwarding is successful, and I am able to connect to the postgres instance from inside the docker container. What I am not able to do is to connect from outside the container with the exposed and published port
I think there are two possible solutions that may help in your case:
- You can add the
--address
argument to thekubectl port-forward
command with the IP address of the container running this command. By default,kubectl
binds only to localhost and therefore it does not work as you expect (see: Kubectl Reference Docs). - All newly-started containers connect to a default
bridge
network unless otherwise specified. To solve your problem, you can use thehost
network instead of thebridge
network. As may be found in the Docker host networking documentation:
If you use the host network mode for a container, that container’s network stack is not isolated from the Docker host (the container shares the host’s networking namespace), and the container does not get its own IP-address allocated.
I will briefly describe both solutions to show you how it works.
First, I prepared postgres
:
# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE
pod/postgres 1/1 Running 0 155m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/postgres ClusterIP 10.110.151.73 <none> 5432/TCP 2s
Ad 1.
This approach is very similar to yours, I just added the --address
argument:
NOTE: I used a container with kubectl
already installed. I just want you to pay attention to the kubectl port-forward --address $(hostname -i),localhost service/postgres 2223:5432
command.
root@kworker:~# docker run -it --name=k8s-conn-12 -p 2223:2223 -v /config:/config mattjcontainerregistry/forward:latest bash
root@31b05af956ab:/# kubectl port-forward --address $(hostname -i),localhost service/postgres 2223:5432 --kubeconfig=config
Forwarding from 127.0.0.1:2223 -> 5432
Forwarding from 172.17.0.2:2223 -> 5432
From another terminal tab we can check if it works:
root@kworker:~# docker exec -it k8s-conn-12 bash
root@31b05af956ab:/# psql -U postgres -h localhost -p 2223
psql (12.7 (Ubuntu 12.7-0ubuntu0.20.04.1), server 13.3 (Debian 13.3-1.pgdg100+1))
WARNING: psql major version 12, server major version 13.
Some psql features might not work.
Type "help" for help.
postgres=#
In addition, we can do the same from the host machine (from outside the container with the exposed and published port):
root@kworker:~# psql -U postgres -h localhost -p 2223
psql (11.12 (Debian 11.12-0+deb10u1), server 13.3 (Debian 13.3-1.pgdg100+1))
WARNING: psql major version 11, server major version 13.
Some psql features might not work.
Type "help" for help.
postgres=#
Ad 2.
This approach requires the use of a host network:
host: For standalone containers, remove network isolation between the container and the Docker host, and use the host’s networking directly.
NOTE: I just want you to pay attention to the --network=host
option (I used the same container as before):
root@kworker:~# docker run -it --name=k8s-conn-12 --network=host -v /config:/config mattjcontainerregistry/forward:latest bash
root@kworker:/# kubectl port-forward service/postgres 2223:5432 --kubeconfig=config
Forwarding from 127.0.0.1:2223 -> 5432
Forwarding from [::1]:2223 -> 5432
Again, we can check if it works as expected from outside the container:
root@kworker:~# psql -U postgres -h localhost -p 2223
psql (11.12 (Debian 11.12-0+deb10u1), server 13.3 (Debian 13.3-1.pgdg100+1))
WARNING: psql major version 11, server major version 13.
Some psql features might not work.
Type "help" for help.
postgres=#
Additionally, it's worth considering if you really need a docker container for port forwarding. Perhaps running kubectl port-forward
in the background would be better (see: Perform kubectl port-forward in background).