Bash 如何等待Kubernetes将外部IP分配给负载平衡器服务?

Bash 如何等待Kubernetes将外部IP分配给负载平衡器服务?,bash,kubernetes,Bash,Kubernetes,创建会立即返回(例如:kubectl create-f…或kubectl expose svc NAME--NAME=LoadBalancer--port=80--type=LoadBalancer) 我知道在shell中手动等待的方法: external_ip="" while [ -z $external_ip ]; do sleep 10 external_ip=$(kubectl get svc load-balancer --template="{{range .sta

创建会立即返回(例如:
kubectl create-f…
kubectl expose svc NAME--NAME=LoadBalancer--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 Ingress IP)设置或设置失败?

实际上没有“设置失败”的情况,因为我们将永远重试。失败可能是云提供程序中的一个暂时性错误,或者是在数小时或数天内解决的配额问题,或者是任何数量的问题。唯一的失败来自“你愿意等多久?”——这只有你自己知道


我们没有一个通用的“wait-for-expression”命令,因为它最终会变得任意复杂,最好用一种真正的语言编写它。在上面的bash循环中遍历。我们可以更好地使用“watch”命令,但最后还是超时。

为了补充这里的答案,现在最好的选择是使用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\u 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'

实际上,这只是对@Dan Garfield工作示例的清理;我的强迫症患者不会放过这一切。在这种情况下:

  • 关于GCP
  • 请求内部lb
  • 在服务定义中使用注释

注意:我只能通过外部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.ingres[*].ip}”
也可以工作;只要行得通


感谢您让我们开始Dan:-)

这是一个通用的bash函数,用于在给定命令的输出中查看任何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(这花费了一分钟多):


0。。。1.2.3.63... 64…
3.22.37.41这是一个有点棘手的工作解决方案:

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

也许这不是您正在寻找的解决方案,但至少它的代码行更少:

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

“失败”是什么意思?整个系统将停止尝试?为什么?然后它是否应该将服务标记为失败?我不清楚您想要实现什么-您是否不知道环境是否支持LB?或者你认为云提供商会失败?不管怎样-你已经有办法做到这一点,你只是不喜欢循环:)失败意味着退出1,如果没有外部IP已在X秒内分配。是的,我不喜欢创建要部署的脚本。部署应该尽可能简单,以避免脚本中的错误造成严重损害,因为每个项目一个脚本比所有Kuberentes项目的通用脚本/功能更有可能出现错误。我不反对kubectl中的通用“等待条件,可选超时”命令,但概括起来很复杂,可能需要一段时间。通过将其包装在shell循环中,您将更快地获得结果。
kubectl get svc$1--output=“jsonpath={.status.loadBalancer.ingres[0].hostname}”
适用于我
.status.loadBalancer.ingres[0].hostname>如果您在AWS或其他提供程序上运行k8s,而该提供程序的负载均衡器不受IP支持,而是由DNS名称支持
$ watch_for "kubectl get nodes -l node-role.kubernetes.io/worker -o wide | awk '{print \$7}'" \
"[0-9]" 100
until [ -n "$(kubectl get svc load-balancer -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" ]; do
    sleep 10
done