Поиск и фильтрация контейнеров в Marathon: полное практическое руководство | AdminWiki

Поиск и фильтрация контейнеров в Marathon: полное практическое руководство

30 июля 2026 9 мин. чтения

Поиск контейнеров в Marathon начинается с прямого API-запроса к эндпоинту /v2/apps. Если вам нужен конкретный контейнер по ID или имени приложения, используйте GET /v2/apps/{appId}. AppId чувствителен к регистру и всегда начинается с прямого слэша. Базовый запрос с авторизацией через заголовок выглядит так:

curl -s -H "Authorization: token=$MARATHON_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  "https://marathon.example.com/v2/apps//production/backend-service"

В ответе вы получите JSON с полным определением приложения. Ключевые поля для быстрой оценки состояния: tasksRunning (сколько задач сейчас работает), tasksHealthy (сколько прошли health check), tasksUnhealthy (сколько не прошли проверку здоровья) и tasksStaged (ожидают запуска). Если tasksUnhealthy больше нуля - приложение требует немедленного внимания.

Практика показывает, что администраторы тратят до 40% времени инцидента на поиск нужного контейнера среди сотен запущенных. Правильно построенный фильтр сокращает этот этап до одной команды. В этом руководстве собраны готовые шаблоны запросов для всех типовых сценариев: от поиска по меткам до массовых операций перезапуска.

Для сложных случаев, когда стандартных фильтров недостаточно, используется утилита jq - она обрабатывает JSON-вывод Marathon и даёт гранулярный контроль над выборкой. Все примеры ниже протестированы на Marathon 1.11+ и предполагают наличие jq в системе.

Как быстро найти контейнер по ID или имени через Marathon API

Эндпоинт /v2/apps без параметров возвращает список всех приложений. Добавление appId сужает выборку до одного. AppId формируется по иерархическому принципу: группы разделяются слэшами, например /team-alpha/staging/payment-worker.

Частая ошибка - пропуск начального слэша или несовпадение регистра. Marathon считает /MyApp и /myapp разными приложениями. Проверьте точное написание через список всех приложений:

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/apps" | jq '.apps[].id'

Вывод покажет полные идентификаторы. Скопируйте нужный и подставьте в запрос. Поле health в ответе содержит массив результатов проверок: alive означает успех, unreachable - контейнер не отвечает на health check. Для приложений без health check поле будет пустым.

Если приложение не найдено, Marathon возвращает HTTP 404. Причина может быть в удалении приложения или опечатке в appId. В таких случаях поможет диагностика проблем поиска контейнеров - проверьте права доступа к ZooKeeper и актуальность кэша.

Фильтрация контейнеров по меткам: синтаксис и готовые примеры

Метки - основной механизм организации приложений в Marathon. Они задаются при создании приложения в секции labels и позволяют группировать контейнеры по средам, командам, сервисам или любым другим признакам. Фильтрация по меткам выполняется параметром label в query string.

Синтаксис: ?label=KEY==VALUE для точного совпадения и ?label=KEY!=VALUE для исключения. Оператор == чувствителен к регистру. Если значение содержит спецсимволы - пробелы, слэши, двоеточия - его нужно URL-кодировать. Пример поиска всех приложений staging-среды:

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/apps?label=environment==staging" \
  | jq '.apps[] | {id: .id, env: .labels.environment}'

Для поиска по команде используйте метку team:

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/apps?label=team==backend" \
  | jq '.apps | length'

Последняя команда выводит количество приложений backend-команды - удобно для быстрой инвентаризации.

Поиск по нескольким меткам одновременно

Marathon объединяет несколько параметров label через логическое AND. Запрос с двумя метками вернёт только приложения, у которых совпали обе. Это позволяет сужать выборку до конкретного сервиса в конкретной среде:

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/apps?label=environment==staging&label=role==worker" \
  | jq '[.apps[] | {id: .id, env: .labels.environment, role: .labels.role}]'

OR-логика нативно не поддерживается. Если нужно найти приложения с меткой team==backend ИЛИ team==frontend, придётся сделать два запроса и объединить результаты через jq:

{
  curl -s -H "Authorization: token=$TOKEN" \
    "https://marathon.example.com/v2/apps?label=team==backend";
  curl -s -H "Authorization: token=$TOKEN" \
    "https://marathon.example.com/v2/apps?label=team==frontend";
} | jq -s '.[0].apps + .[1].apps | unique_by(.id)'

Этот подход работает для любых несовместимых условий. При большом количестве меток лучше написать скрипт с циклом.

Отбор контейнеров по состоянию: как найти все проблемные инстансы

