Apache httpd-Tomcat mod_jk 연동

Apache HTTP Server의 mod_jk로 Tomcat AJP Connector에 연동하는 구조, workers.properties, JkMount와 보안 점검을 정리한다.


mod_jk 요청 경로

Client
  -> Apache HTTP Server
  -> mod_jk
  -> Tomcat AJP Connector

참고: AJP란? AJP(Apache JServ Protocol)는 Apache HTTP Server 같은 앞단 Web Server와 Tomcat 사이에서 요청 정보를 주고받기 위해 사용하던 전용 연동 프로토콜이다. 브라우저가 직접 호출하는 HTTP가 아니라 Web Server와 Tomcat 사이의 내부 통신에 가깝고, Tomcat에서는 보통 8009 포트의 AJP Connector로 받는다. 외부에 열어두면 위험하므로 address, secret, 방화벽으로 접근 범위를 제한해야 한다.

mod_jk는 Apache HTTP Server와 Tomcat을 AJP 프로토콜로 연결하는 커넥터다. 오래된 Java 웹 운영 환경이나 공공/엔터프라이즈 환경에서 여전히 마주칠 수 있다.

연동 방식 요약

mod_jk는 Apache HTTP Server가 특정 URL을 Tomcat AJP worker로 넘기도록 만드는 Tomcat Connector다.

mod_proxy와 다른 점

구분mod_proxy HTTPmod_jk
backend 프로토콜HTTPAJP
Tomcat 포트보통 8080보통 8009
핵심 설정ProxyPass, ProxyPassReverseJkWorkersFile, JkMount, workers.properties
장점단순하고 HTTP로 직접 점검 가능기존 AJP 기반 구성, 세밀한 JK worker 설정
주의점proxy header와 timeoutAJP 포트 노출, secret, worker pool

새 구축에서는 HTTP reverse proxy가 더 단순할 수 있다. 하지만 기존 시스템을 운영하거나 분석할 때는 mod_jk 설정을 읽을 수 있어야 한다.

구성 파일

파일역할
mod_jk.soApache HTTP Server에 로드되는 모듈
mod_jk.confJK 공통 설정
workers.propertiesTomcat worker 목록과 연결 정보
server.xmlTomcat AJP Connector 설정
jk.logmod_jk 로그

경로는 배포판과 설치 방식마다 다르다. 운영에서는 httpd.confconf.d/*.conf에서 LoadModule jk_module, JkWorkersFile, JkMount를 먼저 찾는다.

Apache HTTP Server 설정 예시

LoadModule jk_module modules/mod_jk.so

JkWorkersFile conf/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel info
JkShmFile logs/jk-runtime-status

<VirtualHost *:80>
    ServerName example.com

    JkMount /app/* worker1
    JkMount /api/* worker1

    ErrorLog logs/example-error.log
    CustomLog logs/example-access.log combined
</VirtualHost>

JkMount는 어떤 URL을 어떤 worker로 보낼지 결정한다. 정적 파일을 Apache HTTP Server에서 직접 응답하게 하려면 JkUnMount나 별도 Alias 구성을 함께 확인한다.

workers.properties 예시

worker.list=worker1

worker.worker1.type=ajp13
worker.worker1.host=127.0.0.1
worker.worker1.port=8009
worker.worker1.secret=change-this-secret
worker.worker1.socket_timeout=60
worker.worker1.socket_connect_timeout=5000
worker.worker1.ping_mode=A
worker.worker1.ping_timeout=10000

worker.list는 사용할 worker 이름 목록이다. 각 worker는 type, host, port로 Tomcat AJP Connector를 가리킨다. AJP secret을 쓰는 Tomcat이면 worker에도 같은 secret을 지정해야 한다.

Tomcat AJP Connector 예시

<Connector protocol="AJP/1.3"
           address="127.0.0.1"
           port="8009"
           secretRequired="true"
           secret="change-this-secret" />

AJP는 Tomcat 내부 구조에 더 가까운 프로토콜이므로 보안 설정을 가볍게 보면 안 된다. Tomcat 9 기준으로 secretRequired 기본값은 true이며, secret 없이 사용하려면 명시적으로 낮춰야 한다. 운영에서는 secret을 설정하고, address와 방화벽으로 접근 범위를 제한하는 쪽이 안전하다.

로드밸런싱 예시

worker.list=lb

worker.tomcat1.type=ajp13
worker.tomcat1.host=10.0.0.11
worker.tomcat1.port=8009
worker.tomcat1.secret=change-this-secret
worker.tomcat1.lbfactor=1

worker.tomcat2.type=ajp13
worker.tomcat2.host=10.0.0.12
worker.tomcat2.port=8009
worker.tomcat2.secret=change-this-secret
worker.tomcat2.lbfactor=1

worker.lb.type=lb
worker.lb.balance_workers=tomcat1,tomcat2
worker.lb.sticky_session=true

세션을 Tomcat별 메모리에 저장하면 sticky session이 필요하다. 이때 Tomcat의 jvmRoute와 세션 쿠키 뒤의 route 값까지 함께 맞춰야 한다.

장애별 확인

증상확인 지점
503worker down, AJP 연결 실패, Tomcat 미기동
404JkMount 경로와 Tomcat Context 경로 불일치
403 / 거부AJP secret 불일치, address/firewall 제한
간헐적 실패socket_timeout, ping_mode, connection pool
세션 튐sticky session, jvmRoute, load balancer worker 설정

점검 명령

apachectl configtest
apachectl -M | grep jk
ss -lntp | grep 8009
tail -f logs/mod_jk.log
tail -f $CATALINA_BASE/logs/catalina.out

mod_jk 문제는 Apache HTTP Server error log만으로 부족할 때가 많다. mod_jk.log와 Tomcat 로그를 같은 시간대에서 같이 봐야 한다.

관련 블로그 기록

공식 문서

닫기 전 질문

  • JkMount 경로와 Tomcat Context 경로는 맞는가?
  • Apache HTTP Server에서 AJP worker로 연결할 수 있는가?
  • Tomcat AJP Connector의 address, secret, port는 안전하게 제한되어 있는가?
  • 세션 유지가 필요하다면 jvmRoute와 sticky session 설정이 맞는가?