本文将主要分享以下四方面的内容:
首先,我们来回顾一下 Kubernetes 的资源对象组成:主要包括了 Spec、Status 两部分。其中 Spec 部分用来描述期望的状态,Status 部分用来描述观测到的状态。
今天我们将为大家介绍 K8s 的另外一个部分,即元数据部分。该部分主要包括了用来识别资源的标签:Labels, 用来描述资源的注解:Annotations, 用来描述多个资源之间相互关系的 OwnerReference。这些元数据在 K8s 运行中有非常重要的作用。后续课程中将会反复讲到。
第一个元数据,也是最重要的一个元数据是:资源标签。资源标签是一种具有标识型的 Key:Value 元数据,这里展示了几个常见的标签。
前三个标签都打在了 Pod 对象上,分别标识了对应的应用环境、发布的成熟度和应用的版本。从应用标签的例子可以看到,标签的名字包括了一个域名的前缀,用来描述打标签的系统和工具, 最后一个标签打在 Node 对象上,还在域名前增加了版本的标识 beta 字符串。
标签主要用来筛选资源和组合资源,可以使用类似于 SQL 查询 select,来根据 Label 查询相关的资源。
[root@k8s-master ~]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-6799fc88d8-drb2s 1/1 Running 2 40d app=nginx,pod-template-hash=6799fc88d8
[root@k8s-master ~]# kubectl get svc --show-labels
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE LABELS
kubernetes ClusterIP 10.96.0.1 443/TCP 40d component=apiserver,provider=kubernetes
nginx NodePort 10.99.50.2 80:31332/TCP 40d app=nginx
[root@k8s-master ~]# kubectl get node --show-labels
NAME STATUS ROLES AGE VERSION LABELS
k8s-master Ready master 40d v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master,kubernetes.io/os=linux,node-role.kubernetes.io/master=
k8s-node1 Ready 40d v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
k8s-node2 Ready 40d v1.19.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node2,kubernetes.io/os=linux
最常见的 Selector 就是相等型 Selector。现在举一个简单的例子:
假设系统中有四个 Pod,每个 Pod 都有标识系统层级和环境的标签,我们通过 Tie:front 这个标签,可以匹配左边栏的 Pod,相等型 Selector 还可以包括多个相等条件,多个相等条件之间是逻辑”与“的关系。
在刚才的例子中,通过 Tie=front,Env=dev 的Selector,我们可以筛选出所有 Tie=front,而且 Env=dev 的 Pod,也就是下图中左上角的 Pod。另外一种 Selector 是集合型 Selector,在例子中,Selector 筛选所有环境是 test 或者 gray 的 Pod。
除了 in 的集合操作外,还有 notin 集合操作,比如 tie notin(front,back),将会筛选所有 tie 不是 front 且不是 back 的 Pod。另外,也可以根据是否存在某 lable 的筛选,如:Selector release,筛选所有带 release 标签的 Pod。集合型和相等型的 Selector,也可以用“,”来连接,同样的标识逻辑”与“的关系。
另外一种重要的元数据是:annotations。一般是系统或者工具用来存储资源的非标示性信息,可以用来扩展资源的 spec/status 的描述,这里给了几个 annotations 的例子:
我们当时讲到最后一个元数据叫做 Ownereference,所谓所有者,一般就是指集合类的资源,比如说 Pod 集合,就有 replicaset、statefulset,这个将在后序的课程中讲到。
集合类资源的控制器会创建对应的归属资源。比如:replicaset 控制器在操作中会创建 Pod,被创建 Pod 的 Ownereference 就指向了创建 Pod 的 replicaset,Ownereference 使得用户可以方便地查找一个创建资源的对象,另外,还可以用来实现级联删除的效果。
这里通过 kubectl 命令去连接我们 ACK 中已经创建好的一个 K8s 集群,然后来展示一下怎么查看和修改 K8s 对象中的元数据,主要就是 Pod 的一个标签、注解,还有对应的 Ownerference。
首先我们看一下集群里现在的配置情况:
(1)查看 Pod,现在没有任何的一个 Pod
kubectl get pods
(2)然后用事先准备好的一个 Pod 的 yaml,创建一个 Pod 出来;
kubectl apply -f pod1.yaml
kubectl apply -f pod2.yaml
(3)现在查看一下 Pod 打的标签,我们用 --show-labels 这个选项,可以看到这两个 Pod 都打上了一个部署环境和层级的标签;
kubectl get pods —show-labels
(4)我们也可以通过另外一种方式来查看具体的资源信息。首先查看 nginx1 第一个 Pod 的一个信息,用 -o yaml 的方式输出,可以看到这个 Pod 元数据里面包括了一个 lables 的字段,里面有两个 lable;
kubectl get pods nginx1 -o yaml | less
(5)现在再想一下,怎么样对 Pod 已有的 lable 进行修改?我们先把它的部署环境,从开发环境改成测试环境,然后指定 Pod 名字,在环境再加上它的一个值 test ,看一下能不能成功。 这里报了一个错误,可以看到,它其实是说现在这个 label 已经有值了
kubectl label pods nginx1 env=test
(6)如果想覆盖掉它的话,得额外再加上一个覆盖的选项。加上之后呢,我们应该可以看到这个打标已经成功了
kubectl label pods nginx1 env=test —overwrite
(7)我们再看一下现在集群的 lable 设置情况,首先可以看到 nginx1 的确已经加上了一个部署环境 test 标签
kubectl get pods —show-labels
(8)如果想要对 Pod 去掉一个标签,也是跟打标签一样的操作,但是 env 后就不是等号了。只加上 label 名字,后面不加等号,改成用减号表示去除 label 的 k:v
kubectl label pods nginx tie-
(10)可以看到这个 label,去标已经完全成功
kubectl get pods —show-labels
(10)下面来看一下配置的 label 值,的确能看到 nginx1 的这个 Pod 少了一个 tie=front 的标签。有了这个 Pod 标签之后,可以看一下怎样用 label Selector 进行匹配?首先 label Selector 是通过 -l 这个选项来进行指定的 ,指定的时候,先试一下用相等型的一个 label 来筛选,所以我们指定的是部署环境等于测试的一个 Pod,我们可以看到能够筛选出一台
kubectl get pods —show-labels -l env=test
(11)假如说有多个相等的条件需要指定的,实际上这是一个与的关系,假如说 env 再等于 dev,我们实际上是一个 Pod 都拿不到的
kubectl get pods —show-labels -l env=test,env=dev
(12)然后假如说 env=dev,但是 tie=front,我们能够匹配到第二个 Pod,也就是 nginx2
kubectl get pods —show-labels -l env=dev,tie=front
(13)我们还可以再试一下怎么样用集合型的 label Selector 来进行筛选。这一次我们还是想要匹配出所有部署环境是 test 或者是 dev 的一个 Pod,所以在这里加上一个引号,然后在括号里面指定所有部署环境的一个集合。这次能把两个创建的 Pod 都筛选出来
kubectl get pods —show-labels -l ’env in (dev,test)’
我们再试一下怎样对 Pod 增加一个注解,注解的话,跟打标是一样的操作,但是把 label 命令改成 annotate 命令;然后,一样指定类型和对应的名字。后面就不是加上 label 的 k:v 了,而是加上 annotation 的 k:v。这里我们可以指定一个任意的字符串,比如说加上空格、加上逗号都可以。
kubectl annotate pods nginx1 my-annotate=‘my annotate,ok’
然后,我们再看一下这个 Pod 的一些元数据,我们这边能够看到这个 Pod 的元数据里面 annotations,这是有一个 my-annotate 这个 Annotations;
kubectl get pods nging1 -o yaml | less
然后我们这里其实也能够看到有一个 kubectl apply 的时候,kubectl 工具增加了一个 annotation,这也是一个 json 串。
然后我们再演示一下看 Pod 的 Ownereference 是怎么出来的。原来的 Pod 都是直接通过创建 Pod 这个资源方式来创建的,这次换一种方式来创建:通过创建一个 ReplicaSet 对象来创建 Pod 。首先创建一个 ReplicaSet 对象,这个 ReplicaSet 对象可以具体查看一下
kubectl apply -f rs.yaml
kubectl get replicasets nginx-replicasets -o yaml |less
我们可以关注一下这个 ReplicaSet 里面 spec 里面,提到会创建两个 Pod,然后 selector 通过匹配部署环境是 product 生产环境的这个标签来进行匹配。所以我们可以看一下,现在集群中的 Pod 情况;
kubectl get pods
将会发现多了两个 Pod,仔细查看这两个 Pod,可以看到 ReplicaSet 创建出来的 Pod 有一个特点,即它会带有 Ownereference,然后 Ownereference 里面指向了是一个 replicasets 类型,名字就叫做 nginx-replicasets;