「开源人说」| 全栈声明式可观测:KubeVela 的云原生应用洞察体系

本文涉及的产品
云原生网关 MSE Higress,422元/月
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 随着云原生技术的日趋成熟,越来越多的工作负载都迁移到 Kubernetes 之上,包括各类无状态微服务和复杂的有状态应用。为了支撑这些应用所需的各项基础设施,开发者不得不面对大量的底层 API。这就形成了两个挑战,一方面是难以标准化,各种工作负载自身都会形成自己的运维管理平台,带来了企业平台层的分化;另一方面是过于复杂,带来了很高的使用门槛和稳定性风险。

KubeVela 是一个开箱即用的现代化应用交付与管理平台,它通过统一的应用模型、可编程可扩展的架构,帮助企业构建统一的平台,向上为不同场景的业务团队按需提供差异化、且开箱即用的平台层能力,大大降低了云原生技术的使用门槛。除了核心的云资源交付、应用管理、多集群、工作流等技术,KubeVela 还提供了全栈的声明式可观测能力,帮助业务开发者灵活定制,轻松洞察各类复杂的云原生工作负载。


本文我们将聚焦 KubeVela 的可观测体系,介绍云原生时代的可观测挑战及 KubeVela 的解决方案。


01 云原生可观测的挑战


通常情况下,为了给上层业务提供可观测性能力,运维团队会通过“熟练掌握” 业务团队的使用场景,然后将运行应用服务的基础设施与各类可观测性基础设施衔接,通过相对固化的脚本和系统,将采集指标、收集日志、聚合处理、图表分析等一系列流程合并,从而将最底层的运行态实时反馈到监控报警系统中,为运维团队自身及上层业务团队做预警,并在第一时间发现异常、排查故障。

1.png

(图 1)CNCF landscape 的插件已经达到 1000+,且每天都在新增


随着云原生生态的不断繁荣,平台工程的理念逐渐深入人心,一个基础平台团队往往需要服务上层多个微服务化的业务团队,而业务团队的架构也随着基础设施的丰富逐渐产生了多样性,这就打破了传统保姆式地从“熟练掌握”到“硬编码”的可观测体系建设路径。举例而言,业务团队刚开始构建业务的时候可能使用基础的 ingress 做服务网关,而半年之后可随着需求的复杂化会切换成以 istio 为核心的流量治理方案,这意味着从 API 到上层架构相关的可观测能力都要跟着改变。如图 1 所示,在 CNCF landscape 的繁荣生态里,每个子领域都能找到多个替换方案。传统模式下相对固定的可观测性体系构建方式不再适用,平台团队需要根据业务层的架构灵活定制和扩展可观测方案


“割裂”则是可观测领域面临的第二个巨大挑战,这通常会体现在三个维度。第一个维度是不同业务间数据的割裂,从基础设施(计算/存储/网络)、容器、应用到业务,从移动端、前端、后端到数据库和云服务,企业的不同部门通常会采用不同的监控方案,监控数据彼此形成孤岛,无法打通。第二个维度是不同基础设施配置的割裂,随着云时代到来,企业面临多云、多集群、多账号的管理,可观测数据分布在不同云和集群内,多云多集群的可观测无法统一配置。第三个维度是数据链路的割裂,例如开源社区的 Prometheus(Exporter)、Grafana 分别有自己繁荣的社区,但他们的采集源和大盘往往没有很好的连接在一起,常常是一头输出大量无效数据占用存储资源,另一头则展示错误或者延迟很高的数据。


2.png

(图 2)社区找到的具备对应关系的大盘和 Exporter 通常无法直接使用


而传统监控系统采用的基于图形界面点击的配置方式显然也不再适用,虽然上手简单,但是迁移、复制成本极高。在多集群管理下,监控配置不易于复制,漏采、漏配很常见。也难以与应用交付的配置绑定,无法实现监控随着应用生命周期而主动变化。


如果沿着云原生声明式统一 API 的理念去思考,你就会发现我们也需要一套声明式的配置方式,让我们能够以统一的方式、灵活的对接可观测基础设施,按需串联和定制全套的可观测能力,自动完成监控探针安装、采集、存储、展现、告警等配置的多环境统一下发和治理。这个模式我们也可以称之为全栈声明式可观测(Full Stack Observability as Code)。


