2 万字长文!声明式配置技术概述

零、前言


文本仅用于澄清声明式配置技术概述,KCL 概念以及核心设计,以及与其他配置语言的对比。

一、声明式配置概述


1.1 配置的重要性

  • 软件不是一成不变的,每天有成千上万的配置更新,并且配置本身也在逐渐演进,对规模化效率有较高的诉求

  • 配置更新越来越频繁:配置提供了一种改变系统功能的低开销方式,不断发展的业务需求、基础设施要求和其他因素意味着系统需要不断变化。

  • 配置规模越来越大:一份配置往往要分发到不同的云站点、不同的租户、不同的环境等。

  • 配置场景广泛:应用配置、数据库配置、网络配置、监控配置等。

  • 配置格式繁多:JSON, YAML, XML, TOML, 各种配置模版如 Java Velocity, Go Template 等。

  • 配置的稳定性至关重要,系统宕机或出错的一个最主要原因是有大量工程师进行频繁的实时配置更新,表 1 示出了几个由于配置导致的系统出错事件。

时间

事件

2021 年 7 月

中国 Bilibili 公司由于 SLB Lua 配置计算出错陷入死循环导致网站宕机

2021 年 10 月

韩国 KT 公司由于路由配置错误导致在全国范围内遭受重大网络中断

表 1 配置导致的系统出错事件

1.2 声明式配置分类

云原生时代带来了如雨后春笋般的技术发展,出现了大量面向终态的声明式配置实践,如图 1 所示,声明式配置一般可分为如下几种方式。

图 1 声明式配置方式分类

1.2.1 结构化 (Structured) 的 KV

结构化的 KV 可以满足最小化数据声明需求,比如数字、字符串、列表和字典等数据类型,并且随着云原生技术快速发展应用,声明式 API 可以满足 X as Data 发展的诉求,并且面向机器可读可写,面向人类可读。其优劣如下:

  • 优势

  • 语法简单,易于编写和阅读

  • 多语言 API 丰富

  • 有各种 Path 工具方便数据查询,如 XPath, JsonPath 等

  • 痛点

  • 冗余信息多:当配置规模较大时,维护和阅读配置很困难,因为重要的配置信息被淹没在了大量不相关的重复细节中

  • 功能性不足

  • 约束校验能力

  • 复杂逻辑编写能力

  • 测试、调试能力

  • 不易抽象和复用

  • Kustomize 的 Patch 比较定制,基本是通过固定几种 Patch Merge 策略

结构化 KV 的代表技术有

  • JSON/YAML:非常方便阅读,以及自动化处理,不同的语言均具有丰富的 API 支持。

  • Kustomize:提供了一种无需模板DSL 即可自定义 Kubernetes 资源基础配置和差异化配置的解决方案,本身不解决约束的问题,需要配合大量的额外工具进行约束检查如 Kube-linterCheckov 等检查工具,图 2 示出了 Kustomize 的典型工作方式。

图 2 Kustomize 典型工作方式

1.2.3 模版化 (Templated) 的 KV

模版化 (Templated) 的 KV 赋予静态配置数据动态参数的能力,可以做到一份模版+动态参数输出不同的静态配置数据。其优劣如下:

  • 优势

  • 简单的配置逻辑,循环支持

  • 支持外部动态参数输入模版

  • 痛点

  • 容易落入所有配置参数都是模版参数的陷阱

  • 当配置规模变大时,开发者和工具都难以维护和分析它们

模版化代表技术有:

  • Helm:Kubernetes 资源的包管理工具,通过配置模版管理 Kubernetes 资源配置。图 3 示出了一个 Helm Jekins Package ConfigMap 配置模版,可以看出这些模版本身都十分短小,可以书写简单的逻辑,适合 Kubernetes 基础组件固定的一系列资源配置通过包管理+额外的配置参数进行安装。相比于单纯的模版化的 KV,Helm 一定程度上提供了模版存储/引用和语义化版本管理的能力相比于 Kustomize 更适合管理外部 Charts, 但是在多环境、多租户的配置管理上不太擅长。

图 3 Helm Jekins Package ConfigMap 配置模版

  • 其他各种配置模版:Java Velocity, Go Template 等文本模板引擎非常适合 HTML 编写模板。但是在配置场景中使用时,存在所有配置字段即模版参数的风险,开发者和工具都难以维护和分析它们。

1.2.3 代码化 (Programmable) 的 KV

Configuration as Code (CaC), 使用代码产生配置,就像工程师们只需要写高级 GPL 代码,而不是手工编写容易出错而且难以理解的服务器二进制代码一样。配置变更同代码变更同样严肃地对待,同样可以执行单元测试、集成测试等。代码模块化和重用是维护配置代码比手动编辑 JSON/YAML 等配置文件更容易的一个关键原因。其优劣如下:

  • 优势

  • 必要的编程能力(变量定义、逻辑判断、循环、断言等)

  • 代码模块化与抽象(支持定义数据模版,并用模版得到新的配置数据)

  • 可以抽象配置模版+并使用配置覆盖

  • 痛点

  • 类型检查不足

  • 运行时错误

  • 约束能力不足

代码化 KV 的代表技术有:

  • GCL:一种 Python 实现的声明式配置编程语言,提供了必要的言能力支持模版抽象,但编译器本身是 Python 编写,且语言本身是解释执行,对于大的模版实例 (比如 K8s 型) 性能较差。

  • HCL:一种 Go 实现结构化配置语言,原生语法受到 libuclnginx 配置等的启发,用于创建对人类和机器都友好的结构化配置语言,主要针对 devops 工具、服务器配置及 Terraform 中定义资源配置等。

  • Jsonnet:一种 C++ 实现的数据模板语言,适用于应用程序工具开发人员,可以生成配置数据并且无副作用组织、简化、统一管理庞大的配置。

1.2.4 类型化 (Typed) 的 KV

类型化的 KV,基于代码化 KV,多了类型检查和约束的能力,其优劣如下:

  • 优势

  • 配置合并完全幂等,天然防止配置冲突

  • 丰富的配置约束语法用于编写约束

  • 将类型和值约束编写抽象为同一种形式,编写简单

  • 配置顺序无关

  • 痛点

  • 图合并和幂等合并等概念复杂,用户理解成本较高

  • 类型和值混合定义提高抽象程度的同时提升了用户的理解成本,并且所有约束在运行时进行检查,大规模配置代码下有性能瓶颈

  • 对于想要配置覆盖、修改的多租户、多环境场景难以实现

  • 对于带条件的约束场景,定义和校验混合定义编写用户界面不友好

类型化 KV 的代表技术有:

  • CUE:CUE 解决的核心问题是“类型检查”,主要应用于配置约束校验场景及简单的云原生配置场景

1.2.5 模型化 (Structural) 的 KV

模型化的 KV 在代码化和类型化 KV 的基础上以高级语言建模能力为核心描述,期望做到模型的快速编写与分发,其优劣如下:

  • 优势

  • 引入可分块、可扩展的 KV 配置块编写方式

    • 0
      点赞
    • 0
      收藏
      觉得还不错? 一键收藏
    • 0
      评论

    “相关推荐”对你有帮助么?

    • 非常没帮助
    • 没帮助
    • 一般
    • 有帮助
    • 非常有帮助
    提交
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值