全部产品
Search
文档中心

容器服务 Kubernetes 版 ACK:Service FAQ

更新时间:Aug 09, 2024

本文汇总了使用容器服务ACK Service时的一些常见问题。包括但不限于为什么集群内无法访问SLB IP、为什么复用已有SLB没有生效、CCM升级失败如何处理等问题的解决方案。

索引

使用已有SLB常见问题

其他

SLB相关

ACK集群中SLB实例的具体用途

如果创建Kubernetes集群时安装了Nginx Ingress组件,那么集群会默认自动创建两个SLB实例。

两个SLB实例的用途说明如下:

  • APIServer SLB:该SLB实例为API Server的访问入口,访问集群均需要与该SLB实例通信。监听端口为6443,监听协议为TCP。后端节点为APIServer Pod或者Master ECS。

  • Nginx Ingress Controller SLB:该SLB实例与kube-system命名空间下的nginx-ingress-controller服务关联,虚拟服务器组会动态绑定Nginx Ingress Controller Pod,实现对外部请求的负载均衡和路由转发。监听端口为80和443,监听协议为TCP。

创建Service时,Local和Cluster两种外部流量策略如何选择?

不同网络插件,Local和Cluster两种外部流量策略的功能不同。关于Local和Cluster两种外部流量策略的详细区别,请参见外部流量策略Local和Cluster介绍

为什么看不到Service与LoadBalancer同步过程的事件Event信息?

如果执行命令kubectl -n {your-namespace} describe svc {your-svc-name}后看不到Event信息的话,请确认您的CCM组件版本。

  • 低于v1.9.3.276-g372aa98-aliyun版本:低版本CCM组件无法看到Service与LoadBalancer同步过程的事件信息,请升级组件版本。关于如何查看及升级CCM版本,请参见升级CCM组件

  • 大于或等于v1.9.3.276-g372aa98-aliyun版本:请提交工单

SLB创建一直处于Pending状态如何处理?

  1. 执行命令kubectl -n {your-namespace} describe svc {your-svc-name}查看事件信息。

  2. 处理事件中的报错信息。关于事件中不同报错信息的处理方式,请参见报错事件及对应处理方式

    如果看不到报错信息,请参见为什么看不到Service与LoadBalancer同步过程的事件Event信息?

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

  1. 执行命令kubectl -n {your-namespace} describe svc {your-svc-name}查看事件信息。

  2. 处理事件中的报错信息。关于事件中不同报错信息的处理方式,请参见报错事件及对应处理方式

    如果看不到报错信息,请参见为什么看不到Service与LoadBalancer同步过程的事件Event信息?

Service注解不生效如何处理?

  1. 按照以下步骤查看报错信息。

    1. 执行命令kubectl -n {your-namespace} describe svc {your-svc-name}查看事件信息。

    2. 处理事件中的报错信息。关于事件中不同报错信息的处理方式,请参见报错事件及对应处理方式

  2. 如果没有报错信息,分以下三种场景解决:

为何SLB的配置被修改?

CCM使用声明式API,会在一定条件下根据Service的配置自动更新SLB配置。您自行在SLB控制台上修改的配置均存在被覆盖的风险。建议您通过注解的方式配置SLB。关于注解配置方式的更多信息,请参见通过Annotation配置传统型负载均衡CLB

重要

请勿在SLB控制台上手动修改Kubernetes创建并维护的SLB的任何配置,否则有配置丢失的风险,造成Service不可访问。

为什么集群内无法访问SLB IP?

  • 场景一:设置SLB IP为私网地址,并且没有通过Service方式创建SLB,那么SLB后端Pod和访问SLB Pod将在同一个节点,导致在集群内访问SLB IP失败。

    对于四层负载均衡服务,目前不支持负载均衡后端ECS实例直接为客户端提供服务的同时,又作为负载均衡的后端服务器。因此在集群内访问SLB IP会失败。您可以通过以下方式解决该问题,从而避免访问端和目的端在同一个节点。

    • 将SLB IP修改为公网地址。

    • 使用Service的方式创建SLB,同时设置外部流量策略为Cluster,这种情况下kube-proxy会劫持集群内访问SLB流量,绕过SLB本身限制。

  • 场景二:使用Service发布服务时,设置了外部流量策略为Local,导致在集群内访问SLB IP失败。

    关于该问题的详细原因和解决方案,请参见如何解决Kubernetes集群中访问LoadBalancer暴露出去的SLB地址不通?

