用更云原生的方式做诊断 |大规模kubernetes集群诊断利器深度解析

alk is cheap, show me the demo

背景

我们基于Erda(现已开源)管理了有相当规模数量的Kubernetes集群,集群的稳定性决定了的服务质量以及对外口碑,很长一段时间我们在这件事情上都显得很被动,经常会出现 Erda 支持同学或者客户将问题反馈到说有业务出现了问题,需要我们协助查询一下是不是平台导致的,然后我们上去一顿操作最后解决问题,答复客户,看似专业且厉害,急用户之所急,实则无章无法,一地鸡毛。

通常我们依赖监控系统来提前发现问题,但是监控数据作为一个正向链路,很难覆盖到所有场景,经常会有因为集群配置的不一致性或者一些更底层资源的异常,即使监控数据完全正常,但是整个系统依然会有一些功能不可用,对此我们做了一套巡检系统,针对系统中一些薄弱点以及一致性做诊断,但是这套系统的扩展性不是很好,对集群跟巡检项的管理也相对粗暴了一点。

最后我们决定做一个更加云原生的诊断工具,使用operator来实现集群跟诊断项的管理,抽象出集群跟诊断项的资源概念,来解决大规模kubernetes集群的诊断问题,通过在中心来下发诊断项到其他集群,并统一收集其他集群的诊断结果来实现任何时刻都可以从中心获取到其他所有集群的运行状态,做到对大规模kubernetes集群的有效管理以及诊断。

Kubeprober

项目介绍

项目地址:https://github.com/erda-project/kubeprober

官网地址:https://k.erda.cloud

KubeProber 是一个针对大规模 Kubernetes 集群设计的诊断工具,用于在 kubernetes 集群中执行诊断项以证明集群的各项功能是否正常,KubeProber 有如下特点:

  • 支持大规模集群 支持多集群管理,支持在管理端配置集群跟诊断项的关系以及统一查看所有集群的诊断结果;
  • 云原生 核心逻辑采用 operator 来实现,提供完整的Kubernetes API兼容性;
  • 可扩展 支持用户自定义巡检项。

其核心架构如下:

区别于监控系统,kubeProber 从巡检的角度来证明集群的各项功能是否正常,监控作为正向链路,无法覆盖系统的中的所有场景,系统中各个环境的监控数据都正常,也不能保证系统是 100% 可以用的,因此需要一个工具从反向来证明系统的可用性,根本上做到先于用户发现集群中不可用的点,比如:

  • 集中的所有节点是否均可以被调度,有没有特殊的污点存在等;
  • pod是否可以正常的创建,销毁,验证从 kubernetes,kubelet 到 docker 的整条链路;
  • 创建一个service,并测试连通性,验证 kube-proxy 的链路是否正常;
  • 解析一个内部或者外部的域名,验证 CoreDNS 是否正常工作;
  • 访问一个 ingress 域名,验证集群中的 ingress 组件是否正常工作;
  • 创建并删除一个namespace,验证相关的 webhook 是否正常工作;
  • 对Etcd执行 put/get/delete 等操作,用于验证 Etcd 是否正常运行;
  • 通过 mysql-client 的操作来验证 MySQL 是否正常运行;
  • 模拟用户对业务系统进行登录,操作,验证业务的主流程是否常常;
  • 检查各个环境的证书是否过期;
  • 云资源的到期检查;
  • ... 更多

组件介绍

Kubeprober整体采用Operator来实现核心逻辑,集群之间的管理使用 remotedialer来维持被纳管集群跟管理集群之间的心跳链接,被纳管集群通过RBAC赋予probe-agent最小所需权限并且通过心跳链接实时上报被纳管集群元信息以及访问apiserver的token,实现在管理集群可以对被管理集群的相关资源进行操作的功能。

probe-master

运行在管理集群上的 operator,这个 operator 维护两个 CRD,一个是 Cluster,用于管理被纳管的集群,另一个是 Probe,用于管理内置的以及用户自己便编写的诊断项,probe-master 通过 watch 这两个 CRD,将最新的诊断配置推送到被纳管的集群,同时 probe-master 提供接口用于查看被纳管集群的诊断结果。

probe-agent

运行在被纳管集群上的 operator,这个 operator 维护两个 CRD,一个是跟 probe-master 完全一致的 Probe,probe-agent 按照 probe 的定义去执行该集群的诊断项,另一个是 ProbeStatus,用于记录每个 Probe 的诊断结果,用户可以在被纳管的集群中通过kubectl get probestatus 来查看本集群的诊断结果。

