本文介绍关于LoadBalancer型Service的异常问题诊断流程和排查思路。

背景信息

当Service的类型设置为 Type=LoadBalancer 时,容器服务ACK的CCM(Cloud Controller Manager)组件会自动为该Service创建或配置阿里云负载均衡SLB(Server Load Balancer),包括SLB、监听、后端服务器组等资源。关于SLB的自动更新策略,请参见 Service的负载均衡配置注意事项

诊断流程

执行排查前,请确保CCM组件版本不低于V1.9.3.276-g372aa98-aliyun。关于如何升级CCM,请参见 升级CCM组件 。关于CCM的发布记录,请参见 Cloud Controller Manager

Service troubleshooting process
  1. 执行以下命令,确定SLB关联的Service。

    kubectl get svc -A |grep -i LoadBalancer|grep {XXX.XXX.XXX.XXX}  # XXX.XXX.XXX.XXX是loadbalancer IP。
  2. 执行以下命令,检查对应Service是否存在报错事件。

    kubectl -n {your-namespace} describe svc {your-svc-name}
    重要

    如果您执行命令后看不到Event信息,请确认您的CCM组件版本不低于V1.9.3.276-g372aa98-aliyun。关于如何查看及升级CCM版本,请参见 升级CCM组件

  3. 如果以上排查无果,请 提交工单

Service异常事件及处理方式

不同报错信息的解决方法如下表所示。

报错信息

说明及解决方法

The backend server number has reached to the quota limit of this load balancers

指SLB的后端服务器配额不足。

解决方案:您可以采取以下方式,优化配额消耗。

  • 默认情况下一个SLB实例可以挂载200个后端服务器,请申请提升配额。关于如何查询和提升配额,请登录 负载均衡SLB配额管理

  • 建议您设置SLB外部流量策略为Local模式(设置 externalTrafficPolicy: Local ),因为Cluster模式会快速消耗配额。如果需要使用Cluster模式,建议通过标签 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-backend-label 来指定使用的虚拟服务器,从而减少配额消耗。关于如何在注解中添加标签关联后端的虚拟服务器的操作,请参见 通过Annotation配置传统型负载均衡CLB

  • 由于多个Service复用一个SLB时,后端服务器数是累加的。建议您创建Service时,新建SLB。

The loadbalancer does not support backend servers of eni type

共享型SLB不支持ENI。

解决方案:如果SLB后端使用的是ENI,您需要选择性能保障型SLB实例。在Service中添加注解 annotation: service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec: "slb.s1.small"

重要

添加注解需要注意是否符合CCM的版本要求。关于注解和CCM的版本对应关系,请参见 常用注解

There are no available nodes for LoadBalancer

SLB无后端服务器,请确认Service是否已关联Pod且Pod正常运行。

解决方案:

  • 若未关联Pod,请将Service关联至应用Pod。

  • 若关联的Pod运行异常,请定位解决Pod异常,具体操作请参见 Pod异常问题排查

  • 如果SLB无后端服务器但Pod正常运行,请检查Pod所在节点是否为Master节点。如果是,请将业务Pod驱逐到Worker节点。如果不是,请 提交工单

  • alicloud: not able to find loadbalancer named [%s] in openapi, but it's defined in service.loaderbalancer.ingress. this may happen when you removed loadbalancerid annotation

  • alicloud: can not find loadbalancer, but it's defined in service

无法根据Service关联SLB。

解决方案:登录 负载均衡管理控制台 ,根据Service的 EXTERNAL-IP ,在其所在的地域搜索SLB。

  1. 如果搜索不到SLB,且该Service无需再使用,则删除对应的Service即可。

  2. 如果SLB存在,执行以下步骤。

    1. 如果SLB是手动在SLB控制台创建,在Service中添加注解 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id 。详情请参见 通过Annotation配置传统型负载均衡CLB

    2. 如果SLB是由CCM自动创建,确认该SLB是否有标签 kubernetes.do.not.delete 。如果没有,请添加标签。具体操作,请参见 旧版本CCM如何支持SLB重命名?

