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 HTTP | mod_jk |
|---|---|---|
| backend 프로토콜 | HTTP | AJP |
| Tomcat 포트 | 보통 8080 | 보통 8009 |
| 핵심 설정 | ProxyPass, ProxyPassReverse | JkWorkersFile, JkMount, workers.properties |
| 장점 | 단순하고 HTTP로 직접 점검 가능 | 기존 AJP 기반 구성, 세밀한 JK worker 설정 |
| 주의점 | proxy header와 timeout | AJP 포트 노출, secret, worker pool |
새 구축에서는 HTTP reverse proxy가 더 단순할 수 있다. 하지만 기존 시스템을 운영하거나 분석할 때는
mod_jk 설정을 읽을 수 있어야 한다.
구성 파일
| 파일 | 역할 |
|---|---|
mod_jk.so | Apache HTTP Server에 로드되는 모듈 |
mod_jk.conf | JK 공통 설정 |
workers.properties | Tomcat worker 목록과 연결 정보 |
server.xml | Tomcat AJP Connector 설정 |
jk.log | mod_jk 로그 |
경로는 배포판과 설치 방식마다 다르다. 운영에서는 httpd.conf나 conf.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 값까지 함께 맞춰야 한다.
장애별 확인
| 증상 | 확인 지점 |
|---|---|
| 503 | worker down, AJP 연결 실패, Tomcat 미기동 |
| 404 | JkMount 경로와 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 로그를
같은 시간대에서 같이 봐야 한다.
관련 블로그 기록
- 폐쇄망에서 서버 시간 맞추기 — Web Server와 WAS 로그를 같은 시간축에서 비교하기 위한 기반 사례
- Tomcat Catalina.out 파일 용량 증가 문제 해결 — Tomcat 로그 운영 사례
공식 문서
- Tomcat Connectors Apache HTTP Server HowTo
- Tomcat Connectors workers.properties
- Apache Tomcat AJP Connector
닫기 전 질문
JkMount경로와 Tomcat Context 경로는 맞는가?- Apache HTTP Server에서 AJP worker로 연결할 수 있는가?
- Tomcat AJP Connector의
address,secret,port는 안전하게 제한되어 있는가? - 세션 유지가 필요하다면
jvmRoute와 sticky session 설정이 맞는가?