YAML是kubernetes世界里的标准工作语言,它有一个非常关键的特性“声明式”(Declarative),与其相对的有另一词“命令式”(Imperative)。
举例说明 假设要打车去高铁站
- 命令式:遇到的司机不熟悉路况,作为乘客的你需要不厌其烦的告诉司机该走哪条路、在哪个路口转向、在哪里出主路,停在哪个路口。虽然最后到达了目的地,但这一路上也费了不少口舌,发出来无数条的“命令”。很显然,这就属于“命令式”
- 声明式:遇到的司机经验丰富,哪里有拥堵、哪条路的红绿灯多、哪段路有临时管控、哪里可以抄小道,此时作为乘客的你再多嘴无疑会干扰他的正常驾驶,只要给他一个“声明”:我要去高铁站,接下来就可以舒舒服服地躺在后座上休息,顺利到达目的地了。很显然,这就属于“声明式”
kubernetes就是这样的一位熟练的司机,Master/Node 架构让它对整个集群的状态了如指掌,内部的众多组件和插件也能够自动监控管理应用。这时我们再用“命令式”跟它打交道就不太合适了,因为它知道的信息比我们更多更全面,不需要我们这个外行去指导它这个内行。
介绍到这里YAML就该上场了,它很适合在这样的场景下与kubernetes进行交互
什么是YAML
YAML官网地址https://yaml.org 访问 ,有对语言的规范的完整介绍。
YAML是JSON的超集,支持整数、浮点数、布尔、字符串、数组和对象等数据类型。
和JSON比起来,YAML的语法更简单,形式也更清晰紧凑,比如:
- 使用空白与缩进表示层次(有点类似 Python),可以不使用花括号和方括号。
- 可以使用 # 书写注释,比起 JSON 是很大的改进。
- 对象(字典)的格式与 JSON 基本相同,但 Key 不需要使用双引号。
- 数组(列表)是使用 - 开头的清单形式(有点类似 MarkDown)。
- 表示对象的 : 和表示数组的 - 后面都必须要有空格。
- 可以使用 --- 在一个文件里分隔多个 YAML 对象。
YAML的简单示例
YAML数组
列出了三种操作系统
# YAML数组(列表)
OS:
- linux
- macOS
- Windows
对应的json如下:
{
"OS": ["linux", "macOS", "Windows"]
}
YAML对象
声明了1个Master节点,3个Worker节点
# YAML对象(字典)
Kubernetes:
master: 1
worker: 3
对应的json如下:
{
"Kubernetes": {
"master": 1,
"worker": 3
}
}
YAML复杂示例
# 复杂的例子,组合数组和对象
Kubernetes:
master:
- apiserver: running
- etcd: running
node:
- kubelet: running
- kube-proxy: down
- container-runtime: [docker, containerd, cri-o]
什么是API对象
YAML语言只相当于“语法”,要与kubernetes对话,我们还必须有足够的“词汇”来表示“语义”。
kubernetes在理论层面抽象出很多个概念,用来描述系统的管理运维工作,这些概念就叫做“API 对象”。
比如kubernetes组件apiserver,它正式来源与此。
apiserver是kubernetes 系统的唯一入口,外部用户和内部组件都必须和它通信,而它采用了 HTTP 协议的 URL 资源理念,API 风格也用 RESTful 的 GET/POST/DELETE 等等,所以,这些概念很自然地就被称为是“API 对象”了。
那都有哪些API对象呢?
kubectl api-resources来查看当前 Kubernetes 版本支持的所有对象
kubectl api-resources
输出的“NAME”一栏,就是对象的名字,比如 ConfigMap、Pod、Service 等等,第二栏“SHORTNAMES”则是这种资源的简写,在我们使用 kubectl 命令的时候很有用,可以少敲几次键盘,比如 Pod 可以简写成 po,Service 可以简写成svc
如何描述API对象
比如kubectl run ngx --image=nginx:alpine改成“声明式”:
apiVersion: v1
kind: Pod
metadata:
name: ngx-pod
labels:
env: demo
spec:
containers:
- image: nginx:alpine
name: ngx
ports:
- containerPort: 80
看完上面的这段描述,基本上能够知道是一个Pod,要使用nginx:alpine镜像创建一个容器,开放端口80,其他的部分,就是kubernetes对API对象强制的格式要求了。
可以和http的报文格式进行类比,API对象的描述分成“header”和“body”两部分。
“header”包含的是 API 对象的基本信息,有三个字段:apiVersion、kind、metadata
- apiVersion 表示操作这种资源的 API 版本号,由于kubernetes的迭代速度很快,不同的版本创建的对象会有差异,为了区分这些版本就需要使用apiVersion这个字段,比如 v1、v1alpha1、v1beta1等等
- kind表示资源对象的类型,这个应该很好理解,比如Pod、Node、Job、Service 等等。
- metadata这个字段顾名思义,表示的是资源的一些“元信息”,也就是用来标记对象,方便kubernetes管理的一些信息
“body”部分则会与对象特定相关,每种对象会有不同的规格定义,在 YAML 里就表现为 spec 字段(即 specification),表示我们对对象的“期望状态”(desired status)
比如pod的spec:一个 containers 数组,里面的每个元素又是一个对象,指定了名字、镜像、端口等信息
spec:
containers:
- image: nginx:alpine
name: ngx
ports:
- containerPort: 80
最后使用kubectl apply、kubectl delete,再加上参数 -f,就可以使用这个YAML文件,创建或者删除对象了
kubectl apply -f ngx-pod.yml
kubectl delete -f ngx-pod.yml
如何编写 YAML
可以访问官方文档 (https://kubernetes.io/docs/reference/kubernetes-api访问)进行查阅,API对象的所有字段都可以在里面找到。不过官方文档内容太多太细,查阅起来有些费劲。
推荐三个小技巧可以很方便的找到对应的说明。
- 技巧一
kubectl api-resources命令,它会显示出资源对象相应的 API 版本和类型,比如 Pod 的版本是“v1”,Ingress 的版本是networking.k8s.io/v1,照着它写绝对不会错。 - 技巧二
kubectl explain命令,它相当于是 Kubernetes 自带的 API 文档,会给出对象字段的详细说明,这样我们就不必去网上查找了。比如想要看 Pod 里的字段该怎么写,就可以这样:
kubectl explain pod
kubectl explain pod.metadata
kubectl explain pod.spec
kubectl explain pod.spec.containers
- 技巧三 kubectl的两个特殊参数 --dry-run=client 和 -o yaml,前者是空运行,后者是生成 YAML 格式,结合起来使用就会让 kubectl 不会有实际的创建动作,而只生成 YAML 文件。
kubectl run ngx --image=nginx:alpine --dry-run=client -o yaml
会生成一个绝对正确的YAML文件
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: ngx
name: ngx
spec:
containers:
- image: nginx:alpine
name: ngx
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
还可以把--dry-run=client -o yaml定义为shell变量,这样会更加方便,比如使用$out代替:
export out="--dry-run=client -o yaml"
kubectl run ngx --image=nginx:alpine $out
希望本篇文章对你有所帮助,谢谢。