ORDER.ARREARAGE Message: The account is arrearage.

账号欠费。

PAY.INSUFFICIENT_BALANCE Message: Your account does not have enough balance.

账号余额少于100元,请充值。

Status Code: 400 Code: Throttlingxxx

SLB OpenAPI限流。

解决方案:

  1. 请登录 负载均衡SLB配额管理 ,查看并确保SLB配额充足。

  2. 执行以下命令,查看集群Service是否存在异常。如果存在,请参照此表处理异常事件。

    kubectl -n {your-namespace} describe svc {your-svc-name}

Status Code: 400 Code: RspoolVipExist Message: there are vips associating with this vServer group.

无法删除虚拟服务器组关联的监听。

解决方案:

  1. 确认Service中的注解是否带有SLB实例的ID(例如 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: {your-slb-id} )。

    如果注解带有SLB实例ID,说明是复用的SLB。

  2. 在SLB控制台中删除Service中 port 对应的监听。关于如何删除SLB监听,请参见 管理监听转发规则

Status Code: 400 Code: NetworkConflict

复用内网SLB时,该SLB和集群不在同一个VPC内。

解决方案:请确保您的SLB和集群在同一个VPC内。

Status Code: 400 Code: VSwitchAvailableIpNotExist Message: The specified VSwitch has no available ip.

虚拟交换机不足。

解决方案:通过 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-vswitch-id: "${YOUR_VSWITCH_ID}" 指定同VPC下另一个虚拟交换机。

Message:The specified VSwitch does not exist.

虚拟交换机不存在。

解决方案:

  • 如果Service中配置了注解 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-vswitch-id 请确认对应的vSwitch是否存在。

  • 如果Service中未配置 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-vswitch-id ,请确认集群默认的vSwitch ID是否存在。您可以在集群默认节点池(defaut-nodepool)的 基本信息 页签查看 节点虚拟交换机 。具体操作请参见 创建节点池

    如果不存在,请通过上述注解指定其他vSwitch。

The specified Port must be between 1 and 65535.

ENI模式不支持String类型的 targetPort

解决方案:将Service YAML中的 targetPort 字段改为INT类型或者升级CCM。关于如何升级CCM,请参见 升级CCM组件

Status Code: 400 Code: ShareSlbHaltSales Message: The share instance has been discontinued.

低版本CCM默认创建共享型SLB,但该类型SLB已停止售卖。

解决方案: 升级CCM组件

can not change ResourceGroupId once created

SLB资源组一旦创建后不支持修改。

解决方案:移除Service中的注解 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-resource-group-id:"rg-xxxx"

can not find eniid for ip x.x.x.x in vpc vpc-xxxx

无法在VPC内找到指定的ENI IP。

解决方案:确认Service中是否配置了注解 service.beta.kubernetes.io/backend-type:eni 。如果已配置,请确认集群网络插件是否为Flannel。Flannel网络模式不支持ENI模式,移除Service中对应的注解即可。

  • The operation is not allowed because the instanceChargeType of loadbalancer is PayByCLCU.

  • User does not have permission modify InstanceChargeType to spec.

SLB计费类型不支持从按量付费转为按规格收费。

解决方案:

  • 移除service中的Annotation: service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec

  • 如果service中有 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-instance-charge-type ,取值需设置为 PayByCLCU

SyncLoadBalancerFailed the loadbalancer xxx can not be reused,can not reuse loadbalancer created by kubernetes.

复用了CCM创建的SLB。

