ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Kubernetes部署故障排查指北(问题排除能力提升篇)

2020-09-27 23:51:15  阅读:207  来源: 互联网

标签:指北 kubectl Ingress 服务 name Kubernetes 排查 Pod kube


准备了一个k8s故障排除示意图,可帮助你效调试Kubernetes中的部署的任何问题
Kubernetes部署故障排查指北(问题排除能力提升篇)
这是一个pdf,如有需要可发评论,随时在~

下面几个示例可以大幅度提升你的k8s奇能技巧
当你希望在Kubernetes中部署应用程序时,我们一般都是通常定义三个组件:

一个部署 -这是用于创建应用程序时我们会调用pod的模版来实现应用的具体详细信息描述
一个服务 -内部负载平衡器到路由流量我们的pod中
一个入口 -如何应该从集群外部流入到你的服务的描述。

在Kubernetes中,你的应用程序通过两层负载均衡器公开:内部和外部。

假设你希望部署一个简单的Hello World应用程序,则该应用程序的YAML应该类似于以下内容:

hello-world.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  labels:
    track: canary
spec:
  selector:
    matchLabels:
      any-name: my-app
  template:
    metadata:
      labels:
        any-name: my-app
    spec:
      containers:
        - name: cont1
          image: learnk8s/app:1.0.0
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
    - port: 80
      targetPort: 8080
  selector:
    name: app
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - http:
      paths:
        - backend:
            serviceName: app
            servicePort: 80
          path: /

定义很长,很容易忽略组件之间的相互关系。

例如:

什么时候应使用端口80,何时应使用端口8080?
你是否应该为每个服务创建一个新端口,以免它们冲突?
标签名称重要吗?到处都应该一样吗?
在进行调试之前,让我们回顾一下这三个组件如何相互链接起来的。

让我们从部署和服务开始。

连接部署和服务
令人惊讶的消息是,服务和部署根本没有连接。

而是,该服务直接指向Pod,并完全跳过部署。

因此,你应该注意的是Pod和服务之间的相互关系。

你应该记住三件事:

服务选择器应至少与Pod的一个标签匹配
服务targetPort应与containerPortPod中容器的匹配
服务port可以是任何端口号。多个服务可以使用同一端口,因为它们分配了不同的IP地址。

如果你查看YAML,则标签和ports/ targetPort应该匹配:

hello-world.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  labels:
    track: canary
spec:
  selector:
    matchLabels:
      any-name: my-app
  template:
    metadata:
      labels:
        any-name: my-app
    spec:
      containers:
        - name: cont1
          image: learnk8s/app:1.0.0
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
    - port: 80
      targetPort: 8080
  selector:
    any-name: my-app

track: canary部署顶部的标签如何?

那也应该匹配吗?

该标签属于部署,服务的选择器未使用它来路由流量。

换句话说,你可以安全地删除它或为其分配其他值。

那matchLabels选择器呢?

它始终必须与Pod标签匹配,并且由Deployment用来跟踪Pod。

假设你进行了正确的更改,如何测试它?

你可以使用以下命令检查Pod是否具有正确的标签:

kubectl get pods --show-labels
或者,如果你具有属于多个应用程序的Pod:

kubectl get pods --selector any-name=my-app --show-labels
any-name=my-app标签在哪里any-name: my-app。

你也可以连接到Pod!

你可以使用port-forwardkubectl中的命令连接到服务并测试连接。

kubectl port-forward service/<service name> 3000:80

service/<service name> 是服务的名称-在当前的YAML中是“ my-service”
3000是你希望在计算机上打开的端口
80是服务在port现场暴露的端口
如果可以连接,则说明设置正确。

如果不行,则很可能是你放错了标签或端口不匹配。

连接服务和入口
公开你的应用的下一步是配置Ingress。

入口必须知道如何检索服务,然后检索Pod并将流量路由到它们。

入口按名称和公开的端口检索正确的服务。

在Ingress和Service中应该匹配两件事:

在servicePort该入口的应该匹配port的服务
在serviceName该入口的应该匹配name的服务

在实践中,你应该查看以下几行:

hello-world.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
    - port: 80
      targetPort: 8080
  selector:
    any-name: my-app
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - http:
      paths:
        - backend:
            serviceName: my-service
            servicePort: 80
          path: /

你如何测试Ingress的功能?

你可以使用与以前相同的策略kubectl port-forward,但是应该连接到Ingress控制器,而不是连接到服务。

首先,使用以下命令检索Ingress控制器的Pod名称:

kubectl get pods --all-namespaces
NAMESPACE   NAME                              READY STATUS
kube-system coredns-5644d7b6d9-jn7cq          1/1   Running
kube-system etcd-minikube                     1/1   Running
kube-system kube-apiserver-minikube           1/1   Running
kube-system kube-controller-manager-minikube  1/1   Running
kube-system kube-proxy-zvf2h                  1/1   Running
kube-system kube-scheduler-minikube           1/1   Running
kube-system nginx-ingress-controller-6fc5bcc  1/1   Running

