пятница, 10 марта 2023 г.

Мучение с no_proxy в hadoop-aws

Про боль с настройками прокси для разных приложений в своё время хорошо написали в блоге GitLab. Я лишь немного добавлю про комбинацию Docker, HTTP Proxy и Hadoop-AWS, который мы используем в Apache Spark для записи данных в объектное хранилище.

Ранее я уже писал про тестовое окружение в котором чтобы скачать что-либо за пределами VPC нужно использовать корпоративный прокси-сервер. На CI сервере прокси настроен в Docker и этого достаточно чтобы собирались образы. Настройки прокси пробрасываются внутрь контейнеров в виде переменных окружения (подробности тут). Чтобы прокси не использовался там где не нужно задана переменная окружения "no_proxy" в которой перечислены все исключения на сервисы тестируемого приложения, ядром которого является Apache Spark.

На днях было подготовлено изменение, которое без ошибок проходило тест локально, но проваливало тест на стороне CI сервера. В логах обнаружились ошибки записи данных в объектное хранилище и в сообщении об ошибке фигурировал адрес прокси-сервера. Причина такого поведения нашлась быстро - с новым изменением процесс Spark наследует переменные окружения, которые касаются прокси-сервера (http_proxy, https_proxy и no_proxy). Но все еще непонятно как это влияет - настройки прокси в Java берутся из system properties, а не из переменных окружения (подробности в Java Networking and Proxies). Если бы прокси использовался во всех компонентах Spark, то пострадало бы больше функционала (например регистрация воркеров на мастере).

Поскольку проблема только с записью в S3 совместимое хранилище, то начал искать документацию на hadoop-aws, который используется для работы с S3. Если верить его документации, то настройки прокси берутся из свойств, которые задаются в Spark (fs.s3a.proxy.host, fs.s3a.proxy.port, и т.д.), но ничего подобного у нас не делается.

Далее под подозрение попадает AWS SDK for Java, который используется в hadoop-aws. Использование переменной окружения no_proxy есть в функции getNonProxyHostsEnvironment() и в ней же делается замена "," на "|" чтобы соответствовать формату "http.nonProxyHosts" в Java.

Теперь ясно почему "подтягиваются" настройки прокси и почему это затрагивает только запись в S3. Поскольку Java не поддерживает CIDR записи в http.nonProxyHosts, то добавляю в no_proxy запись через wildcard ("172.16.*"), но и с таким изменением все равно валится ошибка. Если же использовать "*" в переменной no_proxy, то начинает работать, но это сломает сборку Docker образов.

Порядком вымотавшись с этим "детективчиком" добавил в скрипт запуска Spark unset на все переменные, которые связаны с прокси, и пометил как FIXME. Вообще такие фиксы это мина замедленного действия и возможно когда-то прокси приложению понадобится, но лучшего решения пока не смог придумать.

Комментариев нет:

Отправить комментарий