Setup SSH or reverse SSH tunnel to only one kubernetes service - postgresql

I need to allow inbound connections from a remote platform to do some administrative tasks on one of my databases (in my case, allow a reverse-ETL service to feed one of my postgresql databases in a pod in my k8s cluster)
The remote platform lets me configure a PostgreSQL destination through SSH tunnels or reverse SSH tunnels, or direct connections. Of course, I would like traffic to be encrypted, so I’m opting for the SSH or reverse SSH Tunnel.
Any idea if/how I can setup this access on my k8s cluster ?
I would like to give the remote service ONLY access to one of my pg database (and not the whole cluster/namespace for security reasons)
The scenario I was thinking about
Traefik listens to ssh on specific port (like 2222)
route this port to a SSH bastion pod capable of managing incoming SSH connections, and log in as a specific linux user. Only allow connections from the remote service IPs via an ip whitelist middleware.
Allow connections from this bastion host pod (or ideally, this linux user) ONLY to my postgresql instance on the default pg port
If I open a bastion host (2), by default, all my users will have access to all services on the cluster...right ? How can I isolate my bastion host instance to only connect it to PG ? I haven't used Network policies yet, but I believe they may be the answer... however, would it be possible to activate networking policies for a single pod only ? (my bastion host) and leave the rest as it is ?

Related

Access Kubernetes applications via localhost from the host system

Is there any other way except port-forwarding, I can access the apps running inside my K8s cluster via http://localhost:port from my host operating system.
For example
I am running minikube setup to practise the K8s and I deployed three pods along with their services, I choose three different service type, Cluster IP, nodePort and LoadBalancer.
For Cluster IP, I can use port-forward option to access my app via localhost:port, but the problem is, I have to leave that command running and if for some reason, it is distributed, connection will be dropped, so is there any alternate solution here ?
For nodePort, I can only access this via minikube node IP not with the localhost, therefore, if I have to access this remotely, I wont have a route to this node IP address
For LoadBalancer, not a valid option as I am running minikube in my local system not in cloud.
Please let me know if there is any other solution to this problem, the reason why I am asking this when I deploy same application via docker compose, I can access all these services via localhost:port and I can even call them via VM_IP:port from other systems.
Thanks,
-Rafi

Allow users to ssh into pods through a single service in k8s

I am developing an application where users can spin up compute pods running jupyter notebooks and can ssh into their pod. We are using k8s to provision and manage the compute. Since we run our infrastructure in AWS using EKS and elastic IPs are scarce, we need to route ssh traffic through a bastion instance which forwards ssh traffic (also http for jupyter notebooks) to the correct pod. I am hoping for any suggestions on how to implement this. From my understanding so far, I need to have a separate port for each user for ssh on the bastion instance. This seems unwieldily but AFAIK ssh traffic cannot be routed in any other way. For HTTP, we can have routing rules which should be much more straightforward.

How to whitelist entire kubernetes cluster on external server

I have a kubernetes cluster with several nodes, and it is connecting to a SQL server outside of the cluster. How can I whitelist these (potentially changing) nodes on the SQL server firewall, without having to whitelist each Node's external IP independently?
Is there a clean solution for this? Perhaps some intra-cluster tooling to route all requests through a single node?
You would have to use a NAT. It is possible, but fiddly (we do this weekly in order to connect to a hosted service to make backups, and the hosted service only whitelists a specific IP.)
We used Terraform for spinning up a cluster, then deploying our backup job to it so it could connect to the hosted service, and since it was going via the NAT IP, the remote host would allow the connection.
We used Cloud NAT via Terraform (as we were on GKE): https://registry.terraform.io/modules/terraform-google-modules/cloud-nat/google/latest
Though there are surely similar options for whichever Kubernetes provider you are using. If you are running bare-metal, you'll need to do the routing yourself.

How do I make an external REST API (running in .Net on my host computer) accessible within K8s from a Service or ExternalName?

I have a REST API running locally on my laptop at https://localhost:5001/something. I want that to be reachable inside the Kubernetes cluster from a K8s DNS name. For example, an application running inside a Pod could use some-service instead of needing the entire Url.
Also, since localhost is relative to the host machine, how would I get the Service or ExternalName to reach localhost on the host machine, instead of inside the K8s cluster?
I tried docker.host.internal (as suggested here) but that didn't work.
And this from K8s documentation says that it can't be the loopback:
The endpoint IPs must not be: loopback (127.0.0.0/8 for IPv4, ::1/128 for IPv6), or link-local (169.254.0.0/16 and 224.0.0.0/24 for IPv4, fe80::/64 for IPv6).
I'm running:
Host Machine: Ubuntu 20.04
K8s: k3d
Web API: (.Net Core 3.1 on Linux, created by dotnet new webapi MyAPI)
Telepresence is a tool created for that quick local testing your application with k8s cluster. It allows you to run single service locally while connecting it to remote Kubernetes cluster.
It substitutes a two-way network proxy for your normal pod running in the Kubernetes cluster. This pod proxies data from your Kubernetes environment (e.g., TCP connections, environment variables, volumes) to the local process. The local process has its networking transparently overridden so that DNS calls and TCP connections are routed through the proxy to the remote Kubernetes cluster.
Alternative way would be to create service that is being backed by ssh server running in a pod and use reverse tunnel to open reverse connection to your local machine.

How to access internal services in production environment of Kubernetes from local machine? (Need: performance & security)

I have a Kubernetes cluster running my production environments. I have bastion machine, and my own computer can connect to bastion & the bastion can access the cluster machines. I want to connect to some internal (i.e. not exposed to public network) services, such as MySQL, Redis, Kibana, etc, on my own computer. I need to have enough performance (e.g. the kubectl forward is toooo slow), and have enough security.
I have tried to use kubectl forward. But it is very slow, and after a search, they say it is just slow. So I guess I cannot make it faster.
I guess I can also expose every service as a NodePort. Then I can use things like ssh port forward. However, I am afraid whether the security is low? Because we have to create a NodePort, then if hacker can touch the cluster, he can use the nodeport to access my MySQL, Redis, Kafka, etc, which is terrible.
EDITED: In addition, I need not only my own computer, but my mobile phone to able to touch some services, such as my Spring Boot internal admin url. currently I do ssh port forward and bind to 0.0.0.0, so my mobile phone can connect to my_computer_ip:the_port to use it. But how can I do it without ssh port forward?
Thank you!