# Label & Annotation 介紹
來了解 Kubernetes object 中 metadata 會出現的 Label 和 Annotation 的作用。
## [Labels and Selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/)
Label 是附加到 object(例如 Pod)的 key-value 形式。**Label 旨在用於指定 object 的識別屬性**,這些屬性對用戶來說具有意義且相關,但並未直接向核心系統暗示語義。
Label 可用於組織和選擇 object 的子集。而 object 之間的連接(Selector)也是透過 Label 來識別。
Label 可以在建立時附加到 object 上,並隨後隨時新增和修改。每個 object 都可以定義一組 key-value Labels。對於一個 object 來說,每個 key 必須是唯一的。
:::success
:notebook: **Note:**
Label 可實現高效查詢和監視,非常適合在 UI 和 CLI 中使用。非識別資訊應使用 [Annotation](https://hackmd.io/GxNJtFfzQ_W8X2Tx6uCtHw?both#Annotation) 來記錄。
:::
以下是具有兩個 Label 的 Pod:**`environment: production`** 和 **`app: nginx`**:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: label-demo
labels: # ==================
environment: production # ===>> here <<===
app: nginx # ==================
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
```
### Label selectors
與 [names 和 UIDs](https://kubernetes.io/docs/concepts/overview/working-with-objects/names/) 不同,Label 不提供唯一性。一般來說,我們期望許多 object 帶有相同的 Label。
透過 *Label Selector*,客戶端/用戶可以識別一組 object。
此 API 目前支援兩種類型的選擇器:*equality-based* 和 *set-based*。Label Selector 可以由多個以逗號分隔的 *requirements* 組成。如果有多個要求,則必須滿足所有要求,因此逗號分隔符號可作為邏輯 *AND*(**`&&`**)運算子。
:::warning
:warning: **警告:**
對於 equality-based 和 set-based 的條件,沒有邏輯 *OR*(**`||`**)運算子。確保您的篩選器語句具有對應的結構。
:::
#### Equality-based requirement
*Equality-* 或 *inequality-based* 要求允許按 Label 的 key 和 value 進行篩選。匹配的 object 必須滿足所有指定的 Label 約束,儘管它們也可能具有其他的 Label。有三種運算子被接受:**`=`**、**`==`**、**`!=`**。前兩者代表 *equality*(並且是同義詞),而後者代表 *inequality*。例如:
```
environment = production
tier != frontend
```
前者選擇所有 key 等於 **`environment`**、value 等於 **`production`** 的資源。後者選擇所有 key 等於 **`tier`** 且 value 與 **`frontend`** 不同的資源,以及所有沒有帶有 **`tier`** key 的資源。可以使用逗號運算子篩選 **`production`** 中的資源但不包含 **`frontend`**:**`environment=Production,tier!=frontend`**
```bash
kubectl get pods -l environment=production,tier=frontend
```
Equality-based 的 Label 要求的一種使用場景是讓 Pod 指定 Node 選擇標準。例如,下面的範例 Pod 選擇帶有 Label「**`accelerator=nvidia-tesla-p100`**」的 Node。
```yaml
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 # ===>> here <<===
```
#### Set-based requirement
*Set-based* 的 Label 要求允許根據一組 value 篩選 key。支援三種運算子:**`in`**、**`notin`** 和 **`exists`**(僅識別是否有該 key)。例如:
```
environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
```
+ 第一個範例選擇 key 等於 **`environment`**、value 等於 **`production`** 或 **`qa`** 的所有資源。
+ 第二個範例選擇 key 等於 **`tier`** 且 value 除 **`frontend`** 和 **`backend`** 之外的所有資源,以及沒有帶有 **`tier`** key 的所有資源。
+ 第三個範例選擇所有帶有 **`partition`** key 的資源;不檢查任何 value。
+ 第四個範例選擇所有沒有 **`partition`** key 的資源;不檢查任何 value。
*Set-based* 的要求可以與 *equality-based* 的要求混合。例如:**`partition in (customerA, customerB),environment!=qa`**。
#### Service and ReplicationController
一些 Kubernetes object(例如 **`services`** 和 **`replicationcontrollers`**)也會使用 Label Selector 來指定其他資源集(例如 Pod)。
這兩個 object 的 Label Selector 都是使用映射在 **`json`** 或 **`yaml`** 檔案中定義的,並且僅支援 *equality-based* 的要求選擇器:
```yaml
selector:
component: redis
```
#### 支援 set-based 要求的資源
較新的資源(例如 **`Job`**、**`Deployment`**、**`ReplicaSet`** 和 **`DaemonSet`**)也支援 *set-based* 的要求。
```yaml
selector:
matchLabels:
component: redis
matchExpressions:
- { key: tier, operator: In, values: [cache] }
- { key: environment, operator: NotIn, values: [dev] }
```
**`matchLabels`** 和 **`matchExpressions`** 的所有要求都透過 AND 組合在一起,它們必須全部滿足才能匹配。
### 更新 Labels
如果 Pod 運行後想要更新 Label,也可以透過指令更改。這邊是使用 **`kubectl label`**。
```bash
kubectl label pods -l app=nginx tier=fe
```
這邊會先篩選出 Label **`app=nginx`** 的 Pod,之後加上 **`tier=fe`** Label。
## [Annotation](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)
您可以使用 Annotation 將**任意非識別 metadata** 附加到 object。Annotation 中的 metadata 可以小或大、結構化或非結構化,並且可以包含 Label 不允許的字元。可以在同一個 object 的 metadata 中使用 Label 和 Annotation。
```yaml
apiVersion: v1
kind: Pod
metadata:
name: annotations-demo
annotations:
imageregistry: "https://hub.docker.com/" # ===>> here <<===
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
```
:::success
:notebook: **Note:**
key 和 value 必須是字串。換句話說,您不能對 key 或 value 使用數字、布林值、列表或其他類型。
:::