修改角色标签会把一个就绪 Pod 移出 Service,但不会自动建立网络访问边界。

Kubernetes 标签定义选择关系,不代替授权

标签是 Kubernetes 用于选择对象的键值元数据。Service 选择器、运维查询和工作负载控制器都可能依赖标签,但每个消费者有自己的 API 和处理方式。因此,标签变化可能改变对象所属集合,同时底层进程仍然健康。审阅时应把标签视为真实消费者的输入,而不是仅用于展示的贴纸,否则看似简单的文字修改也可能改变路由。 确认正在使用哪一种选择语言 标签键采用限定名称格式,值也有字符和长度约束。标签值可以为空;不为空时,其允许字符及首尾位置受到限制,最大长度为六十三个字符。任意长段落或不受约束的 JSON 并不适合放在标签值里。描述性信息可以采用 annotation,但仍然要遵守对应格式和消费契约,不能把换字段当成取消所有限制。 等值条件检查某个键是否具有指定值,集合条件还支持成员关系与存在性检查。同一个选择器里的多个条件需要同时满足。有一个容易忽略的细节:track!=canary 也会匹配根本没有 track 键的对象。如果不允许键缺失,应另外要求这个键存在,不能认为“不等于某值”就已经隐含“这个键肯定存在”。 不同资源的选择字段结构并不相同。普通带选择器的 Service 使用等值映射,不能把完整集合表达式随意塞进某个映射值。另一些 API 提供 LabelSelector 结构,而 kubectl 列表查询能够接受选择表达式。把命令行中方便使用的查询转换成清单之前,应核对目标字段的真实结构,避免把同一个概念误当成完全相同的输入格式。 坏掉的样子 Service 选择器会识别本命名空间中匹配的 Pod,端点机制再跟踪地址与就绪状态。标签匹配本身不证明服务已经准备好,也不证明端口配置正确。在普通就绪策略下,路由可用目标还取决于端点条件。检查时应查看相应 EndpointSlice 和应用探测结果,不能在一次标签查询成功后就停止验证。 publishNotReadyAddresses 设置会改变服务发现对就绪状态的处理。在这种配置下,不能仅凭端点被标成就绪,就断言对应容器已经通过应用探测。下面实验采用普通默认行为,没有测试这个覆盖设置,因此结果也不应无条件推广到使用该选项的服务。 给健康 Pod 修改标签,可能把它移出 Service,却并不终止进程。过宽的条件则可能把原本不该提供服务的工作负载加入后端。如果 Pod 由控制器管理,手工改标签还可能影响所属关系与协调行为。应通过负责的控制器更新预期状态,并在改变共享键含义之前核对主要消费者,避免修好一个查询却破坏另一条路由。 选择器不是网络授权。某个 Pod 即使不属于一个 Service,也可能继续通过自身地址或其他 Service 被访问,除非另有控制阻止。NetworkPolicy、应用授权和路由分别解决不同部分,不能把选择器描述成能够拒绝所有未选中对象直连流量的访问名单。对象是否被发现,与请求最终是否允许,必须分别成立。 ...

九月 9, 2027 · 3 分钟 · XB Field Notes
样本过滤与标签删除主题封面,展示观察、判断与行动三个步骤。

样本重新标记在入库前过滤指标