02 全栈声明式可观测


虽然云原生时代的可观测存在诸多挑战,但是也得益于云原生开源技术的发展,以 Prometheus、Grafana、OpenTelemetry 为代表的可观测基础设施正在逐渐成为各自领域的事实标准,周边生态的集成正在以滚雪球的态势累积,这让可观测基础设施的统一成为了可能。选型这些开源项目为核心构建可观测解决方案成为了非常自然的选择,不仅帮助我们统一了技术和数据,还可以让我们借力生态,快速满足业务场景的需要。


统一的声明式可观测 API

一个关键的挑战是如何将可观测基础设施的能力变成声明式的?你可能容易想到 Kubernetes 的 CRD(自定义资源)Operator 技术,确实已经有相当一部分可观测能力可以直接使用 CRD 这样的声明式 API。比如 Prometheus 就可以通过安装 Prometheus-Operator 获得 ServiceMonitor 这个声明式 API。然而还有一部分其他项目(比如 Grafana),以及大量的云服务,他们并不具备成熟的 CRD Operator。为每个服务都编写 CRD Operator 存在不小的技术难度,不仅费时费力,同时还要消耗额外的 Pod 资源,整体成本比较高。


我们自然会想,是否有一种方式可以这些服务的 API 自动转换成符合 Kubernetes 标准的声明式 API?针对这种情况,Kubernetes 的 Aggregated API Server(简称 AA) 模式提供了答案,即通过开发符合 Kubernetes API 规范的 REST 服务,通过 APIService 对象将其注册到 Kubernetes apiserver 上,从而达到扩展 Kubernetes apiserver 能处理的请求类型的效果。相较于 CRD + Operator 的模式,AA 模式提供了与 CRD 统一的 API,但处理过程并不是面向终态的,它能够提供同步的请求处理,灵活性和交互性较高。而 AA 模式的缺点则是它自身不具备调谐重试的能力,需要配合额外的手段针对出错等异常状态做面向终态的重试。


而 KubeVela 中的 Prism 子项目正是这样一个基于 AA 模式将第三方 API 转换成 Kubernetes 标准 API 的服务,它对接 Kubernetes 的 AA 机制,向上提供统一的 K8s API,向下对接 Grafana 自身的 API,将数据源创建、大盘导入等操作统一融入到了 Kubernetes 用户习惯的 YAML 操作中。比如用户想要在 Kubernetes 上查询已有的 Grafana Dashboard,它可以使用 kubectl get grafanadashboard命令,调用 Kubernetes API 的 GrafanaDashboard 资源,该请求经过 Prism 后会转换位请求 Grafana API,查询结果则会再次经过 Prism 转回原生的 GrafanaDashboard 资源,从而用户就可以得到和操作 Deployment、Configmap 等原生资源一致的使用体验。



3.png

(图 3)KubeVela 通过提供原生 API 接口及 Addon 体系,支持多种方式接入可观测性基础设施


如图 3 所示,Prism 就像一座桥梁,它可以对接用户自建、使用 KubeVela 插件自动安装、使用云服务这三种不同部署形态的差异。不仅如此,由于 AA 模式不强制要求数据存储在 etcd,我们可以以 Grafana 本身的存储作为数据的源头(Source of Truth),这意味着无论用户是在 Kubernetes API 操作,还是通过 Grafana 的 API,亦或是通过 Grafana 的 UI 进行变更修改,相应的变化都能够即刻反映在各种客户端上。在权限处理上,由于 Grafana API 经过 KubeVela Prism 已经被映射成了原生的 Kubernetes 资源,因此用户可以完全依赖在 Kubernetes 的 RBAC 权限控制体系上来调节不同 Kubernetes 用户对于 Grafana 上数据的访问权限,不需要担心数据穿透及泄漏问题。

而 AA 模式自身不具备的错误重试,则可以结合应用本身的生命周期,交由 KubeVela 控制器对 Kubernetes API 返回状态统一做调谐,从而达到面向终态的声明式处理模式。