如何解决Kubernetes集群中访问LoadBalancer暴露出去的SLB地址不通?

问题描述

在Kubernetes集群中,有部分节点能够访问集群暴露出去的Local类型的SLB,但是也有部分节点不能访问,且Ingress出现该问题较多。

问题原因

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

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

解决方案

可以参见以下方法解决问题,推荐您使用第一种方法:

  • 在Kubernetes集群内通过ClusterIP或者服务名访问内部服务。其中Ingress的服务名为:nginx-ingress-lb.kube-system

  • 将LoadBalancer的Service中的externalTrafficPolicy修改为Cluster。这种方式虽然可以确保流量能够被转发到所有节点上的Pod,但会导致源IP地址丢失,因为集群会执行SNAT(源网络地址转换)。这意味着后端应用无法获取到客户端的真实IP地址。Ingress的服务修改命令如下:

    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的策略取决于SLB是否由CCM自动创建。删除策略如下表所示。

Service操作

CCM自动创建的SLB

复用的已有SLB

删除Service

删除SLB

保留SLB

修改LoadBalancer型Service为其他类型

删除SLB

保留SLB

删除Service是否会删除SLB?

如果是复用已有SLB(Service中有service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: {your-slb-id}注解),删除Service时不会删除SLB;否则删除Service时会删除对应的SLB。

如果您更改Service类型(例如从LoadBalancer改为NodePort)也会删除对应的CCM自动创建的SLB。

误删除SLB怎么办?

  • 场景一:误删除API Server SLB如何处理?

    无法恢复,您需要重建集群。具体操作,请参见创建ACK Pro版集群

  • 场景二:误删除Ingress SLB如何处理?

    按照以下步骤重新创建SLB。

    1. 登录容器服务管理控制台,在左侧导航栏选择集群

    2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择网络 > 服务

    3. 服务页面顶部的命名空间下拉列表中,单击kube-system,然后在服务列表中,找到目标服务nginx-ingress-lb,然后单击目标服务。

      如果没有nginx-ingress-lb,请在当前页面右上角单击使用YAML创建资源,使用以下模板创建名为nginx-ingress-lb的Service。

      apiVersion: v1
      kind: Service
      metadata:
        labels:
          app: nginx-ingress-lb
        name: nginx-ingress-lb
        namespace: kube-system
      spec:
        externalTrafficPolicy: Local
        ports:
        - name: http
          port: 80
          protocol: TCP
          targetPort: 80
        - name: https
          port: 443
          protocol: TCP
          targetPort: 443
        selector:
          app: ingress-nginx
        type: LoadBalancer
    4. 在目标服务的操作列,单击YAML编辑,移除status内容后,然后单击更新以让CCM重新构建SLB。

  • 场景三:误删除业务相关的SLB如何处理?

    • 如果不需要SLB对应的Service,删除Service。

    • 如果对应的Service还需要使用,解决方法如下。

      1. 登录容器服务管理控制台,在左侧导航栏选择集群

      2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择网络 > 服务

      3. 服务页面顶部的命名空间下拉框中,单击所有命名空间,然后在服务列表中,找到业务Service。

      4. 在目标服务的操作列,单击YAML编辑,移除status内容后,然后单击更新以让CCM重新构建SLB。

旧版本CCM如何支持SLB重命名?

Cloud Controller Manager组件V1.9.3.10后续版本创建的SLB支持自动打TAG从而可以重命名,而V1.9.3.10及之前的版本,您需要手动给该SLB打上一个特定的TAG从而支持SLB重命名。

