简介: 随着 Kubernetes 集群规模和复杂性的减少,集群越来越难以保障高效率、低提早的交付 pod。本文将分享蚂蚁金服在设计 SLO 架构和实现高 SLO 的办法和教训。
作者 | 蚂蚁金服技术专家 姚菁华;蚂蚁金服高级开发工程师 范康
导读:随着 Kubernetes 集群规模和复杂性的减少,集群越来越难以保障高效率、低提早的交付 pod。本文将分享蚂蚁金服在设计 SLO 架构和实现高 SLO 的办法和教训。
Why SLO?
Gartner 对 SLO 的定义:在 SLA 框架下,SLO 是零碎必须要达到的指标;须要尽可能地保障调用方的胜利。有些人可能会对 SLI/SLO/SLA 有困惑,能够先来看下三者的关系:
- SLI 定义一个指标,来形容一个服务有多好算达到好的规范。比方 Pod 在 1min 内交付。咱们通常从迟延、可用性、吞吐率及成功率这些角度来制订 SLI。
- SLO 定义了一个小指标,来掂量一个 SLI 指标在一段时间内达到好的规范的比例。比如说,99% 的 Pod 在 1min 内交付。当一项服务颁布了其 SLO 的当前,用户方就会对该服务的品质有了冀望。
- SLA 是 SLO 衍生进去的协定,罕用于 SLO 定义的指标比例没有实现时,服务方要赔多少钱。通常来说,SLA 的协定会具体白纸黑字造成有法律效率的合同,罕用于服务供应商和内部客户之间(例如阿里云和阿里云的使用者)。一般来说对于外部服务之间的 SLO 被突破,通常不会是经济上的抵偿,可能更多的是职责上的认定。
所以,咱们在零碎外部更多关注的是 SLO。
What we concern about Larger K8s Cluster?
随着生产环境一直倒退、K8s 集群越来越简单、集群规模一直增大。如何保障大规模环境 K8s 集群的可用性?是摆在泛滥厂家背后的一个难题。对于 K8s 集群,咱们通常关怀以下几个问题:
- 第一个问题就是集群是否衰弱,所有组件是否失常工作,集群中 Pod 创立的失败数量有多少,这是一个整体指标的问题。
- 第二个问题就是集群中产生了什么,集群中是否有异样产生了,用户在集群中做了些什么事件,这是一个追踪能力的问题。
- 第三个问题就是有了异样后,是哪个组件出了问题导致成功率升高,这是一个起因定位的问题。
那么,咱们该如何解决下面的问题呢?
- 首先,咱们要定义一套 SLO,来形容集群的可用性。
- 接着,咱们必须有能力对集群中 Pod 的生命周期进行追踪;对于失败的 Pod,还须要剖析出失败起因,以疾速定位异样组件。
- 最初,咱们要通过优化伎俩,打消集群的异样。
SLls on Large K8s Cluster
咱们先来看下集群的一些指标。
- 第一项指标:集群衰弱度。目前有 Healthy/Warning/Fatal 三个值来形容,Warning 和 Fatal 对应着告警体系,比方 P2 告警产生,那集群就是 Warning;如果 P0 告警产生,那集群就是 Fatal,必须进行解决。
- 第二项指标:成功率。这里的成功率是指 Pod 的创立成功率。Pod 成功率是一个十分重要的指标,蚂蚁一周 Pod 创立量是百万级的,成功率的稳定会造成大量 Pod 的失败;而且 Pod 成功率的上涨,是集群异样的最直观反馈。
- 第三项指标:残留 Terminating Pod 的数量。为什么不必删除成功率呢?因为在百万级别的时候,即便 Pod 删除成功率达到 99.9%,那么 Terminating Pod 的数量也是千级别的。残留如此多的 Pod,会占着利用的容量,在生产环境中是不可承受的。
- 第四项指标:服务在线率。服务在线率是通过探针来掂量的,探针失败,意味着集群不可用。服务在线率是会对 Master 组件来设计的。
- 最初一项指标:故障机数量,这是一个节点维度的指标。故障机通常是指那些无奈正确交付 Pod 的物理机,可能是磁盘满了,可能是 load 太高了。集群故障机并须做到“疾速发现,疾速隔离,及时修复”,毕竟故障机会对集群容量造成影响。
The success standard and reason classification
有了集群的指标后,咱们须要把这些指标进行细化,定义出胜利的规范。
先来看 Pod 创立成功率指标。咱们把 Pod 分为了一般 Pod 和 Job 类 Pob。一般 Pod 的 RestartPolicy 为 Always,Job 类 Pod 的 RestartPlicy 为 Never 或 OnFailure。两者都设定有交付工夫,比方必须在 1 分钟以内实现交付。一般 Pod 的交付规范是 1min 内 Pod 曾经 Ready;Job 类 Pod 的交付规范是 1min 内 Pod 的状态已达 Running、Succeeded 或 Failed。当然创立的工夫须要把 PostStartHook 执行工夫排除。
对于 Pod 的删除,胜利的规范为:在规定工夫内,Pod 从 ETCD 内删除。当然,删除的工夫须要把 PreStopHookPeriod 工夫排除。
对于故障机,要尽快的发现并进行隔离和降级。比方物理机磁盘只读,那必须在 1min 内实现对该 Pod 打 taint。至于故障机的复原工夫,须要按不同的故障起因,制订不同的复原工夫。比方系统故障须要重要装置零碎,那复原工夫就会长些。
有了这些规范后,咱们也对 Pod 失败的起因进行了整顿,有些失败起因是零碎引起的,是咱们须要关怀的;有些失败起因是用户引发的,是咱们不须要关怀的。
比方 RuntimeError,就是一个零碎谬误,底层 Runtime 有问题了;ImagePullFailed,Kubelet 下载镜像失败,因为蚂蚁有 Webhook 对镜像准入做了校验,所有镜像下载失败个别都是零碎起因造成的。
对于用户起因,在零碎侧无奈解决,咱们只把这些失败起因以接口查问的形式提供给用户,让用户本人解决。比方 ContainerCrashLoopBackOff,通常是由用户容器退出引起的。
The infrastructure
围绕 SLO 指标,咱们构建了一整套体系,一方面用于向终端用户、运维人员展现以后集群各项指标状;另一方面,各个组件相互协作,通过剖析以后集群状态,失去影响 SLO 的各项因素,为晋升集群 pod 交付成功率提供数据反对。
自顶向下而看,顶层组件次要面向各种指标数据,如集群衰弱状态、pod 创立、删除、降级成功率,残留 pods 数量、不衰弱节点数量等指标。其中 Display Board 就是咱们常说的监控大盘。
咱们同样构建了 Alert 告警子系统,反对灵便的配置形式,能够为不同的指标,依据指标的上涨百分比,指标上涨绝对值等配置多种告警形式,如电话,短信,邮件等。
Analysis System 通过剖析指标历史数据,以及采集到的节点 metrics 和 master 组件指标,给出更具体的集群经营报告。其中:
- Weekly Report 子系统给出以后集群本周 pod 创立 / 删除 / 降级的数据统计,以及失败案例起因汇总。
- Terminating Pods Number 给出一段时间内集群内新增的无奈通过 K8s 机制删除的 pods 列表和 pods 残留起因。
- Unhealthy Nodes 则给出一个周期内集群所有节点的总可用工夫占比,每个节点的可用工夫,运维记录,以及不能主动复原,须要人工染指复原的节点列表。
为了撑持上述这些性能,咱们开发了 Trace System,用来剖析展现单个 pod 创立 / 删除 / 降级失败的具体起因。其中蕴含日志和事件采集、数据分析和 pod 生命周期展现三个模块:
- 日志和事件采集模块采集各 master 组件以及节点组件的运行日志和 pod/node 事件,别离以 pod/node 为索引存储日志和事件。
- 数据分析模块剖析还原出 pod 生命周期中各阶段用时,以及判断 pod 失败起因及节点不可用起因。
- 最初,由 Report 模块向终端用户裸露接口和 UI,向终端用户展现 pod 生命周期以及出错起因。
The trace system
接下来,以一个 pod 创立失败案例为例,向大家展现下 tracing 零碎的工作流程。
用户输出 pod uid 之后,tracing system 通过 pod 索引,查找到 pod 对应生命周期剖析记录、交付胜利与否断定后果。当然,storage 存储的数据不仅为终端用户提供根底数据,更重要的是通过对集群内 pods 生命周期,剖析出周期内集群的经营情况及每个节点的经营情况。比如说集群内太多 pods 调度到热点节点,不同 pods 的交付引起节点上资源竞争,导致节点负载太高,而交付能力却在降落,最终体现为节点上 pods 交付超时。
再举个例子,通过历史统计数据,剖析出 pods 生命周期中各阶段的执行工夫基线,以基线为评估规范,比拟组件不同版本的均匀用时、用时散布,给出组件改良倡议。另外,通过整体的 pods 生命周期中各组件负责的步骤工夫占比,找出占比拟多的步骤,为后续优化 pod 交付工夫提供数据反对。
Node Metrics
一个运行状况良好的集群,不仅须要 master 组件放弃高可用,节点稳定性也不容忽视。
如果把 pod 创立比作是 rpc 调用,则每个节点就是一个 rpc 服务提供者,集群的总容量等于每个节点能解决的 pod 创立申请的总和。每多一个不可用的节点,都代表着集群交付能力的降落,也代表着集群可用资源的降落,这就要求尽量保障集群内节点高可用;每一次 pod 交付 / 删除 / 降级失败,也意味着用户应用成本上升,体验降落,这就要求集群节点只有保障良好的衰弱度,调度到节点上的 pods 能力胜利交付。
换句话说,不仅要尽早发现节点异样,也要尽快修复节点。通过剖析各组件在 pod 交付链路上的性能,咱们补充了各种不同类型的组件的 metrics,以及将 host 运行状态转换为 metrics,一并采集到数据库之后,联合每个节点上 pod 交付后果,能够构建模型预测节点可用性,剖析节点是否存在不可复原异样,适当调整节点在调度器中比重,从而晋升 pod 交付成功率。
Pod 创立 / 降级失败,用户能够通过重试来解决,但 pod 删除失败,尽管有着 K8s 面向终态的理念,组件会一直重试,但究竟也会存在脏数据,如 pod 在 etcd 上删除,然而节点上还残留着脏数据。咱们设计实现了一个巡检零碎,通过查问 apiserver 获取调度到以后节点上的 pods,通过比照,找到节点上残留的过程 / 容器 /volumes 目录 /cgroup / 网络设备等,通过其余路径尝试开释残留资源。
Unhealthy node
接下来形容故障机的解决流程。
故障机判断的数据起源有很多,次要有节点的监控指标,比方:
- 某类 Volume 挂载失败
- NPD(Node Problem Detector),这是社区的一个框架
- Trace 零碎,比方某个节点上 Pod 创立继续报镜像下载失败
- SLO,比方单机上残留大量 Pod
咱们开发了多个 Controller 对这些某类故障进行巡检,造成故障机列表。一个故障机能够有好几项故障。对于故障机,会依照故障进行不同的操作。次要的操作有:打 Taint,避免 Pod 调度下来;升高 Node 的优先级;间接主动解决进行复原。对于一些非凡起因,比方磁盘满,那就须要人工染指排查。
故障机系统每天都会产生一个日报,来表明故障机系统明天做了哪些事件。开发人员能够通过一直地增加 Controller 和解决规定欠缺整个故障机处理零碎。
Tips on increasing SLO
接下来,咱们来分享下达到高 SLO 的一些办法。
- 第一点,在晋升成功率的过程中,咱们面临的最大问题就是镜像下载的问题。要晓得,Pod 必须在规定工夫内交付,而镜像下载通常须要十分多的工夫。为此,咱们通过计算镜像下载工夫,还专门设置了一个 ImagePullCostTime 的谬误,即镜像下载工夫太长,导致 Pod 无奈按时交付。
还好,阿里镜像散发平台 Dragonfly 反对了 Image lazyload 技术,也就是反对近程镜像,在 Kubelet 创立容器时,不必再下载镜像。所以,这大大减速了 Pod 的交付速度。无关 Image lazyload 技术,大家能够看下阿里 Dragonfly 的分享。
- 第二点,对于晋升单个 Pod 成功率,随着成功率的晋升,难度也越来越难。能够引入一些 workload 进行重试。在蚂蚁,paas 平台会一直重试,直到 Pod 胜利交付或者超时。当然,在重试时,之前的失败的节点须要排除。
- 第三点,要害的 Daemonset 肯定要进行查看,如果要害 Daemonset 缺失,而把 Pod 调度下来,就非常容易出问题,从而影响创立 / 删除链路。这须要接入故障机体系。
- 第四点,很多 Plugin,如 CSI Plugin,是须要向 Kubelet 注册的。可能存在节点上一切正常,但向 Kubelet 注册的时候失败,这个节点同样无奈提供 Pod 交付的服务,须要接入故障机体系。
- 最初一点,因为集群中的用户数量是十分多的,所以隔离十分重要。在权限隔离的根底上,还须要做到 QPS 隔离,及容量的隔离,避免一个用户的 Pod 把集群能力耗尽,从而保障其余用户的利益。
原文链接
本文为阿里云原创内容,未经容许不得转载。