← Kubernetes: основы
6 мин · просто · Урок 10 из 11

Labels и селекторы

По каким меткам объекты кластера находят друг друга и как их фильтровать через -l.

Что такое label

Label это пара ключ-значение в поле metadata.labels любого ресурса. И ключ, и значение - строки.

metadata:
  name: web-1
  labels:
    app: web
    env: prod

Label служит не для описания. По нему объекты в кластере находят друг друга. Service по label находит свои Pod. Deployment по label считает, какие реплики принадлежат ему. NetworkPolicy - правило, которое ограничивает сетевой трафик между Pod. Она тоже опирается на label, чтобы выбрать, к каким Pod применяется. Pod без label почти бесполезен: ни один Service на него не наведётся.

Annotation - произвольная пометка на объекте (metadata.annotations). Выглядит как label, но служит другому: это данные для инструментов. По annotation нельзя фильтровать. Если значение нужно для поиска, клади его в label. Если это просто заметка, клади в annotation.

Признакmetadata.labelsmetadata.annotations
Фильтр -lработаетне работает
Кто читаетService, Deployment, NetworkPolicyвнешние инструменты
Что кластьзначение для поисказаметку

Фильтрация через -l

Флаг -l (или --selector) фильтрует ресурсы по label. Простейшая форма проверяет равенство:

kubectl get pod -l app=web

Команда покажет только Pod с label app=web. Условия можно соединять через запятую, это логическое И:

kubectl get pod -l app=web,env=prod

Неравенство пишется через !=:

kubectl get pod -l env!=dev

Есть и более гибкий синтаксис на множествах (set-based):

kubectl get pod -l 'env in (prod, staging)'
kubectl get pod -l 'env notin (dev)'
kubectl get pod -l 'tier'             # есть label tier с любым значением
kubectl get pod -l '!tier'            # нет label tier вообще

Кавычки здесь обязательны. Без них оболочка интерпретирует скобки и восклицательный знак как спецсимволы, и команда сломается.

Большая буква -L работает иначе. kubectl get pod -L app,env не фильтрует, а добавляет значения этих label в вывод как колонки.

Ещё один способ посмотреть метки:

kubectl get pod --show-labels

Команда kubectl label

Навесить label:

kubectl label pod web-1 tier=backend

Поменять значение существующего label (нужен --overwrite, иначе ошибка):

kubectl label pod web-1 tier=frontend --overwrite

Снять label (суффикс - после ключа, без значения):

kubectl label pod web-1 tier-

Применить сразу к нескольким Pod по селектору:

kubectl label pod -l app=db tier=backend
kubectl label pod --all env-

-l app=db пройдётся по всем Pod, у которых уже есть label app=db. --all берёт все Pod в namespace без условий.

Зачем это нужно

Service ищет свои Pod через поле spec.selector. Это label-селектор такого же вида:

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 80

Selector это не ссылка на объект, а совпадение строк. Никто не проверяет, что метка с такой парой ключ-значение вообще существует в кластере.

Ключи label регистрозависимы. app и App - это разные ключи. Если в селекторе написать App: web, а Pod лежат с app: web, Service не найдёт ни одного Pod. Ошибки при этом не будет, просто список endpoints (реальные адреса Pod за Service) останется пустым.

Смотрят его так:

kubectl get endpointslice -l kubernetes.io/service-name=web

Старая команда kubectl get endpoints web выводит то же самое, но объект v1 Endpoints deprecated с 1.33 и kubectl печатает про это предупреждение.

Если снять label app=web у работающего Pod, он выпадет из Service. Снаружи это выглядит как «Pod в статусе Running, а трафика нет».

Deployment держит свои Pod через spec.selector.matchLabels. Если у Pod убрать подходящий label, Deployment перестанет его видеть и поднимет новый Pod на замену. Старый Pod останется висеть в namespace без управления. Это полезно для разбора инцидента: Pod жив, но изолирован от системы.

Домашка

Теорию закрепляет задание на своём кластере: 3 шага с проверкой. Кластер поднимается по треку Kubernetes локально, задания лежат в репозитории k8s-practice.

./run.sh start k8s-labels-selectors     # развернуть стартовое состояние
./run.sh verify k8s-labels-selectors    # проверить текущий шаг

Коротко

Прошли материал до конца? Отметьте урок пройденным.