Kubernetes 服务外部 ip pending

Kubernetes service external ip pending

我正在尝试在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 仪表板上,还在终端上显示为挂起。

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

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

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

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

这里有更多信息:Minikube GitHub

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

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

使用节点端口:

$ 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):(端口)

访问

我使用 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"]}}'

此后,它开始通过 public 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

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

$ minikube tunnel

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

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

同样的问题:

os>kubectl get svc right-sabertooth-wordpress

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
right-sabertooth-wordpress LoadBalancer 10.97.130.7 "pending" 80:30454/TCP,443:30427/TCP

os>minikube service list

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

| NAMESPACE | NAME | URL |

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

| default | kubernetes | No node port |

| default | right-sabertooth-mariadb | No node port |

| default | right-sabertooth-wordpress | http://192.168.99.100:30454 |

| | | http://192.168.99.100:30427 |

| kube-system | kube-dns | No node port |

| kube-system | tiller-deploy | No node port |

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

但是,可以通过 http://192.168.99.100:30454.

访问

删除现有服务并创建相同的新服务解决了我的问题。我的问题是使用了我定义的负载平衡 IP,因此外部端点处于挂起状态。我换了一个新的负载均衡IP还是不行

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

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

minikube 服务 << service_name >> --url --namespace=<< namespace_name >>

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

关注@Javier 的回答。我决定为我的负载均衡器使用 "patching up the external IP"。

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

这会将 'pending' 替换为可用于集群的新修补 IP 地址。

有关此的更多信息。请在 LoadBalancer support with Minikube for Kubernetes

上查看 karthik 的 post

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

使用Minikube时,可以获取到你使用的IP和端口 可以通过 运行:

访问服务
minikube service [service name]

例如:

minikube service kubia-http

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

如果您使用的是 minikube,那么 运行 从终端执行下面的命令,

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

LoadBalancer ServiceType 只有在底层基础设施支持自动创建负载均衡器并且在 Kubernetes 中有相应的支持时才会起作用,Google 云平台和 AWS 就是这种情况。如果没有配置这样的功能,LoadBalancer IP 地址字段不会被填充并且仍然处于 pending 状态,并且该服务将以与 NodePort 类型服务相同的方式工作

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

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

kubectl 补丁服务 my-loadbalancer-service-name \ -n lb-服务命名空间\ -p '{"spec": {"type": "LoadBalancer", "externalIPs":["xxx.xxx.xxx.xxx Private IP of Physical Server - Node - where deployment is done "]}}'

如果是你的私有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 安装后:

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

首先运行:

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

2: 子网未根据提到的要求进行标记 here

使用以下标记 VPC:

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

标记 public 个子网:

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

公开您的服务有三种类型 节点端口 集群IP 负载均衡器

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

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

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

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

microk8s enable metallb

<pending> 应该变成一个实际的 IP 地址。

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

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

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

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

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

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

只有 LoadBalancer 为外部 IP 列提供价值。并且它仅在 Kubernetes 集群能够为该特定服务分配 IP 地址时才有效。您可以使用 metalLB 负载均衡器为您的负载均衡器服务提供 IP。

希望你的疑惑能消失。

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

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

如果您使用的是裸机,则需要 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 

使用 public IP

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

否则您将收到您所描述的无穷无尽的“待定”消息。在此处的视频中可见:https://www.youtube.com/watch?v=p6FYtNpsT1M

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

minikube 隧道

以下解决方案适用于我的情况。

首先,试试这个命令:

minikube tunnel

如果它不适合你。遵循以下:

我重新启动 minikube 容器。

docker minikube stop 

然后

docker minikube start

之后re-runkubernetes

minikube dashboard

完成后执行:

 minikube tunnel

我在使用 AWS EKS 时遇到了同样的问题

这里是如何解决的:

The correct tags for your Amazon Virtual Private Cloud (Amazon VPC) subnets

The required AWS Identity and Access Management (IAM) permissions for your cluster's IAM role A valid Kubernetes service definition Load balancers that stay within your account limit Enough free IP addresses on your subnets

需要确保以下标签

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

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

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

仅供参考,还要确保您正在处理的区域启用了 sts 设置可以在用户、区域设置下找到。

我也遇到了同样的问题。 Windows 10 桌面版 + Docker 桌面版 4.7.1 (77678) + Minikube v1.25.2

根据我这边的 official docs,我决定:

PS C:\WINDOWS\system32> kubectl expose deployment sito-php --type=LoadBalancer --port=8080 --name=servizio-php
service/servizio-php exposed
PS C:\WINDOWS\system32> minikube tunnel
 * Tunnel successfully started

 * NOTE: Please do not close this terminal as this process must stay alive for the tunnel to be accessible ...

 * Starting tunnel for service servizio-php.


PS E:\docker\apache-php> kubectl get service
NAME           TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes     ClusterIP      10.96.0.1      <none>        443/TCP          33h
servizio-php   LoadBalancer   10.98.218.86   127.0.0.1     8080:30270/TCP   4m39s

http://127.0.0.1:8080/

上打开的浏览器