如何等待Kubernetes为LoadBalancer服务分配外部IP?

moiiocjp  于 2023-03-29  发布在  Kubernetes
关注(0)|答案(7)|浏览(216)

创建Kubernetes LoadBalancer会立即返回(例如:kubectl create -f ...kubectl expose svc NAME --name=load-balancer --port=80 --type=LoadBalancer)。
我知道一种在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

但这并不理想:

  • 至少需要5行Bash脚本。
  • 即使在错误的情况下也要无限等待(否则需要超时,这会增加批次线计数)。
  • 可能效率不高;可以使用--wait--wait-once,但使用这些命令永远不会返回。

是否有更好的方法等待服务 * 外部IP*(又名 LoadBalancer入口IP)设置或设置失败?

omqzjyyz

omqzjyyz1#

为了补充这些问题的答案,现在最好的选择是使用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不可用时执行等待。最后一位将导出一个名为“endpoint”的环境变量。

检查给定服务的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'
w80xi6nr

w80xi6nr2#

这是有点棘手的工作解决方案:

kubectl get service -w load-balancer -o 'go-template={{with .status.loadBalancer.ingress}}{{range .}}{{.ip}}{{"\n"}}{{end}}{{.err}}{{end}}' 2>/dev/null | head -n1
nukf8bse

nukf8bse3#

我们有a similar problem on AWS EKS,并希望在CI管道中使用一行程序。我们简单地使用until循环"watched" the output of a command until a particular string is observed and then exit

until kubectl get service/<service-name> --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done

为了避免无限循环,可以增强using timeoutbrew install coreutils on a Mac):

timeout 10s bash -c 'until kubectl get service/<service-name> --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done'

在此之后获取IP很容易使用:

kubectl get service/<service-name> --output=jsonpath='{.status.loadBalancer.ingress[0].ip}'

或者使用AWS EKS等服务时,您很可能填充了hostname而不是ip

kubectl get service/<service-name> --output=jsonpath='{.status.loadBalancer.ingress[0].hostname}'

侧记(更新03.2023)kubectl wait将是理想的,但将not be able to wait on arbitrary jsonpath直到v1.23(参见this PR)。但即使从1.24开始,我们似乎也是to not be able to use kubectl wait,因为.status.loadBalancer.ingress[0]是一个列表,kubectl wait jsonpath实现不支持它。因此命令kubectl wait service/<service-name> --for=jsonpath='{.status.loadBalancer}'=ingress抛出以下错误之一(参见this so question):

error: jsonpath wait format must be --for=jsonpath='{.status.readyReplicas}'=3
error: jsonpath leads to a nested object or list which is not supported
h9vpoimq

h9vpoimq4#

也许这不是你想要的解决方案,但至少它有更少的代码行:

until [ -n "$(kubectl get svc load-balancer -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" ]; do
    sleep 10
done
j9per5c4

j9per5c45#

实际上并没有“设置失败”的情况,因为我们会永远重试。失败可能是云提供商的暂时错误,或者是在几小时或几天内解决的配额问题,或者任何数量的事情。唯一的失败来自“您愿意等待多久?”-这只有您自己知道。
我们没有一个通用的“wait for expression”命令,因为它最终会变得任意复杂,你最好用一种真实的的语言来编写它。因此,上面的bash循环。我们可以用一个“watch”命令做得更好,但它最终仍然是一个超时。

cyvaqqii

cyvaqqii6#

实际上只是对@Dan加菲猫的工作示例的清理;我的强迫症不会放过这个的。在这种情况下:

  • 关于GCP
  • 请求 * 内部 * lb
  • 在服务定义中使用注解
apiVersion: v1
kind: Service
metadata:
  name: yo
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
    # external-dns.alpha.kubernetes.io/hostname: vault.stage.domain.tld.
...
  • 注意:我只能获得external-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}"也可以工作;只要管用就行。
谢谢你让我们开始丹:-)

z0qdvdin

z0qdvdin7#

下面是一个通用的bash函数,它可以***用timeout***监视给定命令输出中的任何regexp:

function watch_for() {
  CMD="$1" # Command to watch. Variables should be escaped \$
  REGEX="$2" # Pattern to search
  ATTEMPTS=${3:-10} # Timeout. Default is 10 attempts (interval of second)
  COUNT=0;

  echo -e "# Watching for /$REGEX/ during $ATTEMPTS seconds, on the output of command:\n# $CMD"
  until eval "$CMD" | grep -m 1 "$REGEX" || [[ $COUNT -eq $ATTEMPTS ]]; do
    echo -e "$(( COUNT++ ))... \c"
    sleep 1
  done
  if [[ $COUNT -eq $ATTEMPTS ]]; then
    echo "# Limit of $ATTEMPTS attempts has exceeded."
    return 1
  fi
  return 0
}

下面是我如何使用它来等待工作节点获得外部IP(这花了一分钟多的时间):

$ watch_for "kubectl get nodes -l node-role.kubernetes.io/worker -o wide | awk '{print \$7}'" \
"[0-9]" 100

0... 1... 2... 3... .... 63... 64...**3.22.37.41

相关问题