Kubernetes Labels 和 Selectors
Table of Contents
以下将 Label 翻译成标签,Selector 翻译成选择器。
标签 是附加到 Kubernetes 对象(比如 Pods)上的键值对。
- 标签的含义由用户定义;
- 可以用来组织和选择对象的子集;
- 标签在创建时附加到对象,然后可以随时添加和修改;
- 每个对象都可以定义一组键/值标签,键不可重复;
"metadata": { "labels": { "key1" : "value1", "key2" : "value2" } }
标签会被设置成索引,以提高查询效率和监控,非常適合在 UIs 和 CLIs 中使用。 如果是非标识性的,尤其是大型的结构化数据应该使用注解来记录,而不是标签。
1. 动机
标签使用户能够以松散耦合的方式将他们自己的组织结构映射到系统对象,而无需客户端存储这些映射。
其实就是一个轻量级的标识,用于多纬度的管理(查询),具体含义由用户约定。标签举例:
"release": "stable"
,"release" : "canary"
"environment" : "dev"
,"environment" : "qa"
,"environment" : "production"
"tier" : "frontend"
,"tier" : "backend"
,"tier" : "cache"
"partition" : "customerA"
,"partition" : "customerB"
"track" : "daily"
,"track" : "weekly"
这些是常用的标签,你可以自己约定规范。只要留意,标签键必须是要唯一的。
2. 语法和字符集
键值对。
- 键,可选的前缀和名称,用斜杠(
/
)分隔,。- 名称是必须的,以字母数字字符
[a-z0-9A-Z]
开头和结尾,中间包含-
_
.
和[a-z0-9A-Z]
- 前缀是可选的,如果指定必须是 DNS 子域:点(
.
)分隔的一系列 DNS 标签,总共不超过 253 个字符,后跟斜杠(/
)
- 名称是必须的,以字母数字字符
- 值,小于 64 字符,
[a-z0-9A-Z]
开头和结尾,中间包含-
_
.
和[a-z0-9A-Z]
键 如果省略前缀,则假定是对用户是私有的。
自动化的系统组件( kube-scheduler
, kube-controller-manager
, kube-apiserver
, kubectl
等,或者第三方自动化)必须指定前缀。
kubernetes.io/
和 k8s.io/
前缀是为 Kubernetes 核心组件保留的。
有效的标签不得超过 63 个字符,并且必须为空或者字母数字字符( [a-z0-9A-Z]
)开头和结尾,中间可带有破折号,下划线或者点。
比如,下面的配置文件带有两个标签: environment: production
和 app: nginx
:
apiVersion: v1 kind: Pod metadata: name: label-demo labels: environment: production app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
3. 标签选择器(Label selectors)
不像名称和 UID,标签不需要提供唯一性。而且,我们希望许多对象带有相同的标签。
通过 标签选择器 ,客户端/用户可以标识一组对象。标签选择器是 Kubernetes 中的核心分组原语。
API 目前支持两种类型的选择器: 基于相等性的 和 基于集合的 。标签选择器可以由逗号分隔的多个 需求(requirements) 组成。 在多个需求的情况下,必须满足所有的要求,因为逗号分隔符充当的是逻辑 AND(&&) 运算符。
空的或未指定选择器的语义取决于上下文,并且使用选择器的 API 类型应记录他们的有效性和含义。
注意: 对于一些 API 类型,比如 ReplicaSets,两个实例的标签选择器不能在命名空间(namespace)内重叠,否则控制器会将其视为冲突的指令, 而无法确定应存在多少个副本。
警告: 基于相等和基于集合的条件都没有逻辑 OR(||) 运算。确保你的过滤器语句具有相应的结构。
3.1. 基于相等性的请求
基于相等或者不相等的请求允许按照标签的 key 和 value 进行过滤。匹配的对象必须满足所有指定的标签约束,尽管它们可能还有额外的标签。
接受三种类型的运算符: =
, ==
, !=
。前两种表达的是 相等 ,最后表示 不等 。比如:
environment = production tier != frontend
前者选择符合 environment
为 key, production
为 value 的所有资源。
后者选择符合 tier
为 key,value 不是 frontend
,并且标签中不包含 tier
key 的所有资源。
一个可以过滤 production
不包含 frontend
的所有资源,使用逗号运算符: environment=production,tier!=frontend
。
一种使用场景给 Pods 要指定节点选择标准。比如,下面示例的 Pod 选择带有 accelerator=nvidia-tesla-p100
标签的节点。
apiVersion: v1 kind: Pod metadata: name: cuda-test spec: containers: - name: cuda-test image: "k8s.gcr.io/cuda-vector-add:v0.1" resources: limits: nvidia.com/gpu: 1 nodeSelector: accelerator: nvidia-tesla-p100
3.2. 基于集合的请求
基于集合的请求允许根据一组值过滤 key。支持 3 种运算符: in
, notin
和 exists
。比如:
environment in (production, qa) tier notin (frontend, backend) partition !partition
- 第一个例子选择 key 等于
environment
且 value 等于production
或者qa
的资源; - 第二个例子选择 key 等于
tier
且 value 在frontend
和backend
之外,以及所有标签中不包含tier
key 的资源; - 第三个例子选择标签 key 包含
partition
的资源(不判断 value 的值); - 第四个例子选择标签 key 不包含
partition=
的资源(不判断 value 的值);
相似的逗号运算符充当 AND 运算。当只包含一个条件时, in
等价于 =
,而 notint
等价于 !=
。
基于集合的和基于相等的过滤可以混用,比如 partition in (customerA, customerB),environment!=qa
。
4. API
4.1. LIST 和 WATCH 过滤
LIST 和 WATCH 操作可以指定标签选择器以过滤使用查询参数(query string)返回的对象集。这两种请求都是允许的:
- 基于相等的请求:
?labelSelector=environment%3Dproduction,tier%3Dfrontend
- 基于集合的请求:
?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29
两种标签选择器的风格都可用户 REST 客户端。比如:使用 kubectl
定位 apiserver
可以这样写:
kubectl get pods -l environment=production,tier=frontend
或者:
kubectl get pods -l 'environment in (production),tier in (frontend)'
4.2. API 对象中的设置参考
一些 Kubernetes 对象,比如 services 和 replicationcontrollers,也可以使用标签选择器来指定其它资源集,比如 pods。
4.2.1. Service 和 ReplicationController
service
指向的 pods 集合通过标签选择器来定义。类似的, replicationcontroller
使用标签定义了它所管理的 pods 数量。
在 json
或者 yaml
文件中使用 map 来定义标签选择器,并且只支持基于相等的请求选择器:
"selector": { "component" : "redis", }
selector: component: redis
4.2.2. 支持基于集合请求的资源
较新的资源,比如 Job,Deployment,ReplicaSet 和 DaemonSet,也支持基于集合的请求。
selector: matchLabels: component: redis matchExpressions: - {key: tier, operator: In, values: [cache]} - {key: environment, operator: NotIn, values: [dev]}
4.2.3. 选择节点集合
标签选择器的一个用例是约束 pod 可以调度的节点集合。在节点选择文档中有更多的描述。