Marathon не предоставляет прямого фильтра по статусу задачи в query string эндпоинта /v2/apps. Но состояние приложения отражается в полях tasksRunning, tasksHealthy, tasksUnhealthy и tasksStaged. Комбинация /v2/apps и jq решает задачу фильтрации по этим полям.

Поиск всех приложений с проблемами - те, у которых есть нездоровые или застревающие в staged задачи:

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/apps" \
  | jq '[.apps[] | select(.tasksUnhealthy > 0 or .tasksStaged > 0) | {
    id: .id,
    running: .tasksRunning,
    unhealthy: .tasksUnhealthy,
    staged: .tasksStaged
  }]'

Этот запрос - первая команда при инциденте. За 2 секунды вы получаете список всех проблемных приложений кластера. Для production-сред с сотнями контейнеров это экономит 10-15 минут ручного обхода.

Приложения без health check не будут иметь заполненных полей tasksHealthy и tasksUnhealthy. Для них ориентируйтесь на tasksRunning относительно желаемого количества instances. Расхождение означает, что часть задач не смогла запуститься.

Фильтрация задач по статусу (TASK_RUNNING, TASK_FAILED и др.)

Детальный статус каждой задачи доступен через эндпоинт /v2/tasks. Он возвращает плоский список всех задач кластера с их состояниями. Фильтрация через jq по полю state даёт гранулярный контроль:

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/tasks" \
  | jq '[.tasks[] | select(.state == "TASK_FAILED") | {
    appId: .appId,
    taskId: .id,
    state: .state,
    message: .message
  }]'

Основные статусы задач:

  • TASK_RUNNING - задача работает
  • TASK_FAILED - задача завершилась с ошибкой
  • TASK_FINISHED - задача успешно завершилась
  • TASK_STAGING - задача ожидает ресурсов
  • TASK_STARTING - задача запускается
  • TASK_KILLING - задача в процессе остановки
  • TASK_KILLED - задача принудительно остановлена

Поле message в ответе содержит причину сбоя - нехватка памяти, ошибка образа, таймаут health check. Это ключевая информация для диагностики. При большом кластере /v2/tasks возвращает значительный объём данных. Используйте пагинацию через заголовки ответа или фильтруйте по appId на стороне клиента.

Поиск контейнеров по потреблению ресурсов: CPU и память

Marathon хранит запрошенные ресурсы в определении приложения: cpus (дробное число ядер) и mem (мегабайты). Эти значения - лимиты, которые контейнер запросил у Mesos. Реальное потребление может отличаться, для него нужны метрики Mesos или системы мониторинга.

Сортировка приложений по убыванию CPU - быстрый способ найти самых тяжёлых потребителей:

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/apps" \
  | jq '[.apps[] | {id: .id, cpus: .cpus, mem: .mem}] | sort_by(-.cpus)'

Поиск приложений с памятью больше 1024 МБ:

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/apps" \
  | jq '[.apps[] | select(.mem > 1024) | {id: .id, mem: .mem}]'

Эти запросы помогают при планировании ресурсов кластера и поиске приложений с завышенными лимитами. Приложение, запросившее 8 CPU, но использующее 0.1 - кандидат на оптимизацию. Для мониторинга реального потребления настройте связку Prometheus и Grafana, как описано в руководстве по мониторингу контейнеров.

Массовые операции: перезапуск и масштабирование отфильтрованных контейнеров

Результаты фильтрации можно направить на вход циклу, выполняющему действия над группой приложений. Типовой сценарий: перезапустить все контейнеры с определённой меткой после изменения конфигурации или для применения нового образа.

Базовый шаблон: получить список appId через фильтр, затем в цикле отправить PUT-запрос на эндпоинт /v2/apps/{appId}/restart. Для масштабирования используется PUT на /v2/apps/{appId} с телом {"instances": N}.

Меры предосторожности при массовых операциях:

  • Добавьте подтверждение перед выполнением - выведите список затрагиваемых приложений и запросите ввод
  • Ограничьте количество одновременных операций - Marathon может отклонить запросы при превышении лимита
  • Проверяйте HTTP-код ответа каждого запроса - одиночный сбой не должен останавливать всю операцию

Пример скрипта для перезапуска всех приложений с определенной меткой

Скрипт получает список appId приложений с меткой environment==staging, выводит их для подтверждения и выполняет перезапуск каждого с задержкой 2 секунды между запросами:

#!/bin/bash

MARATHON_URL="https://marathon.example.com"
AUTH_TOKEN="$MARATHON_AUTH_TOKEN"
LABEL_FILTER="environment==staging"