围绕应用生命周期的灵活编排

当基础设施的能力都能通过 Kubernetes API 用统一的方式描述时,我们还剩下两个核心问题需要解决:

1.如何灵活编排这些可观测的声明式 API,融入应用的生命周期中?

2.如何针对不同的可观测场景,做到灵活扩展、按需定制?


而这两个核心问题与 KubeVela 一直以来坚持的设计原则相对应。

以工作流为核心的应用交付模型。基于 Kubernetes API 做编排的轻量级工作流引擎一直是 KubeVela 的“杀手锏”,它不仅能够以 DAG 的方式完成各种带上下文的复杂工作流编排场景,还能围绕应用的生命周期对资源做管理,包括应用删除时对资源的回收。与此同时,它本身不消耗额外的 pod 资源,是一个线程级工作流,非常适合应用交付这类管控面的使用场景。


按需定制、可编程,一套配置完整描述可观测需求。KubeVela 在设计之初就选择了 Infra as Code(IaC)的可编程扩展方式,KubeVela 的开发者和企业的平台工程师可以通过 CUE 配置语言 按需定制,对接各类 Kubernetes API,最终将其转化成用户易于安装、使用和理解的模块化插件,最重要的是可以通过声明式 API 的方式在一套配置中完整的描述可观测需求。丰富的插件市场也是 KubeVela 的一大生态特色。


具体而言,KubeVela 的开发者或者平台运维人员可以使用 CUELang 编写各式定制化的 Definition 描述文件,以 IaC 的方式去定义可观测的场景,比如采集 metrics、收集日志、创建数据源、导入大盘等。而业务的开发者则只需要选用这些现成的模块(通常被定义为运维特征“Trait”或者工作流步骤“WorkflowStep”)去绑定应用配置。

4.png

(图 4)通过 KubeVela 的 X-Definition 体系扩展模块化可插拔的应用观测能力


如图 5 所示,KubeVela 的最终用户在描述应用时,描述了 metrics 和日志收集的信息,同时在工作流步骤中定义了在部署完成后去创建可观测大盘。这个流程的编排过程全部由 KubeVela 控制器自动完成,包括流程的顺序执行、可观测 API 和工作负载 API 的绑定、统一版本和标签、状态检查和异常重试、多集群管理,以及维持资源面向终态的一致性。更为重要的是,KubeVela 很好的平衡了可扩展性和易用性,最终用户在灵活选择不同可观测模块的同时无需关心下层的配置参数细节


5.png

(图 5)围绕应用的全栈声明式可观测


多集群/混合云的可观测统一配置

KubeVela 自身也天然支持现代应用的多集群、混合云需求,所以当我们满足了统一通过应用交付声明式可观测需求时,也可以借助 KubeVela 多集群交付的能力,满足多集群、混合云可观测的统一配置,如图 6 所示,我们可以针对不同的集群配置不同的可观测需求。

6.png

(图 6)多集群/混合云的差异化可观测配置和统一交付


KubeVela 的可观测性能力除了高度可定制化之外,还可以通过统一的接口与云厂商的可观测性服务进行对接。以指标采集为例,如果用户的系统中已经存在了其他 Prometheus 实例,或者采用了云厂商的 Prometheus 服务(如阿里云的 ARMS 产品),你也可以通过注册 Grafana 数据源的方式将 Prometheus 实例接入到 Grafana 监控大盘中。KubeVela Prism 提供的 Grafana API 接口中支持以原生的方式创建 GrafanaDatasource 资源,KubeVela 上的应用也可以使用 grafana-datasource 这种组件来管理数据源的配置。


另一方面,如果用户的系统中已经存在了其他的 Grafana 实例,用户也可以通过使用 grafana-access 这种类型的组件,将已有的 Grafana 实例注册在 KubeVela 系统中,完成集成。集成后,KubeVela 的应用就可以通过使用 grafana-dashboard 这种类型的组件,将监控大盘以应用资源的方式进行配置及管理。


