Fork me on GitHub
Fork me on GitHub

Kubernetes资源清单定义

资源和对象

Kubernetes之上常用的资源,它把所有内容都抽象为资源,把资源实例化出来后称为对象。
Kubernetes核心资源:

  • workload: 工作负载型资源,运行应用程序,对外提供服务。
    Pod, ReplicaSet, Deployment, StatefulSet, DaemonSet, Job, Cronjob, …
  • 跟服务发现及均衡相关:
    Service, Ingress, …
  • 配置与存储相关:
    Volume, CSI:还支持容器存储接口来对接第三方存储卷, ConfigMap, Secret, DownwardAPI
  • 集群级的资源:上面提到的都是配置在名称空间级别的资源。只不过没指都是default名称空间的。而有些资源需要在集群级别定义。
    Namespace, Node, Role, ClusterRole, RoleBinding, ClusterRoleBinding
  • 元数据型资源:
    HPA:能够自动去调整其他资源的元数据信息。
    PodTemplate, LimitRange

资源清单示例

在上一篇博文中,我们使用了命令去创建了一些资源。在创建这些资源时,除了使用命令去创建,还可以使用配置清单来创建。举例看看配置清单是什么样子的:

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
[root@spark32 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
client-69fd89d767-95nqt 1/1 Running 1 2d15h
myapp-5bc569c47d-qq8lb 1/1 Running 0 2d18h
myapp-5bc569c47d-stvj9 1/1 Running 0 2d18h
myapp-5bc569c47d-tzlsf 1/1 Running 0 2d18h
nginx-deploy-55d8d67cf-wf28j 1/1 Running 0 2d19h
[root@spark32 ~]# kubectl get pod myapp-5bc569c47d-qq8lb -o yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2019-08-02T06:54:36Z"
generateName: myapp-5bc569c47d-
labels:
pod-template-hash: 5bc569c47d
run: myapp
name: myapp-5bc569c47d-qq8lb
namespace: default
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: myapp-5bc569c47d
uid: f241ea22-b4eb-11e9-9e1c-60a44c223099
resourceVersion: "13132088"
selfLink: /api/v1/namespaces/default/pods/myapp-5bc569c47d-qq8lb
uid: 64232e79-b4f2-11e9-9e1c-60a44c223099
spec:
containers:
- image: ikubernetes/myapp:v1
imagePullPolicy: IfNotPresent
name: myapp
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-wb7fl
readOnly: true
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: ubuntu31
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: default-token-wb7fl
secret:
defaultMode: 420
secretName: default-token-wb7fl
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2019-08-02T06:54:46Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2019-08-02T06:54:49Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2019-08-02T06:54:49Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2019-08-02T06:54:36Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://bebf87f526684a20413175bce9f9aa2382bd000ef5b9446c49e390d585e04db8
image: ikubernetes/myapp:v1
imageID: docker-pullable://ikubernetes/myapp@sha256:9c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513
lastState: {}
name: myapp
ready: true
restartCount: 0
state:
running:
startedAt: "2019-08-02T06:54:48Z"
hostIP: 172.16.206.31
phase: Running
podIP: 10.244.2.12
qosClass: BestEffort
startTime: "2019-08-02T06:54:46Z"

【说明】:
apiVersion: v1
指定该对象属于k8s的哪个api版本,或者叫api组。这叫api群组的名称和版本。我们给定apiversion时有两个部分组成,group/version。如果group省略,表示core,核心组,最根本的资源。

kind: Pod
资源类别,Pod、控制器、service都是资源。

metadata:
元数据。内部嵌套了很多二级字段,甚至三级字段来定义。

spec:
可以理解为“规格”。我们要去定义接下来要创建的资源对象应该具有什么样的特性,或者应该满足什么样的规范。比如说容器有几个,每个容器应该用什么镜像文件来创建。包括它的容忍度,能容忍哪些污点。这也是资源对象中一个最重要的字段,因为它正是用来定义我们所期望的资源应该拥有什么样的特性。而后靠控制器来确保它的特性能够被满足。

status:
spec用来让用户定义一个资源对象应该所处的目标状态。而status则是显示当前这个资源的当前状态。如果当前状态和目标状态不一样怎么办?应该以目标状态为准。k8s保证当前状态无限向目标状态靠近或转移从而能满足用户期望。因此从这个角度讲,status应该是只读的,因为会动态维护。而spec是用户定义的。

创建资源的方法

1.在定义资源时,apiserver仅接收JSON格式的资源定义;
之前通过kubectl run创建一个deployment的时候,run命令被自动把我们给的内容转成了JSON格式而已。但JSON格式写起来太重量级了,而yaml格式几乎没有冗余数据。人更容易理解和记忆的是yaml格式的。

2.提供yaml格式的配置清单
apiserver可自动将其转为JSON格式,而后在执行。JSON格式对于apiserver才是根本。

资源的配置清单详解

大部分资源的配置清单都有5个一级字段组成:

apiVersion: group/version

api版本。

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
# kubectl api-versions
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
apps/v1beta1
apps/v1beta2
authentication.k8s.io/v1
authentication.k8s.io/v1beta1
authorization.k8s.io/v1
authorization.k8s.io/v1beta1
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
batch/v1
batch/v1beta1
certificates.k8s.io/v1beta1
coordination.k8s.io/v1
coordination.k8s.io/v1beta1
events.k8s.io/v1beta1
extensions/v1beta1
networking.k8s.io/v1
networking.k8s.io/v1beta1
node.k8s.io/v1beta1
policy/v1beta1
rbac.authorization.k8s.io/v1
rbac.authorization.k8s.io/v1beta1
scheduling.k8s.io/v1
scheduling.k8s.io/v1beta1
storage.k8s.io/v1
storage.k8s.io/v1beta1
v1

资源所属群组,k8s把apiserver中所支持的api有多少种,分组来管理。
分组的好处是:如果不分组,假设将来要更新一个,牵一发而动全身。而现在分成组以后,如果某一组当中的改变了,我们只需要改这一个组就可以了,其他组不受影响,可以继续使用。另外,组还加了版本号,同一个群组的多个不同版本还可以并存。Pod是最核心的资源,所以属于核心群组v1。像控制器Deployment、ReplicaSet等属于应用程序管理的资源,属于群组apps/v1。在创建Deployment的时候,可以使用apps/v1,也可以使用apps/v1beta1,或者apps/v1beta2。如果某一组标记为beta,意味着属于公测版。不同的版本,对于同一个资源来讲,可支持的字段有可能是不一样的。

kind

资源类别

metadata

元数据

  • name,对象名称
  • namespace: 对象属于哪个名称空间的
  • labels:标签
  • annotation:资源注解
  • uid:系统自己生成的,不要自己去定义。自己去定义有可能冲突。
  • 每个资源的引用PATH:基于HTPP
    /api/GROUP/VERSION/namespaces/NAMESPACE/TYPE/NAME

spec

期望的状态。disired state。
不同的资源类型,spec中所需要嵌套的字段不尽相同。字段这么多,我们可能无法全部记下来,可以通过命令行来查看文档。比如查看Pod清单定义文档:

1
[root@spark32 ~]# kubectl explain pods


1
[root@spark32 ~]# kubectl explain pods.metadata


1
[root@spark32 ~]# kubectl explain pods.spec


1
[root@spark32 ~]# kubectl explain pods.spec.containers


status

资源当前状态,current state。
该字段由Kubernetes集群维护,用户不能定义和删除。

清单定义示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@spark32 ~]# mkdir manifests
[root@spark32 ~]# cd manifests/
[root@spark32 manifests]# vim 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"


