3月增发近100亿?操纵BTC?USDT究竟什么来头?| 火星号精选

超长可视化指南!最强K8S部署的debug思路

本文将帮助你厘清在Kubernetes中调试 deployment的思路。下图是完整的故障排查思路,如果你想获得更清晰的图片,请在公众号后台(Ranl 1 T kct L / | therLabs)回复“troub5 3 2 8 T | I hleshooting”。

超长可视化指南!最强K8S部署的debug思路

当你希望在Kubernetes中部署一个应用程序,你通常需要定义三个组件:

  • Deployment—q U n &—这是创建名为Pods的应用程序副本的方法
  • Serivce——内部负载均衡器,将流量路由到Podsw H 2 U
  • Ingress——可以描述流量如何从集群外部流向Service

接下来,我们通过图片快速回顾一下。E f % L o 8 [ l `

超长可视化指南!最强K8S部署的debug思路

在Kubernetes中,你的应用程序通过两层负载均衡器暴露:^ = d J内部和外部。

超长可视化指南!最强K8S部署的debug思路

内部负载均衡器称为Servic0 W 5 s n 9 0 D `e,而外部负载均衡器则称为Ing2 : Oress。

超长可视化指南!最强K8S部署的debug思路

Pod未直接部署,因此- u S } 1 8 T b,Deployment创建Pod并监视它们。

假设你想部署一个简单的Hello World应用程序,那么m I # v 5 W对于此类应. l K X # X K用程序,其YAML文件与以下类似:

apiVersion: apps/v1
kin5 r G P V nd: Deployment
metadataP X b 3 n x + 6:
name: my-deploymeM , , 5 . x pnt
labels:
track: canary
spec:
selector:
matchLabels:
any-naD W a 9 q ;me: my-app
template:
metadata:
labels:
any-name: my-app
spec:
containers:
- name: cont1
image: learnk8s/app:1.0.0
ports:
- containerPort: 8080
---
apiVersion: v1
kin- z x I x 4 p dd: Service
metY k G ~ n j 1adata:
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:| = } G
paths:
- backend:
serviceName:0 Z a - f - p $ app
servicePort: 80
path: /

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

例如:

  • 你什么时候应该使用8% D !0端口,什么时候使用端口8080?
  • 你是否应该为每个服务创建一个o _ [ n ] &新端口,以免它们冲突?
  • 标签(label)名称重要吗?是否应该每一处都一样Y 7 2 a @

在进行debug之前,我们先来回顾一下这Y X L P N =三个组件之间的关系如何。

首先,我们从Deployment和Service开始。

连接Deployment和Service

实际上,Dep( y I ;loyment和ServQ D K $ Sice根本没有连接。相反,该Service直接指向Pod,并完全跳过I 0 , ( Deployment。所以,你应该关注的是Pod和Service) j r & X [ 8是如何与彼此关联的。你应m R G Z + 7 }该记住三件事:

  1. Service selector至少与Pod的一个标签匹配
  2. Serivce targetPort应该与P N ? G C aod内的容器的c d F iontainerPort相匹配
  3. Service port可以是任何数字。多个Service可以使用同一个端口,因l F P #为它们已经被分配了不同的IP地址

以下图片总结了如何连接端口:Q % l W . ; s

超长可视化指南!最强K8S部署的debug思路

考虑由Service暴露的pod

超长可视化指南!最强K8S部署的debug思路

当你创建一个pod,你应该在你的Pod中为每个容器定义端口containerPort

超长可视化指南!最强K8S部署的debug思路

当你创建一S 4 e H T个Service时,你能E I f o / % y ] O够定义一个port和一个targetPort。但你应该将哪一个连接到容器呢?

超长可视化指南!最强K8S部署的debug思路

targetPort与containerPort应该能够匹配

超长可视化指南!最强K8S部署的debug思路

如果你的容器暴露端口3000,那么targetPort应该与该数字相匹配。

_ # j i C ^ B l *果你查看了YAML,标签与ports或targerPort应该匹配:

kubectl get pods --show-labels

那么在Deployment顶部的track: canary标签呢?也应该匹配吗?

那个标签属于deployJ S y Gment,并且Service selector不使用它来路由流量。换言之,你可以安全地将其移除或者给它分配不同的值。

那么matchLabels selects f , ] q + O 8or呢?它需要与Pod标2 M C ( p签匹配并且DeploymenQ U 8 } U 6 | 6t使用它来跟踪Pod。

假设你做了一个正确的更改,你应该如何测试它呢?你可以使用以下命令检查Pod是否拥有正确的标签:

kubectl get pods --show-labels

或者如果你有属于多个应O e 5用程序的Pod:

kubectl ge0 Z F Ft pods --selector any, ` Q f-name=my? e u = 0 ^ t J 9-app --show-labels

] G g 7 a ; m 7中aL j 7 m B h n 4 sny-name=my-app是标签an@ 5 : $ ) Ky-name: my-app。依旧存在问题?你也可以连接到Pod。你可以在kubectl中使用命令port-fo! d g O Q Yrward连接到Serivce并测试连接。

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

其中:

  • servu p 8ice/<servicR 7 S Se name>是serivce的名称——在当前YAML中,是“my-service”。
  • 3000是你希望在你的电脑上打开的端口
  • 80是Service在porV - - [ X ; b ]t字段中暴露的端口6 S 5 t _ h Z

如果你能够连接,. U | @ n N p y那么设置就是正确的。如果你无法连接,你很有可能弄错了标签或者端口未匹配。

连接Service和IngressZ : G e u 0 % $ E

暴露应用程序的下一步是配置Ingress。Ingress必须知道如何检索Service,然后检索Pod并将流量路由到它们。Ingr8 ! gess通过名称和暴露的端口来检索正确的Service。

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

  1. Ingress的servicePort应该与Service的port匹配
  2. Ingress的serviceName应该与Service的name相匹配

以下图片将总结如何连接端口o * W 7 ~ ;

超长可视化指南!最强K8S部署的debug思路

你已经知道该服务暴露了一个端口

超长可视化指南!最强K8S部署的debug思路

Ingress有一个名为servicePort的字段。

超长可视化指南!最强K8S部署的debug思路

Service port和Ingress servicePort应该相匹配

超长可视化指南!最强K8S部署的debug思路

如果你决定分配端口80给该service& 3 ~ V M L f,你应该同时更改servicePort为80

实际操作中,你需要查看这些命令行:


kubectl get pods --all-namespaces
NAMESPACE NAME READY STAT4 : { ` E W 7US
kube-system coredns-5644d7b6d9-jn7cq 1/1 Running
kube-system etcd-minikube 1/1 Running
kube-9 h ; ? ~ x 7 Rsystem kube-apiserver-minikube 1/1 Running
kube-system kube-controller-manager-minikube 1/1 Running
kube-systa ^ e I D ? k iem kube-proxy-zvf2h 1/1 Runw i Pning
kube-c g G : d osystem kube-scheduler-minikube 1/1 Running
kube-system nginx-ingress-controller-6fc5bcc 1m a s K/1 Running

你应该如何测试Ingress是否正常运行呢?你可以使用和之前相同U $ l c A g } 6的策略,即kubectl port-forward,但不是连接到service,而是连接到Ingress controller。

首先,使用以下命令为Ingress controllerS R P & 1 Z检索Pod名称:


kubectl get p& ( S _ t 8 +ods --{ q O e : 4 . ? nall-namY E = t bespaces
NAMESPACE NAME READY STATUS
kube-system core~ 5 [dns-5644d7b6d9-jn7cq 1/1 Running
kube-system etcd-minikube 1/1 Running
ku` v A P T O ` } wbe-system kube-apiserver-minikube 1/1 Running
kube-system kube-controller-managQ ; c _ 3 S I .er-minikube 1/1 Running
kube-systeT { J } I Mm kube-proxy-zvf2h 1/1 Runninj Z L = J $ V og
kube-system kube-scheduq ~ 7 v g 0 ler-mini@ U i 5kube 1+ S h/1 Running
kube-system nginx-ingress-controller-6fc5bcc 1/1# O @ $ x 2 r 0 Y Running

验证Ingress Pod(; t b v Q 3 b h 可能在不同的命名空间)并且描述它以检索端口:


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

最后,连接到Pod:

kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-system

此时,每次你在你的电脑u / ? C . 7 F上访问端口3000,请求就会被转发到在IngressH D 4 # Y controller Pod上的端口80。

如果你访问 http://localhost:3000,你应该能找Q C |到提供网页的应用程序。

简单回顾一下m G A u

现在,我们来快速回顾一下什么端口和标签需要X ] 3 3 l | ! y i匹配:

  1. Service selector应该匹配Pod的标签
  2. Service targerPort应该匹配在Pod内容器@ 2 5 x s 1的containerPort
  3. ST u X X I * n $ervice 端口可以是任意数字。多个Service可以使用同个端口,因为它们已经分配了不同的IP地址
  4. Ingress的servicePort应该匹配在a F E dSerY e m $ S L g I Uvice中的6 ~ ) ^ E W ? N }port
  5. Service的名称应该匹配在Ingress中的serviceName的字段