Prometheus 存在多个重新标记阶段,相似语法容易遮住不同作用。目标重新标记在采集之前处理发现目标,样本重新标记则在抓取之后、入库之前处理采集样本。前一个阶段的 drop 可以让某个端点不被抓取,后一个阶段的相同动作则从已经获取的响应中丢弃匹配样本。首先确定阶段,才能判断配置到底改变了哪一部分观测。 先决定删除数据,还是删除标签 在 metric_relabel_configs 中,action: drop 匹配组合后的源标签值,并丢弃匹配样本。使用 __name__ 作为输入时,可以拒绝指定指标族。它不是删除这个源标签却保留样本的意思。如果对一个广泛存在的值使用过宽条件,可能丢掉远超预期的数据,所以不能仅凭动作名称中有“删除”就认为它只影响元数据。 action: labeldrop 则把正则表达式用于标签名称,从保留样本中移除匹配标签;labelkeep 只保留名称匹配的标签。两者都不会求和或生成汇总。前一类操作删除观测,后一类操作改变身份,应该按照预期数据契约选择,而不是把名称相近的动作当成可互换参数。留下数值但删掉维度,也可能比直接过滤一部分样本带来更隐蔽的问题。 重新标记表达式默认在两端锚定。替换或过滤规则需要在对应阶段使用正确的源标签与模式。发现元数据通常属于目标阶段,到样本处理阶段时,已不能继续期待使用 __meta_ 输入。需要保留的上下文应提前复制到普通目标标签,而不是假定每个导出指标都会携带内部发现字段。配置语法相同,不代表输入集合也相同。 删除维度之后仍须保持唯一身份 时间序列由指标名和完整标签集合识别。移除区分两条观测的标签,可能让它们身份重叠,产生重复样本冲突或丢失区别。Prometheus 不会自动推断这些数值该求和、取平均还是任选其一。如果真正需要服务总量,应优先采用受控维度的仪表化以及明确查询聚合,而不是把标签删除当成自动汇总机制。 本例只在剩余路由身份本来就唯一的情况下删除构建标签,这是受控前提,不表示可以从任意导出器移除任何昂贵标签。上线前应使用有代表性的输出检查碰撞,也应核对引用被删标签的面板和告警。抓取成功只能说明采集过程完成,不能保证这些消费者仍会选择正确数据,更不能保证历史与新数据可以直接比较。 坏掉的样子 把样本过滤规则放进目标重新标记中,可能移除整个端点,而不是一类昂贵指标。反过来,样本过滤也不会阻止导出器生成响应,或阻止响应字节经过网络。它减少的是入库保留的样本。如果昂贵部分在采集本身,还需要处理仪表化或导出器行为,不能把存储侧过滤描述为同时消除了全部上游成本。 up 等自动生成的抓取序列不经过样本重新标记,因此在这个阶段尝试删除 up,不会隐藏系统生成的指标。健康的 up 可以与被主动丢弃的业务指标同时存在,解释数据缺失时应结合过滤配置。修改规则影响未来入库,不会重写已经保存的历史标签,所以查询跨越变更时刻时也可能看到两种身份。 快速验证 保存为 metric-relabel.py 后执行 python3 metric-relabel.py。需要 Docker 与 Prometheus 3.5.1,必要时由 Docker 获取镜像。同一个静态文本端点分别被原始任务与过滤任务抓取。路径使用 .txt 以提供文本内容类型,启动过程等待真正出现样本,不假定服务刚启动时目标列表已经填充完成。 ...

八月 4, 2027 · 2 分钟 · XB Field Notes
对外采集器标签主题封面,展示观察、判断与行动三个步骤。

外部标签标识 Prometheus 对外发送的数据

