A little bit of background: I have a Go service that uses gRPC to communicate with client apps. gRPC uses HTTP2, so I can't use Google App Engine or the Google Cloud HTTP Load Balancer. I need raw TCP load balancing from the internet to my Go application.
I went through the GKE tutorials and read the various docs and I can't find any way to give my application a static IP address. So how do you get a static IP attached to something running in GKE?
This is not supported in kubernetes v1.0.x but in v1.1.x it will be available as service.spec.loadBalancerIP
. As long as you actually own that IP we will use it.
I eventually figured this out. To do this, you ask GKE to set up an external load balancer for you, then you selectively replace pieces of the stack. The good news is that along the way you can also set up HTTP health checking, which GKE doesn't do by default.
Make sure you have a static IP available from Google Cloud Platform. You can request on in the Console.
Get your service up and running with something like:
kubectl expose rc api-server --name=api-server --port=8080,8081 --create-external-load-balancer=true
(I'm using port 8080 for HTTP health checking and 8081 to serve gRPC requests).
--create-external-load-balancer=true
updates the Kubernetes services with an ingress rule, sets up a target pool, sets up a network load balancer and adds a firewall rule. We're going to have to fix #1 and #3.
Figure out where everything is running already.
export TARGET_POOL_NAME=$(gcloud compute target-pools list | head -n 2 | tail -n 1 | cut -d " " -f 1)
export EXTERNAL_IP=$(gcloud compute addresses list | head -n 2 | tail -n 1 | cut -d " " -f 3)
Attach the health check to the target pool
gcloud compute http-health-checks create api-server-http-basic-check --port 8080 --request-path "/_health"
gcloud compute target-pools add-health-checks ${TARGET_POOL_NAME} --http-health-check api-server-http-basic-check
Create a new forwarding rule to replace the one generated by GKE
gcloud compute forwarding-rules create api-server \
--region us-central1 --port-range 8080-8081 \
--address ${EXTERNAL_IP} --target-pool ${TARGET_POOL_NAME}
Delete the original GKE forwarding rule
gcloud compute forwarding-rules delete $(gcloud compute forwarding-rules list | head -n 2 | tail -n 1 | cut -d " " -f 1)
Update the Kubernetes Service to allow ingress from the new IP:
kubectl patch services api-server -p "{\"status\":{\"loadBalancer\":{\"ingress\": [{\"ip\": \"${EXTERNAL_IP}\"} ]}}}"
That should do it!
Be careful with copy pasting, my heads and tails work for me because I only have one app running, but you might see things in a different order.