了解如何构造YAML只是开始。那么,出了问题时会有什么表现?Pod可能无法启动,或者直接崩溃。

3步排查K8S Deployment故障

在我们深入研究有故障的deployment之前,必须有一个明确定义的模型,以了解Kubernetes的工作方式。

既然在每个deployment中都有那三个组件,你应该从底层开始按顺序调试它们。

  1. 你应该确保你的Pod正在运行
  2. 着重关注使Service将流量路由到Pod
  3. 检查Ingress是否正确配置

超长可视化指南!最强K8S部署的debug思路

你应该从底层开始排查Deployment故障。首先,检查Pod是否准备就绪S ^ a K并且正在运行

超长可视化指南!最强K8S部署的debug思路

如果Pod已经准备就绪,你需要检查Service是否可以将流量分配到Pod。

超长可视化指南!最强K8S部署的debug思路

最后你应Z u Y h h E u该检查Servi; - ) , Q 8 u A vce和Ingress之间的连接。

1、 故障排查d o xPod

在大多数情况下,问题出现在Pod本身。所n k ( I以你应该确保Pod正在运行并准备就绪。应该如何检查呢?


kubectl get pods
NAME READY STATUS RESTARTS AGE
app1 0/1 ImagePullBackOff 0 47h
app2 0/1 Error 0 47h+ I P
app3-76f9f* 3 q w ; r Ucd46b-xbv4k 1/1 RunninL b i 9 B Q E ) xg 1 47h

以上部分,只有最后一个 T 3 y x _ 2Pod是正在运行并且准备就绪的,而前两个Pod既y 4 `没有Running也没有ReadG B 6 E Yy。那么,你应该如何定A a I ; { ` | +位是什么出了问题呢?