解决方案:

  1. 查看Service YAML中的annotation service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id 对应的SLB ID。

  2. 根据Service状态处理报错。

    • 如果Service为pending状态,您需要替换annotation service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id 中的SLB ID,更改为手动在 传统型负载均衡CLB控制台 创建的SLB。

    • 如果Service不是pending状态,根据以下实际情况处理。

      • 如果SLB对应的IP与Service的external IP一致,删除annotation service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id 即可。

      • 如果SLB对应的IP与Service的external IP不一致,您需要登录 传统型负载均衡CLB控制台 ,找到集群对应Region,根据Service的external IP查找对应的SLB,更改annotation service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id 中的SLB ID。如果没有找到对应的SLB,更改annotation service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id 中的SLB ID为手动在SLB控制台创建的SLB,然后重建Service。

alicloud: can not change LoadBalancer AddressType once created. delete and retry

SLB的类型一旦创建后不可更改,创建Service后更改了SLB的类型会导致该报错。

解决方案:删除重建Service。

the loadbalancer lb-xxxxx can not be reused, service has been associated with ip [xxx.xxx.xxx.xxx], cannot be bound to ip [xxx.xxx.xxx.xxx]

Service已经绑定一个SLB,不能再绑定另一个SLB。

解决方案:不支持通过更改 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id 的SLB ID的方式复用已有SLB。如果需要更改绑定的SLB,需要删除重建Service。

排查思路

对于非Service报错类的异常问题,请参考下表进行排查。

问题类别

问题现象

解决方案

SLB访问类

SLB负载不均

SLB负载不均

应用更新过程中访问SLB出现503报错

应用更新过程中访问SLB出现503报错

集群内无法访问SLB

集群内无法访问SLB

集群外无法访问SLB

集群外无法访问SLB

访问HTTPS端口报错 The plain HTTP request was sent to HTTPS port

无法连接到后端HTTPS服务

SLB配置类

Serivce注解未生效

Service注解不生效如何处理?

SLB配置被修改

为何SLB的配置被修改?

复用已有SLB未生效

为什么复用已有SLB没有生效?

复用已有SLB未配置监听

为什么复用已有SLB时没有配置监听?

SLB后端不一致

SLB虚拟服务器组未更新如何处理?

SLB删除类

SLB被删除

什么情况下会自动删除SLB?

Service删除后SLB未删除

什么情况下会自动删除SLB?

SLB负载不均

问题原因

SLB的调度算法设置不合理。

问题现象

SLB后端服务器负载不均。

解决方案

  • Local模式Service(即 externalTrafficPolicy: Local )需要将SLB调度算法设置为加权轮询算法,即为Service添加注解 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-scheduler:"wrr"

  • 如果业务为长连接,则需要将SLB调度算法设置为加权最少连接算法,即为Service添加注解 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-scheduler:"wlc"

应用更新过程中访问SLB出现503报错

问题原因

没有对SLB监听设置连接优雅中断,或没有对Pod设置优雅终止。

问题现象

应用更新过程中访问SLB出现503报错。

解决方案

  1. 通过 service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain 等注解为SLB监听设置连接优雅中断。关于注解的详细说明,请参见 监听的典型操作

  2. 根据容器网络模式,设置Pod的 preStop readinessProbe

    • readinessProbe 为就绪检查。只有就绪检查通过后,Pod才会被加入到Endpoint中。容器服务ACK监控到Endpoint变化后才会将Node挂载到SLB后端。需要合理设置就绪检测( readinessProbe )的探测频率、延时时间、不健康阈值等数据,部分应用启动时间本身较长,如果设置的时间过短,会导致Pod反复重启。

    • preStop 时间建议设置为业务处理完所有剩余请求所需的时间, terminationGracePeriodSeconds 时间建议设置为 preStop 的时间再加30秒以上。

    Pod配置示例:

    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      namespace: default
    spec:
      containers:
      - name: nginx
        image: nginx
        # 存活检测
        livenessProbe:
          failureThreshold: 3
          initialDelaySeconds: 30
          periodSeconds: 30
          successThreshold: 1
          tcpSocket:
            port: 5084
          timeoutSeconds: 1
        # 就绪检测
        readinessProbe:
          failureThreshold: 3
          initialDelaySeconds: 30
          periodSeconds: 30
          successThreshold: 1
          tcpSocket:
            port: 5084
          timeoutSeconds: 1
        # 优雅退出
        lifecycle:
          preStop:
            exec:
              command:
              - sleep
      terminationGracePeriodSeconds: 60

