在前面的学习中,我们学到了 Deployment 部署,以及副本数(ReplicaSet),但是 Pod 部署到哪个 Worker 节点是随机的,即使有 3个 Woker 和 3个 Pod 副本,不一定每个 Node 刚刚好运行一个 Pod,也可能其中一个 Node 运行着三个副本。当然使用 Daemont 可以保证每个 Node 平均运行这种一个 Pod 副本。但是有的机器内存大,我想尽量将 Redis Pod 调度到此节点;而有的服务器磁盘容量大,我想尽可能将日志服务等调度到这些节点,那么该如何处理呢?为什么 master 不会部署我们创建的 Pod 呢?

在本篇我们将探究 Kubernetes 中的 DaemonSet、容忍度、亲和性、Label、选择器等概念,以便控制 Pod 的调度。

本文为作者的 Kubernetes 系列电子书的一部分,电子书已经开源,欢迎关注,电子书浏览地址:

https://k8s.whuanle.cn【适合国内访问】

https://ek8s.whuanle.cn 【gitbook】

标签和选择器

标签

标签主要是用于表示对用户有意义的对象的属性标识。

标签(Label)是附加到 Kubernetes 对象上的键值对,在对象描述信息中以 Labels 字段保存,例如 Pod 可通过 kubectl describe pods 查询,可以看到每个 Pod 都带有 Labels: app=...

... ...
Labels:       app=nginxpod-template-hash=85b45874d9
... ...

[Info] 提示

每个 Pod 都有 app 标签,表示 Pod 模板的名称,app 标签的值跟 Pod 模板名称一致。

当我们创建 Deployment 时,如果没有指定 Pod 的 app 标签值,那么一般跟 Deployment 名称一致。如 kubectl create deployment nginx --image=nginx:latest 创建的 Pod,其 app 标签值就是 nginx。

Deployment 、ReplicaSet 等都是通过 Pod 的 app 标签识别 Pod 是不是属于1自己管控的。

在 kubectl get 后面加上 --show-labels 可以快速筛选获得对象的 Label :

kubectl get pods --show-labels
NAME                     READY   STATUS    RESTARTS   AGE     LABELS
nginx-55495b586f-4hlzm   1/1     Running   0          4h16m   app=nginx,pod-template-hash=55495b586f
nginx-55495b586f-5m985   1/1     Running   0          4h16m   app=nginx,pod-template-hash=55495b586f
nginx-55495b586f-cs4zh   1/1     Running   0          4h16m   app=nginx,pod-template-hash=55495b586f
... ...

在对象的 YAML 文件中,metadata.label 存储了这个对象的标签元数据。

如果用 JSON 表示附加到 metadata 的 label:

"metadata": {"labels": {"key1" : "value1","key2" : "value2"}
}

如果用 YAML 表示附加到 metadata 的 label

metadata:labels:key1: "value1"key2: "value2"

使用 kubectl get pod {名称} -o yaml 查询,或者使用 kubectl edit pod {名称} 查看修改 Pod 的 标签。

在 Deployment 中,selector 字段设置了如何查找属于此对象的 Pod。

selector:matchLabels:app: nginx

Label 可以在多个地方使用,例如在 Node 上添加 Label,标识此 Node;而在 NodeSelector 里使用,可以选择合适的 Node 运行 Pod;在 metadata 中使用,可以对元数据加以描述。在 metadata 中添加的 Label,可以在命令查询时做筛选。

设置 Label

我们也可以手动给一个 Node 或者别的对象 添加标签。

kubectl label nodes <node-name> <label-key>=<label-value>
kubectl label pod {pod名称} <node-name> <label-key>=<label-value>

例如我们给一个 Pod 设置一个 disksize,表示 Pod 需要很大的硬盘。

kubectl label pod nginx-55495b586f-4hlzm disksize=big

如果要删除一个标签,只需要在标签名字后面加上 - 。

kubectl label pod nginx-55495b586f-4hlzm disksize-

如果标签已经存在,需要覆盖:

kubectl label pod nginx-55495b586f-4hlzm disksize=big --overwrite

在 kube-system 命名空间中,运行着 Kubernetes 的核心组件,我们可以查看此命名空间中所有组件的 Label。

kubectl get nodes --namespace=kube-system --show-labels
beta.kubernetes.io/arch=amd64,
beta.kubernetes.io/os=linux,
kubernetes.io/arch=amd64,
... ...

节点选择器

假如有个 Pod 需要很大的存储空间,而集群中的不同机器的硬盘容量都不同,我们希望 Pod 在硬盘很大的服务器上部署,我们可以通过给节点设置标签,然后在 Pod 的 YAML 文件中加上选择器,让 Pod 自动查找这类容量大的节点,并部署。

获取集群中的所有节点的 Label:

kubectl get nodes --show-labels
root@master:~# kubectl get nodes --show-labels
NAME     STATUS   ROLES                  AGE   VERSION   LABELS
master   Ready    control-plane,master   47h   v1.22.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
slave1   Ready    <none>                 47h   v1.22.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=slave1,kubernetes.io/os=linux

我们的节点名称不一样,读者按照实际名称修改后面的命令。

给节点加上标签:

kubectl label node instance-2 disksize=big

然后我们在编写 yaml 文件时,希望这个 pod 在容量大的 Node 上运行,可以这样写:

nodeSelector:disksize=big

下面我们来练习一下,先删除以前的 Deployment:kubectl delete deployment nginx

然后我们使用 YAML 创建一个 Deployment,保存下面 YAML 到 nginx.yaml 文件:

apiVersion: apps/v1
kind: Deployment
metadata:name: nginx
spec:selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- image: nginx:latestname: nginxnodeSelector:disksize: "big"

执行 kubectl apply -f nginx.yaml ,部署 Pod。

上面的例子由于是 Deployment 的,selector 和别的字段是必填的,所以看起来内容比较多,但是这里核心是 nodeSelector

我们需要使用节点选择器时,在 spec 下面增加 nodeSelector,其位置如下 YAML 所示:

spec:containers:- image: nginx:latestname: nginxnodeSelector:disksize: "big"

顺便聊一下官方的一个例子,设置 Node 的 Label,表示硬盘是 ssd。

kubectl label nodes node-1 disktype=ssd

在 yaml 文件的节点选择器中,添加选择。

spec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentnodeSelector:disktype: ssd

使用 Pod 选择节点:

apiVersion: v1
kind: Pod
metadata:name: nginxlabels:env: test
spec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentnodeSelector:disktype: ssd

命令式标签选择

在前面,我们学习了 nodeSelector ,可以帮助我们选择合适的 Node 运行 Pod,实际上 Kubernets 的标签选择是丰富多样的,例如:

nodeSelector:disktype: ssddisksize: big

上面的例子表示节点选择器是等值选择,表达式是 disktype=ssd && disksize=big,节点需要具备这两个 Label (key和value都要符合)。

我们也可以使用类似方式筛选符合条件的 Pod。

查询 Pod 所有的 Label:

kubectl get pods --show-labels

查找符合条件的 pod(参考 LABELS 字段,可以根据里面的标签选择):

kubectl get pods -l app=nginx
kubectl get pods -l app!=nginx

列出不包含某个标签的 Pod:

kubectl get pods -l '!env'
kubectl get pods -l '!app'

获取同时包含两个标签的 Pod:

kubectl get pods -l app,env

标签选择有等值和集合两种,其中等值选择有 ===!= 三种符号,= 和 == 无任何区别,所以实际只有 等于 、不等于 两种选择情况。

在多个需求(多个label)的情况下,可以使用 && 运算符,表示需要同时符合多个条件,但是选择器不存在 || 这种逻辑或运算符。

查看符合两个条件的 节点:

kubectl get nodes -l disktype=ssd,disksize!=big
# 多个条件使用 逗号","" 隔开,而不是 "&&"。

注意,多条件使用 , 隔开,而不是 &&,不能写成 disktype=ssd && disksize!=big

对于集合选择方式,支持三种操作符:innotin 和 exists。不过别理解成是从集合中选择,下面举个例子。

假如有三个 Node,其 disksize 有 big、medium、small 三种类型。

NAME        LABELS
node1      disksize=big
node2      disksize=medium
node3      disksize=small

我们要部署一个 pod,在 big、medium 中都可以运行,则可以写成

kubectl get nodes -l disksize in (big,medium)
# ... -l disksize in (big,medium)
kubectl get nodes -l disksize notin (small)
# ... -l disksize notin (small)
# 不在 small 中运行

而 exists 则跟 != 类似,但是 exists 表示只要存在这个 label 即可,而不论其设置了是什么值。

kubectl get nodes -l exists disksize
# -l exists disksize
# 等同 -l disksize in (big,medium,small)

我们也可以使用 '' 把选择表达式包起来。

kubectl get pods -l 'app=nginx'

目前提到的标签选择,主要是命令式选择,比较容易使用,而且支持的选择方式比较多;但是写进 YAML 或 JSON 中的选择器,则编写比较复杂,而且不支持所有的运算符。

selector

前面已经提到了 YAML 的 nodeSelector 和 命令式的选择,这里我们介绍 YAML 的 selector

在 Deployment 的 YAML 中,有这样的内容:

spec:selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginx

由 Deployment 部署的每个 Pod 的名称都不同(随机生成),所以不可能以 Pod 名称作为表示,何况 Pod 只是临时性的,所以会为每个 Pod 加上一个相同的 label,表示它们都是同一个 Deployment 创建的。

YAML 文件配置示例:

template:metadata:labels:app: nginx

其中 spec.template 是定义所有 Pod 的模板,template.metadata 可以为所有 Pod 设置一些元数据,例如 labels,对于 Deployment 等控制器,设置标签是必不可少的。

接下来是 spec.selectorselector 字段定义 Deployment 如何查找要管理的 Pods。spec.selector 有个 matchLabels 字段,每个 Deployment 都要配置 matchLabelsmatchLabels 里面的标签是集合运算的 in,Pod 只需要包含这些标签,就会被此 Deployment 管理。

在之前的创建的 Deployment(nginx) ,其 Pod 都会带上 app=nginx 的标签,我们可以在创建 Pod 之前,设置 Pod 的标签。Deployment 的 YAML 文件如下:

apiVersion: apps/v1
kind: Deployment
metadata:name: nginx
spec:selector:matchLabels:app: nginx666template:metadata:labels:app: nginx666type: testspec:containers:- image: nginx:latestname: nginx

查询创建的 Pod:

NAME                     READY   STATUS    RESTARTS   AGE   LABELS
nginx-64b465ddc9-8t9c8   1/1     Running   0          23s   app=nginx666,pod-template-hash=64b465ddc9,type=test

同样,当我们创建 Service 或者使用 ReplicationController 时,也可以使用标签选择合适的 Pod。

回忆一下,我们之前已经学习过怎么创建 Service,示例命令:

kubectl expose deployment xxx ...

命令式的选择很简单,加上 deployment xxx 即可。对于 YAML ,我们可以使用 seletcor 选择器,表示该 Service 在什么对象上起效。

假如我们已经部署了 nginx,那么查询 kubectl get pods --show-labels 时,其 Pod 的 LABELS 会有 app=nginx,那么我们可以这样选择:

selector:app: nginx

使用 Service 时,要绑定具体的 Pod,完整的 YAML 示例如下:

apiVersion: v1
kind: Service
metadata:name: my-service
spec:type: LoadBalancerselector:app: nginxports:- protocol: TCPport: 80targetPort: 6666
status:loadBalancer:ingress:- ip: 192.0.2.127

选择器的复合运算

nodeSelector、selector 还支持以下选择方式 matchLabelsmatchExpressions,在前面我们已经了解 Deployment 有 matchLabels ,接下来我们继续深入了解。

matchExpressions 是 Pod 选择算符需求的列表。有效的运算符包括 InNotInExists 和 DoesNotExist。来自 matchLabels 和 matchExpressions 的所有要求都按逻辑与的关系组合到一起 -- 它们必须都满足才能匹配。

在 In 和 NotIn 标签中,设置的值必须是非空的。

Exists、DoesNotExist 表示某个标签是否存在;

In、NotIn 表示 A 集合中的标签是否都在 B 集合中。

matchExpressions 的表达比较复杂,下面是一个示例:

matchExpressions:- {key: tier, operator: In, values: [cache1,cache2]}- {key: environment, operator: NotIn, values: [dev]}- {Key: disksize, operator: Exists}

Pod 必须有 tier 这个标签,并且值必须在 [cache1,cach2] 中找到。

Pod 必须有 environment 这个标签,并且值不能为 dev,或者说不能在 [dev] 中出现。

Pod 必须存在 disksize 这个标签。

还可以使用 YAML 格式表示:

- matchExpressions:- key: kubernetes.io/e2e-az-nameoperator: Invalues:- e2e-az1- e2e-az2

读者可以根据自己喜好使用其中一种编写格式。

matchLabels 是由 {key,value} 对组成的映射。 matchLabels 映射中的单个 {key,value } 等同于 matchExpressions 的元素, 其 key 字段为 "key",operator 为 "In",而 values 数组仅包含 "value"。

举个例子,matchLabels 示例为:

matchLabels:component: redis

相对于 matchExpressions :

matchExpressions:- {key: component, operator: In, values: [redis]}

两种选择器可以结合使用,示例如下:

selector:matchLabels:component: redismatchExpressions:- {key: tier, operator: In, values: [cache]}- {key: environment, operator: NotIn, values: [dev]}

[Info] 提示

复合选择比较复杂,只需了解即可。

注解

我们可以使用 Kubernetes 注解为对象附加任意的非标识的元数据,注解使用 annotations 标识。客户端程序(例如工具和库)能够获取这些元数据信息。

我们查看 dashboard 的相关 annotations :

kubectl describe services -n kubernetes-dashboard
... ...
Labels:                   k8s-app=kubernetes-dashboard
Annotations:              <none>
... ...

annotations 由 key/value 组成,类似 label,但是 annotations 支持一些特殊字符,可以用作构建发布镜像时的信息、日志记录等。

kubectl annotate service kubernetes-dashboard -n kubernetes-dashboard description='my test'
key=descriptionvalue=my test

