06-资源清单定义格式解释

Catalogue
  1. 1. 配置格式
  2. 2. pod定义示例
  3. 3. 标签
  4. 4. 标签选择器
  5. 5. 节点标签选择器
  6. 6. annotations
  7. 7. 参考资料

在 Kubernetes 系统中,Kubernetes 资源对象是持久化的条目。Kubernetes 使用这些条目去表示整个集群的状态。通过创建对象,可以有效地告知 Kubernetes 系统,所需要的集群工作负载看起来是什么样子的,这就是 Kubernetes 集群的 期望状态。一旦创建对象,Kubernetes 系统将持续工作以确保对象存在。

每个 Kubernetes 对象包含两个嵌套的对象字段,它们负责管理对象的配置:对象 spec 和 对象 statusspec 必须提供,它描述了对象的 期望状态—— 希望对象所具有的特征。status 描述了对象的 实际状态,它是由 Kubernetes 系统提供和更新。在任何时刻,Kubernetes 控制平面一直处于活跃状态,管理着对象的实际状态以与我们所期望的状态相匹配。

例如,Kubernetes Deployment 对象能够表示运行在集群中的应用。当创建 Deployment 时,可能需要设置 Deployment 的 spec,以指定该应用需要有 3 个副本在运行。Kubernetes 系统读取 Deployment spec,启动我们所期望的该应用的 3 个实例 —— 更新状态以与 spec 相匹配。如果那些实例中有失败的(一种状态变更),Kubernetes 系统通过修正来响应 spec 和状态之间的不一致,这种情况,会启动一个新的实例来替换。

配置格式

apiserver在定义资源时,仅接收JSON格式的资源定义,我们一般提供yaml格式的配置清单,apiservere可自动将其转为json格式,而后再提交,大部分资源的配置清单格式都由5个一级字段组成:

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: group/version  指明api资源属于哪个群组和版本,同一个组可以有多个版本
kind: 标记创建的资源类型,如Deployment,StatefulSet,DaemonSet,Job,Cronjob等
metadata:元数据,主要提供以下字段
name:同一类别下的name是唯一的
namespace:对应的对象属于哪个名称空间
labels:标签,每一个资源都可以有标签,标签是一种键值数据
annotations:资源注解
每个的资源引用方式(selflink):
/api/GROUP/VERSION/namespace/NAMESPACE/TYPE/NAME

spec: 定义目标资源的期望状态(disired state),资源对象中最重要的字段
status: 显示资源的当前状态(current state),本字段由kubernetes进行维护

K8s存在内嵌的格式说明,可以使用kubectl explain 进行查看,如查看Pod这个资源的定义:kubectl explain pods,从结果可以看到apiVersion,kind等定义的键值都是<string>,而metadata和spec看到是一个<Object>,当看到存在<Object>的提示,说明该字段可以存在多个二级字段,那么可以使用如下命令继续查看二级字段的定义方式:kubectl explain pods.spec

二级字段下,每一种字段都有对应的键值类型,常用类型大致如下:

  • <[]string>:表示是一个字串列表,也就是字串类型的数组
  • <Object>:表示是可以嵌套的字段
  • <map[string]string>:表示是一个由键值组成映射
  • <[]Object>:表示是一个对象列表
  • <[]Object> -required-:required表示该字段是一个必选的字段

pod定义示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: default
labels:
app: myapp
tier: frontend
spec:
containers:
- name:myapp
image: ikubernetes/myapp:v1
- name: busybox
image: busybox:latest
command:
- "/bin/sh"
- "-c"
- "sleep 3600"
  • Pod资源下spec的containers必需字段解析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@k8s-master ~]# kubectl explain pods.spec.containers

name <string> -required- # containers 的名字,必须的
image <string> # 镜像地址
imagePullPolicy <string> # 如果标签是latest 就是Always(总是下载镜像) IfNotPresent(先看本地是否有此镜像,如果没有就下载) Never (就是使用本地镜像)

ports <[]Object> #是个对象列表 可以暴露多个端口 可以对每个端口的属性定义 例如:(名称(可后期调用)端口号 协议 暴露在的地址上) 暴露端口只是提供额外信息的,不能限制系统是否真的暴露

   - containerPort 容器端口
    hostIP 主机地址(基本不会使用)
    hostPort 节点端口
    name 名称
    protocol (默认是TCP)

args <[]string> 传递参数给command 相当于docker中的CMD
command <[]string> 相当于docker中的ENTRYPOINT
  • 关于command和args

如果Pod不提供commandargs使用Container,则使用Docker镜像中的cmd或者ENTRYPOINT。

如果Pod提供command但不提供args,则仅使用提供 command的。将忽略Docker镜像中定义EntryPoint和Cmd。

