什么是 KCL

KCL (Kusion Configuration Language) 是一个开源的基于约束的记录及函数言语,主要用于装备编写和战略校验场景。KCL 希望经过老练的编程言语技术和实践来改进对很多冗杂装备的编写,致力于构建环绕装备的更好的模块化、扩展性和稳定性,更简略的逻辑编写,以及更快的自动化集成和杰出的生态延展性。

所谓装备就是当咱们部署软件体系时,咱们并不认为它们是固定不变的。不断发展的事务需求、根底架构要求和其他因素意味着体系不断改变。当咱们需求快速更改体系行为,而且更改进程需求昂贵、冗长的重建和重新部署进程时,事务代码更改往往是不行的。而装备能够为咱们提供了一种低开支的方法来改变体系功用,比方咱们会经常为体系编写一些如下所示的 JSON 或 YAML 文件作为咱们体系的装备。

  • JSON 装备
{
  "server": {
    "addr": "127.0.0.1",
    "listen": 4545
  },
  "database": {
    "enabled": true,
    "ports": [
      8000,
      8001,
      8002
    ],
  }
}
  • YAML 装备
server:
 addr: 127.0.0.1
 listen: 4545
database:
 enabled: true
 ports:
 - 8000
 - 8001
 - 8002

咱们能够依据需求选择在 JSON 和 YAML 文件中存储静态装备。此外,装备还能够存储在答应更灵敏装备的高级言语中,经过代码编写、烘托并得到静态装备。KCL 就是这样一种装备言语,咱们能够编写 KCL 代码来生成 JSON/YAML 等装备。这篇文章咱们要点叙述运用 KCL 生成并办理 Kubernetes 资源,并经过一些简略的比方给咱们一个简略的快速开端,更多的内容咱们会在后续文章展开。

为什么运用 KCL

当咱们办理 Kubernetes 资源清单时,咱们常常会手写保护,或许运用 Helm 和 Kustomize 等东西来保护咱们 YAML 装备或许装备模版,然后经过 kubectl 和 helm 指令行等东西将资源下发到集群。但是作为一个 “YAML 工程师” 每天保护 YAML 装备无疑是琐碎且无聊的,而且简单出错。

apiVersion: apps/v1
kind: Deployment
metadata: ...  # Omit
spec:
 selector:
  matchlabels:
   cell: RZ00A
 replicas: 2
 template:
  metadata: ...  # Omit
  spec:
   tolerations:
   - effect: NoSchedules
    key: is-over-quota
    operator: Equal
    value: 'true'
   containers:
   - name: test-app
     image: images.example/app:v1  # Wrong ident
    resources:
     limits:
      cpu: 2  # Wrong type. The type of cpu should be str
      memory: 4Gi
       # Field missing: ephemeral-storage
   affinity:
    nodeAffinity:
     requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
      - matchExpressions:
       - key: is-over-quota
        operator: In
        values:
        - 'true'
    1. YAML 中的结构化数据是无类型的,缺少验证方法,无法当即查看所有数据的有效性
    1. YAML 编程才能欠佳,简单写出不正确的缩进,也没有逻辑判断、等常见代码安排方法,简单写出很多重复装备,难以保护
    1. 用户很难了解 YAML 装备所有细节,比方上 Kubernetes 装备中的tolerationaffinity字段,如果用户不了解调度逻辑,它可能被过错地省略掉或许剩余的添加

因而,KCL 希望在 Kubernetes YAML 资源办理层面处理如下问题:

    1. 生产级高性能编程言语编写代码的方法提高装备的灵敏度,比方条件句子、循环、函数、包办理等特性提高装备重用的才能
    1. 在代码层面提高装备语义验证的才能,比方字段可选 / 必选、类型、规模等装备查看才能
    1. 提供装备分块编写、组合和抽象的才能,比方结构界说、结构继承、约束界说等才能

本篇文章是 KCL 能够做什么系列文章第一篇,要点叙述 KCL 快速入门,后续会持续更新和分享 KCL 的一系列特点和运用场景,咱们敬请期待!

怎么运用 KCL 生成并办理 Kubernetes 资源

前提条件

首要能够在KCL 项目首页依据指导下载并装置 KCL,然后准备一个Kubernetes环境

生成 Kubernetes 资源

咱们能够编写如下 KCL 代码并命名为 main.k ,KCL 受 Python 启示,根底语法十分接近 Python, 比较简单学习和上手

apiVersion = "apps/v1"
kind = "Deployment"
metadata = {
  name = "nginx"
  labels.app = "nginx"
}
spec = {
  replicas = 3
  selector.matchLabels = metadata.labels
  template.metadata.labels = metadata.labels
  template.spec.containers = [
    {
      name = metadata.name
      image = "${metadata.name}:1.14.2"
      ports = [{ containerPort = 80 }]
    }
  ]
}

