Перенос приложений Tomcat в контейнеры в Службе Azure Kubernetes

Узнайте, что следует учитывать при переносе существующего приложения Tomcat для запуска в контейнере Службы Azure Kubernetes (AKS).

Подготовка к миграции

Чтобы обеспечить успешную миграцию, перед ее началом выполните шаги оценки и инвентаризации, описанные в следующих разделах.

Проверка внешних ресурсов

Внешние ресурсы, такие как источники данных, брокеры сообщений JMS и другие, внедряются с помощью API JNDI (Java Naming and Directory Interface). Возможно, для некоторых из этих ресурсов потребуется выполнить перенос или перенастройку.

В приложении

Проверьте файл META-INF/context.xml. Найдите элементы <Resource> в элементе <Context>.

На серверах приложений

Проверьте файлы $CATALINA_BASE/conf/context.xml и $CATALINA_BASE/conf/server.xml, а также файлы с расширением .xml в каталогах $CATALINA_BASE/conf/[имя_модуля]/[имя_узла].

В файлах context.xml для описания ресурсов JNDI будут использоваться элементы <Resource> в элементе <Context> верхнего уровня.

В файлах server.xml для описания ресурсов JNDI будут использоваться элементы <Resource> в элементе <GlobalNamingResources>.

Источники данных

Источники данных — это ресурсы JNDI с атрибутом type, для которого задано значение javax.sql.DataSource. Для каждого источника данных запишите следующие сведения:

  • имя источника данных;
  • конфигурация пула подключений;
  • путь к JAR-файлу драйвера JDBC.

Дополнительные сведения см. в руководстве по использованию источника данных JNDI в документации по Tomcat.

Другие связанные внешние ресурсы

Нет смысла описывать все возможные внешние зависимости, перечисленные в этом руководстве. Ваша команда должна убедиться в том, что после переноса все внешние зависимости приложения будут доступными.

Проверка секретов

Пароли и защищенные строки

Проверьте все свойства и файлы конфигурации на рабочих серверах на наличие секретных строк и паролей. Обязательно проверьте файлы server.xml и context.xml в каталоге $CATALINA_BASE/conf. Кроме того, в приложении есть файлы конфигурации, содержащие пароли или учетные данные. К ним может относиться файл META-INF/context.xml, а для приложений Spring Boot — файлы application.properties и application.yml.

Определение того, используется ли файловая система и как именно она используется

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

Статическое содержимое только для чтения

Если ваше приложение сейчас обслуживает статическое содержимое, вам потребуется альтернативное расположение для этого статического содержимого. Вы можете переместить статическое содержимое в хранилище BLOB-объектов Azure и включить Azure CDN для быстрого скачивания в глобальном масштабе. Дополнительные сведения см. в статье "Размещение статических веб-сайтов" в служба хранилища Azure и кратком руководстве. Интеграция учетной записи хранения Azure с Azure CDN. Вы также можете напрямую развернуть статическое содержимое в приложении в плане Azure Spring Apps Enterprise. Дополнительные сведения см. в разделе "Развертывание статических веб-файлов".

Динамически опубликованное статическое содержимое

Если приложение допускает использование статического содержимого, которое передается или создается приложением и после этого становится неизменяемым, вы можете использовать хранилище BLOB-объектов Azure и Azure CDN, как описано выше, с Функциями Azure для выполнения отправки и обновления CDN. Практический пример реализации см. в руководстве по отправке и предварительной загрузке статического содержимого CDN с помощью Функций Azure. Вы также можете напрямую развернуть статическое содержимое в приложении в плане Azure Spring Apps Enterprise. Дополнительные сведения см. в разделе "Развертывание статических веб-файлов".

Динамическое или внутреннее содержимое

Для использования файлов, которые часто записываются и считываются приложением (например, временные файлы данных), или статических файлов, видимых только для вашего приложения, вы можете подключить общие папки службы хранилища Azure в качестве постоянных томов. См. сведения о динамическом создании и использовании постоянного тома с Файлами Azure в Службе Azure Kubernetes.

Определение механизма сохранения сеанса

Чтобы узнать, какой используется диспетчер сохраняемости сеансов, изучите файлы context.xml в приложении и конфигурации Tomcat. Найдите элемент <Manager> и запишите значение атрибута className.

Встроенные реализации Tomcat PersistentManager, например StandardManager или FileStore, не предназначены для использования с распределенной, масштабируемой платформой, такой как Kubernetes. AKS может распределять нагрузку между несколькими группами pod и прозрачно перезапускать любую группу в любое время, поэтому не рекомендуется сохранять изменяющееся состояние в файловой системе.

