标签和选择器

标签 是附加到 对象(例如 Pod)的键/值对。标签旨在用于指定对用户有意义和相关,但不直接暗示核心系统语义的对象的识别属性。标签可用于组织和选择对象的子集。标签可以在创建时附加到对象,随后可以随时添加和修改。每个对象都可以定义一组键/值标签。每个键对于给定的对象必须是唯一的。

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

标签允许高效的查询和监视,非常适合在 UI 和 CLI 中使用。非识别信息应使用 注解 记录。

动机

标签使用户能够以松耦合的方式将他们自己的组织结构映射到系统对象上,而无需客户端存储这些映射。

服务部署和批处理管道通常是多维实体(例如,多个分区或部署、多个发布轨道、多个层、每个层的多个微服务)。管理通常需要跨领域操作,这会打破严格分层表示的封装,特别是基础设施而不是用户决定的刚性层级结构。

标签示例

  • "release" : "stable", "release" : "canary"
  • "environment" : "dev", "environment" : "qa", "environment" : "production"
  • "tier" : "frontend", "tier" : "backend", "tier" : "cache"
  • "partition" : "customerA", "partition" : "customerB"
  • "track" : "daily", "track" : "weekly"

这些是常用标签的示例;您可以自由制定自己的约定。请记住,对于给定的对象,标签键必须是唯一的。

语法和字符集

标签 是键/值对。有效的标签键有两个部分:可选的前缀和名称,用斜杠 (/) 分隔。名称部分是必需的,并且必须是 63 个字符或更少,以字母数字字符 ([a-z0-9A-Z]) 开头和结尾,中间可以使用短划线 (-)、下划线 (_)、点 (.) 和字母数字。前缀是可选的。如果指定,前缀必须是 DNS 子域:一系列用点 (.) 分隔的 DNS 标签,总长度不超过 253 个字符,后跟斜杠 (/)。

如果省略前缀,则标签键被认为是用户私有的。将标签添加到最终用户对象的自动化系统组件(例如,kube-schedulerkube-controller-managerkube-apiserverkubectl 或其他第三方自动化)必须指定前缀。

kubernetes.io/k8s.io/ 前缀为 Kubernetes 核心组件保留

有效的标签值

  • 必须为 63 个字符或更少(可以为空),
  • 除非为空,否则必须以字母数字字符 ([a-z0-9A-Z]) 开头和结尾,
  • 中间可以包含短划线 (-)、下划线 (_)、点 (.) 和字母数字。

例如,这是一个具有两个标签 environment: productionapp: nginx 的 Pod 的清单

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

标签选择器

名称和 UID不同,标签不提供唯一性。一般来说,我们预计许多对象都带有相同的标签。

通过标签选择器,客户端/用户可以识别一组对象。标签选择器是 Kubernetes 中的核心分组原语。

API 当前支持两种类型的选择器:基于相等性基于集合。标签选择器可以由多个以逗号分隔的要求组成。在有多个要求的情况下,必须满足所有要求,因此逗号分隔符充当逻辑 (&&) 运算符。

空或未指定选择器的语义取决于上下文,并且使用选择器的 API 类型应记录它们的有效性和含义。

基于相等性 的要求

Equality- or inequality-based requirements allow filtering by label keys and values. Matching objects must satisfy all of the specified label constraints, though they may have additional labels as well. Three kinds of operators are admitted =

environment = production
tier != frontend

前者选择所有键(key)等于 environment 且值等于 production 的资源。后者选择所有键等于 tier 且值不等于 frontend 的资源,以及所有没有 tier 键标签的资源。可以使用逗号操作符过滤 production 中排除 frontend 的资源:environment=production,tier!=frontend

基于等式的标签要求的一个应用场景是 Pod 指定节点选择标准。例如,下面的示例 Pod 选择 accelerator 标签存在且设置为 nvidia-tesla-p100 的节点。

apiVersion: v1
kind: Pod
metadata:
  name: cuda-test
spec:
  containers:
    - name: cuda-test
      image: "registry.k8s.io/cuda-vector-add:v0.1"
      resources:
        limits:
          nvidia.com/gpu: 1
  nodeSelector:
    accelerator: nvidia-tesla-p100

基于集合 的要求

基于集合 的标签要求允许根据一组值过滤键。支持三种运算符:innotinexists(仅限键标识符)。例如

environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
  • 第一个示例选择所有键等于 environment 且值等于 productionqa 的资源。
  • 第二个示例选择所有键等于 tier 且值不是 frontendbackend 的资源,以及所有没有 tier 键标签的资源。
  • 第三个示例选择所有包含 partition 键的标签的资源;不检查值。
  • 第四个示例选择所有不包含 partition 键标签的资源;不检查值。

类似地,逗号分隔符充当 AND 运算符。因此,可以使用 partition,environment notin (qa) 来过滤具有 partition 键(无论值是什么)且 environmentqa 不同的资源。基于集合 的标签选择器是等式的通用形式,因为 environment=production 等同于 environment in (production);对于 !=notin 也是类似的。

基于集合 的要求可以与 基于等式 的要求混合使用。例如:partition in (customerA, customerB),environment!=qa

API

LIST 和 WATCH 过滤