至此我们可以看到,一个“全栈声明式可观测”的解决方案已经形成,为了进一步提升用户体验,我们在灵活定制和可扩展的基础上,针对 Kubernetes 中的核心场景做了大量开箱即用的可观测能力。另一方面,KubeVela 本身微内核高可扩展的架构可以快速通过插件(Addon)机制扩展周边生态,我们将可观测性能力做成了插件,可以获得非常流畅的安装体验。


03 KubeVela 开箱即用的可观测体验


接下来,让我们从接入、使用、定制三个方面看看实际的使用过程是怎么样的。

接入可观测性基础设施

在 KubeVela 中,用户既可以从零开始搭建可观测性体系,也可以对接已有的可观测性基础设施与 KubeVela 系统。


对于从零开始搭建的 KubeVela 用户,只需几行简单的 vela addon enable 语句,即可快速将所需的插件装入自己的 Kubernetes 环境中,而且天然支持多集群架构,这意味着如果你有多个集群需要管理,通过 KubeVela,你可以很轻松地将相同的配置与服务装入所有集群中。当然你也可以按需只选择安装部分需要的服务,或者只对于某一部分集群进行安装,具体命令可以参考官方文档,流程如图 7 所示。


7.gif

(图 7)在多集群中安装可观测性插件


目前 KubeVela 官方支持的可观测性 Addon 已经覆盖了指标、日志、可视化等领域,为运维人员和应用开发者提供了开箱即用的部署方法,同时与已有自建基础设施,甚至是云厂商提供的 SaaS 服务进行无缝衔接。为了简化用户上手成本,提升体验,KubeVela 的可观测性 Addon 针对各类使用场景提供了高度可定制化的解决方案。例如,在多集群场景下,为了提供和单集群场景下具有一致体验的跨集群指标,KubeVela 的 Prometheus Addon 默认包含了基于 Thanos 的分布式采集部署方案。而在日志领域,KubeVela 的 Loki Addon 则是提供了包括 Promtail 和 Vector 在内的多种 Agent 采集方案,辅以 vector-controller 等运维工具,帮助运维人员在日志配置上获得与 Kubernetes 原生资源一致的体验。官方文档中包含了更为详细的介绍。


开箱即用的可观测大盘

KubeVela 提供的可观测性基础设施内置了一系列监控大盘,方便用户从系统及应用两个不同的维度监控运维 KubeVela 及其上应用的运行状态。


洞察 Kubernetes 和 KubeVela 系统

系统维度上,内置的 Kubernetes System 监控从基础的集群角度向用户展示了 KubeVela 管控的各个集群状态,包括 Kubernetes APIServer 的负载、请求量、响应延迟、etcd 存储量等指标。这些指标能够帮助用户快速发现整个系统的异常状态,或者是用于排查系统响应慢的原因。


8.png

(图 8 )Kubernetes 系统监控大盘


另一方面,KubeVela 还内置了针对于自身 Controller 系统的监控大盘,这一大盘被广泛应用在各种 KubeVela 系统的压力测试中,可以用来排查控制器性能的负载状况及瓶颈点。比如如果控制器的处理队列开始堆积,说明目前的控制器无法应对如此庞大规模的应用请求数量,长时间的堆积会导致应用无法被及时处理。而堆积的原因,则可以通过资源使用量、各类资源请求延迟、不同类型操作的延迟来排查,并依据不同监控表现来进行相应的优化


9.png

(图 9 )KubeVela 系统监控大盘


面向应用的可观测大盘

除了系统大盘外,KubeVela 还内置了面向应用的基础数据可视化界面,针对 Deployment 等原生工作负载类型资源的可观测界面,以及面向 nginx 日志分析这类场景化的可观测界面,如图 10-12 所示。这些大盘为应用提供了通用化的监控指标,便于运维人员排查常见的风险点(如应用资源不足、配置错误等)。未来,更多基础资源类型的监控大盘也会被进一步继承到内置的监控体系中。


10.png

(图 10 )KubeVela 应用可视化界面


11.png

(图 11 )Deployment 资源的监控大盘


12.png

(图 12)基于 Nginx 日志的分析大盘


定制你的可观测性流程