重新查看 describe,可以看到:

Annotations:              description: my test

如果要覆盖 key 的值,需要加上 --overwrite 。

如果要删除一个 key:

kubectl annotate service kubernetes-dashboard description-

Kubernetes:标签、选择器、注解、容忍度、亲和性相关推荐

  1. Kubernetes 调度 - 污点和容忍度详解

    当我们使用节点亲和力(Pod 的一个属性)时,它会将Pod吸引到一组节点(作为偏好或硬性要求).污点的行为完全相反,它们允许一个节点排斥一组 Pod. 在 Kubernetes 中,您可以标记(污染) ...

  2. 云原生kubernetes七 :Pod进阶篇:污点-容忍度-亲和性-Affinity-调度

    1.pod资源清单详细介绍 #版本号 apiVersion: v1 #资源类型 kind: Pod #元数据 metadata:#Pod名字name: string#pod所属命名空间namespac ...

  3. k8s pod的三类调度策略:资源限制策略、nodeSelector标签选择器、硬/软亲和性

  4. kubernetes 【调度和驱逐】【1】污点和容忍度

    kubernetes 学习污点和容忍度 tags: 策略 文章目录 kubernetes 学习污点和容忍度 1. 概念 2. 示例 3. 基于污点的驱逐 4. 基于节点状态添加污点 1. 概念 节点亲 ...

  5. K8S 污点和容忍度

    污点和容忍度 节点亲和性(详见这里) 是 Pod 的一种属性,它使 Pod 被吸引到一类特定的节点. 这可能出于一种偏好,也可能是硬性要求. Taint(污点)则相反,它使节点能够排斥一类特定的 Po ...

  6. k8s的标签和标签选择器

    k8s的标签和标签选择器 标签可以附加在kubernetes任何资源对象之上的键值型数据,常用于标签选择器的匹配度检查,从而完成资源筛选 资源标签 当Kubernetes对系统的任何API对象如Pod ...

  7. 学习笔记:k8s的标签和标签选择器

    标签可以附加在kubernetes任何资源对象之上的键值型数据,常用于标签选择器的匹配度检查,从而完成资源筛选. 一.标签 当Kubernetes对系统的任何API对象如Pod和节点进行"分 ...

  8. 云原生之容器编排实践-Kubernetes资源管理:标签选择器,注解以及命名空间

    背景 前面的几篇文章我们从一个简单的 SpringBoot 服务开始,依次将其打包为镜像,推送至私有镜像仓库,安装 Kubernetes 的极简实践环境 minikube , minikube 传递秘 ...

  9. Kubernetes资源调度之污点与Pod容忍度

    Kubernetes资源调度之污点与Pod容忍度 概述 污点是定义在节点之上的键值型属性数据,用于让节点有能力主动拒绝调度器将Pod调度运行到节点上,除非该Pod对象具有接纳节点污点的容忍度.容忍度( ...

最新文章

  1. 拼接的option会多出空行_液晶拼接屏与墙面安装技巧
  2. CentOS 6.5系统下安装和配置NFS服务
  3. Java多线程编程笔记之Condition
  4. 慢 SQL 诊断优化套路包,套路用的对,速度升百倍
  5. 使用ffmpeg视频切片并加密
  6. SQL - 创建一个学生表,要求有主键约束和非空约束
  7. 日志,错误日志,成功日志,日志是个好东西。
  8. 《原力计划【第二季】》第1周周榜揭晓!!!
  9. 从前端到后台,开发一个完整功能的小程序
  10. 后端开发之如何写接口设计文档
  11. Linux -- 搜狗输入法安装完成之后的设置
  12. 浏览器访问Linux的Tomcat
  13. android波浪动画简书,Android贝塞尔曲线————波浪效果(大波浪)
  14. c语言俄罗斯方块视频,c语言自己写俄罗斯方块(完整版)
  15. CobaltStrike YARA规则 检测 环境搭建
  16. Element-UI中走马灯图片无法显示的问题
  17. 南通蓝领技工学校计算机咋样,南通市蓝领技工学校
  18. pvr.ccz和png等大图切图工具
  19. c语言中静态存储类别是,小议C语言中数据的存储类型
  20. 2022年中小企业数据安全如何保障?对比华为云与其他云计算大厂

热门文章

  1. golang reflect
  2. 让DIV中文字换行显示
  3. oracle的环境配置-基本配置
  4. 在Idea中测试各JVM语言的交互性
  5. Spring.net学习记录
  6. poj--2019 Cornfields 2维RMQ
  7. 如何用C#在Excel中生成图表?
  8. 用SQL Server Compact Edition创建移动应用程序 【转载】
  9. 用java编写一个计算器_用java程序编写一个计算器
  10. 如何在Windows 10上使用Microsoft Defender扫描文件或文件夹中的恶意软件