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

时间:2016-02-03 14:13:13

标签: bash kubernetes

立即创建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 Ingress IP )设置或无法设置?

6 个答案:

答案 0 :(得分:7)

只是为了在这里添加答案,现在最好的选择是使用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'

答案 1 :(得分:1)

没有真正的"未能设置"因为我们将永远重试它。失败可能是云提供商中的暂时性错误或在数小时或数天或任何数量的事情中解决的配额问题。唯一的失败来自"你愿意等多久?" - 只有你才能知道。

我们没有将军等待表达"命令,因为它最终是任意复杂的,你最好只用真实语言编码。以上的bash循环。我们可以做一个关于观看'命令,但它最终仍然是超时。

答案 2 :(得分:1)

通过有效的解决方案,这有点棘手:

import numpy as np
import pandas as pd

import pyspark
from pyspark.sql.types import *
from pyspark.sql import functions as F
from pyspark.sql.window import Window
from pyspark import SparkConf, SparkContext, SQLContext
spark = pyspark.sql.SparkSession.builder.appName('app').getOrCreate()
sc = spark.sparkContext
sqlContext = SQLContext(sc)

df = pd.DataFrame({
    'name': [
        'Molly', 'Ashes', 'Felix', 'Smudge', 'Tigger', 'Alfie', 'Oscar',
        'Millie', 'Misty', 'Puss', 'Smokey', 'Charlie'
    ],
    'breed': [
        'Persian', 'Persian', 'Persian', 'British Shorthair',
        'British Shorthair', 'Siamese', 'Siamese', 'Maine Coon', 'Maine Coon',
        'Maine Coon', 'Maine Coon', 'British Shorthair'
    ],
    'weight': [4.2, 4.5, 5.0, 4.9, 3.8, 5.5, 6.1, 5.4, 5.7, 5.1, 6.1, 4.8],
    'color': [
        'Black', 'Black', 'Tortoiseshell', 'Black', 'Tortoiseshell', 'Brown',
        'Black', 'Tortoiseshell', 'Brown', 'Tortoiseshell', 'Brown', 'Black'
    ],
    'age': [1, 5, 2, 4, 2, 5, 1, 5, 2, 2, 4, 4]
})

schema = StructType([
    StructField('name', StringType(), True),
    StructField('breed', StringType(), True),
    StructField('weight', DoubleType(), True),
    StructField('color', StringType(), True),
    StructField('age', IntegerType(), True),
])

sdf = sqlContext.createDataFrame(df, schema)
sdf.createOrReplaceTempView("cats")

答案 3 :(得分:0)

真的只是对@Dan Garfield的工作示例的清理;我的OCD不会放过这张幻灯片。在这种情况下:

  • 在GCP上
  • 请求内部
  • 在服务定义中带有注释

required

注意:我只能通过外部DNS将名称与公共IP地址相关联。


此脚本被编写为接受一些参数,现在它是一个库;例如:

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.
...

稍后,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也可以工作;任何有效的方法。

感谢让我们开始使用Dan:-)

答案 4 :(得分:0)

对于给定命令输出中的任何正则表达式,这是一个通用的bash函数,用于 超时监视

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

答案 5 :(得分:0)

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

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