# GKE - Terraform through bastion - the best solution

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](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](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:

```bash
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](https://github.com/sshuttle/sshuttle) 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` :

```bash
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:

```bash
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.
