AKS(Azure Kubernetes Service)에서 Tomcat 애플리케이션을 컨테이너로 마이그레이션
이 가이드에서는 AKS(Azure Kubernetes Service)에서 실행되도록 기존 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 사전 로드에서 사용할 샘플 구현을 제공했습니다.
동적 또는 내부 콘텐츠
애플리케이션에서 자주 쓰고 읽는 파일(예: 임시 데이터 파일) 또는 애플리케이션에만 표시되는 정적 파일의 경우 Azure Storage 공유를 영구 볼륨으로 탑재할 수 있습니다. 자세한 내용은 AKS(Azure Kubernetes Service)에서 Azure Files를 사용하여 볼륨 만들기 및 사용을 참조하세요.
세션 지속성 메커니즘 식별
사용 중인 세션 지속성 관리자를 식별하려면 애플리케이션 및 Tomcat 구성에서 context.xml 파일을 검사합니다. <Manager>
요소를 찾은 다음, className
특성의 값을 확인합니다.
StandardManager 또는 FileStore와 같은 Tomcat의 기본 제공 PersistentManager 구현은 Kubernetes와 같은 분산형 확장 플랫폼에서 사용하도록 설계되지 않았습니다. AKS는 여러 Pod 간에 부하를 분산하고 언제든지 모든 Pod를 투명하게 다시 시작할 수 있으므로 변경 가능한 상태를 파일 시스템에 유지하는 것은 권장되지 않습니다.
세션 지속성이 필요한 경우 외부 데이터 저장소에 쓰는 대체 PersistentManager
구현(예: Redis Cache를 사용하는 VMware Tanzu 세션 관리자)을 사용해야 합니다. 자세한 내용은 Tomcat을 사용하여 Redis를 세션 캐시로 사용을 참조하세요.
특별 케이스
특정 프로덕션 시나리오에는 추가 변경이 필요하거나 추가 제한 사항이 있을 수 있습니다. 이러한 시나리오는 드물지만 애플리케이션에 적용할 수 없거나 올바르게 해결되었는지 확인하는 것이 중요합니다.
애플리케이션이 예약된 작업에 의존하는지 여부 확인
Quartz Scheduler 작업 또는 cron 작업과 같은 예약된 작업은 컨테이너화된 Tomcat 배포에 사용할 수 없습니다. 애플리케이션의 규모가 확장되면 예약된 작업 하나가 예약된 기간당 두 번 이상 실행될 수 있습니다. 이 상황은 의도하지 않은 결과를 초래할 수 있습니다.
애플리케이션 서버 내부 또는 외부에서 예약된 작업을 인벤토리로 작성합니다.
애플리케이션에 OS 관련 코드가 포함되어 있는지 확인
애플리케이션에 애플리케이션이 실행 중인 OS를 수용하는 코드가 포함된 경우 기본 OS를 사용하지 않도록 애플리케이션을 리팩터링해야 합니다. 예를 들어 파일 시스템 경로의 /
사용 또는 \
사용은 대체해야 Path.get
할 File.Separator
수도 있습니다.
MemoryRealm 사용 여부 확인
MemoryRealm 에는 지속형 XML 파일이 필요합니다. Kubernetes에서 이 파일을 컨테이너 이미지에 추가하거나 컨테이너에서 사용할 수 있는 공유 스토리지에 업로드 해야 합니다. 이에 따라 pathName
매개 변수를 적절하게 수정해야 합니다.
현재 사용되는지 여부를 MemoryRealm
확인하려면 server.xml 검사하고 파일을 context.xml 특성이 className
설정된 요소를 검색 <Realm>
합니다org.apache.catalina.realm.MemoryRealm
.
SSL 세션 추적 사용 여부 확인
컨테이너화된 배포에서 SSL 세션은 일반적으로 수신 컨트롤러에 의해 애플리케이션 컨테이너 외부에서 오프로드됩니다. 애플리케이션에 SSL 세션 추적이 필요한 경우 SSL 트래픽이 애플리케이션 컨테이너로 직접 전달되어야 합니다.
AccessLogValve 사용 여부 확인
AccessLogValve를 사용하는 경우 매개 변수를 directory
탑재된 Azure Files 공유 또는 해당 하위 디렉터리 중 하나로 설정해야 합니다.
내부 테스트
컨테이너 이미지를 만들기 전에 애플리케이션을 AKS에서 사용하려는 JDK 및 Tomcat으로 마이그레이션합니다. 애플리케이션을 철저히 테스트하여 호환성 및 성능을 확인합니다.
구성 매개 변수화
마이그레이션 전, 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}"
/>
마이그레이션
첫 번째 단계("컨테이너 레지스트리 및 AKS 프로비저닝")를 제외하고는 마이그레이션하려는 각 애플리케이션(WAR 파일)에 대해 아래 단계를 개별적으로 수행하는 것이 좋습니다.
참고 항목
일부 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 빠른 시작 GitHub 리포지토리를 복제합니다. 권장되는 여러 최적화가 포함된 Dockerfile 및 Tomcat 구성 파일이 포함되어 있습니다. 아래 단계에서는 컨테이너 이미지를 빌드하고 AKS에 배포하기 전에 이러한 파일을 수정해야 할 수 있는 수정 사항을 간략하게 설명합니다.
필요한 경우 클러스터링을 위한 포트 열기
AKS에서 Tomcat 클러스터링을 사용하려는 경우 필요한 포트 범위가 Dockerfile에 노출되는지 확인합니다. server.xml 서버 IP 주소를 지정하려면 컨테이너 시작 시 초기화된 변수의 값을 Pod의 IP 주소로 사용해야 합니다.
또는 복제본에서 사용할 수 있는 대체 위치에 세션 상태를 유지할 수 있습니다.
애플리케이션에서 클러스터링을 사용하는지 여부를 확인하려면 server.xml 파일의 요소 또는 <Engine>
내부 <Host>
요소를 찾 <Cluster>
습니다.
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>
추가 데이터 원본 지침은 Tomcat 설명서의 JNDI Datasource 방법 의 다음 섹션을 참조하세요.
이미지 빌드 및 푸시
AKS에서 사용하기 위해 이미지를 빌드하고 ACR(Azure Container Registry)에 업로드하는 가장 간단한 방법은 명령을 사용하는 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 .
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"
# 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"
자세한 내용은 Azure에서 컨테이너 이미지를 빌드하고 저장하기 위한 Learn 모듈을 참조하세요.
공용 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 연결 문자열)을 포함하지 마세요. 비밀은 KeyVault FlexVolume 구성 섹션에서 다룹니다.
영구 스토리지 구성
애플리케이션에 비휘발성 스토리지가 필요한 경우 하나 이상의 영구 볼륨을 구성합니다.
Tomcat 로그 디렉터리(/tomcat_logs)에 탑재된 Azure Files를 사용하여 영구 볼륨을 만들어 로그를 중앙에서 유지할 수 있습니다. 자세한 내용은 AKS(Azure Kubernetes Service)에서 Azure Files를 사용하여 영구 볼륨을 동적으로 만들고 사용하는 것을 참조하세요.
KeyVault FlexVolume 구성
Azure KeyVault 를 만들고 필요한 모든 비밀을 채웁다. 그런 다음, Pod에서 이러한 비밀을 액세스할 수 있도록 KeyVault FlexVolume을 구성합니다.
컨테이너의 Tomcat GitHub 리포지토리에서 startup.sh 시작 스크립트를 수정하여 인증서를 컨테이너의 로컬 키 저장소로 가져와야 합니다.
예약된 작업 마이그레이션
AKS 클러스터에서 예약된 작업을 실행하려면 필요에 따라 Cron 작업을 정의합니다.
마이그레이션 후
이제 애플리케이션을 AKS로 마이그레이션했으므로 예상대로 작동하는지 확인해야 합니다. 이렇게 하면 애플리케이션을 클라우드 네이티브로 만들 수 있는 몇 가지 권장 사항이 있습니다.
수신 컨트롤러 또는 애플리케이션 부하 분산 장치에 할당된 IP 주소에 DNS 이름을 추가하는 것이 좋습니다. 자세한 내용은 AKS(Azure Kubernetes Service)에서 수신 컨트롤러와 함께 TLS 사용을 참조하세요.
애플리케이션에 대한 HELM 차트를 추가하는 것이 좋습니다. HELM 차트를 사용하면 더 다양한 고객 세트에서 사용하고 사용자 지정할 수 있도록 애플리케이션 배포를 매개 변수화할 수 있습니다.
DevOps 전략을 설계하고 구현합니다. 개발 속도를 높이면서 안정성을 유지하려면 Azure Pipelines를 사용하여 배포 및 테스트를 자동화하는 것이 좋습니다.
클러스터에 대한 Azure Monitoring을 사용하도록 설정하여 컨테이너 로그 수집, 사용률 추적 등을 허용합니다.
Prometheus를 통해 애플리케이션별 메트릭을 공개하는 것이 좋습니다. Prometheus는 Kubernetes 커뮤니티에서 광범위하게 채택된 오픈 소스 메트릭 프레임워크입니다. 사용자 고유의 Prometheus 서버를 호스팅하는 대신 Azure Monitor에서 스크랩하는 Prometheus 메트릭을 구성하여 애플리케이션에서 메트릭 집계를 사용하도록 설정하고 비정상 조건에 대한 자동화된 응답 또는 에스컬레이션을 수행할 수 있습니다.
비즈니스 연속성 및 재해 복구 전략을 설계하고 구현합니다. 중요 업무용 애플리케이션의 경우 다중 지역 배포 아키텍처를 고려하세요.
Kubernetes 버전 지원 정책을 검토합니다. 항상 지원되는 버전을 실행하도록 AKS 클러스터를 계속 업데이트해야 합니다.
클러스터 관리 및 애플리케이션 개발을 담당하는 모든 팀 구성원이 관련 AKS 모범 사례를 검토하도록 합니다.
logging.properties 파일의 항목을 평가합니다. 성능을 향상시키기 위해 일부 로깅 출력을 제거하거나 줄이는 것이 좋습니다.
성능을 더욱 최적화하기 위해 코드 캐시 크기를 모니터링하고 Dockerfile의
JAVA_OPTS
변수와-XX:ReservedCodeCacheSize
매개 변수-XX:InitialCodeCacheSize
를 추가하는 것이 좋습니다.