Saltar al contenido

Label Selector Tester · Kubernetes

Ve qué pods coinciden con tu selector — y por qué.

Pega los pods y el selector — un string kubectl -l o un bloque matchLabels / matchExpressions — y obtén un veredicto por recurso con la cláusula exacta que lo decidió. Incluida la regla que casi todo el mundo responde al revés: NotIn y != coinciden con un recurso que no tiene esa label en absoluto.

Se ejecuta en tu navegador: nada de lo que pegas sale de esta página. Cómo lo demostramos

Se ejecuta en tu navegador Sin clúster Sin registro Actualizado el 31 jul 2026

Playground del Kubernetes Label Selector Tester

Examples
Selector grammar

Equality-based clauses (=, !=) and set-based ones (in, notin, a bare key, !key) can be mixed freely in one -l string — commas mean AND. A Deployment's spec.selector accepts both forms but is immutable after creation; a Service's spec.selector is a plain label map and supports equality only.

resources.yaml input

Results update as you type — press Enter to run now.

Paste one manifest, a --- stream, a kind: List or a YAML list. Press Esc to release keyboard focus from the editor; /Ctrl + Enter runs and leaves it. Nothing you paste is uploaded.

Verdicts

Paste the resources above — or tap an example — to see, per resource, whether the selector matches it and which clause decided.

El hueco

Un selector que no coincide con nada no es un error en ninguna parte de Kubernetes.

kubectl apply lo acepta. El API server lo acepta. Ningún controlador registra un aviso, no se emite ningún evento, ningún campo se marca como inválido. El único síntoma de un Service cuyo selector falla por un carácter es un objeto Endpoints sin direcciones — y cuando estás mirando eso, ya estás depurando en el sitio equivocado. El mismo silencio cubre una NetworkPolicy cuyo podSelector no selecciona nada, que falla en abierto justamente como un control de seguridad no debería.

Las reglas en sí son la otra mitad del problema, porque dos de ellas se leen al revés. env!=prod coincide con un pod que no tiene ninguna label envNotIn se satisface con una clave ausente, por diseño, en una rama de Requirement.Matches. Y un selector vacío coincide con todo, mientras que un selector nil no coincide con nada. Cada hecho es una línea de Go, y los dos se recuerdan del revés con regularidad.

Por eso esto es una herramienta y no un artículo. Pregunta a un asistente «¿coincide env!=prod con un pod sin label env?» y recibirás una respuesta fluida con un cincuenta por ciento de probabilidades de estar mal — y los manifiestos generados meten matchExpressions en el spec.selector de un Service con toda naturalidad, un campo que solo acepta un mapa plano de labels. Pega la afirmación aquí y la respuesta sale de la misma semántica que implementa apimachinery, con el motivo adjunto, en una pestaña que no envía nada a ningún sitio.

¿Dimensionar el workload en lugar de seleccionarlo? Kubernetes Resource Calculator suma requests y limits entre réplicas, y Env Example Checker encuentra las variables que un contenedor espera y nunca recibe.

El pipeline

Cómo funciona.

Cuatro pasos, todos dentro de tu pestaña, reejecutados mientras escribes.

  1. Parsear el selector como lo hace apimachinery.

    La gramática `-l` pasa por un port de su propio lexer y parser — sensible al contexto, así que `op in (in,notin)` es legal, y tolerante con los espacios, así que `env in ( prod , dev )` es el mismo selector. Los selectores estructurados siguen en cambio las reglas de `LabelSelectorAsSelector`.

  2. Leer lo que haya en el portapapeles.

    Un manifiesto, un flujo `---`, un `kind: List` o una lista YAML. El `spec.template.metadata.labels` de un workload se convierte en su propia fila, porque un Service selecciona labels de pod y no las del Deployment.

  3. Evaluar cláusula por cláusula.

    `Requirement.Matches`, una vez por recurso y cláusula: `In` necesita la clave presente, `NotIn` se satisface con una clave ausente, `Exists` acepta el valor vacío y `DoesNotExist` no.

  4. Mostrar la razón, no solo el veredicto.

    Cada cláusula lleva la frase que la decidió, nombrando el valor real de la label. Las coincidencias por clave ausente reciben una anotación ámbar, porque son las que las personas y los modelos de lenguaje responden al revés.

Referencia

Cada operador, y qué hace una clave ausente.

Siete formas de escribir una cláusula, cuatro operadores detrás y la columna que casi nunca se imprime junto a la sintaxis: qué pasa cuando el recurso no lleva la clave. Tres de las siete coinciden en ese caso.

