在 Kubernetes 中,Label(标签) 和 Annotation(注解) 都是存储在对象 metadata 中的键值对,但它们的设计目的、使用场景和技术限制有着本质的区别。本文通过两者对比的视角来强化对Label和Annotation的记忆。
一句话总结:Label 是给 K8s 系统看的(用来筛选和分组),Annotation 是给工具和人类看的(用来记录和配置)。
1. 核心区别对比表
| 维度 | Label (标签) | Annotation (注解) |
|---|---|---|
| 核心目的 | 标识与分组 (Identifying) | 记录与配置 (Non-identifying) |
| 能否被筛选 | 能 (支持 Label Selector) | 不能 (不支持筛选) |
| K8s 核心组件 | 深度使用 (Service, Deployment, Scheduler) | 基本不用 (主要由外部工具使用) |
| 数据验证 | 严格 (必须符合 DNS 标签规范,长度短) | 宽松 (可存长文本、JSON 等) |
| 索引机制 | 有索引 (查询效率高) | 无索引 (仅存储) |
| 大小限制 | 较小 (通常 63 字符以内) | 较大 (单对象总元数据限 256KB) |
| 典型示例 | app=nginx, version=v1 |
prometheus.io/scrape=true, git-commit=abc |
2. 详细差异解析
2.1 用途不同
- Label :用于建立对象之间的关系 。
- 例如:Service 通过 Label 找到背后的 Pod;Deployment 通过 Label 管理属于它的 Pod;调度器通过 Label 将 Pod 调度到特定 Node。
- 关键:如果 Label 错了,服务会中断,控制器会失联。
- Annotation :用于附加非标识性信息 。
- 例如:记录构建版本、负责人联系方式、配置 Ingress 规则、告诉 Prometheus 是否抓取指标。
- 关键:如果 Annotation 错了,通常只影响外部工具行为,不影响 K8s 核心功能。
2.2 查询能力不同
- Label:支持高效的查询和筛选。
bash
# 可以这样查
kubectl get pods -l app=nginx
- Annotation:不支持直接筛选。
bash
# 不能这样查 (会报错或无效)
kubectl get pods -l prometheus.io/scrape=true
# 只能用 jsonpath grep 等工具后期处理
2.3 技术限制不同
- Label :
- 值必须简短,字符集受限(字母、数字、
-_.)。 - 因为被索引,不适合存储频繁变化或过大的数据。
- 值必须简短,字符集受限(字母、数字、
- Annotation :
- 值可以较长,甚至可以是一段 JSON 配置。
- 存储在 etcd 中,过大的 Annotation 会增加 etcd 负担。
3. 典型使用场景
3.1 Label 的场景
- 服务发现 :
service.spec.selector匹配 Pod 的 Label。 - 调度约束 :
nodeSelector或nodeAffinity匹配 Node 的 Label。 - 版本管理 :标记
track=stable,track=canary用于灰度发布。 - 成本分摊 :标记
department=finance用于计算资源成本。
3.2 Annotation 的场景
- 工具配置 :
- Ingress:
nginx.ingress.kubernetes.io/rewrite-target - Service Mesh:
sidecar.istio.io/inject - Monitoring:
prometheus.io/scrape
- Ingress:
- 审计与追溯 :
kubectl.kubernetes.io/last-applied-configuration(K8s 自动添加)build.image.sha256owner.email
- 隐藏信息 :
- 某些控制器需要读取但不希望用户直接修改的配置。
4. 常见误区与最佳实践
| 误区 | 正确做法 |
|---|---|
| 把配置信息放 Label | 配置信息应放 Annotation 或 ConfigMap。Label 应保持简洁稳定。 |
| 把敏感信息放 Annotation | 绝对禁止 。Annotation 明文存储,任何有读权限的人都能看到。敏感信息请放 Secret。 |
| 自定义名称不加前缀 | 自定义 Label/Annotation 建议加域名前缀,如 example.com/my-key,避免与 K8s 系统保留字冲突。 |
| 用 Annotation 做调度 | 原生调度器只认 Label。虽然有些外部调度器可能读 Annotation,但标准做法是用 Node Affinity (Label)。 |
5. 形象类比
如果把 K8s 集群比作一个大型仓库:
- Label 是货物上的"条形码" :
- 仓库管理系统(K8s Core)靠它来识别货物属于哪个订单(Service),应该放在哪个货架(Node)。
- 格式必须标准,扫描枪(Selector)才能识别。
- Annotation 是货物上的"便利贴" :
- 上面写着"易碎品"、"收货人电话"、"入库时间"。
- 仓库管理系统不靠它来分拣货物,但搬运工(外部工具/管理员)会看它来决定怎么操作。
总结
- 需要被 K8s 原生功能(Service、Deployment、Scheduler)识别和操作的 → 用 Label。
- 只需要记录信息、配置外部插件或供人类阅读的 → 用 Annotation。