对于 listwatch 操作,您可以指定标签选择器来过滤返回的对象集合;您可以使用查询参数指定过滤器。(要详细了解 Kubernetes 中的 watches,请阅读高效检测变更)。允许两种要求(此处以 URL 查询字符串的形式呈现)

  • 基于等式 的要求:?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)'

正如已经提到的,基于集合 的要求更具表现力。例如,它们可以在值上实现 OR 运算符

kubectl get pods -l 'environment in (production, qa)'

或通过 notin 运算符限制负匹配

kubectl get pods -l 'environment,environment notin (frontend)'

API 对象中的集合引用

一些 Kubernetes 对象,例如 servicesreplicationcontrollers,也使用标签选择器来指定其他资源集合,例如 pods

Service 和 ReplicationController

service 定位的 Pod 集合使用标签选择器定义。类似地,replicationcontroller 应该管理的 Pod 群体也使用标签选择器定义。

这两种对象的标签选择器都在 jsonyaml 文件中使用映射定义,并且仅支持 基于等式 的要求选择器

"selector": {
    "component" : "redis",
}

selector:
  component: redis

此选择器(分别采用 jsonyaml 格式)等同于 component=rediscomponent in (redis)

支持基于集合要求的资源

较新的资源,例如 JobDeploymentReplicaSetDaemonSet,也支持 基于集合 的要求。

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

matchLabels{key,value} 对的映射。matchLabels 映射中的单个 {key,value} 等效于 matchExpressions 的一个元素,其 key 字段为“key”,operator 为“In”,并且 values 数组仅包含“value”。matchExpressions 是 pod 选择器要求的列表。有效的运算符包括 In、NotIn、Exists 和 DoesNotExist。在 In 和 NotIn 的情况下,值集必须非空。来自 matchLabelsmatchExpressions 的所有要求都进行 AND 运算——必须全部满足才能匹配。

选择节点集合

使用标签选择的一个用例是约束 Pod 可以调度到的节点集。有关更多信息,请参阅关于 节点选择 的文档。

有效地使用标签

您可以将单个标签应用于任何资源,但这并不总是最佳实践。在许多情况下,应该使用多个标签来区分不同的资源集。

例如,不同的应用程序将对 app 标签使用不同的值,但多层应用程序(例如 guestbook 示例)还需要区分每个层。前端可以携带以下标签

labels:
  app: guestbook
  tier: frontend

而 Redis 主节点和副本将具有不同的 tier 标签,甚至可能还有一个额外的 role 标签

labels:
  app: guestbook
  tier: backend
  role: master

labels:
  app: guestbook
  tier: backend
  role: replica

标签允许沿着标签指定的任何维度对资源进行切片和切块

kubectl apply -f examples/guestbook/all-in-one/guestbook-all-in-one.yaml
kubectl get pods -Lapp -Ltier -Lrole
NAME                           READY  STATUS    RESTARTS   AGE   APP         TIER       ROLE
guestbook-fe-4nlpb             1/1    Running   0          1m    guestbook   frontend   <none>
guestbook-fe-ght6d             1/1    Running   0          1m    guestbook   frontend   <none>
guestbook-fe-jpy62             1/1    Running   0          1m    guestbook   frontend   <none>
guestbook-redis-master-5pg3b   1/1    Running   0          1m    guestbook   backend    master
guestbook-redis-replica-2q2yf  1/1    Running   0          1m    guestbook   backend    replica
guestbook-redis-replica-qgazl  1/1    Running   0          1m    guestbook   backend    replica
my-nginx-divi2                 1/1    Running   0          29m   nginx       <none>     <none>
my-nginx-o0ef1                 1/1    Running   0          29m   nginx       <none>     <none>
kubectl get pods -lapp=guestbook,role=replica
NAME                           READY  STATUS   RESTARTS  AGE
guestbook-redis-replica-2q2yf  1/1    Running  0         3m
guestbook-redis-replica-qgazl  1/1    Running  0         3m

更新标签

有时您可能希望在创建新资源之前重新标记现有 pod 和其他资源。这可以使用 kubectl label 完成。例如,如果您想将所有 NGINX Pod 标记为前端层,请运行

kubectl label pods -l app=nginx tier=fe
pod/my-nginx-2035384211-j5fhi labeled
pod/my-nginx-2035384211-u2c7e labeled
pod/my-nginx-2035384211-u3t6x labeled

这首先过滤所有带有标签“app=nginx”的 pod,然后用“tier=fe”标记它们。要查看您标记的 pod,请运行

kubectl get pods -l app=nginx -L tier
NAME                        READY     STATUS    RESTARTS   AGE       TIER
my-nginx-2035384211-j5fhi   1/1       Running   0          23m       fe
my-nginx-2035384211-u2c7e   1/1       Running   0          23m       fe
my-nginx-2035384211-u3t6x   1/1       Running   0          23m       fe

这将输出所有“app=nginx”pod,以及 pod 层的附加标签列(使用 -L--label-columns 指定)。

有关更多信息,请参阅 kubectl label

下一步

上次修改时间为 2024 年 7 月 30 日晚上 11:13(太平洋标准时间):更正了加速器的标签 (bbb4553bb0)