pod.yaml 只有一個 Pod,用名字就找得到它。但真實情況是一個 namespace 裡面會塞幾十個 Pod,總不可能每次都背名字,所以今天要來搞懂 K8s 怎麼分類東西,也就是 Label
Label 就是掛在物件上的鍵值對,寫在 metadata 底下。它不影響 Pod 怎麼跑,純粹是給人、也給其他物件拿來找東西用的
先把昨天的檔案改一下,多塞一個 Pod 進去
apiVersion: v1
kind: Pod
metadata:
name: web-pod
namespace: ithome-lab
labels:
app: web
tier: frontend
spec:
containers:
- name: nginx
image: nginx:alpine
---
apiVersion: v1
kind: Pod
metadata:
name: api-pod
namespace: ithome-lab
labels:
app: api
tier: backend
spec:
containers:
- name: nginx
image: nginx:alpine
中間那三個減號是 YAML 的分隔符號,代表這是兩份獨立的文件,K8s 讀到會當成兩個物件分開處理
kubectl apply -f manifests/base/pod.yaml
kubectl get pods -n ithome-lab --show-labels

加了 --show-labels 會多開一欄把標籤全部列出來,這時候就可以來篩了
kubectl get pods -n ithome-lab -l app=web
kubectl get pods -n ithome-lab -l tier=backend
kubectl get pods -n ithome-lab -l app!=web

這個 -l 是 --selector 的縮寫。想一次下多個條件就用逗號串起來,另外也有集合式的寫法
kubectl get pods -n ithome-lab -l app=web,tier=frontend
kubectl get pods -n ithome-lab -l 'app in (web,api)'

Label 也可以事後再補,不用改 YAML 重跑一次
kubectl label pod web-pod -n ithome-lab env=dev
kubectl label pod web-pod -n ithome-lab env=prod --overwrite
kubectl label pod web-pod -n ithome-lab env-
第一行是加新的,第二行是改已經存在的,沒帶 --overwrite 會直接噴錯,第三行在鍵名後面接一個減號就是刪掉。要注意的是,用指令加上去的 label 不在 YAML 的管理範圍內,下次 apply 同一份 YAML 並不會把它清掉,想復原得自己再下一次指令刪除
那 Label 到底重要在哪,因為 K8s 內部很多物件不是靠名字找對象,是靠 Label。Service 要把流量送去哪些 Pod、Deployment 要管哪些 Pod,靠的都是 selector 去比對 Label
這件事的可怕之處在於,Label 打錯一個字不會報錯。YAML 格式合法、Pod 也活得好好的,只是 selector 會對不上東西,然後你就會盯著一個 Running 的 Pod 想不通為什麼連不上
metadata 底下還有個長很像的欄位叫 annotations,一樣是鍵值對,但 annotations 不能拿來篩選,純粹是放備註跟給工具讀的資料,要拿來找東西的放 labels,想寫點什麼的放 annotations
最後清乾淨
kubectl delete -f manifests/base/pod.yaml
明天見 :D

我想請問幾個問題
在大型專案或團隊協作中,為了避免這種手滑打錯 Label,或是每個人命名風格不一(例如有人寫 app: web、有人寫 app_name: frontend),你們團隊通常會有什麼規範嗎?例如使用標準的 app.kubernetes.io/name 這套 Recommended Labels,還是會靠 CI/CD 流程中的 Linter(如 kube-linter)來自動檢查格式?
內文點出了『Selector 對不上會連不上』的問題,但其實還有另一種相反的惡夢:『手滑給別的 Pod 掛了相同的 Label,結果被 Service 誤抓進去分流』!
在這種狀況下,Pod 既是 Running,流量又偶爾正常偶爾出錯(打了不該打的 Pod)。想問作者在遇到這種『多扣』或『少扣』流量的鬼故事時,第一時間會習慣怎麼下指令進行除錯?
提到用 kubectl label 動態改標籤不會被 kubectl apply 覆蓋掉這個觀念很讚!這涉及到了 kubectl.kubernetes.io/last-applied-configuration 的運作機制。
如果未來團隊開始用 GitOps(例如 ArgoCD / Flux)做聲明式管理,這種透過命令列手動改過的 Label 是不是就會被 GitOps controller 強制修正(Drift Detection)修回來?在權限允許下,你會建議平時練習就盡量一律修改 YAML 走 apply 嗎?