I use Kubernetes (via GKE) at my day job, and have a small personal cluster that I use for hosting a few cronjobs, personal websites, etc. It’s configured with a single n1-standard-1 node, which comes with 1 vCPU and ~4gb of ram for $24 / month. This is sufficient to run a few small websites.
Within the cluster I run helm to manage my applications, nginx-ingress to terminate ssl connections and route traffic to my applications, and cert-manager to automatically provision and renew ssl certificates using letsencrypt. Since all of my traffic is routed through nginx-ingress, I only need to provision one load balancer, but unfortunately load balancing and forwarding rules cost $18 / month for the first 5 rules, almost as much as we are paying for our entire cluster.
Since I’m only running a single node in my cluster, I really don’t need a load balancer. Ideally I could expose nginx by configuring a NodePort service in front of it, but by default these are limited to ports 30000-32767. To get around this, we can configure nginx to run as a DaemonSet (one pod per node), and bind to the host network directly as detailed here (please read the security considerations before proceeding).
To configure this, we can use the nginx-ingress helm chart with the following custom configuration:
rbac:
create: true
controller:
kind: DaemonSet
daemonset:
useHostPort: true
service:
type: ClusterIP
This configuration ensures that Nginx:
- Runs as a DaemonSet
- Binds to ports 80 and 443 on the host network of each node
Make sure you have helm installed in your cluster, and then save this configuration to a file (values.yaml), and run the following command to install nginx:
helm install my-nginx -f values.yaml
Next we need to configure a firewall rule to allow traffic from outside our cluster to reach ports 80 and 443. First, visit this page, and create a new rule targetting our gke cluster:
- Direction: Ingress
- Action on match: Allow
- Targets: Specified Target Tags
- Target tags: node name here
- Source IP ranges: 0.0.0.0/0
- Protocols and ports: tcp:80,443
Once this is complete, we can visit the list of vms to find the ip of our gke node, and use this to direct traffic at our cluster. To be safe we should also mark our node ip as static rather than ephemeral so it does not change on us in the future. This can be done from the external ips page in Google Cloud.
In summary, we now have a Kubernetes cluster running on Google Cloud that accepts internet traffic for a total cost of ~$24 / month + the cost of any persistent storage we provision and any egress traffic. For me this typically adds a dollar or two, mostly from persistent disks I utilize.
Limitations:
- Any time you upgrade your gke nodes you will have to reassign the static ip to the new node