0x00 前言
上一篇 已经介绍了jsonnet这个语法的一般用法, 学习之后就来体验一下它的使用场景:
我们先写好一些常用的部署配置模板, 比如Deployment, Service 等.
然后在需要临时部署的时候 , 只需要写最小化代码, 完成配置文件的生成,验证,部署.
0x01 相关工具
-
jsonnet
: 用于解析jsonnet源码至json文档, 安装方式:brew install jsonnet
-
gojsontoyaml
: json格式向yaml格式转换go install github.com/brancz/gojsontoyaml@latest
-
kubeval
: 验证生成的yaml 是否是合法的k8s部署文件, 安装:brew tap instrumenta/instrumenta && brew install kubeval
-
kubecfg
: 支持jsonnet文件的yaml展示, 以及与k8s集群的交互, 详见这里 安装:brew install kubecfg
-
开发环境
: 使用VSCode, 加上插件 Jsonnet NG就可以高亮, 格式化, 错误提示等.
0x02 模板文件编写
先编写两个模板文件
deploy-base.jsonnet
{
name:: error 'name is required',
container:: error 'container is required',
apiVersion: 'apps/v1',
kind: 'Deployment',
metadata: {
name: $.name,
labels: { app: $.name },
},
spec: {
selector: { matchLabels: $.metadata.labels },
template: {
metadata: { labels: $.metadata.labels },
spec: {
containers: [
$.container { name: $.name },
],
},
},
},
}
service-base.jsonnet
{
name:: error 'name is required',
namespace:: error 'namespace is required',
# 定义默认值,外部可以覆盖
port:: {
port: 8080,
targetPort: 8080,
},
apiVersion: 'v1',
kind: 'Service',
metadata: {
name: $.name,
namespace: $.namespace,
},
spec: {
selector: { app: $.name },
ports: [
$.port,
],
type: 'ClusterIP',
},
}
先来写一个部署文件:
my-nginx.jsonnet
local deploy = import 'deploy-base.jsonnet';
deploy {
name: 'my-nginx',
container: {
image: 'nginx:1.12',
},
}
我们看到部署文件就比较简单, 只需提供最基础参数完成配置.
接下来看看, 如何使用上面的工具, 进行格式转换/部署.
jsonnet 作用是翻译成json格式, 此时, 这个json文件也是可以被kubectl 提交部署的.
但是, 一般我们还是习惯了使用 yaml 格式. 先看下图效果:
![](https://img.haomeiwen.com/i3004399/7e1b5fbb71992e1c.png)
当然, 这时候, 如果这个yaml 没有问题的话, 我们可以直接在后面 , 再跟一个部署指令就好:
jsonnet my-nginx.jsonnet | gojsontoyaml | kubectl apply -f -
但是, 我们还是希望提交前先验证一下:
![](https://img.haomeiwen.com/i3004399/11c35b498c48e306.png)
接下来, 再写一个
Service
服务试一下:
local service = import 'service-base.jsonnet';
service {
name: 'my-nginx',
namespace: 'dev',
}
执行转换: jsonnet demo-svc.jsonnet | gojsontoyaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx
namespace: dev
spec:
ports:
- port: 8080
targetPort: 8080
selector:
app: my-nginx
type: ClusterIP
问题不大.
到这里, 似乎可以结束了.
但是, 我们发现, 每一个部署, 都要单独写一个文件, 是不是有点不够优雅?
要是能把 Deployment, Service 这些写在一个文件里, 应该真的很香.
解决方法, 也是参考了 这里, 关于 YAML Stream Output
的描述.
我们把两个文件结合后, 效果如下:
local deploy = import 'deploy-base.jsonnet';
local service = import 'service-base.jsonnet';
local
a = deploy {
name: 'my-nginx',
container: {
image: 'nginx:1.12',
},
},
b = service {
name: 'my-nginx',
namespace: 'dev',
};
[a, b]
此时, 解析的方式稍有不同, 需要以 yaml 流的方法进行解析:
jsonnet -y my-service.jsonnet
得到结果:
---
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"labels": {
"app": "my-nginx"
},
"name": "my-nginx"
},
"spec": {
"selector": {
"matchLabels": {
"app": "my-nginx"
}
},
"template": {
"metadata": {
"labels": {
"app": "my-nginx"
}
},
"spec": {
"containers": [
{
"image": "nginx:1.12",
"name": "my-nginx"
}
]
}
}
}
}
---
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"name": "my-nginx",
"namespace": "dev"
},
"spec": {
"ports": [
{
"port": 8080,
"targetPort": 8080
}
],
"selector": {
"app": "my-nginx"
},
"type": "ClusterIP"
}
}
...
这里拿 gojsontoyaml
去转换, 只能拿到一个yaml对象:jsonnet -y my-service.jsonnet | gojsontoyaml
, 这个就有点拉垮了 - -!
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: my-nginx
name: my-nginx
spec:
selector:
matchLabels:
app: my-nginx
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- image: nginx:1.12
name: my-nginx
但是不影响我们进行验证可用性, 和部署.
![](https://img.haomeiwen.com/i3004399/5653ed014e65bbad.png)
是不是到这里就可以结束了?
不不不, 是时候请出 kubecfg
了.
来, 我们直接用kubecfg 查看一下jsonnet的yaml格式:kubecfg show my-service.jsonnet
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: my-nginx
name: my-nginx
spec:
selector:
matchLabels:
app: my-nginx
template:
metadata:
labels:
app: my-nginx
spec:
containers:
- image: nginx:1.12
name: my-nginx
---
apiVersion: v1
kind: Service
metadata:
name: my-nginx
namespace: dev
spec:
ports:
- port: 8080
targetPort: 8080
selector:
app: my-nginx
type: ClusterIP
还可以进行和线上的对比和部署更新:
kubecfg diff my-service.jsonnet
kubecfg update my-service.jsonnet
0x03 总结
我们已经有了Kustomize
这样的模板化工具, 还需要 jsonnet
么?
我的答案是需要的, 特别是在临时部署, 比如只需要增加一个Service 之类的场景.
只需要打开VSCode
, 新加一个svc.jsonnet , 再加一个命令行, 就可以搞定.
另一个总结: kubectl
支持 json
, yaml
格式的部署文件, 以 -f
参数指定; 同时以 -k
的参数 支持kustomize
文件.
但是 kubectl
目前不支持jsonnet
格式,有两种方案:
- 直接使用
kubecfg
进行维护 - 通过格式转换工具, 拿到 yaml 文件后, 再通过
kubectl
进行部署.
网友评论