如果Pod中仅提供args,则args将作为参数提供给Docker镜像中EntryPoint。

如果提供了commandargs,则Docker镜像中的ENTRYPOINT和CMD都将不会生效,Pod中的args将作为参数给command运行

标签

key=value

  • key:只能使用 字母 数字 _ - . (只能以字母数字开头,不能超过63给字符)
  • value: 可以为空 只能使用 字母 数字开头
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@k8s-master mainfests]# kubectl get pods --show-labels  #查看pod标签
NAME READY STATUS RESTARTS AGE LABELS
pod-demo 2/2 Running 0 25s app=myapp,tier=frontend

[root@k8s-master mainfests]# kubectl get pods -l app  #过滤包含app的标签
NAME READY STATUS RESTARTS AGE
pod-demo 2/2 Running 0 1m
[root@k8s-master mainfests]# kubectl get pods -L app
NAME READY STATUS RESTARTS AGE APP
pod-demo 2/2 Running 0 1m myapp

[root@k8s-master mainfests]# kubectl label pods pod-demo release=canary  #给pod-demo打上标签
pod/pod-demo labeled
[root@k8s-master mainfests]# kubectl get pods -l app --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-demo 2/2 Running 0 1m app=myapp,release=canary,tier=frontend

[root@k8s-master mainfests]# kubectl label pods pod-demo release=stable --overwrite  #修改标签
pod/pod-demo labeled
[root@k8s-master mainfests]# kubectl get pods -l release
NAME READY STATUS RESTARTS AGE
pod-demo 2/2 Running 0 2m
[root@k8s-master mainfests]# kubectl get pods -l release,app
NAME READY STATUS RESTARTS AGE
pod-demo 2/2 Running 0 2m

标签选择器

  • 等值关系标签选择器:=, == , != (kubectl get pods -l app=test,app=dev)
  • 集合关系标签选择器: KEY in (v1,v2,v3), KEY notin (v1,v2,v3) !KEY (kubectl get pods -l “app in (test,dev)”)

许多资源支持内嵌字段

  • matchLabels: 直接给定建值
  • matchExpressions: 基于给定的表达式来定义使用标签选择器,{key:”KEY”,operator:”OPERATOR”,values:[V1,V2,….]}
  • 操作符: in notin:Values字段的值必须是非空列表 Exists NotExists: Values字段的值必须是空列表

节点标签选择器

1
2
3
4
5
6
7
8
9
10
11
[root@k8s-master mainfests]# kubectl explain pod.spec
nodeName <string>
NodeName is a request to schedule this pod onto a specific node. If it is
non-empty, the scheduler simply schedules this pod onto that node, assuming
that it fits resource requirements.

nodeSelector <map[string]string>
NodeSelector is a selector which must be true for the pod to fit on a node.
Selector which must match a node's labels for the pod to be scheduled on
that node. More info:
https://kubernetes.io/docs/concepts/configuration/assign-pod-node/

nodeSelector可以限定pod创建在哪个节点上,举个例子,给节点k8s-node01打上标签disktype=ssd,让pod-demo指定创建在k8s-node01上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
(1)给k8s-node01节点打标签
[root@k8s-master mainfests]# kubectl label nodes k8s-node01 disktype=ssd
node/k8s-node01 labeled

[root@k8s-master mainfests]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8s-master Ready master 10d v1.11.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=k8s-master,node-role.kubernetes.io/master=
k8s-node01 Ready <none> 10d v1.11.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/hostname=k8s-node01
k8s-node02 Ready <none> 9d v1.11.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=k8s-node02

(2)修改yaml文件,增加标签选择器
[root@k8s-master mainfests]# cat pod-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-demo
namespace: default
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
- name: busybox
image: busybox:latest
command:
- "/bin/sh"
- "-c"
- "sleep 3600"
nodeSeletor:
disktype: ssd

(3)重新创建pod-demo,可以看到固定调度在k8s-node01节点上
[root@k8s-master mainfests]# kubectl delete -f pod-demo.yaml
pod "pod-demo" deleted

[root@k8s-master mainfests]# kubectl create -f pod-demo.yaml
pod/pod-demo created
[root@k8s-master mainfests]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
pod-demo 2/2 Running 0 20s 10.244.1.13 k8s-node01
[root@k8s-master mainfests]# kubectl describe pod pod-demo
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 42s default-scheduler Successfully assigned default/pod-demo to k8s-node01
......

annotations

与label不同的地方在于,annotations不能用于挑选资源对象,仅用于为对象提供”元数据”,没有键值长度限制。

类似于Java的注解,即当资源对象添加了某些注解后,就具有了某种能力,前提是有实现支解释支持这些注解,也就是要赋予这些注解相应能力。

参考资料