什么是Probe

kubeprobe中运行的诊断计划我们称之为Probe,一个Probe为一个诊断项的集合,我们建议将统一场景下的诊断项作为一个Probe来运行,probe-agent组件会watch probe资源,执行Probe中定义的诊断项,并且将结果写在 ProbeStatus的资源中。

我们期望有一个输出可以清晰的看到当前集群的运行状态,因此我们建议所有的Probe都尽可能数属于应用,中间件,Kubernets,基础设置这四大场景,这样我们可以再展示状态的时候清楚的自上而下的查看究竟是系统中的哪个层面引起的问题。

目前的Probe还比较少,我们还在继续完善,也希望跟大家一起共建。自定义Probe

对比其他诊断工具

目前社区已经有kuberhealthy以及kubeeye来做kubernetes集群诊断这件事情。

kuberheathy提供一套比较清晰的框架可以让你轻松编写自己的诊断项,将诊断项CRD化,可以轻松的使用kubernetes的方式来对单个kubernetes进行体检。

kubeeye同样是针对单个集群,主要通过调用kubernetes 的 event api 以及 Node-Problem-Detector 来检测集群控制平面以及各种节点问题,同时也支持自定义诊断项。

kubeprober 做的也是诊断 kubernetes 集群这件事情,提供框架来编写自己的诊断项,除此之外,kubeprober 主要解决了大规模kubernetes 集群的诊断问题,通过中心化的思路,将集群跟诊断项抽象成CRD,可以实现在中心 kubernetes 集群管理其他kubernetes 诊断项配置,诊断结果收集,未来也会解决大规模 kubernetes 集群的运维问题。

kuberhealthy

kubeeye

kubeprober

开发团队

kuberhealthy

kubesphere

erda

开发语言

GoLang

GoLang

GoLang

诊断范围

k8s集成测试

k8s控制面功能,节点异常检测,yaml规范

k8s核心链路,节点异常事件,中间件状态等。

自定义诊断项

支持

支持基于npd的自定义检查规则

支持

命令行工具

kubectl

ke

kubectl + plugin

多集群支持

不支持

不支持

支持

支持手动触发诊断任务

支持

不支持

支持

告警

不支持

不支持

支持

可视化

不支持

不支持

支持

如何使用

kubeprober主要解决大规模kubernetes集群的诊断问题,通常我们选择其中一个集群作为master集群,部署probe-master,其他集群作为被纳管集群,部署probe-agent。

master端的安装

master 端只有一个 probe-master 的组件,其依赖与 Kubernetes 的 Webhook做一个资源的前置校验工作,我们使用 cert-manager 服务来进行 webhook 证书的自动签发,所以需要先部署一下 cert-manager 服务,等 cert-manager 的 pod 全部启动成功后再进行后续组件的安装。

kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml

关于Secret-key

probe-master 跟 probe-tunnel(agent端中的一个组件)交互使用Secret-key来进行认证,用户可以在 probe-master 配置 Secret-key 来作为集群接入的统一凭证,被管理集群的 probe-tunnel 组件也配置相应的 Secret-key 来跟probe-master 交互。

配置 probe-master 的 Secret-key

vimdeployment/probe-master.yaml apiVersion: apps/v1 kind: Deployment metadata: name: probe-master spec: template: spec: containers: -command: -/probe-master env: -name: SERVER_SECRET_KEY value: your-token-here

部署master组件

APP=probe-master make deploy

agent端的安装

agent 端包含 probe-agent 跟 probe-tunnel 组件,probe-tunnel 使用 websocket 跟 probe-master 建立连接,提供 probe-master 到被管理集群的控制通道,probe-agent 管理诊断项的声生命周期,创建,执行,删除等。

由于 Kubernetes 本身没有集群名的概念,因此我们在 agent 端加入了集群名的概念,结合 master 端介绍的 Secret-key,因此在 agent 端需要配置 master地址, 集群名,Secret-key这三个配置。

vimdeployment/probe-agent.yaml --- apiVersion: v1 kind: ConfigMap metadata: name: probeagent namespace: system data: probe-conf.yaml: | probe_master_addr: http://probe-master.kubeprober.svc.cluster.local:8088 cluster_name: erda-cloud secret_key: your-token-here

部署 agent 组件

APP=probe-agent make deploy

