【问题标题】:Kubernetes service external ip pendingKubernetes 服务外部 ip 待定
【发布时间】: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 仪表板上显示为挂起,在终端上也显示为待处理。

【问题讨论】:

    标签: nginx kubernetes load-balancing


    【解决方案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
    

    【讨论】:

    【解决方案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】:

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

          首先运行:

          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
                                猜你喜欢
                                • 2019-05-13
                                • 2018-11-14
                                • 1970-01-01
                                • 2020-06-02
                                • 2020-01-30
                                • 2018-08-27
                                • 1970-01-01
                                • 2021-05-12
                                相关资源
                                最近更新 更多