T k J C N里有4个十分有用的命令可以帮助你排查Pod的故障:

  • kubectl logs <pod name>能够帮助检索Pod的容器日志
  • kubectl describe pod <pod naV 5 1 ( e P Xme>能够有效V 3 q h b P G = I地检索与Pod相关的事件列表
  • kub) / D J 3ectl get pod <pod name>对于提取存储在Kubernet8 _ a b 7 U m [es中的Pod的YA7 b e G t W p !ML定义十分有用
  • kubectl e+ K sxec -ti <pod name> bash可以用于在Pod其中一个容器中运行一个交H H u e { M @ / 2互式命令

你应该使用哪一个呢?实际上,没有一种命令是万能的,你可以根据实际情况结合使用。

常见的Pod错误

Pod可能会出现启动和运行时的错误。

启动错误包括:

  • ImagePullBackoff
  • ImageInspectError
  • ErrImagePulL V Gl
  • ErrImageNeverPull
  • RegistryUnavailable
  • Invalip { (dIX 9 z ;mageName

运行时错误包括:

  • CrashLoopBackOff
  • RunContainerError
  • KillContainA ! nerError
  • VerifyNonRootError
  • RunIni~ j S d 3 F utContainerError
  • CreatePodSandboxError
  • ConfigPodSandboxES 5 2rror
  • KillPodSandboxError
  • SetupNetworkError
  • TeardownNetworkError

这些错误中,有些比其他错误更为常见。以下是最常见的错误以及如何修复它们:

ImagePullBackOff

当Kubernetes无法检索Pod其中之一的容器镜像时U b F k 4,将出现% p ; J 6 s $ d b此错误。

有三种常见原因:

  • 镜像名称无效——例如,你错误拼写名称或镜像不存在
  • 你给这一镜像指定了一个不存在的tag
  • 你所检索的镜像是私有仓库的,! . u A 3并且Kubernetes没有访问它的凭据

前两个原因可以通过更正镜像名称和tag解决。最后一个,你` * R需要将凭据添加到“Secret”中的私有镜像仓库中,并在Pod中引用它。

官方文档可以让你更加清楚:

https://kubernetes.io/docs/tasks/configure-pod-containe9 G or/pull-image-private-regJ Q E - } Yistry/

CrashLoopBackOff

如果容器无法启动,Kubernetes状态将显示CrashLoopBack9 ) U 4 | ! % ROff消m 3 x息。

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

  • 应用; 8 V @程序中存在错E ^ x M a b a 7 {误,导致无法启动
  • 你错误配置了容器https://stackoverflow.com/questions/41604499/my-kubernetes-pods-keep-crashing-wi^ d : O V m _ 7th-crashloopbackoff-but-i-cant-find-any-lo
  • Liveness探针失败次数太多

你应该尝试并检索该容器的日志以确定出现故障的原因。7 5 R

如果由于你的容器重启过快而无法查看日志,你可以使用以下命令:

kubectl logs <pod-name&h z $ $ d F mgt; --prW ! 9 E 4 [ T eevious

它将从之前的容器中打印错误信息。

RunContainerError

容器不能启动时出现错误,甚至在容器内的应用程序启动之前就无法& Y $启动。

这个问题通常由于错误配置导致的,@ ] | y如:

  • 安装一个不! . x A 3存在的volume,如ConfigMO v ( hap或Secret
  • 将只读volume安装为可读写

你应该使用kubectl describe pod <pod-name>来收集和分析错误。b J Z S 0 * K O r

Pod处于Pending状态

当你创建一个Pod时,Pod保持在Pending状态。这是为什么呢?假设你的调度组件运行了解,那么有以下几个原因:

  • 集群没有足够的资源来运行Pod,如CPU和内存
  • 当前p L = D命名空间有一个ResourceQuota对象并且所创建的Po] H m s { P F jd会使该命名空间超过资源额度h , u w 3
  • Pod与一个Pending状态的PersistentVolumeClaim绑定。

那么,最好的选择是使用命令kubectl describe检查事件:


kubectl describe pod <e g ^ * p ! c;pod name>

对于由于ResourceQuotas造成的错误,可以使用以下方法检查集群的日志:

kubectl get events --sort-by=.metadata.crea1 $ h U _ utionTimestamp

Pod不处于Ready状态

如果Pod正在运行但是不Ready,这意味着Readiness探针出现故障。当Readiness探针出现故障时,Pod无法附加到Service上,并且流量无法转发到实例上。

Readiness探针故障是特定于应用程序的错误,因此使用kubectl describe来检查事件部分,以验证错误。

2、 排查Service故障

如果你的Pod正在运行并且准备就绪,但是你依旧无法接收. c C 3来自n @ { ] l ] % U Y应用程序的响应i s o $ s c,你应该检查Service是否配置正确s G @ 8 2 I O u &

Service旨在根据pod的标签将流量路由到Pod。所以第一件事,你需要检查Service target多少个Pod。可以通过检查Service中的Endpoint来完成此步y b - o B ;骤:


kubectl describe ser; q & p S U k (vice <servn l jice-name&W ` d ~ Y ? # ^ 1gt; | grep Endpoints

一个endpoint是一对<ip address:port&g! J R Tt;,并且当Service(至少)taZ b ~ L G . ,rget一个pod时。至少有一对。

如果“Endpoint”部分是空的,那么有两种解释:

  1. 任何正在运行的Pod没有正确的label(提示:你需要检查 c : - u以下h 9 ` + A @ Y你是否在正确的命i } 3 l x z ~ 6名空间内)
  2. 在Service的selector标签中有错别字

如果你看到了endpoint列表,但依旧无法访问你的应用程序,那么你的Service中的targetPort可能是罪魁祸首。

你应该怎么测试Service?无论Service类型是什么,都可以使用kubectl port-5 Q z 3 d Lforward连接M b ( P m到它:


kubectl port-forward service/<service-name- 5 D J q / w f> 3000:80

其中:

  • <service-name>是Se: q Crvice的名称
  • 3000是你想要在电脑上打开的端口
  • 80是由Service暴露的端口

3、 排查U Q # U 9IngressB 4 p 6 J故障

如果你走到了这个部分,这意味着:

  • Pod正r x ] j J G Q在运行并且准备就绪
  • Service可以q } W B e + f }分发流量给Pod

但你依旧无法接收apI O 9 ] L Q X 1 .p的响应。那么这很有可能是Ingress配置出现错误。

由于使用的Ingress controller是集群中的第三方组件,那么根据Ingress controf G i G ^ l b :ller的类型会由不同p K G n /的调试技术。但是在深入研究Ingress特定的工具之前,你可以使用一些简单的方法检查。

Ingress使用serviceName和servicePort连接Service。你应该检查那些是否正确配置。你可以使用以下命令检查Ingress是否正确配置:


kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS
kube-systea j b M 7 p H Em coredns-5644d7b6d9-jn7cq 1/1 Running
kube-sy+ O t N 5 3 0stem etcd-minikube 1/1 RunA a - 2 ? ; |ning
kube-system kube7 E & 3 ) 1 E e-apiserver-minikube 1/1 Running
kube-system kr _ x L ^ B iube-controller-manager-minikube 1/1 Running
kube-system kube-proxy-zvf2h 1/1 Running
kube-system kube-scheduler-minikube 1/1 Runnind b ` D $ b ` i 8g
kube-system ngini a [x-ingrv + X mess-controller-6fc5bcc 1/1 Running

如果Backend列是空的,那么配置中肯定存在错误。

如果你能在Backend列中看到endpoint,但依旧无法访问应用程序,那么可能是以下问题:

  • 你将Ingress暴露于公网的方式
  • 你将集群暴露于公网的方式

你可以通过直接连1 V |接到Ingress+ p B P : K Pod将基础设施X ^ H S Q , $问题与Ingress隔离开来n o [ + x

首先,为你的I` [ p 7 m %ngress Controller检索Pod(可能位于不同的命名空间中):


kubectl get pods --all-namespaceE b p @ ; 2 9s
NAMESPACE NAME RZ ` u z CEADY STATUC . / T n yS
kube-system coredns-5644d7b6d9-jn7cq 1/1* h : ) ) 8 a v G Running
kube-system etcd-minikube 1/k C q R W - @ Y1 Running
kube-Q z z y O b Bsystem kube-apiserver-minikube 1/1 Running
kube-system kube-controller-managerE 0 w W 5 K i v-minikube 1/1 Running
kube-system kube-proxy-zvf2F b . Lh 1/1 Running
kube-system k@ 3 a A 0ube0 . . = /-scheduler-minikube 1/1 Running
ky i | 7 H ( ? nube-system nginJ ~ K # M * h )x-ingress-controller-6fc5bcc 1/1 Running

描述它以检索端口:


kubectl describe pod nginx-ingre! t 3 + o @ss-controller-6fc5z ? l D a / ; 6bcc
--namespace kube-system \\
| grep Ports

最后,连接到Pod:


kubectl port-forward nginx-ingress-controller-6fc5bcc 3000:80 --namespace kube-system

此时,每次你在电脑上访c s . 1 J问端口3000,请求将会转发到Pod上的端口80。

那么,现在能够正常运行了吗?

如果正常工作,问题就出在基础设施。你应该检查流量如何路由到你的集群。

如果无法正常工作,问题就在IngrF @ S } G ^ b J Vess controller。3 K U & g 你应该调试Ingress。

如果仍然无法使Ingress coC e )ntroller正常工作,则应该开始对其进行调试。市场有许多不同版本的Ii & P m ! _ $ngress controller。比较流行的包括Nginx、HAProxy、Traefik等。

你应该查阅Ingress cod w _ R h lntroller的文档以查找故障排查指南。

既然Ingress Nginx是最流行的Ingress controller,那么在下一个部分我们将介绍一些相关的技巧。

调试Ingress Nginx

Ingressc 5 h I 2 x d R Z-nginx有kubectl的官H . l方插件,E 3 l ; : u u } h你可以访问以下网址查看:k # p X 0 1 D *

https:x 2 5 T [ =//ku? $ Z - Fbernetes.github.io/ingress-nq y |ginx/kubecW J H W #tl= ; W p u J-plugin/

你可l Y 4 f0 A O q e使用kubectl ingress-nginx来进行以下操作:

  • 检查日志、Backend、证g k n q F : ? F Q书等9 ? i J u P m
  • 连接到Ingress
  • 检查当前的配置

你还可以尝试以下三个命令:

  • kubectl ingress-nginB X L [ J K B !x lint这是用来检查nginx.conf
  • kubectl ingress-nginx backP t / ( ( U E qend来检查Backend(与s P ^ 1 J | ekubectl de8 8 l d , fscribe ingress <ingress-name&T 4 7 Ggt;类似)
  • kub7 g k g tectl ingress-nginx logs来检查日志

请注意,你需要使用--namespace <namz T 3 6 N t e ae>来指定正确的命名空m ~ C间。

总 结

如果你毫无头绪,那么在Kubernetes中进行故障排除可能是一项艰巨的: 0 v 6 o , C任务。

你应该永远记住以从下至上的顺序解决问题:现检查Pod,然后向上移动堆栈至Service和Ingress。

而本文中的debug技术在其他地方也是通用的,例如:

  • f t Q 6 P现故障的Jobs和CronJobs
  • Stat{ D n h 9 s - MefulSets和DaemonSets

希望大家都没有bug!

上一篇

Redmi首款可穿戴设备将于4月3日面市

下一篇

JavaScript中的模块导入有一个缺点

你也可能喜欢

  • 暂无相关文章!

发表评论

您的电子邮件地址不会被公开。 必填项已用 * 标注

提示:点击验证后方可评论!

插入图片
返回顶部