[kube 027]用CUE配置K8s
CUE
是一种开源数据约束语言,旨在简化涉及定义和使用数据的任务。它是JSON
的超集,可让熟悉JSON
的用户快速入门。
什么是CUE
CUE(https://cuelang.org/)
是一种开源的数据验证语言和推理引擎,其根源在于逻辑编程。虽然该语言不是通用的编程语言,但它有很多应用,如数据验证、数据模板、配置、查询、代码生成甚至脚本。推理引擎可以用来验证代码中的数据,也可以将其作为代码生成流水线的一部分。
CUE
区别于同类语言的一个关键点是它将类型和值合并成一个单一的概念。在大多数语言中,类型和值是严格区分的,而CUE
则将它们排列在一个单一的层次结构(网格)中。这是一个非常强大的概念,它允许CUE
做很多花哨的事情。它还简化了事情。
CUE的应用
CUE
的设计确保了以任何顺序组合CUE
值总是得到相同的结果(它是关联的、互换的和幂等的)。这使得CUE
特别适合于从不同来源的CUE约束组合的情况。
数据验证
不同的部门或组可以各自定义自己的约束条件,应用于同一组数据。代码提取和生成
从多个来源(Go
代码、Protobuf
)提取CUE
定义,将它们组合成一个定义,并使用该定义生成另一种格式的定义(如OpenAPI
)。配置
可以将不同来源的值组合在一起,而不需要导入另一个。
值的排序也允许对整个配置进行集合包含分析。大多数验证系统只限于检查一个具体的值是否匹配一个模式,而CUE可以验证一个模式的任何实例是否也是另一个模式的实例(是否向后兼容?),或者计算一个新的模式,代表所有匹配两个其他模式的实例。
CUE的使用案例
CUE
可用于与数据相关的广泛的连续应用中。在不同的应用领域提供下列优势。
配置
管理基于文本的文件,以定义系统的理想状态。数据验证
验证基于文本或程序的数据。为数据定义一个详细的验证模式(手动或自动从数据中获取)。模式定义
定义模式来传达API
或标准。代码生成和提取
将CUE
约束转换为其他语言中的定义或从其他语言中转换出来。查询
查找符合特定标准的数据。脚本
定义和运行声明式脚本
CUE的安装
二进制文件安装
CUE
在页面https://github.com/cuelang/cue/releases
中下载对应的二进制文件MacOS
和Linux
使用brew
安装CUE
brew install cuelang/tap/cue
- 源码安装
CUE
下载并安装cue
命令行工具运行:
go get -u cuelang.org/go/cmd/cue
要同时下载API
和文档,请运行:
go get -u cuelang.org/go/cue
Kubernetes的CUE
CUE
并非特定于Kubernetes
。它可用于创作任何结构化配置。CloudBuild
或Circle CI
配置,Cloud Init
,CloudFormation
,Azure
资源管理器模板等。CUE
是用于编写配置的工具,而不是另一种序列化有线格式。
下面是一个deployment YAML
中的简单配置:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-kubernetes
spec:
replicas: 3
selector:
matchLabels:
app: hello-kubernetes
template:
metadata:
labels:
app: hello-kubernetes
spec:
containers:
- name: hello-kubernetes
image: paulbouwer/hello-kubernetes:1.8
ports:
- containerPort: 8080
运行下列命令:
$ cue import deployment.yaml
$ ls
deployment.cue deployment.yaml
查看deployment.cue
内容如下:
apiVersion: "apps/v1"
kind: "Deployment"
metadata name: "hello-kubernetes"
spec: {
replicas: 3
selector matchLabels app: "hello-kubernetes"
template: {
metadata labels app: "hello-kubernetes"
spec containers: [{
name: "hello-kubernetes"
image: "paulbouwer/hello-kubernetes:1.5"
ports: [{
containerPort: 8080
}]
}]
}
}
如上所述,CUE
是JSON
的超集。但是也有下列可用性的差异:
- 没有最外面的嵌套"{}"
- 结尾没有逗号
- 嵌套语句的单行格式,如
selector matchLabels app: "hello-kubernetes"
CUE模板
YAML
只是一种序列化格式。为了减少管理多个配置文件时的重复,需要经常在顶部使用模板工具。CUE
使数据成为该语言的一流部分。
package kubernetes
deployment : {
apiVersion: string
kind: "Deployment"
metadata name: Name
spec: {
replicas: *1 | int
selector matchLabels app: Name
template: {
metadata labels app: Name
spec containers: [{name: Name}]
}
}
}
deployment "hello-kubernetes": {
apiVersion: "apps/v1"
spec: {
replicas: 3
template spec containers: [{
image: "paulbouwer/hello-kubernetes:1.5"
ports: [{
containerPort: 8080
}]
}]
}
}
在这里,我们创建了一个deployment
可以重用的模板,然后使用它来定义一个名为的具体部署hello-kubernetes
。注意事项:
apiersionstring
在模板中指定为。如果省略或不是字符串,则CUE
配置的评估将失败replicas
指定为默认值1
或采用int
值- 部署的名称放置在名为的变量中,该变量
Name
随后用于填充元数据和标签
在上面这种简单的情况下,我们只有一个部署,这可能看起来有点多余。但是我们可以将模板重用于许多部署。这样就可以轻松地将属性注入所有类型,或者使某些属性成为必需的或有限的,甚至更多。编写YAML
时,该语言只能看到任意数据,使用CUE
可以引入语义,这意味着可以推理所用语言的配置。
我们可以评估稍微抽象一些的配置,并检查模板是否正常工作:
$ cue eval
{
deployment "hello-kubernetes": {
apiVersion: "apps/v1"
kind: "Deployment"
metadata name: "hello-kubernetes"
spec: {
replicas: 3
selector matchLabels app: "hello-kubernetes"
template: {
metadata labels app: "hello-kubernetes"
spec containers: [{
name: "hello-kubernetes"
image: "paulbouwer/hello-kubernetes:1.5"
ports: [{
containerPort: 8080
}]
}]
}
}
}
}
导出到JSON
如前所述,CUE
是一种创作工具。它不打算直接替换JSON
或YAML
或其他序列化格式。它支持导出到那些格式以供其他工具使用的概念。目前,CUE
仅支持导出到JSON
。
$ cue export
{
"deployment": {
"hello-kubernetes": {
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "hello-kubernetes"
},
"spec": {
"replicas": 3,
"selector": {
"matchLabels": {
"app": "hello-kubernetes"
}
},
"template": {
"metadata": {
"labels": {
"app": "hello-kubernetes"
}
},
"spec": {
"containers": [
{
"name": "hello-kubernetes",
"image": "paulbouwer/hello-kubernetes:1.5",
"ports": [
{
"containerPort": 8080
}
]
}
}
}
}
}
}
}
在这里使用一个简单的Kubernetes
配置文件展示了CUE
的基础知识。有机会接下来再介绍更多更完整的CUE
功能。
欢迎关注我的公众号“互动云原生”,原创技术文章第一时间推送。