echo "Получение списка приложений с меткой $LABEL_FILTER..."

APP_IDS=$(curl -s -H "Authorization: token=$AUTH_TOKEN" \
  "$MARATHON_URL/v2/apps?label=$LABEL_FILTER" \
  | jq -r '.apps[].id')

if [ -z "$APP_IDS" ]; then
  echo "Приложения не найдены. Выход."
  exit 0
fi

echo "Будут перезапущены следующие приложения:"
echo "$APP_IDS"
echo ""
read -p "Подтвердите операцию (yes/no): " CONFIRM

if [ "$CONFIRM" != "yes" ]; then
  echo "Операция отменена."
  exit 0
fi

for APP_ID in $APP_IDS; do
  echo "Перезапуск $APP_ID..."
  HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
    -X PUT -H "Authorization: token=$AUTH_TOKEN" \
    -H "Content-Type: application/json" \
    "$MARATHON_URL/v2/apps${APP_ID}/restart")

  if [ "$HTTP_CODE" -eq 200 ]; then
    echo "  Успешно (HTTP $HTTP_CODE)"
  else
    echo "  Ошибка (HTTP $HTTP_CODE)"
  fi

  sleep 2
done

echo "Операция завершена."

Скрипт требует установленного jq. Переменная MARATHON_AUTH_TOKEN должна быть задана в окружении. Задержка в 2 секунды предотвращает перегрузку Marathon API - при сотнях приложений увеличьте её до 5 секунд.

Экспорт данных о контейнерах для отчетности и аудита

Регулярный сбор информации о контейнерах нужен для инвентаризации, аудита безопасности и планирования ресурсов. Marathon API возвращает JSON, который легко преобразуется в CSV для дальнейшего анализа в таблицах или системах отчётности.

Пример jq-фильтра для выборки ключевых полей и экспорта в CSV с заголовками:

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/apps" \
  | jq -r '["id","cpus","mem","instances","labels"],
    (.apps[] | [
      .id,
      .cpus,
      .mem,
      .instances,
      (.labels | to_entries | map("\(.key)=\(.value)") | join(";"))
    ]) | @csv' > marathon_inventory.csv

Этот однострочник создаёт CSV-файл с идентификатором приложения, запрошенными CPU, памятью, количеством экземпляров и всеми метками, склеенными через точку с запятой. Файл открывается в Excel, Google Sheets или загружается в системы аналитики.

Для регулярного сбора настройте cron-задачу, выполняющую скрипт раз в сутки. Результаты можно складывать в директорию с датой в имени файла - получится история изменений кластера за любой период. При аудите безопасности такой архив незаменим: вы всегда знаете, какие контейнеры работали в конкретный день и с какими метками.

Если кластер управляется через Kubernetes, аналогичный подход к сбору метрик описан в руководстве по диагностике подов и узлов - принципы фильтрации и экспорта данных схожи.

Поиск контейнеров по версии образа (image)

Информация об образе контейнера хранится в секции container.docker.image определения приложения. Поиск по этому полю выявляет приложения с устаревшими версиями или использующие тег :latest, что создаёт риски неконтролируемых обновлений.

Поиск всех приложений, использующих тег :latest:

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/apps" \
  | jq '[.apps[] | select(.container.docker.image | endswith(":latest")) | {
    id: .id,
    image: .container.docker.image
  }]'

Поиск приложений с конкретным тегом, например :v1.0:

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/apps" \
  | jq '[.apps[] | select(.container.docker.image | contains(":v1.0")) | {
    id: .id,
    image: .container.docker.image
  }]'

Использование :latest в production-окружении опасно: перезапуск контейнера может подтянуть новую версию образа, не протестированную в вашем окружении. Результат - внезапная деградация сервиса. Найдите такие приложения первым запросом и замените тег на фиксированную версию.

Поиск приложений вообще без тега (используется образ по умолчанию :latest неявно):

curl -s -H "Authorization: token=$TOKEN" \
  "https://marathon.example.com/v2/apps" \
  | jq '[.apps[] | select(.container.docker.image | test(":[^/]+$") | not) | {
    id: .id,
    image: .container.docker.image
  }]'

Этот запрос находит образы без двоеточия и тега - они так же опасны, как явный :latest. После выявления проблемных приложений обновите определения, указав конкретную версию образа, и выполните плановый перезапуск.

Для отладки проблем с контейнерами после смены образа используйте шпаргалку команд Docker - там собраны проверенные практики диагностики падающих контейнеров и анализа логов.

Поделиться:
Сохранить гайд? В закладки браузера