说明
  • 只有Cloud Controller Manager组件V1.9.3.10及之前版本创建的SLB才需要手动打TAG的方式来支持重命名。

  • Service类型为LoadBalancer。

  1. 登录到Kubernetes集群Master节点,请参见获取集群KubeConfig并通过kubectl工具连接集群

  2. 执行 kubectl get svc -n ${namespace} ${service}命令,查看该Service类型及IP。service类型

    说明

    您需要将namespaceservice替换为所选集群的命名空间及服务名称。

  3. 执行以下命令,生成该SLB所需要的Tag。

    kubectl get svc -n ${namespace} ${service} -o jsonpath="{.metadata.uid}"|awk -F "-" '{print "kubernetes.do.not.delete: "substr("a"$1$2$3$4$5,1,32)}'

    tag

  4. 登录负载均衡控制台根据步骤2中所获取的IP,在其所在的地域搜索到该SLB。

  5. 根据步骤3生成的Key值和Value值(分别对应上图的1和2),为该SLB打上一个Tag。具体操作,请参见管理标签

Local模式下如何自动设置Node权重?

本文以业务Pod(app=nginx)部署在三台ECS上,通过Service A对外提供服务为例,说明在Local模式下Node权重的计算方式。

CCM2

V1.9.3.276-g372aa98-aliyun及之后版本

权重计算方式因为计算精度问题,Pod间还会存在轻微的负载不均。在V1.9.3.276-g372aa98-aliyun及之后版本,CCM将Node上部署的Pod数量设置为Node权重,如下图所示,三台ECS的权重分别为1、2、3,流量会按照1:2:3的比例分配给三台ECS,Pod负载会更加均衡。

计算公式如下所示:node权重

node

V1.9.3.164-g2105d2e-aliyun之后及V1.9.3.276-g372aa98-aliyun之前版本

如图所示,在V1.9.3.164-g2105d2e-aliyun之后及V1.9.3.276-g372aa98-aliyun之前版本,CCM会根据Node上部署的Pod数量计算Node权重。经计算三台ECS权重分别为16、33、50,因此流量将大致按照1:2:3的比例分配给三台ECS,Pod负载更加均衡。

计算公式如下所示:计算公式

ccm4

V1.9.3.164-g2105d2e-aliyun之前版本

如下图所示,在V1.9.3.164-g2105d2e-aliyun之前的版本中,Local模式的Service其所有后端权重均为100,即所有流量平均分配到这三台ECS上,造成ECS 1上Pod负载较重而ECS 3上的Pod负载较轻,导致Pod负载不均衡。

CCM3

如何查询集群中所有SLB的IP、名称及类型

  1. 获取集群KubeConfig并通过kubectl工具连接集群

  2. 执行如下命令,获取所有命名空间中每个LoadBalancer类型服务的名称、IP地址和地址类型信息。

    kubectl get services -A -ojson | jq '.items[] | select(.spec.type == "LoadBalancer") | {name: .metadata.name, namespace: .metadata.namespace, ip: .status.loadBalancer.ingress[0].ip, lb_type: .metadata.annotations."service.beta.kubernetes.io/alibaba-cloud-loadbalancer-address-type"}'

    预期输出如下:

    {
      "name": "test",
      "namespace": "default",
      "ip": "192.168.*.*",
      "lb_type": "intranet"
    }
    {
      "name": "nginx-ingress-lb",
      "namespace": "kube-system",
      "ip": "47.97.*.*",
      "lb_type": "null"
    }

LoadBalancer类型的Service更替后端时,如何确保LB能够优雅中断已有连接

您可以通过Annotation service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain和service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain-timeout配置优雅中断。从Service移除后端后,LB依然会在drain-timeout期间内保持存量连接的处理。详细信息,请参见为监听设置连接优雅中断

使用已有SLB常见问题

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

  • 排查CCM版本,低于v1.9.3.105-gfd4e547-aliyun的CCM版本不支持复用。关于如何查看及升级CCM版本的操作,请参见升级CCM组件

  • 确认复用的SLB是否为集群创建的,不支持复用集群创建的SLB。

  • 确认SLB是否为API Server的SLB,不支持复用API Server的SLB。

  • 如果是私网SLB,请确认SLB是否和集群在同一个VPC中,不支持跨VPC复用SLB。

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

确认是否在注解中配置了service.beta.kubernetes.io/alibaba-cloud-loadbalancer-force-override-listeners"true"。如果没有配置,则不会自动创建监听。

说明

复用已有的负载均衡默认不会覆盖已有的监听,有以下两点原因:

  • 如果已有负载均衡的监听上绑定了业务,强制覆盖可能会引发业务中断。

  • 由于CCM目前支持的后端配置有限,无法处理一些复杂配置。如有复杂的后端配置需求,可以在不覆盖监听的情况下,通过控制台自行配置监听。

