Распределенные системы. Паттерны проектирования - страница 15

стр.

Модульность и возможность повторного применения, как и до-стижение  модульности  в  разработке  высококлассного  про-граммного  обеспечения,  требуют  сосредоточенности  и  дисци-плины. В частности, необходимо сконцентрироваться на таких  трех составляющих, как:

‰ ‰> параметризация контейнеров;

‰ ‰> создание программного интерфейса контейнеров; ‰ ‰> документирование работы контейнера. Параметризованные контейнеры Параметризация контейнеров — важнейший показатель дости-жения модульности и повторного использования контейнеров,  независимо от того, реализуют они паттерн Sidecar или нет. Что я понимаю под параметризацией? Представьте, будто кон-тейнер — это функция в программе. Сколько у нее параметров?  Каждый параметр представляет собой входные данные, которые  помогают подстроить обобщенный контейнер под конкретную  ситуацию.  Рассмотрим,  к  примеру,  контейнер-прицеп  с  SSL,  который мы развернули ранее. Чтобы быть полезным в общем  случае,  он  должен  иметь  по  меньшей  мере  два  параметра:  имя  сертификата, обеспечивающего функциональность SSL, и порт  унаследованного сервера  приложений,  запущенного  на  ло-кальной  машине.  Без  этих  параметров  трудно  сказать,  что  он  будет  полезен  для  широкого  спектра  приложений.  Похожие  параметры есть во всех контейнерах-прицепах, рассмотренных  в данной главе.

Глава 2. Паттерн Sidecar 45

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

менных среды. Пример передачи параметра контейнеру: docker run -e=PORT=<порт> -d <образ>

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

К примеру, можно передать путь к сертификату и порт прило-жения в виде переменных среды следующим образом: docker run -e=PROXY_PORT=8080 \

-e=CERTIFICATE_PATH=/путь/к/сертификату.crt ... Сценарий в контейнере воспользуется значениями этих перемен-ных  для  формирования  конфигурационного  файла  nginx.conf ,  который  укажет  серверу,  где  искать  файл  сертификата  и  куда  переадресовывать запросы.

Определение API всех контейнеров Если  учитывать,  что  вы  параметризуете  свои  контейнеры,  будет  очевидно, что каждый из них определяет некую «функцию», кото-рая вызывается при запуске контейнера. Эта функция является ча-стью API, определяемого вашим контейнером, но у него есть и дру-гие  составляющие,  включая  вызовы  к  внешним  по  отношению  46 Часть I. Одноузловые паттерны проектирования

к  контейнеру  сервисам  и  предоставляемые  контейнером  API-услуги, доступные по HTTP или любым другим способом. Думая о модульности и повторном использовании контейнеров,  важно понимать, что программный интерфейс (API) контейнера  определяется  всеми  его  аспектами  взаимодействия  с  внешней  средой.  Как  и  в  среде  микросервисов,  микроконтейнеры   рас-считывают  на  наличие  некоторого  программного  интерфейса,  который  бы  четко  разделил  основное  приложение  и  контей-нер-прицеп. Кроме того, наличие API гарантирует, что все по-требители контейнера-прицепа будут работать корректно даже  после выхода последующих его версий. В то же время наличие  четкого  API  у  контейнера-прицепа  позволяет  его  создателю  более  эффективно  работать,  поскольку  в  этом  случае  у  него  есть четкое определение услуг, предоставляемых контейнером  (а желательно и юнит-тестов для них).

Чтобы  понять,  насколько  важно  уделять  внимание  API  кон-тейнера, рассмотрим упомянутый ранее контейнер-прицеп для  управления конфигурацией. Для него мог бы оказаться полез-ным параметр  UPDATE_FREQUENCY , задающий частоту, с которой  необходимо  синхронизировать  конфигурацию  с  файловой  си-стемой. Очевидно, что если название параметра потом поменя-ется  на,  скажем,  UPDATE_PERIOD ,  то  это  уже  будет  нарушением  интерфейса  контейнера  и  воспрепятствует  его  корректному  применению другими пользователями.