前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >故障分析 | Kubernetes 故障诊断流程

故障分析 | Kubernetes 故障诊断流程

作者头像
爱可生开源社区
发布2021-11-11 09:40:55
1.1K0
发布2021-11-11 09:40:55
举报
文章被收录于专栏:爱可生开源社区

作者:郑增权 原创内容未经授权不得随意使用,转载请联系小编并注明来源。

一、本文概述及主要术语

1.1 概述

本文基于 Pod 、Service 和 Ingress 三大模块进行划分,对于 Kubernetes 日常可能出现的故障问题,提供了较为具体的排查步骤,并附上相关解决方法或参考文献。

1.2 主要术语
  1. Pod: Kubernetes 中创建和管理的、最小的可部署的计算单元。是一组(一个或多个) 容器;这些容器共享存储、网络、以及怎样运行这些容器的声明。
  2. Port-forward: 通过端口转发映射本地端口到指定的应用端口。
  3. Service: 一个 Kubernetes 的 Service 是一种抽象,它定义了一组 Pods 的逻辑集合和一个用于访问它们的策略 - 有时被称为微服务。
  4. Ingress: 提供了集群外部到内部 HTTP 和 HTTPS 服务的路由通信,流量路由通过 Ingress 资源上定义的规则控制。

二、故障诊断流程

2.1 Pods 模块检查
  • 以下流程若成功则继续往下进行,若失败则根据提示进行跳转。
2.1.1 检查是否有 pod 处于 PENDING 状态
  1. kubectl get pods:如果有 pod 处于 PENDING 状态则往下看,否则前往 2.1.5 。
代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl get pods
NAME                               READY    STATUS    RESTARTS   AGE
myapp-deploy-55b54d55b8-5msx8      0/1      Pending   0          5m

  1. kubectl describe pod <pod-name>:若正确输出指定的一个或多个资源的详细信息,则判断是否集群资源不足,若不足则进行拓展,否则前往 2.1.2 。
2.1.2 检查是否触发 ResourceQuota limit
  1. kubectl describe resourcequota -n <namespace>:
代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl describe quota compute-resources --namespace=myspace
Name:            compute-resources
Namespace:       myspace
Resource         Used  Hard
--------         ----  ----
limits.cpu       0     2
limits.memory    0     2Gi
pods             0     4
requests.cpu     0     1
requests.memory  0     1Gi
  1. 如有限制则进行相应资源释放或拓展,参考:https://kubernetes.io/zh/docs/concepts/configuration/manage-resources-containers/#extended-resources
  2. 否则前往 2.1.3
2.1.3 检查是否有 PVC 处于 PENDING 状态
  1. 持久卷(PersistentVolume,PV)是集群中的一块存储,可以由管理员事先供应,或者使用存储类(Storage Class)来动态供应;持久卷申领( PersistentVolumeClaim, PVC )表达的是用户对存储的请求。
  2. kubectl describe pvc <pvc-name>:若 STATUS 为 Pending
代码语言:javascript
复制
[root@10-186-65-37 k8s-file]# kubectl get pvc
NAME               STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
local-device-pvc   Pending                                      local-device   72s

则参考如下链接进行解决:https://kubernetes.io/zh/docs/concepts/storage/persistent-volumes/

  1. 否则前往 2.1.4 。
2.1.4 检查 pod 是否被分配至 node
  1. kubectl get pods -o wide:若已被分配至 node
代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl get pods -o wide
NAME                             READY   STATUS    RESTARTS   AGE   IP            NODE            NOMINATED NODE   READINESS GATES
myapp-deploy-55b54d55b8-5msx8    1/1     Running   0          14d   10.244.4.9    10-186-65-122   <none>           <none>
myapp-deploy-55b54d55b8-7ldj4    1/1     Running   0          14d   10.244.2.10   10-186-65-126   <none>           <none>
myapp-deploy-55b54d55b8-cwdwt    1/1     Running   0          14d   10.244.3.9    10-186-65-126   <none>           <none>
myapp-deploy-55b54d55b8-gvmb9    1/1     Running   0          14d   10.244.4.10   10-186-65-122   <none>           <none>
myapp-deploy-55b54d55b8-xbqb6    1/1     Running   0          14d   10.244.5.9    10-186-65-118   <none>           <none>

则是 Scheduler 方面的问题,参考如下链接进行解决:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/kube-scheduler/

  1. 否则为 Kubectl 的问题。
2.1.5 检查是否有 pods 处于 RUNNING 状态
  1. kubectl get pods -o wide:如果 pods 处于 RUNNING 状态则前往 2.1.10 ,否则前往 2.1.6 。
2.1.6 检查 pod 日志
  1. kubectl logs <pod-name>:

若能正确获取日志则根据日志修复相关问题。

