Как подождать, пока Кубернетес назначит внешний IP-адрес службе LoadBalancer?

Создание Kubernetes LoadBalancer возвращает немедленно (ex: kubectl create -f ... или kubectl expose svc NAME --name=load-balancer --port=80 --type=LoadBalancer).

Я знаю ручной способ ожидания в оболочке:

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

Это, однако, не идеально:

  • Требуется не менее 5 строк Bash script.
  • Бесконечное ожидание даже в случае ошибки (иначе требуется тайм-аут, который увеличивает количество строк в строке).
  • Вероятно, неэффективен; может использовать --wait или --wait-once, но используя команды, которые никогда не возвращаются.

Есть ли лучший способ подождать, пока не будет установлен или не установлен внешний IP-адрес службы (aka LoadBalancer Ingress IP)?

Ответ 1

Просто чтобы добавить здесь ответы, лучший вариант сейчас - использовать скрипт bash. Для удобства я поместил его в одну строку, которая включает экспорт переменной среды.

Команда ждать и найти конечную точку сервиса Kubernetes

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'

Я также изменил ваш скрипт, чтобы он выполнял ожидание, только если ip недоступен. Последний бит экспортирует переменную среды с именем "конечная точка"

Скрипт Bash для проверки данного сервиса

Сохраните это как check-endpoint.sh и тогда вы сможете выполнить $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

Используя это в шаге Codefresh

Я использую это для конвейера Codefresh, и когда он это делает, он передает переменную $ endpoint.

  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'

Ответ 2

Там не действительно условие "не удалось установить", потому что мы будем повторять его навсегда. Сбой, возможно, был временной ошибкой в ​​поставщике облака или проблемой квоты, которая разрешается в течение часов или дней или любого количества вещей. Единственный провал - это "сколько времени вы готовы ждать?" - которые только вы можете знать.

У нас нет общей команды "wait for expression", потому что она оказывается произвольно сложной, и вам лучше просто кодировать ее на реальном языке. Ergo bash выше. Мы могли бы лучше сделать команду "смотреть", но в конце концов это еще один тайм-аут.

Ответ 3

На самом деле просто очистка рабочего примера @Dan Garfield; Мой ОКР не позволит этому слайду. В этом случае:

  • на GCP
  • запрашивая внутренний фунт
  • с аннотацией в определении сервиса

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

ПРИМЕЧАНИЕ. Мне удалось получить только внешние DNS, чтобы связать имена с общедоступными IP-адресами.


Это было написано, чтобы принять несколько аргументов, теперь это библиотека; пример:

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

Позже, $lbIngAdd может быть использован для установки записей. Похоже, что -o jsonpath="{.status.loadBalancer.ingress[*].ip}" будет работать; что бы ни работало.

Спасибо, что начали нас Дэн :-)