考虑到以上两种情况,不建议您强制覆盖监听。如果已有负载均衡的监听端口不再使用,则可以强制覆盖。

其他

CCM升级失败如何处理?

关于CCM组件升级失败的解决方案,请参见Cloud Controller Manager(CCM)组件升级检查失败

Service报错信息及对应处理方式

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

报错信息

说明及解决方法

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

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

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

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

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

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

The loadbalancer does not support backend servers of eni type

共享型CLB不支持ENI。

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

重要

添加注解需要注意是否符合CCM的版本要求。关于注解和CCM的版本对应关系,请参见通过Annotation配置传统型负载均衡CLB

There are no available nodes for LoadBalancer

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

解决方案:

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

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

  • 如果CLB无后端服务器但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关联CLB。

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

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

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

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

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

ORDER.ARREARAGE Message: The account is arrearage.

账号欠费。

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

账户余额不足。

Status Code: 400 Code: Throttlingxxx

CLB OpenAPI限流。

解决方案:

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

  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中的注解是否带有CLB实例的ID(例如service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: {your-clb-id})。

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

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

Status Code: 400 Code: NetworkConflict

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

解决方案:请确保您的CLB和集群在同一个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下另一个虚拟交换机。

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默认创建共享型CLB,但该类型CLB已停止售卖。

解决方案:升级CCM组件

can not change ResourceGroupId once created

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

解决方案:移除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.

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

解决方案:

  • 移除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创建的CLB。

解决方案:

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

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

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

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

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

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

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

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

解决方案:删除重建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已经绑定一个CLB,不能再绑定另一个CLB。

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

当Service类型为NodePort时,如何为Service配置监听?

CCM仅支持为LoadBalancer的Service配置监听。您需要将Service类型从NodePort修改为LoadBalancer。

如何访问NodePort类型的Service?

  • 如果在集群内(集群节点内)访问,您可以使用ClusterIP+Port,或者节点IP+Service中NodePort端口访问Service。默认的NodePort端口会大于30000。

  • 如果在集群外(集群节点外)访问,您可以使用节点IP+Service中NodePort端口访问Service。默认的NodePort端口会大于30000。

  • 如果在VPC外部(其他VPC或者公网)访问,您需要发布LoadBalancer类型的Service,然后通过Service的外部端点访问Service。

    说明

    如果您的Service设置了外部流量转发策略为本地,请确保被访问的节点上存在Service后端Pod。关于更多外部流量策略,请参见外部流量策略Local和Cluster介绍

如何正确配置NodePort范围?

在Kubernetes中,APIServer提供了ServiceNodePortRange参数(命令行参数 --service-node-port-range),该参数是用于限制NodePort或LoadBalancer类型的Service在节点上所监听的NodePort端口范围,该参数默认值为30000~32767。在ACK Pro集群中,您可以通过自定义Pro集群的管控面参数修改该端口范围。具体操作,请参见自定义ACK Pro集群的管控面参数

  • 您在修改NodePort端口范围时必须十分谨慎。务必保证NodePort端口范围与集群节点上Linux内核提供的net.ipv4.ip_local_port_range参数中的端口范围不冲突。该内核参数ip_local_port_range控制了Linux系统上任意应用程序可以使用的本地端口号范围。ip_local_port_range的默认值为32768~60999。

  • 您所创建的ACK集群在默认配置情况下,ServiceNodePortRange参数和ip_local_port_range参数不会产生冲突。如果您此前为了提升端口数量限制调整了这两个参数中任意一个,导致两者范围出现重合,则可能会产生节点上的偶发网络异常,严重时会导致业务健康检查失败、集群节点离线等。建议您恢复默认值或同时调整两个端口范围到完全不重合。

  • 调整端口范围后,集群中可能存在部分NodePort或LoadBalancer类型的Service仍在使用ip_local_port_range参数端口范围内的端口作为NodePort。此时您需要对这部分Service进行重新配置以避免冲突,可通过kubectl edit <service-name>的方式直接将spec.ports.nodePort字段的值更改为未被占用的NodePort。