集群内无法访问SLB

问题原因

SLB设置了 externalTrafficPolicy: Local 类型,这种类型的SLB地址只有在Node中部署了对应的后端Pod,才能被访问。因为SLB的地址是集群外使用,如果集群节点和Pod不能直接访问,请求不会到SLB,会被当作Service的扩展IP地址,被kube-proxy的iptables或ipvs转发。

如果刚好集群节点或者Pod所在的节点上没有相应的后端服务Pod,就会发生网络不通的问题,而如果有相应的后端服务Pod,是可以正常访问。相关问题的更多信息请参见 kube-proxy将external-lb的地址添加到节点本地iptables规则

问题现象

集群内无法访问SLB。

解决方案

  • 在Kubernetes集群内通过ClusterIP或者服务名访问。

    其中Ingress的服务名为: nginx-ingress-lb.kube-system

  • 将LoadBalancer的Service中的externalTrafficPolicy修改为Cluster,但是在应用中会丢失原IP,Ingress的服务修改命令如下。

    说明

    若是Ingress的SLB,只有Ingress的Pod所在节点上,Pod才能访问通过Ingress或SLB暴露出去的服务。

    kubectl edit svc nginx-ingress-lb -n kube-system
  • 若是Terway的ENI或者ENI多IP的集群,将LoadBalancer的Service中的externalTrafficPolicy修改为Cluster,并且添加ENI直通的annotation,例如 annotation: service.beta.kubernetes.io/backend-type:"eni" ,具体格式如下,可以保留源IP,并且在集群内访问也没有问题。详细信息,请参见 通过Annotation配置传统型负载均衡CLB

    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        service.beta.kubernetes.io/backend-type: eni
      labels:
        app: nginx-ingress-lb
      name: nginx-ingress-lb
      namespace: kube-system
    spec:
      externalTrafficPolicy: Cluster

集群外无法访问SLB

问题原因

SLB设置了ACL或SLB未正常运行。

问题现象

集群外无法访问SLB。

解决方案

  1. 执行以下命令,查看Service事件信息,并处理异常事件。具体操作,请参见 Service异常事件及处理方式

    kubectl -n {your-namespace} describe svc {your-svc-name}
  2. 确认SLB是否配置了ACL。

    如果配置了ACL,请确认ACL是否允许客户端IP访问。关于SLB的ACL配置,请参见 访问控制

  3. 确认SLB虚拟服务器组是否为空。

    如果虚拟服务器组为空,请检查业务Pod是否关联了Service及业务Pod是否正常运行。如果关联的Pod运行异常,请定位解决Pod异常。具体操作,请参见 Pod异常问题排查

  4. 确认SLB监听的健康检查是否正常。

    如果SLB健康检查异常,请检查业务Pod是否正常运行。关于SLB的健康检查,请参见 健康检查探测

  5. 如果以上步骤未解决您的问题,请 提交工单

无法连接到后端HTTPS服务

问题原因

SLB上配置证书后将会在SLB侧进行解密,导致实际发送到后端Pod的请求为HTTP请求。

问题现象

无法连接到后端HTTPS服务。

解决方案

将Serivce中HTTPS端口对应的Target Port配置为HTTP端口。以Nginx为例,HTTPS端口为443,其对应的 targetPort 需要改为 80

配置示例:

apiVersion: v1
kind: Service
metadata:
  annotations:
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-protocol-port: "https:443"
    service.beta.kubernetes.io/alibaba-cloud-loadbalancer-cert-id: "${YOUR_CERT_ID}"
  name: nginx
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  - port: 443
    protocol: TCP
    targetPort: 80
  selector:
    run: nginx
  type: LoadBalancer