除了 KubeVela 插件体系提供的一系列内置监控外,KubeVela 的用户还可以通过多种方式定制其观测体系。比如,通过为 Prometheus 实例配置 RecordingRules 或者 AlertingRules 来增强 Prometheus 的能力,提供预聚合或报警能力。而这些规则的配置在 KubeVela 体系中也能很轻易的进行多集群同步和差异化配置。


另一方面,运维人员也可以通过编写 CUE 来开发 KubeVela 的工作流步骤,为开发者提供便捷的应用监控自动化生成能力。如此一来,应用的开发者便能够专注在功能或业务本身的指标或运行状态上,而不需要关心这些指标是如何采集、存储并呈现在监控大盘上。


13.gif

(图 13 )部署 KubeVela Application 后自动创建相应的 Grafana 监控大盘


更多的定制功能详见官方文档

14.png

(图 14 )使用 KubeVela Pipeline 编排你自己的可观测性基础设施


除了可观测性插件本身的定制化和可扩展性之外,你还可以使用 KubeVela Pipeline 来自由编排你所需要的可观测性基础设施及配置,对接已有服务。KubeVela Pipeline 可以帮助你将复杂冗长的编排过程串联在一起,从而实现便捷快速的“一键部署”。


04 未来


可观测性体系是系统稳定性的基石,而云原生时代下,复杂多样的应用服务以及相应的观测需求对于运维和开发团队之间的协作也提出了更高的要求。本文中提出的 KubeVela 全栈声明式可观测,能够自动化地构建面向应用的可观测性体系,既可以减轻开发团队对于基础设施使用的认知负担,也可以减少运维团队对于上层业务逻辑的理解需求。理想情况下,开发团队无需理解底层资源的排布,只需要在配置文件中声明所需部署的服务以及关注的指标,他们便可以在相应的基础设施上看到服务的部署状态以及相应的业务指标。而运维团队则无需了解服务及业务指标的具体内容,只需要聚焦在底层资源的运行状态和通用指标上。


目前,KubeVela 的内置可观测性体系主要集中在各类指标、日志的采集和呈现上。未来,KubeVela 还会进一步将应用探针等可观测技术集成到插件体系中,为用户提供便捷的安装、管理和使用体验。此外,目前的 KubeVela 体系支持使用工作流步骤来完成应用监控的自动化发现及报表生成,KubeVela 团队还将继续探索 Dashboard as Code 并总结更多最佳的自动化部署实践方案,推动可观测性与应用模型的进一步结合。


作者介绍:

殷达,KubeVela Maintainer,阿里云高级工程师,深度参与了 KubeVela 混合云多集群管理、可扩展工作流、可观测等核心能力体系的建设。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
24天前
|
Cloud Native 安全 物联网
云原生技术在现代软件开发中的应用与挑战####
云原生,这一词汇如同一股强劲的科技风暴,席卷了整个信息技术领域,它不仅重塑了软件的开发模式,还引领了一场关于效率、可扩展性和弹性的深刻变革。本文旨在深入探讨云原生技术的核心概念,分析其在现代软件开发中的广泛应用,并直面伴随其发展而来的挑战,为读者勾勒出一幅既充满机遇又不乏考验的云原生技术图景。 ####
|
19天前
|
Cloud Native 前端开发 JavaScript
前端开发者必看:不懂云原生你就OUT了!揭秘如何用云原生技术提升项目部署与全栈能力
【10月更文挑战第23天】随着云计算的发展,云原生逐渐成为技术热点。前端开发者了解云原生有助于提升部署与运维效率、实现微服务化、掌握全栈开发能力和利用丰富技术生态。本文通过示例代码介绍云原生在前端项目中的应用,帮助开发者更好地理解其重要性。
53 0
|
5天前
|
Kubernetes Cloud Native 持续交付
云原生技术在现代软件开发中的应用与挑战
【10月更文挑战第37天】随着云计算技术的不断演进,云原生技术已经成为推动软件开发现代化的重要力量。本文将深入探讨云原生技术的核心概念、优势以及面临的挑战,并通过一个实际的代码示例,展示如何在云原生环境中部署一个简单的应用。我们将从云原生的基础架构出发,逐步引导读者理解其在现代软件开发中的关键作用。
16 1
|
1月前
|
运维 监控 Cloud Native
构建行业应用生态:云原生应用市场简化企业软件安装
在移动互联网时代,尽管手机应用市场为用户带来了极大的便利,但企业级软件的安装和管理仍面临诸多挑战,包括安装复杂、交付效率低、应用兼容性差等问题。为此,基于云原生技术的企业级应用市场Rainstore应运而生,旨在简化企业软件的安装和管理,提升交付效率,增强应用兼容性,支持远程管理和个性化定制,构建开放的行业应用生态,助力企业数字化转型。
构建行业应用生态:云原生应用市场简化企业软件安装
|
19天前
|
敏捷开发 Cloud Native 持续交付
云原生技术在现代企业中的应用与实践
【10月更文挑战第23天】本文将深入探讨云原生技术在现代企业中的广泛应用,并结合具体案例分析其对企业数字化转型的推动作用。我们将从云原生技术的基本原理出发,逐步揭示其在提高业务敏捷性、降低成本和增强系统可靠性方面的优势。同时,文章还将分享一系列成功实施云原生技术的企业案例,为读者提供实践中的参考和启示。最后,我们将讨论云原生技术面临的挑战及未来的发展趋势,为企业在这一领域的进一步探索提供指导。
|
20天前
|
Cloud Native 持续交付 云计算
云原生技术深度探索:构建现代化应用的基石####
【10月更文挑战第21天】 本文将深入探讨云原生技术的核心概念、关键技术及其在现代软件开发中的应用。我们将从容器化、微服务架构、持续集成/持续部署(CI/CD)、无服务器架构等关键方面展开,揭示这些技术如何共同作用,帮助企业实现高效、弹性且易于维护的应用部署与管理。通过实例分析,展现云原生技术在实际项目中的显著优势,为读者提供一套全面理解并应用云原生技术的指南。 ####
31 2
|
25天前
|
运维 Cloud Native 持续交付
云原生技术在现代IT架构中的深度应用与挑战####
【10月更文挑战第17天】 本文深入剖析了云原生技术的精髓,探讨其在现代IT架构转型中的核心作用与面临的挑战。云原生不仅是一种技术实现,更是企业数字化转型的重要推手,通过容器化、微服务、持续集成/持续部署(CI/CD)等关键要素,重塑软件开发、部署与运维模式。文章首先概述了云原生的基本原则与核心组件,随后分析了其如何促进企业敏捷性、可扩展性和资源利用率的提升,同时也指出了在安全性、复杂性管理及人才技能匹配等方面存在的挑战,并提出了相应的对策建议。 ####
64 6
|
27天前
|
运维 监控 Cloud Native
云原生技术在现代企业中的应用与挑战####
【10月更文挑战第15天】 本文深入探讨了云原生技术如何重塑企业的IT架构,并分析了其带来的机遇与面临的挑战。通过案例分析,揭示了云原生技术在提升业务敏捷性、降低运维成本方面的显著优势,同时也指出了在安全性、多云管理等方面的潜在难题,为企业决策者提供了有价值的参考。 ####
25 3
|
1月前
|
运维 Cloud Native 持续交付
云原生技术:构建现代应用的基石
【10月更文挑战第9天】在数字化转型的浪潮中,云原生技术如同一股清流,引领着企业走向更加灵活、高效的未来。本文将深入探讨云原生的核心概念,揭示其在现代应用开发与部署中的重要作用,并通过实际案例分析,展现云原生技术如何助力企业实现敏捷开发和自动化运维,最终提升业务竞争力。
77 3
|
1月前
|
运维 Kubernetes Cloud Native
云原生技术:构建现代应用的新范式
【10月更文挑战第9天】 云原生是一种通过云计算环境优化的软件开发和运行方法论,旨在最大化利用云平台的灵活性、可扩展性和弹性。本文将深入探讨云原生技术的基本原理、核心组件以及其在实际项目中的应用。我们将从Kubernetes的容器编排机制入手,逐步探讨如何通过自动化工具实现持续集成与持续部署(CI/CD),最终展示如何构建一个高效、可靠的云原生应用。
50 2