Если требуется сохранение сеанса, необходимо использовать альтернативную реализацию PersistentManager, которая будет выполнять запись во внешнее хранилище данных, например VMware Tanzu Session Manager с Redis Cache. См. сведения о том, как использовать Redis в качестве кэша сеансов с Tomcat.

Особые случаи

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

Определение того, использует ли приложение запланированные задания

Запланированные задания, такие как задачи планировщика Quartz или задания Cron, нельзя использовать с контейнерными развертываниями Tomcat. Если приложение масштабируется, одно запланированное задание может выполняться несколько раз в течение указанного периода. Это может привести к нежелательным последствиям.

Проверьте все запланированные задания на сервере приложений или за его пределами.

Определение того, содержит ли приложение код, зависящий от ОС

Если приложение содержит код, поддерживающий ОС, в которой работает приложение, необходимо выполнить рефакторинг приложения, чтобы приложение НЕ зависело от базовой ОС. Например, все используемые символы / или \ в путях файловой системы необходимо изменить на File.Separator или Path.get.

Определение того, используется ли MemoryRealm

Для работы MemoryRealm требуется сохраненный XML-файл. В Kubernetes этот файл должен быть добавлен в образ контейнера или передан в общее хранилище, доступное контейнерам. Необходимо соответствующим образом изменить параметр pathName.

Чтобы определить, используется ли сейчас MemoryRealm, изучите файлы server.xml и context.xml и найдите элементы <Realm>, в которых для атрибута className задано значение org.apache.catalina.realm.MemoryRealm.

Определение того, используется ли отслеживание сеансов SSL

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

Определение того, используется ли AccessLogValve

Если используется AccessLogValve, для параметра directory укажите подключенную общую папку Файлов Azure или один из подкаталогов.

Тестирование на месте

Прежде чем создавать образы контейнеров, перенесите приложение в JDK и Tomcat для использования в AKS. Тщательно протестируйте приложение, чтобы обеспечить совместимость и высокую производительность.

Параметризация конфигурации

В ходе предварительной миграции будут определены секреты и внешние зависимости, такие как источники данных, в файлах server.xml и context.xml. Для каждого определенного элемента измените имя пользователя, пароль, строку подключения или URL-адрес на переменную среды.

Например, предположим, что файл context.xml содержит следующий элемент:

<Resource
    name="jdbc/dbconnection"
    type="javax.sql.DataSource"
    url="jdbc:postgresql://postgresdb.contoso.com/wickedsecret?ssl=true"
    driverClassName="org.postgresql.Driver"
    username="postgres"
    password="t00secure2gue$$"
/>

В этом случае его можно изменить, как показано в следующем примере.

<Resource
    name="jdbc/dbconnection"
    type="javax.sql.DataSource"
    url="${postgresdb.connectionString}"
    driverClassName="org.postgresql.Driver"
    username="${postgresdb.username}"
    password="${postgresdb.password}"
/>

Миграция

Мы рекомендуем выполнить следующие действия для каждого приложения (WAR-файл), которое вы хотите перенести, за исключением первого шага — подготовки реестра контейнеров и AKS.

Примечание.

Некоторые развертывания Tomcat могут иметь несколько приложений, работающих на одном сервере Tomcat. Если это справедливо для вашего развертывания, мы настоятельно рекомендуем запускать каждое приложение в отдельной группе pod. Это позволяет оптимизировать использование ресурсов для каждого приложения, уменьшая сложность и сокращая степень взаимозависимости.

Подготовка реестра контейнеров и AKS

Создайте реестр контейнеров и кластер Azure Kubernetes, субъект-служба которого имеет роль читателя в реестре. Не забудьте выбрать соответствующую модель сети в соответствии с требованиями к сети кластера.

az group create \
    --resource-group $resourceGroup \
    --location eastus
az acr create \
    --resource-group $resourceGroup \
    --name $acrName \
    --sku Standard
az aks create \
    --resource-group $resourceGroup \
    --name $aksName \
    --attach-acr $acrName \
    --network-plugin azure

Подготовка артефактов развертывания

Клонируйте репозиторий Tomcat on Containers QuickStart на GitHub. Он содержит файлы конфигурации Dockerfile и Tomcat с несколькими рекомендуемыми оптимизациями. В описанных ниже шагах мы рассмотрим изменения, которые следует внести в эти файлы, прежде чем создавать образ контейнера и развертывать его в AKS.

Открытие портов для кластеризации (при необходимости)

Если вы планируете использовать кластеризацию Tomcat в AKS, убедитесь, что в Dockerfile открыты необходимые диапазоны портов. Чтобы указать IP-адрес сервера в файле server.xml, используйте значение переменной, инициализированной при запуске контейнера, в качестве IP-адреса группы pod.

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