多个 Prometheus 向同一系统提供数据时,下游需要知道信息来自哪个采集器或环境。全局 external_labels 可以在与外部系统通信时补充这些上下文。但它不会重写每条本地存储序列,也不会覆盖对外序列中已经存在的同名标签。理解这两条边界,才能避免用错误的查询位置判断配置是否生效,也能避免误以为全局值一定压过目标值。 本地存储与对外身份并不相同 本地查询 up 通常看到抓取和重新标记产生的标签,外部标签 prom_region 并不一定出现。它没有出现在本地查询中,不能证明配置失败。应将适当的对外接口与本地结果比较;联邦接口提供了一种直接观察差异的方法,无需为了验证这个行为先接入远端存储系统。检查位置必须与希望验证的机制对应。 配置契约也涉及远端存储和告警等外部通信,但各条下游路径还可能有自己的重新标记与处理步骤。验证某条路径时,需要观察它实际到达的消费者。本地评估的记录规则不会因为保存了一条新序列,就自动获得所有外部标签。外部标签在相关通信边界补充,不是统一改写所有本地查询结果的机制。 序列已有的标签优先 如果目标序列已经具有 cluster="target-cluster",全局外部标签配置为 cluster="collector-cluster",不会把目标值替换掉。外部标签补充的是缺少的标签名称。这是已定义的行为,不能编造成新版本遇到冲突必定拒绝或记录错误。因此,本地指标对外导出时保留的集群值,可能不同于操作人员以为全局配置会强制设置的值。 需要区分目标身份与采集器身份时,应约定独立的采集器标签名,并检查导出器和重新标记规则是否与之冲突。联邦场景中,目标端的 honor_labels 还决定如何处理源标签与本端抓取标签的冲突。这个接收端行为,与源端如何向联邦响应补充外部标签是两件事,不能因为一侧正确便跳过另一侧检查。 稳定标签不会自动实现去重 改变全局标签值,会改变之后导出序列的身份。已经保存在下游的历史仍在旧标签下,不会被重写。修改选择器和面板时,应考虑这条历史边界。添加很多标签也不必然有益:固定标签提供上下文,不同采集器的不同取值则增加消费者需要处理的身份区别,应根据实际查询需求决定,而不是把能写的字段都写进去。 两个采集器抓取相同目标时,可能在不同副本标签下导出重复观测。直接跨副本求和,会让流量看起来翻倍。外部标签让这些副本可以被区分,却不会替下游配置高可用去重。标签也不是租户授权边界;如果存在隔离要求,应核对存储系统真实的权限和查询行为,不能仅依赖名称看起来来自不同环境。 坏掉的样子 团队可能在本地查询中寻找外部标签,找不到便反复修改本来有效的配置。相反,也可能看到联邦输出带有预期标签,就认为远端写入和告警路由都已验证。应检查具体路径和最终标签,包括下游重新标记的影响,而不是把一个接口的结果当成全部集成已经成功的证据。目标标签与全局值相同的测试,还会掩盖真正的冲突优先级。 快速验证 保存为 external-labels.py 后执行 python3 external-labels.py。实验需要 Docker 与 Prometheus 3.5.1 镜像,未缓存时可能由 Docker 下载。单个一次性 Prometheus 抓取自己,随后比较本地查询响应与文本格式的联邦输出。所有 HTTP 请求都停留在容器回环地址,不发布宿主机端口,也没有外部网络访问。 import json import re import subprocess import uuid # Requires Docker and the public Prometheus 3.5.1 image. # All HTTP traffic stays on loopback inside one disposable container. script = r"""set -eu cat > /tmp/prom.yml <<'CONFIG' global: scrape_interval: 1s scrape_timeout: 500ms external_labels: cluster: collector-cluster prom_region: lab-region replica: one scrape_configs: - job_name: self static_configs: - targets: ['127.0.0.1:9090'] labels: cluster: target-cluster CONFIG /bin/prometheus --config.file=/tmp/prom.yml --storage.tsdb.path=/tmp/data \ --web.listen-address=127.0.0.1:9090 > /tmp/prom.log 2>&1 & for attempt in $(seq 1 30); do if wget -qO /tmp/ready.json 'http://127.0.0.1:9090/api/v1/query?query=up%20%3D%3D%201'; then if grep -q '"status":"success"' /tmp/ready.json && ! grep -q '"result":\[\]' /tmp/ready.json; then wget -qO /tmp/local.json 'http://127.0.0.1:9090/api/v1/query?query=up' wget -qO /tmp/federated.txt --header='Accept: text/plain; version=0.0.4' \ 'http://127.0.0.1:9090/federate?match%5B%5D=up' cat /tmp/local.json printf '\n' cat /tmp/federated.txt exit 0 fi fi sleep 1 done cat /tmp/prom.log >&2 exit 1 """ name = "xbcatm-prom-live-" + uuid.uuid4().hex[:12] try: result = subprocess.run( ["docker", "run", "--rm", "--name", name, "--network", "none", "-i", "--entrypoint", "/bin/sh", "prom/prometheus:v3.5.1", "-s"], input=script, text=True, capture_output=True, timeout=45, ) finally: subprocess.run(["docker", "rm", "-f", name], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) if result.returncode: raise RuntimeError(result.stderr or result.stdout) local_json, _, exported = result.stdout.partition("\n") payload = json.loads(local_json) assert payload["status"] == "success" local = next(a["metric"] for a in payload["data"]["result"] if a["metric"]["job"] == "self") line = next(line for line in exported.splitlines() if line.startswith("up{")) # The fixture's controlled label values contain no quotes or escape sequences. outbound = dict(re.findall(r'(\w+)="([^"]*)"', line)) assert outbound["prom_region"] == "lab-region" and outbound["replica"] == "one" assert outbound["cluster"] == local["cluster"] == "target-cluster" assert "prom_region" not in local and "replica" not in local print(json.dumps({"federated_labels": outbound, "local_labels": local}, indent=2)) 本地标签包含 cluster="target-cluster",但没有 prom_region 和 replica。联邦输出补入 prom_region="lab-region" 与 replica="one",同时保留原有集群值。程序对这三个事实分别断言。解析器仅处理本实验中不含引号和转义序列的受控标签值,不是能够解析任意指标响应的通用组件,不能直接拿去处理未知导出内容。 ...