上述 KCL 代码中咱们别离声明晰一个 Kubernets Deployment 资源的apiVersionkindmetadataspec变量,并别离赋值了相应的内容,特别地,咱们将metadata.labels字段别离重用在spec.selector.matchLabelsspec.template.metadata.labels字段。能够看出,比较于 YAML,KCL 界说的数据结构更加紧凑,而且能够经过界说局部变量实现装备重用。

咱们能够履行如下指令行得到一个 Kubernetes YAML 文件

kcl main.k

输出为:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx
 labels:
  app: nginx
spec:
 replicas: 3
 selector:
  matchLabels:
   app: nginx
 template:
  metadata:
   labels:
    app: nginx
  spec:
   containers:
   - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

当然咱们能够将 KCL 东西与 kubectl 等东西结合运用,让咱们履行如下指令并看看效果

$ kcl main.k | kubectl apply -f -
deployment.apps/nginx configured

能够从指令行的成果看出看出与咱们运用直接运用 YAML 装备和 kubectl apply 的一个 Deployment 体会完全一致

经过 kubectl 查看部署状态

$ kubectl get deploy
NAME  READY  UP-TO-DATE  AVAILABLE  AGE
nginx  3/3   3      3      15s

编写代码办理 Kubernetes 资源

关于 Kubernetes 资源发布时,咱们常常会遇到装备参数需求动态指定的场景,比方不同的环境需求设置不同的image字段值生成不同环境的资源。关于这种场景,咱们能够经过 KCL 的条件句子和option函数动态地接纳外部参数。咱们能够在上述比方的根底上依据不同的环境调整装备参数,比方关于如下代码,咱们编写了一个条件句子并输入一个名为env的动态参数

apiVersion = "apps/v1"
kind = "Deployment"
metadata = {
  name = "nginx"
  labels.app = "nginx"
}
spec = {
  replicas = 3
  selector.matchLabels = metadata.labels
  template.metadata.labels = metadata.labels
  template.spec.containers = [
    {
      name = metadata.name
      image = "${metadata.name}:1.14.2" if option("env") == "prod" else "${metadata.name}:latest"
      ports = [{ containerPort = 80 }]
    }
  ]
}

运用 KCL 指令行-D符号接纳一个从外部设置的动态参数:

kcl main.k -D env=prod

输出为:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deployment
 labels:
  app: nginx
spec:
 replicas: 3
 selector:
  matchLabels:
   app: nginx
 template:
  metadata:
   labels:
    app: nginx
  spec:
   containers:
   - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

上述代码片段中的image = "${metadata.name}:1.14.2" if option("env") == "prod" else "${metadata.name}:latest"意思为:当动态参数env的值被设置为prod时,image 字段值为nginx:1.14.2, 否则为nginx:latest,因而咱们能够依据需求为 env 设置为不同的值取得不同内容的 Kubernetes 资源。

而且 KCL 支撑将 option 函数动态参数保护在装备文件中,比方编写下面展示的kcl.yaml文件

kcl_options:
 - key: env
  value: prod

运用如下指令行也能够得到同样的效果,简化 KCL 动态参数的输入进程

kcl main.k -Y kcl.yaml

输出为:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deployment
 labels:
  app: nginx
spec:
 replicas: 3
 selector:
  matchLabels:
   app: nginx
 template:
  metadata:
   labels:
    app: nginx
  spec:
   containers:
   - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

下一期

本期内容大概简略介绍了用 KCL 编写装备的快速入门和运用KCL 界说并办理 Kubernetes 资源。

目前阶段 Kustomize 和 Helm 现已慢慢演进成在 Kubernetes 装备界说和办理领域的事实意义上的规范,了解 Kubernetes 的小伙伴可能更喜爱显式装备编写方法编写。那么相较于 Kustomize 和 Helm,用 KCL 来写装备文件烘托,又有什么异同呢?考虑到有很多小伙伴现已在运用 Helm,Kustomize 这样的东西,下一期我将介绍用 KCL 的方法来写对应的装备代码,敬请期待!!

如果您喜爱这篇文章,必定记住收藏 + 重视!!更多精彩内容请拜访(如果您喜爱 KCL 这个项目,无妨 star 一下鼓励一下作者哦):

KCL 库房地址:github.com/KusionStack…

Kusion 库房地址:github.com/KusionStack…

Konfig 库房地址:github.com/KusionStack…

一起欢迎参加咱们的社区进行交流:

github.com/KusionStack…