标识Ingress Pod(可能在其他命名空间中)并描述它以检索端口:

kubectl describe pod nginx-ingress-controller-6fc5bcc \
 --namespace kube-system \
 | grep Ports
Ports:         80/TCP, 443/TCP, 18080/TCP

最后,连接到Pod:

kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-system
此时,每次您访问计算机上的端口3000时,请求都会转发到Ingress控制器Pod上的端口80。

如果访问http:// localhost:3000,则应该找到提供网页的应用程序。

快速回顾一下哪些端口和标签应该匹配:

服务选择器应与Pod的标签匹配
服务targetPort应与containerPortPod中容器的匹配
服务端口可以是任何数字。多个服务可以使用同一端口,因为它们分配了不同的IP地址。
在servicePort该入口的应该匹配port在服务
服务名称应与serviceNameIngress 中的字段匹配
知道如何构造YAML定义只是故事的一部分。

出问题了怎么办?

Pod可能无法启动,或者正在崩溃。

解决Kubernetes部署的3个步骤

在深入研究损坏的部署之前,必须有一个明确定义的Kubernetes工作方式的思维模型。

由于每个部署中都有三个组件,因此你应该从底部开始依次调试所有组件。

你应该确保Pods正在运行,然后
专注于让服务将流量路由到Pod,然后
检查是否正确配置了Ingress

1. Pod故障排除
在大多数情况下,问题出在Pod本身。

你应该确保Pod正在运行并准备就绪。

你如何检查?

kubectl get pods
NAME                    READY STATUS            RESTARTS  AGE
app1                    0/1   ImagePullBackOff  0         47h
app2                    0/1   Error             0         47h
app3-76f9fcd46b-xbv4k   1/1   Running           1         47h

在上述会话中,最后一个Pod处于Running and Ready;但是,前两个Pod 既不处于Running也不为Ready。

你如何调查出了什么问题?

有四个有用的命令可以对Pod进行故障排除:

kubectl logs <pod name> 有助于检索Pod容器的日志
kubectl describe pod <pod name> 检索与Pod相关的事件列表很有用
kubectl get pod <pod name> 用于提取存储在Kubernetes中的Pod的YAML定义
kubectl exec -ti <pod name> bash 在Pod的一个容器中运行交互式命令很有用
你应该使用哪一个?

没有一种万能的。

相反,你应该结合使用它们。

常见豆荚错误
Pod可能会出现启动和运行时错误。

启动错误包括:

ImagePullBackoff
ImageInspectError
ErrImagePull
ErrImageNeverPull
注册表不可用
InvalidImageName
运行时错误包括:

CrashLoopBackOff
RunContainerError
KillContainerError
VerifyNonRootError
RunInitContainerError
CreatePodSandboxError
ConfigPodSandboxError
KillPodSandboxError
SetupNetworkError
TeardownNetworkError
有些错误比其他错误更常见。

以下是最常见的错误以及如何修复它们的列表。

ImagePullBackOff
当Kubernetes无法检索Pod容器之一的图像时,将出现此错误。

共有三个罪魁祸首:

图片名称无效-例如,您拼写了错误的名称,或者图片不存在
你为图像指定了不存在的标签
你尝试检索的图像属于一个私有注册表,而Kubernetes没有凭据可以访问它
前两种情况可以通过更正图像名称和标记来解决。

最后,你应该将凭证添加到“秘密”中的私人注册表中,并在Pod中引用它。

官方文档中有一个有关如何实现此目标的示例。

CrashLoopBackOff
如果容器无法启动,则Kubernetes将CrashLoopBackOff消息显示为状态。

通常,在以下情况下容器无法启动:

应用程序中存在错误,导致无法启动
你未正确配置容器
Liveness探针失败太多次
你应该尝试从该容器中检索日志,以调查其失败的原因。

如果由于容器重启太快而看不到日志,则可以使用以下命令:

kubectl logs &lt;pod-name&gt; --previous
从前一个容器打印错误消息。

RunContainerError
当容器无法启动时出现错误。

甚至在容器内的应用程序启动之前。

该问题通常是由于配置错误,例如:

挂载不存在的卷,例如ConfigMap或Secrets
将只读卷安装为可读写
你应该使用kubectl describe pod <pod-name>收集和分析错误。

豆荚处于待处理状态
当你创建Pod时,该Pod保持待处理状态。

为什么?

假设你的调度程序组件运行良好,原因如下:

群集没有足够的资源(例如CPU和内存)来运行Pod
当前的命名空间具有ResourceQuota对象,创建Pod将使命名空间超过配额
该Pod绑定到一个待处理的 PersistentVolumeClaim
最好的选择是检查命令中的“ 事件”部分kubectl describe:

kubectl describe pod &lt;pod name&gt;
对于因ResourceQuotas而导致的错误,可以使用以下方法检查群集的日志:

kubectl get events --sort-by=.metadata.creationTimestamp
pod处于未就绪状态
如果Pod正在运行但未就绪,则表示“就绪”探针失败。

当“就绪”探针失败时,则Pod未连接到服务,并且不会将流量转发到该实例。

“准备就绪”探针失败是特定于应用程序的错误,因此你应检查其中的“ 事件”部分kubectl describe以识别错误。

2.故障排除服务
如果你的Pod正在运行并处于就绪状态,但仍无法收到应用程序的响应,则应检查服务的配置是否正确。

服务旨在根据流量的标签将流量路由到Pod。

因此,你应该检查的第一件事是服务定位了多少个Pod。

你可以通过检查服务中的端点来做到这一点:

kubectl describe service &lt;service-name&gt; | grep Endpoints
端点是一对<ip address:port>,并且在服务(至少)以Pod为目标时,应该至少有一个。

如果“端点”部分为空,则有两种解释:

你没有运行带有正确标签的Pod(提示:你应检查自己是否在正确的命名空间中)
你selector在服务标签上有错字
如果你看到端点列表,但仍然无法访问您的应用程序,则targetPort可能是你服务中的罪魁祸首。

你如何测试服务?

无论服务类型如何,你都可以使用kubectl port-forward它来连接:

kubectl port-forward service/&lt;service-name&gt; 3000:80
哪里:

<service-name> 是服务的名称
3000 是您希望在计算机上打开的端口
80 是服务公开的端口
3.对Ingress进行故障排除
如果你已到达本节,则:

pod正在运行并准备就绪
服务将流量分配到Pod
但是你仍然看不到应用程序的响应。

这意味着最有可能Ingress配置错误。

由于所使用的Ingress控制器是集群中的第三方组件,因此有不同的调试技术,具体取决于Ingress控制器的类型。

但是在深入研究Ingress专用工具之前,你可以检查一下一些简单的方法。

入口使用serviceName和servicePort连接到服务。

你应该检查这些配置是否正确。

你可以检查是否已使用以下命令正确配置了Ingress:


kubectl describe ingress <ingress-name>

如果“ 后端”列为空,则配置中必须有一个错误。

如果你可以在“ 后端”列中看到端点,但是仍然无法访问该应用程序,则可能是此问题:

你如何将Ingress暴露于公共互联网
你如何将群集暴露于公共互联网
你可以通过直接连接到Ingress Pod来将基础结构问题与Ingress隔离开。

首先,为你的Ingress控制器(可以位于其他名称空间中)检索Pod:

kubectl get pods --all-namespaces```


NAMESPACE   NAME                              READY STATUS
kube-system coredns-5644d7b6d9-jn7cq          1/1   Running
kube-system etcd-minikube                     1/1   Running
kube-system kube-apiserver-minikube           1/1   Running
kube-system kube-controller-manager-minikube  1/1   Running
kube-system kube-proxy-zvf2h                  1/1   Running
kube-system kube-scheduler-minikube           1/1   Running
kube-system nginx-ingress-controller-6fc5bcc  1/1   Running

描述它以检索端口:

kubectl describe pod nginx-ingress-controller-6fc5bcc
 --namespace kube-system \
 | grep Ports

最后,连接到Pod:

kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-system
此时,每次你访问计算机上的端口3000时,请求都会转发到Pod上的端口80。

现在可以用吗?

如果可行,则问题出在基础架构中。您应该调查流量如何路由到您的群集。
如果不起作用,则问题出在Ingress控制器中。您应该调试Ingress。
如果仍然无法使Ingress控制器正常工作,则应开始对其进行调试。

有许多不同版本的Ingress控制器。

热门选项包括Nginx,HAProxy,Traefik等。

你应该查阅Ingress控制器的文档以查找故障排除指南。

由于Ingress Nginx是最受欢迎的Ingress控制器,因此在下一部分中我们将介绍一些技巧。

调试Ingress Nginx
Ingress-nginx项目具有Kubectl的官方插件。

你可以kubectl ingress-nginx用来:

检查日志,后端,证书等。
连接到入口
检查当前配置
您应该尝试的三个命令是:

kubectl ingress-nginx lint,它检查 nginx.conf
kubectl ingress-nginx backend,以检查后端(类似于kubectl describe ingress <ingress-name>)
kubectl ingress-nginx logs,查看日志
请注意,你可能需要使用来为Ingress控制器指定正确的名称空间--namespace <name>。

摘要
如果你不知道从哪里开始,在Kubernetes中进行故障排除可能是一项艰巨的任务。

你应该始终记得从下至上解决问题:从Pod开始,然后通过Service and Ingress向上移动堆栈。

标签:指北,kubectl,Ingress,服务,name,Kubernetes,排查,Pod,kube
来源: https://blog.51cto.com/14143894/2537395

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有