代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl logs myapp-deploy-55b54d55b8-5msx8
127.0.0.1 - - [30/Sep/2021:06:53:16 +0000] "GET / HTTP/1.1" 200 65 "-" "curl/7.29.0" "-"
127.0.0.1 - - [30/Sep/2021:07:49:44 +0000] "GET / HTTP/1.1" 200 65 "-" "curl/7.29.0" "-"
127.0.0.1 - - [30/Sep/2021:07:51:09 +0000] "GET / HTTP/1.1" 200 65 "-" "curl/7.29.0" "-"
127.0.0.1 - - [30/Sep/2021:07:57:00 +0000] "GET / HTTP/1.1" 200 65 "-" "curl/7.29.0" "-"
127.0.0.1 - - [30/Sep/2021:08:03:56 +0000] "GET / HTTP/1.1" 200 65 "-" "curl/7.29.0" "-"
  1. 若无法获取日志则判断容器是否快速停止运行,若快速停止则执行:kubectl logs <pod-name> --previous
  2. 无法获取日志,且容器并非快速停止运行,则前往2.1.7
2.1.7 Pod 状态是否处于 ImagePullBackOff
  1. kubectl describe pod <pod-name>:查看 status 是否为 ImagePullBackOff ?不为 ImagePullBackOff 则前往2.1.8 。
  2. 查看 image 名称是否正确,错误则修正。
  3. 查看 image tag 是否存在并经过验证。
  4. 是否从 private registry 拉取镜像?若是则确认配置信息正确。
  5. 若并非从 private registry 拉取镜像,问题可能出在 CRI(容器运行时接口) 或 kubectl 。
2.1.8 Pod 状态是否处于 CrashLoopBackOff
  1. kubectl describe pod <pod-name>:查看 status 是否为 CrashLoopBackOff ?否则前往 2.1.9 。
  2. 若是则查看日志并修复应用程序崩溃。
  3. 确认是否遗漏了 Dockerfile 中的 CMD 指令?Docker history < image-id > (后可加 --no-trunc 显示完整输出)
代码语言:javascript
复制
[root@10-186-65-37 ~]# docker history fb4cca6b4e4c 
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
fb4cca6b4e4c        22 months ago       /bin/sh -c #(nop) COPY file:957630e64c05c549…   121MB               
<missing>           2 years ago         /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B                  
<missing>           2 years ago         /bin/sh -c #(nop) ADD file:1d711f09b1bbc7c8d…   42.3MB
  1. Pod 状态是否频繁重启且状态处于 Running 和 CrashLoopBackOff 之间切换?若是则需修复 liveness probe(存活探测器)的问题,请参考如下链接:https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
2.1.9 Pod 状态是否处于 RunContainerError
  1. kubectl describe pod <pod-name>:查看 status 是否为 RunContainerError 。
  2. 若状态为 RunContainerError 问题可能由于挂载卷 (volume) 导致,请参考如下链接:https://kubernetes.io/zh/docs/concepts/storage/volumes/
  3. 否则请在 StackOverflow 等网站寻求帮助。
2.1.10 检查是否有 pods 处于 READY 状态
  1. 若处于 READY 状态,则继续往下执行进行映射设置
代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
myapp-deploy-55b54d55b8-5msx8    1/1     Running   0          14d
myapp-deploy-55b54d55b8-7ldj4    1/1     Running   0          14d

若无处于 READY 状态的 pods 则前往 2.1.11 。

2. kubectl port-forward <pod-name> 8080:<pod-port>

3. 映射成功前往 2.2 。

a)进行映射

代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl port-forward myapp-deploy-55b54d55b8-5msx8  8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

b)验证映射成功

代码语言:javascript
复制
[root@10-186-65-37 ~]# curl localhost:8080
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
  1. 失败则需确认程序可被所有地址监听,设置语句如下:
代码语言:javascript
复制
kubectl port-forward --address 0.0.0.0 <pod-name> 8080:<pod-port>

若无法被所有地址监听则为未知状态(Unknown state)。

2.1.11 检查 Readiness(就绪探测器)
  1. kubectl describe pod <pod-name>
  2. 正常输出则根据日志和参考如下链接修复相应问题 https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
  3. 失败则为未知状态(Unknown state)。
2.2 Service 模块检查
2.2.1 Service 当前状态检查
  1. kubectl describe service <service-name> 成功输出如下:
代码语言:javascript
复制
[root@10-186-65-37 ~]#  kubectl describe service myapp
\Name:              myapp
Namespace:         default
Labels:            <none>
Annotations:       kubectl.kubernetes.io/last-applied-configuration:
                     {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"myapp","namespace":"default"},"spec":{"ports":[{"name":"http","po...
Selector:          app=myapp,release=canary
Type:              ClusterIP
IP:                10.96.109.76
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.2.10:80,10.244.3.9:80,10.244.4.10:80 + 2 more...
Session Affinity:  None
Events:            <none>
  1. 是否能看到 Endpoints 列且有正常输出?非正常输出则前往 2.2.2 。
  2. kubectl port-forward service/<service-name> 8080:<service-port> 成功输出如下:
代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl port-forward service/myapp 8080:80 
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
  1. 成功则前往 2.3 ,失败则前往 2.2.4 。
2.2.2 Selector 与 Pod label 比对
  1. 查看 pod 的 label 信息 kubectl describe pod <pod-name>
代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl describe pod myapp-deploy-55b54d55b8-5msx8 | grep -i label -A 2
Labels:       app=myapp
              pod-template-hash=55b54d55b8
              release=canary
  1. 查看 service 的 selector 信息 kubectl describe service <service-name>
代码语言:javascript
复制
[root@10-186-65-37 ~]#  kubectl describe service myapp  | grep -i selector 
Selector:          app=myapp,release=canary
  1. 比对两者是否正确匹配,错误则进行修正,正确则前往 2.2.3 。
2.2.3 检查 Pod 是否已分配 IP
  1. 查看 pod 的 ip 信息 kubectl describe pod <pod-name>
  2. 已正确分配 ip ,则问题是由于 kubectl 导致。
代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl describe pod myapp-deploy-55b54d55b8-5msx8 | grep -i 'ip'
IP:           10.244.4.9
IPs:
  IP:           10.244.4.9
  1. 未分配 ip ,则问题是由于 Controller manager 导致。
2.2.4 检查 Service TargetPort 与 Pod ContainerPort
  1. 查看 service 的 TargetPort 信息: kubectl describe service <service-name>
代码语言:javascript
复制
[root@10-186-65-37 ~]#  kubectl describe service myapp  | grep -i targetport
TargetPort:        80/TCP
  1. 查看 pod 的 ContainerPort 信息: kubectl describe pod <pod-name>
代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl describe pod myapp-deploy-55b54d55b8-5msx8 | grep -i port
    Port:           80/TCP
    Host Port:      0/TCP
  1. 上方两者一致则问题是由于 kube-proxy 导致,不一致则进行信息修正。
2.3 Ingress 模块检查
2.3.1 Ingress 当前状态检查
  1. kubectl describe ingress <ingress-name> 成功输出如下:
代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl describe ingress ingress-tomcat-tls
Name:             ingress-tomcat-tls
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<none>)
TLS:
  tomcat-ingress-secret terminates tomcat.quan.com
Rules:
  Host               Path  Backends
  ----               ----  --------
  tomcat.quan.com  
                        tomcat:8080 (10.244.2.11:8080,10.244.4.11:8080,10.244.5.10:8080)
Annotations:
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernets.io/ingress.class":"nginx"},"name":"ingress-tomcat-tls","namespace":"default"},"spec":{"rules":[{"host":"tomcat.quan.com","http":{"paths":[{"backend":{"serviceName":"tomcat","servicePort":8080},"path":null}]}}],"tls":[{"hosts":["tomcat.quan.com"],"secretName":"tomcat-ingress-secret"}]}}

  kubernets.io/ingress.class:  nginx
Events:                        <none>
  1. 是否能看到 backends 列且有正常输出?正常输出前往 2.3.4 ,否则前往 2.3.2 。
2.3.2 检查 ServiceName 和 ServicePort
  1. kubectl describe ingress <ingress-name>
  2. kubectl describe service <service-name>
代码语言:javascript
复制
[root@10-186-65-37 ~]# kubectl describe ingress ingress-tomcat-tls | grep -E 'serviceName|servicePort'
  kubectl.kubernetes.io/last-applied-configuration:  {"apiVersion":"extensions/v1beta1","kind":"Ingress","metadata":{"annotations":{"kubernets.io/ingress.class":"nginx"},"name":"ingress-tomcat-tls","namespace":"default"},"spec":{"rules":[{"host":"tomcat.quan.com","http":{"paths":[{"backend":{"serviceName":"tomcat","servicePort":8080},"path":null}]}}],"tls":[{"hosts":["tomcat.quan.com"],"secretName":"tomcat-ingress-secret"}]}}
  1. 检查前两者的 ServiceName 和 ServicePort 书写是否正确,若正确则前往2.3.3,错误请修正。
2.3.3 Ingress controller 文档
  1. 问题是由于 Ingress controller 导致,请查阅文档寻找解决方法:https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/
2.3.4检查 port-forward ingress
  1. kubectl port-forward <ingress-pod-name> 8080:<ingress-port> 测试是否能正常访问:curl localhost:8080

可正常访问前往 2.3.5 ,否则前往 2.3.3 。

2.3.5 检查能否在外网通过 Ingress 进行访问
  1. 可从外网成功访问,故障排查结束。
  2. 若无法从外网访问,则问题是由于基础设施(infrastructure)或集群暴露(exposed)方式导致,请排查。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 爱可生开源社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、本文概述及主要术语
    • 1.1 概述
      • 1.2 主要术语
      • 二、故障诊断流程
        • 2.1 Pods 模块检查
          • 2.2 Service 模块检查
            • 2.3 Ingress 模块检查
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档