GKE - Terraform through bastion - the best solution
Access Kubernetes cluster in Terraform using bastion host as a proxy
Terraform documentation for the GKE module mentions bastion host access as an alternative to VPN. Of course, that topic does not exist if you use GKE with a public endpoint. A private cluster is recommended, so in this article, I will describe how to use Terraform through the bastion host.
Context
There are 2 ways for accessing a private GKE cluster. Using a VPN or a bastion host. This article is not about VPN solution.
There is a Terraform module that presents the solution. Please, take a look at these sources, because this article will not cover theory.
Terraform module: https://registry.terraform.io/modules/terraform-google-modules/kubernetes-engine/google/latest/examples/safer_cluster_iap_bastion
How to use bastion host: https://cloud.google.com/kubernetes-engine/docs/tutorials/private-cluster-bastion
Tinyproxy
Official documentation (the link above) presents a bastion host approach that uses tinyproxy
application. From my experience, it works stable but slowly. Terraform plan execution takes so much time, especially when there are multiple resources tracked in the state.
I abandoned this solution as it was too slow for me. Too slow means that I've found out other way which is 5-10 times faster.
Socks proxy
The same effect can be achieved using socks proxy. Then, we don't need tinyproxy
installed on the bastion.
Socks is proxying traffic through an SSH connection. It uses pretty same command as the first solution:
gcloud beta compute ssh ${BASTION_HOST} \
--tunnel-through-iap \
--project=${GOOGLE_PROJECT} \
--zone=${GOOGLE_REGION} \
-- -4 -D 127.0.0.1:${KUBE_PROXY_PORT} -N -q -f
# set proxy address in ~/.kube/config
kubectl config set clusters.${KUBE_CLUSTER_NAME}.proxy-url socks5://127.0.0.1:${KUBE_PROXY_PORT}
As I observed, it works much faster than tinyproxy
! But sometimes it crashes without error. Anyway, it's better.
sshuttle
The last solution that I've found uses sshutle application. Please, read what it is and how it works on the author's website.
This solution requires slightly more configuration. It is caused by the fact that I'm using Google IAP auth. I had to configure ~/.ssh/config
:
Host <my-host-name>
ProxyCommand gcloud beta compute start-iap-tunnel <my-bastion-host> <my-ssh-port-number> --listen-on-stdin --project=<my-gcp-project> --zone=<my-zone> --verbosity=warning
IdentityFile /Users/<user>/.ssh/google_compute_engine
UserKnownHostsFile=/Users/<user>/.ssh/google_compute_known_hosts
User <user-on-bastion>
To get <user-on-bastion>
I had to log in bastion host and get my current username by running whoami
.
Now, I can run:
sshuttle -r <my-host-name> <control-plane-ip>
Where <control-plane-network>
is 172.16.0.2
in my case. It means that every traffic for this IP from my local computer will be proxied by sshutle. Kubectl, Terraform and other tools that want to connect to Kubernetes API will be able to do this.
As I observed, this solution has pretty much the same performance as the socks proxy.
My current approach is SSH socks proxy until VPN is not configured 🙂
Let me know how it works for you.