Tomcat 애플리케이션을 Azure Container Apps로 마이그레이션
이 가이드에서는 ACA(Azure Container Apps)에서 실행되도록 기존 Tomcat 애플리케이션을 마이그레이션할 때 알아야 할 사항에 대해 설명합니다.
사전 마이그레이션
마이그레이션을 성공적으로 수행하려면 시작하기 전에 다음 섹션에서 설명하는 평가 및 인벤토리 단계를 완료합니다.
인벤토리 외부 리소스
데이터 원본, JMS 메시지 브로커 등과 같은 외부 리소스는 JNDI(Java 명명 및 디렉터리 인터페이스)를 통해 삽입됩니다. 이러한 리소스 중 일부는 마이그레이션 또는 재구성이 필요할 수 있습니다.
애플리케이션 내부
META-INF/context.xml 파일을 검사합니다. <Context>
요소 내에서 <Resource>
요소를 찾습니다.
애플리케이션 서버에서
$CATALINA_BASE/conf/context.xml 및 $CATALINA_BASE/conf/server.xml 파일과 $CATALINA_BASE/conf/[engine-name]/[host-name] 디렉터리에 있는 .xml 파일을 검사합니다.
context.xml 파일에서 JNDI 리소스는 최상위 <Context>
요소 내의 <Resource>
요소에 의해 설명됩니다.
server.xml 파일에서 JNDI 리소스는 <GlobalNamingResources>
요소 내의 <Resource>
요소로 설명됩니다.
Datasources
데이터 원본은 특성이 type
.로 설정된 javax.sql.DataSource
JNDI 리소스입니다. 각 데이터 원본에 대해 다음 정보를 문서화합니다.
- 데이터 원본 이름은 무엇인가요?
- 연결 풀 구성이란?
- JDBC 드라이버 JAR 파일은 어디에서 찾을 수 있나요?
자세한 내용은 Tomcat 설명서의 JNDI Datasource HOW-TO를 참조하세요.
기타 모든 외부 리소스
이 가이드에서 가능한 모든 외부 종속성을 문서화하는 것은 불가능합니다. 마이그레이션 후 애플리케이션의 모든 외부 종속성을 충족할 수 있는지 확인하는 것은 팀의 책임입니다.
인벤토리 비밀
암호 및 보안 문자열
프로덕션 서버의 모든 속성 및 구성 파일에서 비밀 문자열 및 암호를 확인합니다. $CATALINA_BASE/conf에서 server.xml 및 context.xml 확인해야 합니다. 애플리케이션 내에서 암호 또는 자격 증명을 포함하는 구성 파일을 찾을 수도 있습니다. 여기에는 META-INF/context.xml 및 Spring Boot 애플리케이션, application.properties 또는 application.yml 파일이 포함될 수 있습니다.
파일 시스템의 사용 여부 및 방법 확인
애플리케이션 서버에서 파일 시스템을 사용하려면 재구성하거나 드물게 아키텍처 변경이 필요합니다. 다음 시나리오의 일부 또는 전부를 식별할 수 있습니다.
읽기 전용 정적 콘텐츠
애플리케이션에서 현재 정적 콘텐츠를 제공하는 경우 이를 대체할 위치가 필요합니다. 정적 콘텐츠를 Azure Blob Storage로 이동하고 전역적으로 빠른 다운로드를 위해 Azure CDN을 추가하는 것이 좋습니다. 자세한 내용은 Azure Storage에서 정적 웹 사이트 호스팅 및 빠른 시작: Azure CDN과 Azure Storage 계정 통합을 참조하세요.
동적으로 게시된 정적 콘텐츠
애플리케이션이 애플리케이션에서 업로드/생성되었지만 생성 후 변경할 수 없는 정적 콘텐츠를 허용하는 경우, 위에서 설명한 대로 Azure Blob Storage 및 Azure CDN과 Azure Function을 사용하여 업로드 및 CDN 새로 고침을 처리할 수 있습니다. Azure Functions를 사용하여 정적 콘텐츠 업로드 및 CDN 사전 로드에서 사용할 샘플 구현을 제공했습니다.
세션 지속성 메커니즘 식별
사용 중인 세션 지속성 관리자를 식별하려면 애플리케이션 및 Tomcat 구성에서 context.xml 파일을 검사합니다. <Manager>
요소를 찾은 다음, className
특성의 값을 확인합니다.
StandardManager 또는 FileStore와 같은 Tomcat의 기본 제공 PersistentManager 구현은 ACA와 같은 분산형 확장 플랫폼에서 사용하도록 설계되지 않았습니다. ACA는 여러 인스턴스 간에 부하를 분산하고 언제든지 인스턴스를 투명하게 다시 시작할 수 있으므로 변경 가능한 상태를 파일 시스템에 유지하는 것은 권장되지 않습니다.
세션 지속성이 필요한 경우 외부 데이터 저장소에 쓰는 대체 PersistentManager
구현(예: Redis Cache를 사용하는 VMware Tanzu 세션 관리자)을 사용해야 합니다.
특별 케이스
특정 프로덕션 시나리오에서는 더 많은 변경이 필요하거나 더 많은 제한을 적용할 수 있습니다. 이러한 시나리오는 드물지만 애플리케이션에 적용할 수 없거나 올바르게 해결되었는지 확인하는 것이 중요합니다.
애플리케이션이 예약된 작업에 의존하는지 여부 확인
Quartz Scheduler 작업 또는 cron 작업과 같은 예약된 작업은 컨테이너화된 Tomcat 배포에 사용할 수 없습니다. 애플리케이션의 규모가 확장되면 예약된 작업 하나가 예약된 기간당 두 번 이상 실행될 수 있습니다. 이 상황은 의도하지 않은 결과를 초래할 수 있습니다.
애플리케이션 서버 내부 또는 외부에서 예약된 작업을 인벤토리로 작성합니다.
애플리케이션에 OS 관련 코드가 포함되어 있는지 확인
애플리케이션에 호스트 OS에 대한 종속성이 있는 코드가 포함된 경우 해당 종속성을 제거하려면 리팩터링해야 합니다. 예를 들어 파일 시스템 경로 File.Separator
Paths.get
의 /
사용 또는 \
사용 또는 응용 프로그램이 Windows에서 실행 중인 경우를 바꿔야 할 수 있습니다.
MemoryRealm 사용 여부 확인
MemoryRealm 에는 지속형 XML 파일이 필요합니다. ACA에서는 이 파일을 컨테이너 이미지에 추가하거나 컨테이너에서 사용할 수 있는 공유 스토리지에 업로드해야 합니다. (자세한 내용은 다음을 참조하세요 .세션 지속성 메커니즘 섹션을 식별합니다.) 매개 변수는 pathName
그에 따라 수정해야 합니다.
현재 사용되는지 여부를 MemoryRealm
확인하려면 server.xml 검사하고 파일을 context.xml 특성이 className
설정된 요소를 검색 <Realm>
합니다org.apache.catalina.realm.MemoryRealm
.
내부 테스트
컨테이너 이미지를 만들기 전에 ACA에서 사용하려는 JDK 및 Tomcat으로 애플리케이션을 마이그레이션합니다. 애플리케이션을 철저히 테스트하여 호환성 및 성능을 확인합니다.
구성 매개 변수화
마이그레이션 전, server.xml 및 context.xml 파일에서 데이터 원본과 같은 비밀 및 외부 종속성을 식별했을 수 있습니다. 이렇게 식별된 각 항목에 대해 사용자 이름, 암호, 연결 문자열 또는 URL을 환경 변수로 대체합니다.
참고 항목
사용 가능한 가장 안전한 인증 흐름을 사용하는 것이 권장됩니다. 데이터베이스, 캐시, 메시징 또는 AI 서비스와 같이 이 절차에서 설명하는 인증 흐름은 애플리케이션에 대한 신뢰 수준이 매우 높고 다른 흐름에 존재하지 않는 위험을 수반합니다. 암호 없는 연결 또는 키 없는 연결에 대한 관리 ID와 같은 더 안전한 옵션이 실행 가능하지 않은 경우에만 이 흐름을 사용합니다. 로컬 컴퓨터 작업의 경우 암호 없는 연결이나 키 없는 연결에 사용자 ID를 사용하는 것이 좋습니다.
예를 들어 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="{password}"
/>
이 경우 다음 예제와 같이 변경할 수 있습니다.
<Resource
name="jdbc/dbconnection"
type="javax.sql.DataSource"
url="${postgresdb.connectionString}"
driverClassName="org.postgresql.Driver"
username="${postgresdb.username}"
password="${postgresdb.password}"
/>
마이그레이션
참고 항목
일부 Tomcat 배포에는 단일 Tomcat 서버에서 실행되는 여러 애플리케이션이 있을 수 있습니다. 배포의 경우 각 애플리케이션을 별도의 Pod에서 실행하는 것이 좋습니다. 이렇게 하면 복잡성 및 결합을 최소화하면서 각 애플리케이션에 대한 리소스 사용률을 최적화할 수 있습니다.
배포 아티팩트 준비
컨테이너의 Tomcat 빠른 시작 GitHub 리포지토리를 복제합니다. 이 리포지토리에는 많은 권장 최적화가 포함된 Dockerfile 및 Tomcat 구성 파일이 포함되어 있습니다. 아래 단계에서는 컨테이너 이미지를 빌드하고 ACA에 배포하기 전에 이러한 파일을 수정해야 할 수 있는 수정 사항을 간략하게 설명합니다.
JNDI 리소스 추가
다음 예제와 같이 server.xml 편집하여 마이그레이션 전 단계에서 준비한 리소스(예: 데이터 원본)를 추가합니다.
참고 항목
사용 가능한 가장 안전한 인증 흐름을 사용하는 것이 권장됩니다. 데이터베이스, 캐시, 메시징 또는 AI 서비스와 같이 이 절차에서 설명하는 인증 흐름은 애플리케이션에 대한 신뢰 수준이 매우 높고 다른 흐름에 존재하지 않는 위험을 수반합니다. 암호 없는 연결 또는 키 없는 연결에 대한 관리 ID와 같은 더 안전한 옵션이 실행 가능하지 않은 경우에만 이 흐름을 사용합니다. 로컬 컴퓨터 작업의 경우 암호 없는 연결이나 키 없는 연결에 사용자 ID를 사용하는 것이 좋습니다.
<!-- 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>
추가 데이터 원본 지침은 Tomcat 설명서의 JNDI Datasource 방법 의 다음 섹션을 참조하세요.
이미지 빌드 및 푸시
ACA에서 사용하기 위해 이미지를 빌드하고 ACR(Azure Container Registry)에 업로드하는 가장 간단한 방법은 명령을 사용하는 az acr build
것입니다. 이 명령은 컴퓨터에 Docker를 설치할 필요가 없습니다. 예를 들어 tomcat-container-quickstart 리포지토리의 Dockerfile 및 애플리케이션 패키지 petclinic.war이 현재 디렉터리에 있는 경우 다음 명령을 사용하여 ACR에서 컨테이너 이미지를 빌드할 수 있습니다.
az acr build \
--registry $acrName \
--image "${acrName}.azurecr.io/petclinic:{{.Run.ID}}"
--build-arg APP_FILE=petclinic.war \
--build-arg SERVER_XML=prod.server.xml .
WAR 파일의 --build-arg APP_FILE...
이름이 ROOT.war인 경우 매개 변수를 생략할 수 있습니다. 서버 XML 파일의 --build-arg SERVER_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"
# You can now access your application with a browser at http://localhost:8080.
# Sign in to ACR.
sudo az acr login --name $acrName
# Push the image to ACR.
sudo docker push "${acrName}.azurecr.io/petclinic:1"
자세한 내용은 Azure Container Registry를 사용하여 컨테이너 이미지 빌드 및 저장을 참조 하세요.
Azure Container Apps에 배포
다음 명령은 예제 배포를 보여 줍니다.
az containerapp create \
--resource-group <RESOURCE_GROUP> \
--name <APP_NAME> \
--environment <ENVIRONMENT_NAME> \
--image <IMAGE_NAME> \
--target-port 8080 \
--ingress 'external' \
--registry-server <REGISTRY_SERVER> \
--min-replicas 1
보다 심층적인 빠른 시작은 빠른 시작: 첫 번째 컨테이너 앱 배포를 참조하세요.
마이그레이션 후
이제 애플리케이션을 ACA로 마이그레이션했으므로 예상대로 작동하는지 확인해야 합니다. 이렇게 하면 애플리케이션을 클라우드 네이티브로 만들 수 있는 몇 가지 권장 사항이 있습니다.
권장 사항
비즈니스 연속성 및 재해 복구 전략을 설계하고 구현합니다. 중요 업무용 애플리케이션의 경우 다중 지역 배포 아키텍처를 고려하세요. 자세한 내용은 AKS(Azure Kubernetes Service)의 비즈니스 연속성 및 재해 복구 모범 사례를 참조하세요.
logging.properties 파일의 항목을 평가합니다. 성능을 향상시키기 위해 일부 로깅 출력을 제거하거나 줄이는 것이 좋습니다.
성능을 더욱 최적화하기 위해 코드 캐시 크기를 모니터링하고 Dockerfile의
JAVA_OPTS
변수와-XX:ReservedCodeCacheSize
매개 변수-XX:InitialCodeCacheSize
를 추가하는 것이 좋습니다. 자세한 내용은 Oracle 설명서의 Codecache 튜닝을 참조하세요.Azure Monitor 경고 규칙 및 작업 그룹을 추가하여 비정상적인 조건을 신속하게 감지하고 해결하는 것이 좋습니다.
대기 시간이 짧고 안정성 및 내결함성이 높아지려면 다른 지역에서 Azure Container Apps 배포를 복제하는 것이 좋습니다. Azure Traffic Manager를 사용하여 배포 간에 부하를 분산하거나 Azure Front Door를 사용하여 DDoS 보호를 사용하여 SSL 오프로드 및 웹 애플리케이션 방화벽을 추가합니다.
지역 복제가 필요하지 않은 경우 Azure 애플리케이션 Gateway를 추가하여 SSL 오프로드 및 DDoS 보호를 사용하는 웹 애플리케이션 방화벽을 추가하는 것이 좋습니다.