標籤與選擇器

標籤 (Labels) 是附加到物件 (objects)的鍵/值對。標籤旨在用於指定對使用者有意義且相關的物件識別屬性,但並不直接暗示核心系統的語意。標籤可用於組織和選擇物件的子集。標籤可以在建立物件時附加,並隨後隨時新增和修改。每個物件都可以定義一組鍵/值標籤。對於給定的物件,每個鍵都必須是唯一的。

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

標籤允許高效的查詢和監看,非常適合在 UI 和 CLI 中使用。非識別資訊應使用註解 (annotations)記錄。

動機

標籤使使用者能夠以鬆散耦合的方式將自己的組織結構對應到系統物件,而無需用戶端儲存這些對應關係。

服務部署和批次處理管線通常是多維實體(例如,多個分割區或部署、多個發布軌跡、多個層級、每個層級多個微服務)。管理通常需要跨領域操作,這打破了嚴格階層表示的封裝,尤其是由基礎架構而不是使用者決定的剛性階層。

標籤範例

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

這些是常用標籤的範例;您可以自由開發自己的慣例。請記住,對於給定的物件,標籤鍵必須是唯一的。

語法和字元集

標籤 (Labels) 是鍵/值對。有效的標籤鍵有兩個部分:一個可選的前綴和名稱,以斜線 (/) 分隔。名稱部分是必需的,且長度必須為 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 的 Manifest

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不同,標籤不提供唯一性。一般來說,我們預期許多物件會帶有相同的標籤。

透過標籤選擇器 (label selector),用戶端/使用者可以識別一組物件。標籤選擇器是 Kubernetes 中的核心分組基本元素。

API 目前支援兩種選擇器類型:基於等式 (equality-based)基於集合 (set-based)。標籤選擇器可以由多個以逗號分隔的需求 (requirements) 組成。在多個需求的情況下,所有需求都必須滿足,因此逗號分隔符號充當邏輯 AND (&&) 運算子。

空或未指定選擇器的語意取決於上下文,並且使用選擇器的 API 類型應記錄它們的有效性和含義。

基於等式 (Equality-based) 需求

基於等式基於不等式的需求允許依標籤鍵和值進行篩選。匹配的物件必須滿足所有指定的標籤約束,儘管它們也可能具有額外的標籤。 允許三種運算子 ===!=。前兩個表示等式(且為同義詞),而後者表示不等式。 例如:

environment = production
tier != frontend

前者選取鍵等於 environment 且值等於 production 的所有資源。 後者選取鍵等於 tier 且值與 frontend 不同的所有資源,以及所有沒有 tier 鍵標籤的資源。 可以使用逗號運算子篩選 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: "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 master 和 replica 將具有不同的 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 PST:修正 accelerator 的標籤 (bbb4553bb0)