【说明】:

  • containers的值是个对象列表,列表我们使用 [] 或者 - 来引导。
    容器名、容器镜像。一个pod内可以有多个容器。
  • 对于busybox这个镜像启动起来运行的命令是shell,启动起来一会就挂了,所以需要需要额外改个命令来运行,使用command。command是个列表,可以使用[],也可以使用 - 来引导。对于第一个镜像没有加command,表示运行镜像启动后默认的命令。

访问myapp服务:

1
2
3
4
5
6
7
8
9
10
[root@spark32 manifests]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
client-69fd89d767-95nqt 1/1 Running 1 2d16h 10.244.2.27 ubuntu31 <none> <none>
myapp-5bc569c47d-qq8lb 1/1 Running 0 2d19h 10.244.2.12 ubuntu31 <none> <none>
myapp-5bc569c47d-stvj9 1/1 Running 0 2d19h 10.244.2.13 ubuntu31 <none> <none>
myapp-5bc569c47d-tzlsf 1/1 Running 0 2d19h 10.244.1.9 spark17 <none> <none>
nginx-deploy-55d8d67cf-wf28j 1/1 Running 0 2d21h 10.244.1.5 spark17 <none> <none>
pod-demo 2/2 Running 0 12m 10.244.2.28 ubuntu31 <none> <none>
[root@spark32 manifests]# curl 10.244.2.28
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

查看日志:

进入Pod中的myapp容器:

删除这个Pod:

1
2
[root@spark32 manifests]# kubectl delete pod pod-demo
pod "pod-demo" deleted

1
2
3
4
5
6
7
8
9
10
11
12
[root@spark32 manifests]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
client-69fd89d767-95nqt 1/1 Running 1 2d17h
myapp-5bc569c47d-qq8lb 1/1 Running 0 2d20h
myapp-5bc569c47d-stvj9 1/1 Running 0 2d20h
myapp-5bc569c47d-tzlsf 1/1 Running 0 2d20h
nginx-deploy-55d8d67cf-wf28j 1/1 Running 0 2d21h
pod-demo 2/2 Terminating 0 19m
pod-demo 0/2 Terminating 0 19m
pod-demo 0/2 Terminating 0 19m
pod-demo 0/2 Terminating 0 19m
pod-demo 0/2 Terminating 0 19m

再次创建这个Pod:

1
2
[root@spark32 manifests]# kubectl create -f pod-demo.yaml
pod/pod-demo created

删除这个清单文件中定义的资源:

1
2
[root@spark32 manifests]# kubectl delete -f pod-demo.yaml
pod "pod-demo" deleted

这个文件里定义的资源Pod是“自主式Pod”,不受任何控制器控制的,这种Pod一删除就没了。不像控制器控制的Pod,哪怕删了,也会根据副本数量进行重新创建。

kubectl管理资源的方式

有三种方式:

  • 命令式
  • 刚刚上面演示的配置清单式
  • 第三种也是清单,但要使用另外的命令。和第二种方式的区别为:第二种叫命令式资源清单,第三种叫声明式资源清单。使用声明式,我们可以确保资源尽可能地像我们声明的状态改变,而且可以随时改变我们的声明,并随时应用。后面的博文中将介绍使用声明式方式创建资源。