检查集群信息是否上报

probe-agent 跟 probe-tunnel 启动成功后,会将集群信息上报给 probe-master, probe-master会创建出对应的集群资源,可以用如下命令来进行查看。

kubectl getcluster

执行诊断

Kubeprober 采用中心管理的方式对诊断项进行管理,使用给 cluster 打上 probe label 方式来将诊断项关联到某一个集群中。

创建 probe

在 probe-master 所在的集群来创建 probe 资源(在default的namespace下)。

apiVersion: kubeprober.erda.cloud/v1 kind: Probe metadata: name: k8s spec: policy: # unit: minute runInterval: 30 template: containers: -env: -name: NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName name: k8s image: kubeprober/probe-k8s:v0.1.5 resources: requests: cpu: 10m memory: 50Mi restartPolicy: Never configs: -name: control-plane env: -name: PRIVATE_DOMAIN value: "kubernetes.default" -name: DNS_CHECK_NAMESPACE value: "kube-system" -name: DNS_NODE_SELECTOR value: "k8s-app=kube-dns" -name: PUBLIC_DOMAIN value: "www.baidu.com"

上述 probe 指定了运行策略,即每隔 30 分钟运行一次 k8s 的诊断。

kubectlapply-fprobe.yaml

probe 关联集群

通过 kuebctl label 来关联 probe 跟 cluster,比如将 k8s 的 probe 关联给了 erda-cloud 集群。

kubectllabel cluster erda-cloud probe/k8s=true

查看诊断结果

可以使用 kubectl probe 指令来查看特定集群的诊断结果。

创建 kubectl probe 所需要的配置文件,没有该文件则 kubectl probe 会自动将 ws://probe-master.kubeprober.svc.cluster.local:8088/clusterdialer 作为 master 的 地址,其他情况可以自行修改该配置文件。

vi ~/.kubeprober/config { "masterAddr": "ws://probe-master.kubeprober.svc.cluster.local:8088/clusterdialer" }

查看诊断结果

使用 kubectl probe status 可以查看特定集群的当前诊断结果的状态, 由于诊断项是定时在运行的,因此该命令查到的就是最新一次的诊断结果。

kubectlprobe status -c erda-cloud

执行一次性诊断

除了定时诊断的场景, Kubeprober 也支持一次性诊断,常用来在系统做了变更之后想要查看系统各个方面是否正常使用,默认会诊断当前集群 attach 了的probe,同时也可用指定 probe 进行诊断。

kubectlprobe once -c erda-cloud #诊断已经 attatch 了的 probe kubectl probe once -c erda-cloud -p k8s,host #诊断特定 probe

一次性诊断的历史记录会被保存起来,可以使用如下命令来进行查看历史记录。

kubectlprobe oncestatus -c erda-cloud -l

查看历史某一次一次性诊断的诊断结果。

kubectlprobe oncestatus -c erda-cloud -i 1630566675

单集群使用kubeprober

同时kubeprober也可以用于单集群的诊断,适用于没有那么多kubernetes集群需要诊断的场景,具体的使用方法参考这里:https://docs.erda.cloud/1.3/manual/eco-tools/kubeprober/best-practices/standalone_kubeprober.html

可视化

kubeprober在多集群中根据probe的策略执行诊断项,会产生大量的诊断事件,那对这些诊断项进行可视化的展示就显得尤为重要,可以有一个全局的dashborad对大规模集群的海量诊断项进行统一的查看分析会更有利于我们掌握这些集群的运行状态。

kubeprober支持将诊断项事件写入 infuxdb,通过grafana来配置图表来统一展示诊断结果,比如我们将 ERROR 事件统一展示出来作为最高优先级进行关注。

同时我们也可以通过扩展probe-agent上报的集群信息来展示一张详尽的集群列表

欢迎参与

当前kubeprobe已经发布了第一个版本0.1.0,还有许多功能不太完善,probe-master的管理能力还可以进一步的被放大挖掘,probe的编写也需要更加的简单易用,我们希望跟社区一期共建,通过打造一个大规模Kubernetes集群的管理神器。

Contributing to KubeProber:https://github.com/erda-project/kubeprober/blob/master/CONTRIBUTING.md

END

想象中运行代码 VS 实际中运行代码

有点意思

觉得不错,请点个在看

主营产品:艾默生UPS电源,山特UPS电源,科华UPS电源,图腾机柜,科华精卫蓄电池