I finally figured it out. To do this, you ask GKE to configure 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 configure an HTTP health check, which GKE does not do by default.
Make sure you have a static IP address available on the Google Cloud Platform. You can request it in the console.
Pick up your service and do something like:
kubectl expose rc api-server --name=api-server --port=8080,8081 --create-external-load-balancer=true
(I use port 8080 to test the health of HTTP and 8081 to service gRPC requests).
--create-external-load-balancer=true updates Kubernetes services using an access rule, configures the target pool, configures a network load balancer, and adds a firewall rule. We will need to fix No. 1 and No. 3.
Find out where everything works 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 a health check to the target pool
gcloud compute http-health-checks create api-server-http-basic-check
Create a new forwarding rule to replace the file 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 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 login from the new IP:
kubectl patch services api-server -p "{\"status\":{\"loadBalancer\":{\"ingress\": [{\"ip\": \"${EXTERNAL_IP}\"} ]}}}"
It should be!
Be careful with the copy application, my heads and tails work for me, because I only have one application working, but you can see things in a different order.