How to wait for Kubernetes to assign an external IP address to the LoadBalancer service?

Creating a Kubernetes LoadBalancer returns immediately (ex: kubectl create -f ... or kubectl expose svc NAME --name=load-balancer --port=80 --type=LoadBalancer ).

I know a manual way to wait in a shell:

 external_ip="" while [ -z $external_ip ]; do sleep 10 external_ip=$(kubectl get svc load-balancer --template="{{range .status.loadBalancer.ingress}}{{.ip}}{{end}}") done 

This, however, is not ideal:

  • Requires at least 5 lines of Bash script.
  • Infinite waiting even in case of an error (otherwise a timeout is required that increases the number of lines in a line).
  • Probably ineffective; can use --wait or --wait-once , but using commands that never return.

Is there a better way to wait until the external IP address of the service (aka LoadBalancer Ingress IP) is installed or set?

+12
source share
3 answers

Just to add answers here, the best option now is to use a bash script. For convenience, I put it on one line, which includes the export of the environment variable.

Team wait and find the Kubernetes service endpoint

 bash -c 'external_ip=""; while [ -z $external_ip ]; do echo "Waiting for end point..."; external_ip=$(kubectl get svc NAME_OF_YOUR_SERVICE --template="{{range .status.loadBalancer.ingress}}{{.ip}}{{end}}"); [ -z "$external_ip" ] && sleep 10; done; echo "End point ready-" && echo $external_ip; export endpoint=$external_ip' 

I also changed your script so that it only waits if ip is not available. The last bit exports an environment variable named "endpoint"

Bash script to test this service

Save this as check-endpoint.sh and then you can run $sh check-endpoint.sh SERVICE_NAME

 #!/bin/bash # Pass the name of a service to check ie: sh check-endpoint.sh staging-voting-app-vote # Will run forever... external_ip="" while [ -z $external_ip ]; do echo "Waiting for end point..." external_ip=$(kubectl get svc $1 --template="{{range .status.loadBalancer.ingress}}{{.ip}}{{end}}") [ -z "$external_ip" ] && sleep 10 done echo 'End point ready:' && echo $external_ip 

Using this in the Codefresh Step

I use this for the Codefresh pipeline, and when it does, it passes the $ endpoint variable.

  GrabEndPoint: title: Waiting for endpoint to be ready image: codefresh/plugin-helm:2.8.0 commands: - bash -c 'external_ip=""; while [ -z $external_ip ]; do echo "Waiting for end point..."; external_ip=$(kubectl get svc staging-voting-app-vote --template="{{range .status.loadBalancer.ingress}}{{.ip}}{{end}}"); [ -z "$external_ip" ] && sleep 10; done; echo "End point ready-" && echo $external_ip; cf_export endpoint=$external_ip' 
+6
source

There is not really the condition “failed to establish”, because we will repeat it forever. The failure may have been a temporary error at the cloud provider or a quota issue that resolves within hours or days or any number of things. The only failure is "how long are you ready to wait?" - which only you can know.

We don’t have a common wait for expression command, because it turns out to be arbitrarily complex, and you better just code it in real language. Ergo bash above. We could do a better “watch” command, but in the end this is another timeout.

+1
source

Actually just cleaning up @Dan Garfield's working example; My OCD will not allow this slide. In this case:

  • on gcp
  • requesting an internal pound
  • with annotation in the service definition

 apiVersion: v1 kind: Service metadata: name: yo annotations: cloud.google.com/load-balancer-type: "Internal" # external-dns.alpha.kubernetes.io/hostname: yo.opcon.dev. ... 

NOTE. I was able to get only the external DNS to bind the names to the public IP addresses.


It was written to accept a few arguments, now it is a library; example:

 myServiceLB=$1 while true; do successCond="$(kubectl get svc "$myServiceLB" \ --template="{{range .status.loadBalancer.ingress}}{{.ip}}{{end}}")" if [[ -z "$successCond" ]]; then echo "Waiting for endpoint readiness..." sleep 10 else sleep 2 export lbIngAdd="$successCond" pMsg """ The Internal LoadBalancer is up! """ break fi done 

Later, $lbIngAdd can be used to set records. It seems that -o jsonpath="{.status.loadBalancer.ingress[*].ip}" will work; no matter what works.

Thanks for starting us Dan :-)

0
source

Source: https://habr.com/ru/post/1242210/


All Articles