Escrito como Operador Forma estructurada Clave ausente
key=value In matchLabels: {key: value} Un valor. `=` y `==` son el mismo operador. no coincide
key==value In matchLabels: {key: value} Idéntico a `=`; solo se conserva la forma escrita. no coincide
key!=value NotIn operator: NotIn, values: [value] El que se invierte. Una clave ausente lo satisface. COINCIDE
key in (a,b) In operator: In, values: [a, b] Se exige al menos un valor; el conjunto se deduplica y se ordena. no coincide
key notin (a,b) NotIn operator: NotIn, values: [a, b] La misma regla de clave ausente que `!=`, porque es el mismo operador. COINCIDE
key Exists operator: Exists Cualquier valor, incluido el string vacío. Los values están prohibidos. no coincide
!key DoesNotExist operator: DoesNotExist Falla si la clave está presente con valor vacío — presente sigue siendo presente. COINCIDE

«Tiene la label, y no es prod»

Una sola cláusula no puede decir eso. env!=prod también se lleva todos los recursos sin label env. Pon Exists al lado — las comas significan AND.

BASH
# también se lleva pods sin la label
kubectl get pods -l 'env!=prod'

# tiene una label env, y no es prod
kubectl get pods -l 'env,env!=prod'

El selector vacío, de tres formas

Vacío significa todo; nil significa nada; y un Service omite el campo cuando está vacío, lo que lo deja sin endpoints gestionados.

YAML
# todos los pods del namespace
podSelector: {}

# otra vez todos los recursos
selector:
  matchLabels: {}

# un Service SIN selector: los endpoints
# los gestionas tú a mano
spec:
  ports: [{ port: 80 }]

La valla

Lo que deliberadamente no hace.

Cada punto se estudió y se descartó, porque la alternativa era una respuesta plausible que podía estar mal. Un tester que no puedes auditar es un tester en el que tienes que creer.

Field selectors

Otro mecanismo, con una lista de campos indexados por kind y por versión, casi siempre sin operadores basados en conjuntos. Simularlo offline significaría adivinar qué campos indexa tu clúster.

Gt y Lt de node affinity

Pertenecen a NodeSelectorRequirement, no a LabelSelectorRequirement. Escribir replicas>2 devuelve un mensaje que lo explica, no una comparación que un label selector no puede expresar.

La semántica de namespaceSelector

Un peer de NetworkPolicy combina un namespaceSelector con un podSelector entre namespaces. Sin los objetos Namespace, la respuesta honesta es el podSelector por sí solo.

Todo lo que necesite el clúster

No se contacta con ningún API server, así que no hay lista de pods en vivo, ni resultado de admisión, ni objeto Endpoints. Todo aquí sale del texto que pegaste.

Límites, dichos en lugar de escondidos: hasta 500 documentos de recursos de un pegado de como máximo 500.000 caracteres, y como máximo 100 cláusulas en un selector. El nombre de una clave de label se valida a 63 caracteres, su prefijo de subdominio DNS opcional a 253 y un valor de label a 63 — los mismos límites que aplica el API server.

Siguiente paso

Pega la traza en el canal del incidente.

«Copy report» te da la ejecución completa en texto plano: el selector canónico y luego un bloque por recurso con su veredicto y cada cláusula que lo decidió. Y después sigue — suma lo que el workload reserva de verdad, o comprueba las variables que esperan sus contenedores.

selector-report.txt
Kubernetes Label Selector Tester — 3 of 5 resources match
selector: app=web,tier=frontend

NO MATCH — Pod/web-d
  metadata.labels: app=web, tier=frontnd
  [ok] app=web — label app="web" = "web"
  [no] tier=frontend — label tier="frontnd" ≠ "frontend"

FAQ

Tus preguntas, respondidas.

Toca una pregunta para desplegar la respuesta.

Porque es lo que dice la regla, y es la línea más sorprendente de toda la API de label selectors. En k8s.io/apimachinery, Requirement.Matches resuelve NotIn y != en una sola rama: si el conjunto de labels no tiene la clave, devuelve true. In y == toman la rama opuesta: si falta la clave, devuelven false. Así que env!=prod significa «ninguna label env que diga prod», y un pod sin label env cumple eso perfectamente. Si querías decir «tiene una label env, y no es prod», necesitas dos cláusulas: env,env!=prod — Exists Y NotIn. Este tester marca cada cláusula que se cumple porque la clave está ausente, así nunca tienes que recordar en qué sentido va.

matchLabels es un mapa simple, y cada par se convierte en un requisito de igualdad: {app: web, tier: frontend} es exactamente app=web,tier=frontend. matchExpressions es una lista de entradas {key, operator, values} y es la única forma de escribir los operadores basados en conjuntos In, NotIn, Exists y DoesNotExist. Cuando un selector tiene ambos, apimachinery los une todos con AND — LabelSelectorAsSelector añade cada par de matchLabels y cada expresión a la misma lista de requisitos. En un label selector no hay OR en ningún nivel.

