Kubernetes 服务外部 ip 待定

Posted

技术标签:

【中文标题】Kubernetes 服务外部 ip 待定【英文标题】:Kubernetes service external ip pending 【发布时间】:2017-10-21 23:51:15 【问题描述】:

我正在尝试在kubernetes上部署nginx,kubernetes版本是v1.5.2, 我已经部署了 3 个副本的 nginx,YAML 文件在下面,

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: deployment-example
spec:
  replicas: 3
  revisionHistoryLimit: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.10
        ports:
        - containerPort: 80

现在我想在节点的 30062 端口上公开它的 80 端口,为此我在下面创建了一个服务,

kind: Service
apiVersion: v1
metadata:
  name: nginx-ils-service
spec:
  ports:
    - name: http
      port: 80
      nodePort: 30062
  selector:
    app: nginx
  type: LoadBalancer

该服务运行良好,但它不仅在 kubernetes 仪表板上显示为挂起,在终端上也显示为待处理。

【问题讨论】:

【参考方案1】:

您似乎正在使用自定义 Kubernetes 集群(使用 minikubekubeadm 等)。在这种情况下,没有集成 LoadBalancer(与 AWS 或 Google Cloud 不同)。使用此默认设置,您只能使用 NodePort 或 Ingress Controller。

使用Ingress Controller,您可以设置一个映射到您的 pod 的域名;如果使用 Ingress Controller,则无需为 Service 提供 LoadBalancer 类型。

【讨论】:

这并没有真正回答问题?用户使用LoadBalancer 作为服务类型,这是一个有效的服务类型。 NodePortingress 是其他方法,但不能真正解决问题,对吧? 这是一个有效的服务类型,但它被用于不兼容的平台(至少默认情况下)。为了使用 LoadBalancer,您必须有一个可以为 pod 提供外部 IP 的平台,这是 Google Cloud 或 AWS 所做的事情。 我在 AWS 上使用 kubeadm。我还能LoadBalancer吗? 如果您使用 minikube,请运行“minikube 隧道”。现在检查您的服务,您将获得公共 IP。这是有关更多信息的文档minikube.sigs.k8s.io/docs/tasks/loadbalancer 您还可以考虑 MetalLB,它是通过标准路由协议为裸机 Kubernetes 集群提供的负载均衡器。 Kubernetes(不作为服务)与 MetalLB 非常吻合。【参考方案2】:

如果你使用 Minikube,有一个神奇的命令!

$ minikube tunnel

希望有人可以为此节省几分钟。

参考链接 https://minikube.sigs.k8s.io/docs/handbook/accessing/#using-minikube-tunnel

【讨论】:

我试过minikube tunnel,它实际上解决了pending的问题,但是新的外部IP不起作用:我收到一个超时错误... @a.barbieri 确保您使用的是隧道 ip 而不是 minikube ip。 “使用 IP 10.106.102.98 修补 ingress-nginx” 是的,谢谢彼得。会尝试。无论如何切换到 Docker 桌面,我已经能够通过直接在 localhost 上运行的开箱即用设置来克服这个问题。 @a.barbieri 您能否指出这些选项在哪里以及您必须将它们设置为什么?我也想使用 Docker Desktop 来解决这个问题,但我不知道在哪里以及如何设置它。 @user658182 对不起。自从我用 Kubernetes 做这个探索以来已经两年了。我个人转向了一个更适合我的场景的纯 Docker 解决方案。【参考方案3】:

如果您没有使用 GCE 或 EKS(您使用的是 kubeadm),您可以将 externalIPs 规范添加到您的服务 YAML。您可以使用与节点的主接口关联的 IP,例如 eth0。然后,您可以使用节点的外部 IP 从外部访问该服务。

...
spec:
  type: LoadBalancer
  externalIPs:
  - 192.168.0.10

【讨论】:

这里肯定少了一条信息:“externalIPs不由Kubernetes管理,由集群管理员负责。” (kubernetes.io/docs/concepts/services-networking/service)。我必须安装某种“控制器”吗? 我正在关注 Kubernetes 教程 (kubernetes.io/docs/tutorials/stateless-application/guestbook),它在 kubeadm 上运行良好 谢谢 - 很棒,按预期工作。我已经向节点 eth 网络 IP 公开了服务,现在可以在集群外部访问它【参考方案4】:

要访问minikube 上的服务,您需要运行以下命令:

minikube service [-n NAMESPACE] [--url] NAME

更多信息在这里:Minikube GitHub

【讨论】:

具体例子:minikube service spark-ui-proxy --url 192.168.99.100:30621 这行得通!这个命令实际上做了什么?【参考方案5】:

我使用 kubeadm 创建了一个单节点 k8s 集群。当我尝试 PortForwardkubectl proxy 时,它显示外部 IP 为待处理。

$ kubectl get svc -n argocd argocd-server
NAME            TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
argocd-server   LoadBalancer   10.107.37.153   <pending>     80:30047/TCP,443:31307/TCP   110s

就我而言,我已经像这样修补了服务:

kubectl patch svc <svc-name> -n <namespace> -p '"spec": "type": "LoadBalancer", "externalIPs":["172.31.71.218"]'

此后,它开始通过公共 IP 提供服务

$ kubectl get svc argo-ui -n argo
NAME      TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
argo-ui   LoadBalancer   10.103.219.8   172.31.71.218   80:30981/TCP   7m50s

【讨论】:

或许你应该提一下“172.31.71.218”的来源? @EuRBamarth 我尝试使用我所有节点的 IP 来代替他的 172.31.71.218,它们都可以工作【参考方案6】:

在使用 Minikube 时,您可以获取您通过的 IP 和端口 可以通过运行来访问服务:

minikube service [service name]

例如:

minikube service kubia-http

【讨论】:

【参考方案7】:

如果在 minikube 上运行,如果您不使用默认命名空间,请不要忘记提及命名空间。

minikube 服务 > --url --namespace=>

【讨论】:

【参考方案8】:

如果是您的私有 k8s 集群,MetalLB 会更合适。以下是步骤。

第 1 步:在集群中安装 MetalLB

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml
# On first install only
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"

第 2 步:使用 configmap 进行配置

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 172.42.42.100-172.42.42.105 #Update this with your Nodes IP range 

第 3 步:创建服务以获取外部 IP(不过应该是私有 IP)。

财政年度:

安装 MetalLB 之前:

安装 MetalLB 后:

【讨论】:

MetalLB 会比什么更合适? 对于原问题中描述的场景。 我今天看到了一个使用 TapTun 为 macOS 设置的 MetalLB。有点骇人听闻。我相信可以理解 OP 正在使用本地设置。您是否建议使用本地 TapTun 设置来克服 Linux hyperkit 网络限制? 有什么命令可以获取节点IP范围吗?【参考方案9】:

如果您使用的是 minikube,请从终端运行以下命令,

$ minikube ip
$ 172.17.0.2 // then 
$ curl http://172.17.0.2:31245
or simply
$ curl http://$(minikube ip):31245

【讨论】:

【参考方案10】:

按照@Javier 的回答。我决定为我的负载均衡器“修补外部 IP”。

 $ kubectl patch service my-loadbalancer-service-name \
-n lb-service-namespace \
-p '"spec": "type": "LoadBalancer", "externalIPs":["192.168.39.25"]'

这会将“待处理”替换为可用于集群的新修补 IP 地址。

有关此的更多信息。请参阅 karthik 的帖子LoadBalancer support with Minikube for Kubernetes

这不是最干净的方法。我需要一个临时解决方案。希望这可以帮助某人。

【讨论】:

完美答案!【参考方案11】:

为在amazon-eks 上运行时遇到此错误的用户添加解决方案。

首先运行:

kubectl describe svc <service-name>

然后查看下面示例输出中的 events 字段:

Name:                     some-service
Namespace:                default
Labels:                   <none>
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            "apiVersion":"v1","kind":"Service","metadata":"annotations":,"name":"some-service","namespace":"default","spec":"ports":["port":80,...
Selector:                 app=some
Type:                     LoadBalancer
IP:                       10.100.91.19
Port:                     <unset>  80/TCP
TargetPort:               5000/TCP
NodePort:                 <unset>  31022/TCP
Endpoints:                <none>
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type     Reason                  Age        From                Message
  ----     ------                  ----       ----                -------
  Normal   EnsuringLoadBalancer    68s  service-controller  Ensuring load balancer
  Warning  SyncLoadBalancerFailed  67s  service-controller  Error syncing load balancer: failed to ensure load balancer: could not find any suitable subnets for creating the ELB

查看错误信息:

Failed to ensure load balancer: could not find any suitable subnets for creating the ELB

在我的例子中,没有提供合适的子网来创建 ELB 的原因是:

1: EKS 集群部署在错误的子网组 - 内部子网而不是面向公众的子网。 (*) 默认情况下,如果未提供 service.beta.kubernetes.io/aws-load-balancer-internal: "true" 注释,LoadBalancer 类型的服务将创建面向公众的负载均衡器。

2:子网没有按照here提到的要求进行标记。

将 VPC 标记为:

Key: kubernetes.io/cluster/yourEKSClusterName
Value: shared

使用以下标记公共子网:

Key: kubernetes.io/role/elb
Value: 1

【讨论】:

【参考方案12】:

使用 NodePort:

$ kubectl run user-login --replicas=2 --labels="run=user-login" --image=kingslayerr/teamproject:version2  --port=5000

$ kubectl expose deployment user-login --type=NodePort --name=user-login-service

$ kubectl describe services user-login-service

(记下端口)

$ kubectl cluster-info

(IP->获取master运行的IP)

您的服务可通过 (IP):(port)

访问

【讨论】:

【参考方案13】:

如果有人在使用 MicroK8s:您需要一个网络负载均衡器。

MicroK8s自带metallb,你可以这样启用:

microk8s enable metallb

&lt;pending&gt; 应该会变成一个实际的 IP 地址。

【讨论】:

或者,如果这在 linux 上很清楚 kubernetes,您可以使用一些基本配置安装 MetalLB(负载均衡器),例如 metallb.universe.tf/configuration【参考方案14】:

LoadBalancer ServiceType 仅在底层基础设施支持自动创建负载均衡器并在 Kubernetes 中具有相应支持的情况下才有效,例如 Google Cloud Platform 和 AWS。如果未配置此类功能,则 LoadBalancer IP 地址字段未填充且仍处于挂起状态,并且该服务将与 NodePort 类型的服务以相同的方式工作

【讨论】:

【参考方案15】:

您可以修补托管 pod 的节点 IP(节点的私有 IP),这是简单的解决方法。

参考以上帖子,以下对我有用:

kubectl 补丁服务 my-loadbalancer-service-name \ -n lb-服务命名空间 \ -p '"spec": "type": "LoadBalancer", "externalIPs":["xxx.xxx.xxx.xxx 物理服务器的私有IP-节点-部署完成的地方"]'

【讨论】:

【参考方案16】:

同样的问题:

os>kubectl get svc right-sabertooth-wordpress

名称类型 CLUSTER-IP EXTERNAL-IP PORT(S)right-sabertooth-wordpress LoadBalancer 10.97.130.7 “待定” 80:30454/TCP,443:30427/TCP p>

os>minikube 服务列表

|-------------|---------------|--- -----------------------------------------|

|命名空间 |姓名 |网址 |

|-------------|---------------|--- -----------------------------------------|

|默认 | Kubernetes |无节点端口|

|默认 |右剑齿-mariadb |无节点端口|

|默认 | right-sabertooth-wordpress | http://192.168.99.100:30454 |

| | | http://192.168.99.100:30427 |

| kube 系统 | kube-dns |无节点端口|

| kube 系统 |分蘖部署 |无节点端口|

|-------------|-----------------|--- ------------------------------|

但是,可以通过 http://192.168.99.100:30454 访问。

【讨论】:

这不是对所提问题的回答。【参考方案17】:

暴露你的服务有三种类型 节点端口 集群IP 负载均衡器

当我们使用负载均衡器时,我们基本上要求我们的云提供商给我们一个可以在线访问的 dns 注意不是域名,而是 dns。

所以负载均衡器类型在我们本地的 minikube 环境中不起作用。

【讨论】:

【参考方案18】:

检查 kube-controller 日志。我能够通过将 clusterID 标签设置到我部署集群的 ec2 实例来解决这个问题。

【讨论】:

【参考方案19】:

如果您不在受支持的云(aws、azure、gcloud 等)上,则不能在没有 MetalLB 的情况下使用 LoadBalancer https://metallb.universe.tf/ 但它还处于测试阶段..

【讨论】:

请提供代码示例来解释您的答案。【参考方案20】:

可能是您正在部署服务的子网,没有足够的 ip

【讨论】:

【参考方案21】:

对于您的用例,最好的选择是使用 NordPort 服务而不是负载平衡器类型,因为负载平衡器不可用。

【讨论】:

【参考方案22】:

我在 Docker 桌面上收到此错误。我只是退出并再次打开它(Docker-desktop)。花了几秒钟,然后它工作正常。

【讨论】:

【参考方案23】:

将运行在一组 Pod 上的应用程序公开为网络服务的一般方法在 Kubernetes 中称为服务。 Kubernetes 中有四种类型的服务。

集群IP 该服务只能从集群内访问。

节点端口 您将能够使用NodeIP:NodePort从集群外部与服务通信。默认节点端口范围是30000-32767,并且可以通过在集群创建时定义--service-node-port-range来更改此范围。

负载均衡器 使用云提供商的负载均衡器向外部公开服务。

外部名称 通过返回带有其值的 CNAME 记录,将服务映射到 externalName 字段的内容(例如 foo.bar.example.com)。没有设置任何类型的代理。

只有 LoadBalancer 为 External-IP 列提供值。只有当 Kubernetes 集群能够为该特定服务分配 IP 地址时,它才有效。您可以使用 metalLB 负载均衡器为您的负载均衡器服务提供 IP。

我希望你的疑虑会消失。

【讨论】:

【参考方案24】:

如果您使用的是裸机,则需要 NodePort 类型 https://kubernetes.github.io/ingress-nginx/deploy/baremetal/

LoadBalancer 默认在 Digital Ocean、Aws 等其他云提供商中工作

k edit service ingress-nginx-controller
type: NodePort

spec:
   externalIPs:
   - xxx.xxx.xxx.xx 

使用公共 IP

【讨论】:

【参考方案25】:

删除现有服务并创建相同的新服务解决了我的问题。我的问题是使用了我定义的负载平衡 IP,因此外部端点处于挂起状态。当我更改了一个新的负载平衡 IP 时,它仍然无法工作。

最后,删除现有服务并创建一个新服务解决了我的问题。

【讨论】:

进行性维护并不能帮助 OP 了解发生的实际问题。【参考方案26】:

如果您尝试在本地云中执行此操作,则需要 L4LB 服务来创建 LB 实例。

否则,您最终会收到您描述的无休止的“待处理”消息。在此处的视频中可见:https://www.youtube.com/watch?v=p6FYtNpsT1M

您可以使用开源工具来解决这个问题,该视频提供了一些关于自动化过程应该如何工作的指导。

【讨论】:

虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review

以上是关于Kubernetes 服务外部 ip 待定的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes:没有到主机的路由

Kubernetes v1.14.0 之 kube-apiserver集群部署

k8s 如何使用kube-dns实现服务发现

Kubernetes——Service(SVC)服务

如何在 Kitura 服务器中获取 Kubernetes 外部 IP

将 Google Cloud 中的外部 IP 与 Kubernetes 服务一起使用以将其公开到 Internet