本文介绍关于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 。
-
执行以下命令,确定SLB关联的Service。
kubectl get svc -A |grep -i LoadBalancer|grep {XXX.XXX.XXX.XXX} # XXX.XXX.XXX.XXX是loadbalancer IP。
-
执行以下命令,检查对应Service是否存在报错事件。
kubectl -n {your-namespace} describe svc {your-svc-name}
重要如果您执行命令后看不到Event信息,请确认您的CCM组件版本不低于V1.9.3.276-g372aa98-aliyun。关于如何查看及升级CCM版本,请参见 升级CCM组件 。
-
有异常事件:请参见 Service异常事件及处理方式 。
-
无异常事件:请参见 排查思路 。
-
-
如果以上排查无果,请 提交工单 。
Service异常事件及处理方式
不同报错信息的解决方法如下表所示。
报错信息 |
说明及解决方法 |
|
指SLB的后端服务器配额不足。 解决方案:您可以采取以下方式,优化配额消耗。
|
|
共享型SLB不支持ENI。
解决方案:如果SLB后端使用的是ENI,您需要选择性能保障型SLB实例。在Service中添加注解
重要
添加注解需要注意是否符合CCM的版本要求。关于注解和CCM的版本对应关系,请参见 常用注解 。 |
|
SLB无后端服务器,请确认Service是否已关联Pod且Pod正常运行。 |
|
无法根据Service关联SLB。
解决方案:登录
负载均衡管理控制台
,根据Service的
|
|
账号欠费。 |
|
账号余额少于100元,请充值。 |
|
SLB OpenAPI限流。 解决方案:
|
|
无法删除虚拟服务器组关联的监听。 解决方案:
|
|
复用内网SLB时,该SLB和集群不在同一个VPC内。 解决方案:请确保您的SLB和集群在同一个VPC内。 |
|
虚拟交换机不足。
解决方案:通过
|
|
虚拟交换机不存在。 解决方案:
|
|
ENI模式不支持String类型的
解决方案:将Service YAML中的
|
|
低版本CCM默认创建共享型SLB,但该类型SLB已停止售卖。 解决方案: 升级CCM组件 。 |
|
SLB资源组一旦创建后不支持修改。
解决方案:移除Service中的注解
|
|
无法在VPC内找到指定的ENI IP。
解决方案:确认Service中是否配置了注解
|
|
SLB计费类型不支持从按量付费转为按规格收费。 解决方案:
|
|
复用了CCM创建的SLB。 解决方案:
|
|
SLB的类型一旦创建后不可更改,创建Service后更改了SLB的类型会导致该报错。 解决方案:删除重建Service。 |
|
Service已经绑定一个SLB,不能再绑定另一个SLB。
解决方案:不支持通过更改
|
排查思路
对于非Service报错类的异常问题,请参考下表进行排查。
问题类别 |
问题现象 |
解决方案 |
SLB访问类 |
SLB负载不均 |
|
应用更新过程中访问SLB出现503报错 |
||
集群内无法访问SLB |
||
集群外无法访问SLB |
||
访问HTTPS端口报错
|
||
SLB配置类 |
Serivce注解未生效 |
|
SLB配置被修改 |
||
复用已有SLB未生效 |
||
复用已有SLB未配置监听 |
||
SLB后端不一致 |
||
SLB删除类 |
SLB被删除 |
|
Service删除后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报错。
解决方案
-
通过
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-connection-drain
等注解为SLB监听设置连接优雅中断。关于注解的详细说明,请参见 监听的典型操作 。 -
根据容器网络模式,设置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。
解决方案
-
执行以下命令,查看Service事件信息,并处理异常事件。具体操作,请参见 Service异常事件及处理方式 。
kubectl -n {your-namespace} describe svc {your-svc-name}
-
确认SLB是否配置了ACL。
如果配置了ACL,请确认ACL是否允许客户端IP访问。关于SLB的ACL配置,请参见 访问控制 。
-
确认SLB虚拟服务器组是否为空。
如果虚拟服务器组为空,请检查业务Pod是否关联了Service及业务Pod是否正常运行。如果关联的Pod运行异常,请定位解决Pod异常。具体操作,请参见 Pod异常问题排查 。
-
确认SLB监听的健康检查是否正常。
如果SLB健康检查异常,请检查业务Pod是否正常运行。关于SLB的健康检查,请参见 健康检查探测 。
-
如果以上步骤未解决您的问题,请 提交工单 。
无法连接到后端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