Kubernetes 曾经成为了云原生时代基础设施的事实标准,越来越多的利用零碎在 Kubernetes 环境中运行。Kubernetes 曾经依附其弱小的自动化运维能力解决了业务零碎的大多数运行保护问题,然而还是要有一些情况是须要运维人员去手动解决的。那么和传统运维相比,面向 Kubernetes 解决业务运维问题是否有一些基本思路,是否能够借助其余工具简化排查流程,就是明天探讨的主题。
业务问题的领域
首先有必要明确一点,什么样的问题算是 Kubernetes 畛域的业务零碎问题。Kubernetes 目前曾经是云原生时代各类“上云”业务零碎所处运行环境的事实标准。
咱们假设你曾经领有了一套强壮的 Kubernetes 环境,业务零碎的运行状态不会受到底层运行环境异常的影响,当业务零碎呈现问题时,Kubernetes 也能够正确的收集到业务零碎的运行状态信息。
有了这假设条件之后,咱们就能够将业务零碎问题束缚在业务从部署到失常运行起来这一时间区间内。所以本文探讨的业务零碎问题的领域包含:
- 业务零碎的规格定义问题
- 业务零碎的调度问题
- 业务零碎长期运行中的问题
解决这类问题的意义
解决这一类的问题的意义是不言而喻的,因为将业务零碎运行起来是一种最根底的需要。具备一套强壮的 Kubernetes 运行环境或者是编写了一套业务零碎代码都不会为咱们产生间接的价值。只有将业务零碎代码运行到一个稳固的环境中,面向最终用户提供服务时才会为咱们产生真正的价值。
值得庆幸的是,解决这类问题多半只须要咱们踩一次坑。对于大多数全新的业务零碎而言,部署到 Kubernetes 环境中去时,所可能遭逢的问题只须要被解决一次。一旦部署实现,业务零碎就能够专一于迭代性能,一直循环实现公布过程即可,顺利进入了一个周而复始的 CI/CD 流程之中。
除去根底需要这一不言而喻的意义,咱们也会探讨如何升高解决这类问题的难度,解决问题难度的升高自身也具备意义。云原生时代,咱们提倡每个开发人员都可能掌控本人的业务零碎,这种掌控也对开发人员提出了新的要求,即掌控 Kubernetes 的应用。这有点将运维层面的工作附加给开发人员的意思,理论推广过程并不顺利。为了便于开发人员应用 Kubernetes 来部署与调试本人开发的业务零碎,企业能够抉择云原生利用平台来升高开发人员应用 Kubernetes 的门槛,Rainbond 就是这样一款云原生利用治理平台,其易用性的特点升高了开发人员的学习门槛,同时可能为业务零碎赋能。
从一份 yaml 开始
失常状况下,负责部署业务零碎的工作人员是通过申明式的配置文件来定义业务零碎的,其中的要害局部称之为规约 (Spec)。这些规约字段通过格局严苛的 Yaml 类型配置文件来定义,正确填写其中的键与值须要庞杂的 Kubernetes 常识的保障。而把握配置文件的格局,以及配置中的内容,往往是开发人员学习原生 Kubernetes 的首个平缓门槛。
原生的应用形式中,kubectl 命令行工具会为这些配置文件提供严苛的校验机制,然而在校验无奈通过时,可能给出的提醒却并不是很敌对。
以一份非常简单的 Yaml 配置文件为例:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: my-nginx
name: my-nginx
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: my-nginx
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- image: nginx
name: nginx
env:
- name: DEMO_GREETING
value: "true" # 此处必须用引号扩起来,因为这是个 string 类型
securityContext:
privileged: true # 此处必须不能应用引号,因为这是个 bool 类型
配置中有两个 true
值,然而其中一个必须应用引号,而另一个则不是,这对一些老手而言并不是很敌对。而加载这份配置文件的谬误版本时,零碎给出的报错尽管能够定位问题,然而交互体验更加不敌对。
$ kubectl apply -f my-deployment.yaml
Error from server (BadRequest): error when creating "my-deployment.yaml": Deployment in version "v1" cannot be handled as a Deployment: v1.Deployment.Spec: v1.DeploymentSpec.Template: v1.PodTemplateSpec.Spec: v1.PodSpec.Containers: []v1.Container: v1.Container.Env: []v1.EnvVar: v1.EnvVar.Value: ReadString: expects "or n, but found t, error found in #10 byte of ...|,"value":true}],"ima|..., bigger context ...|ainers":[{"env":[{"name":"DEMO_GREETING","value":true}],"image":"nginx","name":"nginx"}]}}}}
像这样的问题,在相似 Rainbond 这样的云原生利用治理平台中,则不会呈现。产品设计之时,就曾经屏蔽了一些常见输出谬误,用户不须要关注传入值的类型问题,平台会自行进行转换。
平台会主动为环境变量增加引号以匹配 string 类型:
以开启 / 敞开来体现 bool 类型:
对于一些非凡输出,也会进行正当校验,提供的反馈信息更加人性化:
借助这些性能,即便是小白用户也能够正确的定义业务零碎的规格。
调度过程中的问题排查
业务零碎的规格定义实现后,就能够提交给 Kubernetes 零碎了,下一步,Kubernetes 将会借助本身调度机制,将业务零碎调配到适合的宿主机上运行起来。在进行调度的过程中,业务零碎会在一小段时间内处于 Pending
(待定的)的状态,然而长期处于 Pending
状态则阐明调度过程中呈现了问题。
Kubernetes 以事件的模式,记录了业务零碎在进入运行状态之前的每一个步骤。一旦呈现了 Warning
甚至更重大级别的事件时,就阐明业务零碎的部署过程碰壁了。理解如何查看这些事件,并了解其背地代表的意义,对于排查调度问题十分有帮忙。
可能让业务零碎长期处于 Pending
状态的常见问题包含:镜像拉取失败、资源有余等。应用原生 Kubernetes 时,不免和命令行打交道,来获取对应 Pod 的事件信息。
$ kubectl describe pod <podName> -n <nameSpace>
当所有的计算节点都没有足够的内存资源来调度业务零碎的 Pod 时,事件信息是这样的:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling <unknown> default-scheduler 0/3 nodes are available: 3 Insufficient memory.
而拉取镜像失败则是这样的:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Failed 26s kubelet, cn-shanghai.10.10.10.25 Error: ErrImagePull
Normal BackOff 26s kubelet, cn-shanghai.10.10.10.25 Back-off pulling image "nginx_error"
Warning Failed 26s kubelet, cn-shanghai.10.10.10.25 Error: ImagePullBackOff
Normal Pulling 15s (x2 over 29s) kubelet, cn-shanghai.10.10.10.25 Pulling image "nginx_error"
对事件列表的解读,是须要较深厚的 Kubernetes 畛域常识的。开发者须要从事件列表中找到关键词,进而采取正确的口头来解决问题。
在 Rainbond 云原生利用治理平台中,曾经当时想到了升高问题排查老本的需要,用户点击代表有问题的业务零碎 Pod 的方块,即可理解其详细信息。在这个页面中,稀释了外围问题的阐明、以后 Pod 的状态以及阐明,能够帮忙用户极快的定位问题。
运行过程中的问题排查
当业务零碎实现了调度过程后,Kubernetes 零碎就会将业务零碎对应的 Pod 启动起来,到这里,曾经间隔业务零碎对外提供服务很近了。然而不要漫不经心,Pod 启动时是有可能遭逢运行异样的。
个别状况下,失常运行中的 Pod 是体现 Running
状态的,开发人员能够通过命令行的形式获取其状态:
$ kubectl get pod <podName> -n <nameSpace>
然而如果处于异样状态,则可能失去以下后果:
NAME READY STATUS RESTARTS AGE
demo-test-my-nginx-6b78f5fc8-f9rkz 0/1 CrashLoopBackOff 3 86s
CrashLoopBackOff
是一种异样的状态,除此之外还可能呈现一些其余的异样状态,比方:OOMkilled
、Evicted
等。对于每一种谬误类型的解决也不尽相同。这须要十分丰盛的 Kubernetes 问题排查教训。
比方对于 CrashLoopBackOff
这种异样状态,它意味着 Pod 中的某个容器无奈失常运行,代码运行过程中遭逢了不可容忍的问题,报错退出了。正确的解决,是应该查问问题 Pod 的日志,理解业务代码层面的异样。
$ kubectl logs -f <podName> -n <nameSpace>
这种排查的思路是能够固化的,与所部署的业务零碎自身没有关系,所以 Rainbond 云原生利用治理平台做了一些人性化的设计,如果业务零碎的 Pod 处于这种异样状态并被操作记录捕捉,那么用户点击这条异样的操作记录,即可间接跳转到日志页面查看问题日志。这种设计隐式的为用户提供了排查思路,即便用户本人并没有意识到应该这么做。
还有一种非凡类型的运行过程中问题须要留神。CrashLoopBackOff
这种问题个别呈现在 Pod 启动时,用户很容易就能够捕捉到,而相似于 OOMkilled
这种问题个别是在业务零碎运行很久之后,才会呈现。这种问题不容易被用户捕捉到,这是因为 Kubernetes 会主动重启呈现这类问题的业务零碎 Pod 来主动复原,从而导致问题的埋没。
Rainbond 云原生利用治理平台会自动记录这一类异样状态,并留下相应日志供后续的剖析,理解到到底是 Pod 中的哪个容器导致了内存泄露。
写在最初
基于原生 Kubernetes 进行业务零碎的各阶段问题排查,须要开发人员对 Kubernetes 常识体系有较深刻的理解,并且可能接受命令行交互式操作体验。这无形中晋升了对开发人员的技术要求,也对其强加了一些运维畛域的工作内容,使云原生落地体验碰壁。开发人员也不应该拿到能够间接操作 Kubernetes 的命令行权限,这不合乎平安规定。
为了可能让开发人员正当的调试业务零碎,选用一款云原生治理平台将会是个正确的抉择。云原生利用治理平台的设计者,深刻理解过开发人员的诉求,通过为开发人员提供简略易用的性能,以及人性化的设计,让开发人员调试业务零碎变得事倍功半。