2025, Oct 01 21:17

Как выявить реальные конфликты зависимостей при апгрейде Cloud Composer

Почему при апгрейде Cloud Composer pip сыплет предупреждения про google-cloud-aiplatform и как воспроизвести окружение, чтобы найти конфликты зависимостей.

Обновление окружения Cloud Composer нередко оборачивается потоком предупреждений о зависимостях, за которым теряются реальные причины сбоев. Типичный пример — апгрейд с composer-2.13.9-airflow-2.9.3 до composer-2.13.9-airflow-2.10.5, когда pip снова и снова выводит сообщения вокруг google-cloud-aiplatform и extra с именем evaluation. Кажется, что резолвер «крутится на месте», а какие пакеты действительно конфликтуют — неочевидно.

Проблема в контексте

Во время обновления резолвер зависимостей многократно печатает строки вида:

WARNING: google-cloud-aiplatform 0.7.1 does not provide the extra 'evaluation'
WARNING: google-cloud-aiplatform 0.7.0 does not provide the extra 'evaluation'
WARNING: google-cloud-aiplatform 0.6.0 does not provide the extra 'evaluation'
WARNING: google-cloud-aiplatform 0.5.1 does not provide the extra 'evaluation'
WARNING: google-cloud-aiplatform 0.5.0 does not provide the extra 'evaluation'
WARNING: google-cloud-aiplatform 0.4.0 does not provide the extra 'evaluation'
WARNING: google-cloud-aiplatform 0.3.1 does not provide the extra 'evaluation'

По выводу кажется, будто резолвер зациклился, но он не указывает, какие именно зависимости вашего проекта не согласуются с пакетами образа Composer.

Что на самом деле происходит

Из-за «шума» предупреждений легко пропустить настоящий набор конфликтов. На практике корень проблемы часто в жёстких фиксациях версий в ваших собственных требованиях, которые не совпадают с версиями, включёнными в целевой образ Composer. Интерфейс Composer может не показать точные детали конфликта. Повторение установки локально — с тем же Python и тем же набором пакетов, что и в образе — позволяет увидеть конкретные несовместимости.

Воспроизведите локально и выявите реальные конфликты

Сначала создайте чистое виртуальное окружение под тот же Python, что использует ваш образ Composer. В описанном случае это Python 3.11.8. Перед началом убедитесь в версии интерпретатора.

python3.11 -m venv .env_sync
source .env_sync/bin/activate
python --version  # Ожидается 3.11.8
pip install --upgrade pip

Далее установите пакеты, соответствующие конкретно вашему образу Composer. В официальной документации по версиям указаны и версия Python, и набор пакетов для каждого билда Composer. Подготовьте requirements-файл на основе этого списка. Минимальный фрагмент, важный для конфликта, выглядел так:

apache-airflow==2.10.5+composer
google-cloud-aiplatform==1.108.0
google-cloud-bigquery==3.35.1
python-dateutil==2.9.0.post0
requests==2.32.4
backoff==2.2.1

Если какие-то мелкие пакеты не устанавливаются локально из‑за особенностей платформы или версии Python и при этом не важны для вашего проекта, их можно временно исключить, чтобы завершить анализ. В описанном случае локально исключили клиент mysql.

Теперь установите набор пакетов Composer вместе с зависимостями вашего проекта и внимательно просмотрите логи:

pip install -r composer-locked.txt -r local-requirements.txt

Этот шаг выявит конфликты, которые резолвер Composer мог «спрятать». Например, локальный резолвер показал следующее:

ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
mypackage 1.74.0 requires google-cloud-bigquery~=3.16.0, but you have google-cloud-bigquery 3.35.1 which is incompatible.
mypackage 1.74.0 requires python-dateutil~=2.8.2, but you have python-dateutil 2.9.0.post0 which is incompatible.
mypackage 1.74.0 requires requests~=2.31.0, but you have requests 2.32.4 which is incompatible.
analytics-python 1.4.post1 requires backoff==1.10.0, but you have backoff 2.2.1 which is incompatible.

Именно эти явные сообщения и полезны. Корректировка локальных пинов в соответствии с рекомендациями убрала реальные блокеры. После этого окружение Composer без проблем обновилось до composer-2.14.0-airflow-2.10.5.

Почему этот подход работает

Образ Composer включает большую, жёстко согласованную экосистему вокруг Airflow и его провайдеров. Когда ваши фиксации версий расходятся с этими зависимостями, вывод управляемого резолвера может быть шумным и не указывать на истинную причину. Зеркалирование среды локально — с той же версией Python и тем же набором пакетов образа — заставляет pip выдавать прямые и полезные диагностические сообщения о конфликтах. Если встречаются пакеты, проблемные на вашей машине, но не относящиеся к проекту, их локальное исключение помогает сосредоточиться на реальных несовместимостях. Подсказки на Stack Overflow также могут помочь найти версии пакетов, которые локально не заработают.

Практический результат

Вместо попыток «приглушить» предупреждения про evaluation, сосредоточьтесь на полном воспроизведении установки локально и согласовании собственных зависимостей с образом Composer. В описанном случае выравнивание версий google-cloud-bigquery, python-dateutil, requests и backoff сняло блокировки и сделало обновление прямолинейным.

Выводы

Воспринимайте зацикленные предупреждения резолвера как симптом, а не первопричину. Совместите версию Python, установите точный набор пакетов из образа Composer вместе с зависимостями проекта и доверьтесь локальному резолверу pip — он укажет, что действительно конфликтует. Сначала устраните конкретные несовпадения версий — и обновление пройдёт без сюрпризов.

Статья основана на вопросе на StackOverflow от FVCC и ответе автора FVCC.