Чтобы определить, использует ли приложение кластеризацию, найдите элемент <Cluster> в элементах <Host> или <Engine> в файле server.xml.

Добавление ресурсов JNDI

Измените файл server.xml, добавив в него ресурсы, подготовленные на шагах, выполняемых перед миграцией, например источники данных.

Например:

<!-- Global JNDI resources
      Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml"
               />

    <!-- Migrated datasources here: -->
    <Resource
        name="jdbc/dbconnection"
        type="javax.sql.DataSource"
        url="${postgresdb.connectionString}"
        driverClassName="org.postgresql.Driver"
        username="${postgresdb.username}"
        password="${postgresdb.password}"
    />
    <!-- End of migrated datasources -->
</GlobalNamingResources>

Дополнительные инструкции по источникам данных JNDI см. в следующих разделах этого руководства в документации по Tomcat:

Сборка и отправка образа

Самый простой способ создать и передать образ в Реестр контейнеров Azure (ACR) для использования в AKS — с помощью команды az acr build. Для выполнения этой команды устанавливать Docker на компьютере не нужно. Например, если у вас есть соответствующий файл Dockerfile и пакет приложения petclinic.war в текущем каталоге, вы можете создать образ контейнера в ACR, выполнив один шаг.

az acr build \
    --image "${acrName}.azurecr.io/petclinic:{{.Run.ID}}" \
    --registry $acrName \
    --build-arg APP_FILE=petclinic.war \
    --build-arg=prod.server.xml .

Можно опустить параметр --build-arg APP_FILE..., если WAR-файл называется ROOT.war. Можно опустить параметр --build-arg SERVER_XML..., если XML-файл сервера называется server.xml. Оба файла должны находиться в том же каталоге, что и Dockerfile.

Или же вы можете использовать Docker CLI, чтобы создать образ локально. Такой подход упрощает тестирование и дополнительную настройку образа перед первым развертыванием в ACR. Но для этого нужно установить Docker CLI и запустить управляющую программу Docker.

# Build the image locally
sudo docker build . --build-arg APP_FILE=petclinic.war -t "${acrName}.azurecr.io/petclinic:1"

# Run the image locally
sudo docker run -d -p 8080:8080 "${acrName}.azurecr.io/petclinic:1"

# Your application can now be accessed with a browser at http://localhost:8080.

# Log into ACR
sudo az acr login --name $acrName

# Push the image to ACR
sudo docker push "${acrName}.azurecr.io/petclinic:1"

Дополнительные сведения см. в модуле Learn для создания и хранения образов контейнеров в Azure.

Подготовка общедоступного IP-адреса

Если ваше приложение должно быть доступным за пределами внутренней или виртуальной сети, требуется общедоступный статический IP-адрес. Этот IP-адрес должен быть подготовлен в группе ресурсов узла кластера.

export nodeResourceGroup=$(az aks show \
    --resource-group $resourceGroup \
    --name $aksName \
    --query 'nodeResourceGroup' \
    --output tsv)
export publicIp=$(az network public-ip create \
    --resource-group $nodeResourceGroup \
    --name applicationIp \
    --sku Standard \
    --allocation-method Static \
    --query 'publicIp.ipAddress' \
    --output tsv)
echo "Your public IP address is ${publicIp}."

Развертывание в AKS

Создайте и примените файлы Kubernetes YAML. Если вы создаете внешний балансировщик нагрузки (как для приложения, так и для входящего контроллера), обязательно укажите IP-адрес, подготовленный в предыдущем разделе, в качестве LoadBalancerIP.

Включите внешние параметры в качестве переменных среды. Не включайте секреты (например, пароли, ключи API и строки подключения JDBC). Сведения о секретах см. в разделе Настройка хранилища ключей FlexVolume.

Настройка постоянного хранилища

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

Чтобы хранить журналы централизованно, вы можете создать постоянный том с помощью службы "Файлы Azure", подключенной к каталогу журналов Tomcat (/tomcat_logs). См. сведения о динамическом создании и использовании постоянного тома с Файлами Azure в Службе Azure Kubernetes (AKS).

Настройка хранилища ключей FlexVolume

Создайте хранилище ключей в Azure и укажите все необходимые секреты. Затем настройте хранилище ключей FlexVolume, чтобы сделать эти секреты доступными для групп pod.

Вам нужно изменить скрипт запуска (startup.sh в репозитории Tomcat on Containers на GitHub), чтобы импортировать сертификаты в локальное хранилище ключей в контейнере.

Перенос запланированных заданий

Чтобы выполнить запланированные задания в кластере AKS, определите требуемые задания Cron.

После миграции

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