六月 9, 2027 · 2 分钟 · XB Field Notes
目标发现与重新标记主题封面,展示观察、判断与行动三个步骤。

目标重新标记在抓取前选择目标并整理标签

服务发现产生候选目标及其元数据,目标重新标记在 Prometheus 抓取之前处理这些候选项。它可以保留或过滤目标、改变访问地址,并创建随采集序列一起保存的标签。这与改写单个抓取样本发生在不同阶段。先弄清操作阶段,才能避免本来只想去掉一个指标,却因为配置位置错误而把整个目标从采集范围中移除。 定义规则前先查看发现输入 发现结果包含 __address__ 等内部标签,以及由具体发现机制提供的 __meta_ 字段。文件发现中的 __meta_filepath 指明目标来自哪个文件。这些元数据在目标重新标记期间可以使用,但内部标签会在该阶段结束后从最终目标标签集中移除。如果后续查询需要某个值,应明确把它复制到普通标签中,不能假定所有发现信息都会自动入库。 准确的元数据名称取决于发现机制。从 Kubernetes 发现配置复制过来的规则,不会自动适用于文件发现。组合输入时,缺少的源标签贡献空值,因此依赖一个不存在字段的保留规则,可能过滤所有候选项。排查网络故障之前,应通过目标接口或发现视图检查实际输入标签,先确认目标是否真的进入了抓取阶段。 规则顺序决定最终身份 重新标记步骤按照配置顺序执行。keep 动作仅保留组合源标签值匹配正则表达式的目标,drop 动作则移除匹配目标。正则表达式默认在两端锚定。replace 动作可以把捕获的文本复制到目标标签,而新值又能成为同一序列中后续规则的输入。因此,互换两个步骤可能改变结果,即使每条规则本身都能够通过解析。 复制一个值并不会自动删除原标签。确实需要删除时,它是另一项操作,而且不能破坏抓取或消费者依赖的身份信息。修改 __address__ 会改变 Prometheus 实际访问的端点,修改普通标签则改变上下文。两者都不能简单描述成给面板字段换一个好看的名字:地址变化可能影响可达性,标签变化则可能影响路由、聚合和历史查询。 目标标签能够影响从该目标收集的所有序列。应选择服务或有意义的部署范围等稳定字段,而不是复制全部发现注解。频繁变化的构建标识,可能让大量指标同时产生新身份。因此,发现配置中的一个小改动,能够影响远大于配置文件自身规模的存储数据及其消费者,需要根据真实查询需求审阅。 坏掉的样子 被重新标记过滤的目标,不是一个 up=0 的已配置目标。它没有被抓取,失败抓取查询可能永远不会报告它。预期服务消失时,应对照发现候选项、被过滤目标与活动目标。若告警假定全部预期成员始终存在对应 up 序列,一条错误保留规则就可能让整组目标看起来像安静且健康的空集合。 复制错误元数据也可能得到外观合理、语义却错误的归属标签。查询结果很整齐,不代表数据真的属于被标注的服务。应一起审阅执行顺序、捕获组和最终标签。大范围删除标签还可能合并原本不同的身份,目标重新标记不会为了补偿信息损失而自动计算聚合值,不能把去标签当成汇总方法。 快速验证 把程序保存为 target-relabel.py,执行 python3 target-relabel.py。需要 Docker 和 Prometheus 3.5.1,镜像未缓存时可能下载。隔离容器内同时提供静态文本指标端点与文件发现清单,清单包含一个接口目标和一个应被过滤的目标。指标路径使用 /metrics.txt,使 HTTP 响应具有 Prometheus 接受的文本内容类型,避免端点格式问题遮住标签实验。 ...

四月 6, 2027 · 2 分钟 · XB Field Notes