No, y es el error que cometen más a menudo los manifiestos generados. El spec.selector de un Service está tipado como map[string]string, no como LabelSelector: acepta un mapa plano de labels y solo soporta igualdad. Si escribes matchLabels o matchExpressions ahí, el API server rechaza el campo directamente. Deployments, StatefulSets, DaemonSets, Jobs y el podSelector de una NetworkPolicy sí aceptan un LabelSelector de verdad y admiten las dos formas. Pega un manifiesto de Service con matchExpressions en este tester y te avisa, y luego te muestra qué HABRÍA coincidido en un Deployment — así ves el error y la intención a la vez.

Depende de si el campo está vacío o ausente, y no es lo mismo. Un LabelSelector vacío — {}, o matchLabels: {} — es labels.Everything(): coincide con todos los objetos, y por eso una NetworkPolicy con podSelector: {} se aplica a todos los pods del namespace. Un selector nil, en cambio, no coincide con nada: LabelSelectorAsSelector(nil) devuelve labels.Nothing(). Y un Service es un tercer caso: su campo selector se omite cuando está vacío, así que un Service con selector: {} es un Service sin selector, y el controlador de endpoints no gestiona sus endpoints en absoluto.

No. Los dos parsers, la validación y el matcher son JavaScript ejecutándose en tu pestaña — no hay servidor, ni llamada a una API, ni registro, así que se suben 0 bytes. Aquí importa porque un volcado de pods no es texto neutro: lleva referencias a imágenes internas, nombres de nodos, annotations y a veces un token montado como variable de entorno. Esta es la herramienta que puedes usar con salida de producción sin abrir una conversación sobre tratamiento de datos.

Las labels de los pods, no el Service. Pega el manifiesto del Service como selector y los pods reales como recursos: el tester lee spec.selector por ti y muestra una traza por cláusula en cada pod, así una errata de un carácter aparece como label tier="frontnd" ≠ "frontend" en lugar de como una lista de endpoints vacía. Descarta también dos trampas estructurales. Primero, un Service selecciona labels de POD, no las metadata.labels del propio Deployment — por eso este tester lista el spec.template.metadata.labels de un workload como su propia fila «Pod template». Segundo, un selector que no coincide con nada no es un error en ninguna parte de Kubernetes: kubectl lo acepta, el API server lo acepta, y el único síntoma es un objeto Endpoints vacío.

No, y es una frontera deliberada, no una carencia. Los field selectors son otro mecanismo: filtran por los campos propios del objeto, los evalúa el API server contra una lista corta de campos permitidos que varía por tipo de recurso, y casi ninguno soporta operadores basados en conjuntos. Simularlos offline significaría codificar qué campos indexa cada versión de Kubernetes para cada kind, y equivocarse de forma sutil. Esta herramienta cubre los label selectors, que funcionan igual en todos los tipos de recurso y quedan definidos por completo por el objeto que ya tienes en el portapapeles.

Existen, pero no en un label selector. Node affinity usa NodeSelectorRequirement, un tipo aparte cuyo conjunto de operadores es In, NotIn, Exists, DoesNotExist, Gt y Lt. Un LabelSelectorRequirement — el de matchExpressions, spec.selector y podSelector — solo tiene los cuatro primeros. Así que Gt y Lt son válidos en nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution e inválidos en todo lo que mira este tester. Escribe replicas>2 en el campo del selector y te lo dice, en vez de inventar una comparación que un label selector no tiene.

Evalúa los primeros 500 documentos de recursos de un pegado de hasta 500.000 caracteres, y un selector de como máximo 100 cláusulas — cada límite se anuncia en pantalla con la cifra real, así que una ejecución truncada nunca parece completa. Las claves y los valores se validan contra los límites reales: el nombre de una clave de label admite 63 caracteres como máximo, el prefijo de subdominio DNS opcional antes de la / admite 253, y un valor de label admite 63 (el valor vacío es legal). Una clave o un valor inválidos en el SELECTOR son un error duro, porque el API server los rechazaría; una label inválida en un RECURSO es solo una nota, porque lo que preguntaste fue si el selector coincide con él.

More free, private DevOps tools.

El Label Selector Tester es una herramienta de OpsCanopy — una copa creciente de validadores, convertidores y testers que corren en el navegador y nunca tocan un servidor.

39 free tools, every one offline-capable — opscanopy.com works with no signup and nothing uploaded.

Relacionado: Kubernetes Resource Calculator para lo que reserva un workload, Env Example Checker para las variables que espera un contenedor, el Alertmanager Route Tester para el otro árbol de coincidencia por labels que descarta cosas en silencio, y el Convertidor JSON ↔ YAML cuando hay que reformar un manifiesto para kubectl patch — o explora el directorio de herramientas completo.

Se ofrece tal cual por comodidad; confirma siempre la configuración crítica contra el clúster que la va a consumir. OpsCanopy es gratis y abierto.