kubectl 等待 AWS EKS 上的服务公开 .status.loadBalancer.ingress 字段中报告的弹性负载均衡器 (ELB) 地址
kubectl wait for Service on AWS EKS to expose Elastic Load Balancer (ELB) address reported in .status.loadBalancer.ingress field
作为the kubernetes.io docs state about a Service
of type LoadBalancer
:
On cloud providers which support external load balancers, setting the
type field to LoadBalancer provisions a load balancer for your
Service. The actual creation of the load balancer happens
asynchronously, and information about the provisioned balancer is
published in the Service's .status.loadBalancer
field.
在 AWS Elastic Kubernetes Service (EKS) 上提供了一个 AWS 负载均衡器来平衡网络流量 (see AWS docs & the example project on GitHub provisioning a EKS cluster with Pulumi). Assuming we have a Deployment
ready with the selector app=tekton-dashboard
(it's the default Tekton dashboard you can deploy as stated in the docs),Service
类型 LoadBalancer
定义在 tekton-dashboard-service.yml
可能看起来像这样:
apiVersion: v1
kind: Service
metadata:
name: tekton-dashboard-external-svc-manual
spec:
selector:
app: tekton-dashboard
ports:
- protocol: TCP
port: 80
targetPort: 9097
type: LoadBalancer
如果我们使用 kubectl apply -f tekton-dashboard-service.yml -n tekton-pipelines
在我们的集群中创建服务,AWS ELB 会自动创建:
只有一个问题:.status.loadBalancer
字段由 ingress[0].hostname
字段异步填充,因此无法立即使用。我们可以检查这一点,如果我们 运行 以下命令一起使用:
kubectl apply -f tekton-dashboard-service.yml -n tekton-pipelines && \
kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}'
输出将为空字段:
{}%
因此,如果我们想 运行 在 CI 管道中进行此设置(例如 GitHub Actions, see the example project's workflow provision.yml
), 我们需要以某种方式等待 .status.loadBalancer
字段填充了 AWS ELB 的主机名。 我们如何使用 kubectl wait
实现此目的?
TLDR;
Prior to Kubernetes v1.23
使用 kubectl wait
是不可能的,但是像这样将 until
与 grep
一起使用:
until kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done
甚至增强命令 using timeout (brew install coreutils
on a Mac) 以防止命令无限地 运行:
timeout 10s bash -c 'until kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done'
kubectl wait的问题&详细解释的解决方案
如 and the kubernetes issues kubectl wait unable to not wait for service ready #80828 & kubectl wait on arbitrary jsonpath #83094 所述,目前的 Kubernetes 版本无法使用 kubectl wait
。
主要原因是,kubectl wait
假设使用 kubectl get service/xyz --output=yaml
查询的 Kubernetes 资源的 status
字段包含一个 conditions
列表。 Service
没有。在这里使用 jsonpath 将是一个解决方案,并且可以从 Kubernetes v1.23
开始(参见 this merged PR)。但在这个版本在像 EKS 这样的托管 Kubernetes 集群中广泛可用之前,我们需要另一种解决方案。它也应该像 kubectl wait
一样作为“单行”提供。
这个超级用户关于 "watching" the output of a command until a particular string is observed and then exit:
的回答可能是一个很好的起点
until my_cmd | grep "String Im Looking For"; do : ; done
如果我们将这种方法与 kubectl get
一起使用,我们可以制作一个命令,该命令将等待字段 ingress
填充到 [=26= 中的 status.loadBalancer
字段]:
until kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done
这将等到 ingress
字段被填充,然后打印出 AWS ELB 地址(例如,之后通过使用 kubectl get service tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer.ingress[0].hostname}'
):
$ until kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done
{"ingress":[{"hostname":"a74b078064c7d4ba1b89bf4e92586af0-18561896.eu-central-1.elb.amazonaws.com"}]}
现在我们有一个单行命令,它的行为就像 kubectl wait
一样,我们的 Service
可以通过 AWS 负载均衡器使用。我们可以仔细检查这是否与以下命令结合使用(请务必在执行之前使用 kubectl delete service/tekton-dashboard-external-svc-manual -n tekton-pipelines
删除服务,否则包括 AWS LoadBalancer 在内的服务已经存在):
kubectl apply -f tekton-dashboard-service.yml -n tekton-pipelines && \
until kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done && \
kubectl get service tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer.ingress[0].hostname}'
作为the kubernetes.io docs state about a Service
of type LoadBalancer
:
On cloud providers which support external load balancers, setting the type field to LoadBalancer provisions a load balancer for your Service. The actual creation of the load balancer happens asynchronously, and information about the provisioned balancer is published in the Service's
.status.loadBalancer
field.
在 AWS Elastic Kubernetes Service (EKS) 上提供了一个 AWS 负载均衡器来平衡网络流量 (see AWS docs & the example project on GitHub provisioning a EKS cluster with Pulumi). Assuming we have a Deployment
ready with the selector app=tekton-dashboard
(it's the default Tekton dashboard you can deploy as stated in the docs),Service
类型 LoadBalancer
定义在 tekton-dashboard-service.yml
可能看起来像这样:
apiVersion: v1
kind: Service
metadata:
name: tekton-dashboard-external-svc-manual
spec:
selector:
app: tekton-dashboard
ports:
- protocol: TCP
port: 80
targetPort: 9097
type: LoadBalancer
如果我们使用 kubectl apply -f tekton-dashboard-service.yml -n tekton-pipelines
在我们的集群中创建服务,AWS ELB 会自动创建:
只有一个问题:.status.loadBalancer
字段由 ingress[0].hostname
字段异步填充,因此无法立即使用。我们可以检查这一点,如果我们 运行 以下命令一起使用:
kubectl apply -f tekton-dashboard-service.yml -n tekton-pipelines && \
kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}'
输出将为空字段:
{}%
因此,如果我们想 运行 在 CI 管道中进行此设置(例如 GitHub Actions, see the example project's workflow provision.yml
), 我们需要以某种方式等待 .status.loadBalancer
字段填充了 AWS ELB 的主机名。 我们如何使用 kubectl wait
实现此目的?
TLDR;
Prior to Kubernetes v1.23
使用 kubectl wait
是不可能的,但是像这样将 until
与 grep
一起使用:
until kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done
甚至增强命令 using timeout (brew install coreutils
on a Mac) 以防止命令无限地 运行:
timeout 10s bash -c 'until kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done'
kubectl wait的问题&详细解释的解决方案
如 kubectl wait
。
主要原因是,kubectl wait
假设使用 kubectl get service/xyz --output=yaml
查询的 Kubernetes 资源的 status
字段包含一个 conditions
列表。 Service
没有。在这里使用 jsonpath 将是一个解决方案,并且可以从 Kubernetes v1.23
开始(参见 this merged PR)。但在这个版本在像 EKS 这样的托管 Kubernetes 集群中广泛可用之前,我们需要另一种解决方案。它也应该像 kubectl wait
一样作为“单行”提供。
这个超级用户关于 "watching" the output of a command until a particular string is observed and then exit:
的回答可能是一个很好的起点until my_cmd | grep "String Im Looking For"; do : ; done
如果我们将这种方法与 kubectl get
一起使用,我们可以制作一个命令,该命令将等待字段 ingress
填充到 [=26= 中的 status.loadBalancer
字段]:
until kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done
这将等到 ingress
字段被填充,然后打印出 AWS ELB 地址(例如,之后通过使用 kubectl get service tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer.ingress[0].hostname}'
):
$ until kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done
{"ingress":[{"hostname":"a74b078064c7d4ba1b89bf4e92586af0-18561896.eu-central-1.elb.amazonaws.com"}]}
现在我们有一个单行命令,它的行为就像 kubectl wait
一样,我们的 Service
可以通过 AWS 负载均衡器使用。我们可以仔细检查这是否与以下命令结合使用(请务必在执行之前使用 kubectl delete service/tekton-dashboard-external-svc-manual -n tekton-pipelines
删除服务,否则包括 AWS LoadBalancer 在内的服务已经存在):
kubectl apply -f tekton-dashboard-service.yml -n tekton-pipelines && \
until kubectl get service/tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done && \
kubectl get service tekton-dashboard-external-svc-manual -n tekton-pipelines --output=jsonpath='{.status.loadBalancer.ingress[0].hostname}'