Docker 안에 숨어 있는 Web application JMX profiling Tip

안녕하세요, 오랜만에 글을 남기는 거 같네요. 이것 저것 정리만 하다 그냥 끝나버린 글들이 많은데 그러면 안 되겠다 싶어 짧은 팁 글이라도 올립니다.

JMX?

이번에 작성할 Tip 은 JVM application 에 대한 성능 분석 입니다. 현재 운영되고 있는 Web application 의 성능을 올리고자 하는 니즈는 언제나 있는데요, 이런 것을 가능하게 하는 방법 중에 하나가 많이 알려진 JMX(Java Management eXtension) 를 사용하는 것입니다. JXM 는 JVM 위에서 돌아가는 Java application 에 대하여 monitoring 과 management 기능을 제공하는 기본적인 툴입니다. JVM 기반의 application 이라면 option 적용만으로 바로 사용이 가능한 유용한 툴입니다. JMX 에 대한 자세한 설명 및 tutorial 같은 설명은 이 글에서는 다루지 않도록 하겠습니다. JMX 관련 자료는 저보다 오랫동안 많이 활용해오신 분들의 좋은 글들이 많기 때문입니다. 이번에는 docker 안의 java application 에 대한 분석을 위한 Tip 만을 다루도록 하겠습니다.

Docker?

Docker 는 요즘 packaging 된 형태로 배포 환경 및 개발 환경을 배포하고 손쉽게 사용할 수 있도록 해주는 표준화된 형태의 Unit 이라고 볼 수 있습니다. Docker 는 자신이 개발한 혹은 남들이 개발해놓거나 구성해 놓은 환경을 한 묶음으로 묶어줄 수 있습니다. 이 묶는 단위가 기존에 Web application 등을 배포 단위로 만들기 위한 code packaging(WAR, JAR, etc.) 을 하는 정도에서 더 나아가 file system 단위까지 묶어주는 게 됩니다. 여기서 얘기하는 file system 이라는 단위는 code 가 실행 되기 위한 완벽한 구성 set 를 의미합니다. Code, runtime, system tool, system libraries 등을 모두 포함한 file system 입니다. 이렇게 하면 Mac 등의 각기 다른 host OS 에서 docker 를 활용하면 CentOS 기반의 특정 application, Ubuntu 기반 application 등에 대한 실행 환경을 구성/실행할 수 있습니다. 이런 특징이 기존의 OS 별 Provisioning 정책 등에 대해서 매번 고민하고 운용하지 않아도 되도록 만들어 줍니다. 그냥 docker image 를 찾아서 pull 과정을 통해서 바로 실행할 수 있게 됩니다. 기존의 Virtualization 보다는 가벼운 환경을 제공하여 서비스 운영등에서도 바로 활용될 수 있습니다.

WhatIsDocker_1_kernal-2_1

< docker basic architecture >

Docker 간단 사용

Docker 는 image 와 container 라는 개념이 있습니다. image 는 방금 전에 설명하는 packaging 을 하는 기본 단위이며 다른 사람들이 Download 하여 사용할 수 있게 해주는 단위 입니다. Container 는 이렇게 다운 받은 image 를 실행하여 실제 실행되어 운영되는 주체입니다. Docker 를 사용한다는 건 최종적으로 container 가 host OS 에 실행되어 지는 것입니다. 그럼 간단히 Docker image 를 다운 받고 실행하는 과정을 살펴 보도록 하겠습니다.  Docker image 를 준비하기 위해서는 어떤 image 를 download 받을 것인가 혹은 build 할 것인지 선택을 해야합니다. 여기에서는 직접 build 하는 과정보다는 이미 open 되어 공개되어진 image 를 하나 선택하도록 하겠습니다. Docker image 를 찾고자 할 경우에는 당연히 Google 에서 검색을 통해서도 할 수 있으며 Docker hub 에서도 찾아보실 수 있습니다. Docker hub 의 주소는 https://hub.docker.com/ 입니다. 이 사이트에서 검색을 하신 뒤에 image 를 선택하시고 image 의 고유 이름을 찾아서 사용하시면 됩니다.

docker_hub_elasticsearch

<Docker hub 의 “elasticsearch” official image>

위에서 검색을 하셨다면 첨부된 이미지의 화살표가 가리키고 있는 명령어를 shell 에서 실행해주시기만 하면 됩니다. 이 과정을 통해서 내 server 혹은 laptop 으로 docker image 를 가져오실 수 있습니다. 그럼 이제 docker container 를 실행할 준비는 완료 되었습니다.

1
docker pull elasticsearch

다운로드 받은 ElasticSearch 의 docker image 를 container 로 실행하기 위한 과정은 위 첨부된 이미지의 출처 site 의 detail page 에서 확인하실 수 있습니다. 자세한 내용은 위 사이트에서 참고하시기 바랍니다. 일단 여기에서는 실행을 위한 과정만 발췌해서 사용하도록 하겠습니다. Docker image 를 container 형태로 실행하기 위해서는 “docker run” 이라는 명령어를 사용하게 됩니다. 사용법은 “docker image [docker image name]” 입니다. 기타 다른 옵션들도 있는데요, 기본적으로 많이 사용하는 옵션은 “-p” 옵션입니다. 이 옵션은 docker container 가 실행되었을 때, container 안에서 open 되어 있는 port 를 host OS 의 특정 port 를 open 해주는 데 사용하게 됩니다. Docker container 는 실행되었을 때 host OS 와 같은 host OS 에서 실행된 다른 container 들과 완벽히 isolation 되어 독립성 및 security 가 보장이됩니다. 그렇기 때문에 실제 application 이 사용하는 port 와 host OS 가 실제 외부로 연결시켜줄 port 에 대한 mapping 이 필요하게 됩니다. 사용법은 다음과 같습니다.

1
docker run [image name] -p [host OS port number]:[docker container 안의 application 의 port number]

조금 더 살펴볼 옵션은 docker container 자체에 내가 알아볼 수 있는 형태의 name 을 aliasing 시켜줄 수 있는 옵션입니다. docker run 을 해주게 되면 자체 unique ID 가 발급 됩니다. 그래서 반드시 해줄 필요는 없지만 추후에 관리를 위해서는 name 을 부여해 놓는게 편할 수 있습니다. 옵션은 “--name” 입니다. “-d” 라는 옵션도 있는데 이건 foreground mode 가 아닌 background mode 로 container 를 실행하는 것입니다.

1
docker run -d --name NameOfAliasing [docker image name]

그럼 이제 간단히 docker image 를 download, pull 을 받고 container 로 실행할 수 있는 기본적인 사용법을 알아봤으니 이제 제가 말씀 드리고자 했던 Tip 에 대해서 간단히 작성하도록 하겠습니다. 사실 Tip 내용이 변변치 않아서 적기가 민망하지만 제가 삽질을 했던 경험이 있어서 적어도 다른 분들은 1분이라도 삽질로 시간을 낭비하시는 걸 줄여드리고자 적어 놓습니다. 그리고 다음 내용으로 넘어가기 전에 docker 를 실제 서비스에서 사용하는 것에 의구심을 많이 가지시는 분들이 많이 있습니다. 물론 가지는 게 당연한 거고 자신이 직접 검증해보고 사용에 자신감이 생겼을 때 적용하는게 맞는 접근 방식이라는 것에 저도 동의합니다. 그래서 조금이라도 도움이 되고자 현재 저도 실제 서비스에 사용하고 있으며 docker 를 사용하여 배포와 서비스 트래픽을 받아 내고 있습니다. On line 배포도 가이 이뤄지고 있습니다. 서비스 자체가 하는 일이 없고 proxy 역할을 수행하는 것이라서 크게 어려운건 아닐 수 있지만, 트래픽이 현재 수 만 TPS 정도의 트래픽을 감당하고 있습니다. 물론 한대의 서버는 아니지만 docker 없이 기존 방식으로 서비스 하는 것과 비교했을 때, 제 입장에서는 큰 차이를 느끼지 못했습니다. 참고 하시라고 적어 놓습니다.

Java application JMX enable 시키기

JMX 를 사용하기 위해서 실행하고자 하는 java application 에 옵션을 적용하는 건 간단합니다. 아래 옵션을 적용하면 바로 JMX feature 가 enable 되어 사용할 수 있습니다.

1
2
3
export hostname=[something_hostname or IP address]
export APP_JMX_PORT=8999
java … -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=${hostname} -Dcom.sun.management.jmxremote.port=${APP_JMX_PORT} -Dcom.sun.management.jmxremote.rmi.port=${APP_JMX_PORT}  … [Class name to run]

Container 안의 java application 에 위의 옵션을 적용하고 나면 다음 할 일은  위 ${APP_JMX_PORT} 라는 environment variable 에 할당된 port number 를 port mapping 을 통해서 host OS 를 통해서 접속할 수 있도록 해주는 일입니다.

docker run [image name] -d -p [host OS port number]:[docker container 안의 application 의 port number] -p [host os JMX port number]:[container JMX PORT number]

위와 같이 하면 이제 JMX 모니터링이 가능한 java application 을 docker container 형태로 사용하실 수 있습니다. 그럼 제가 이 글을 쓰고자 했던 팁은 뭘까요? 별건 아닙니다. 제가 다른 글들을 참고해서 JMX 옵션을 적용할 때 실수했던 내용들이 있는데 다 옵션을 제대로 주지 않아서 였습니다. 그런데 docker 를 사용해서 사용하지 않을 경우에는 주지 않아도 잘 되는 경우가 있는 옵션입니다. 처음에는 저는 다음 옵션을 빼먹고 적용하지 않았습니다.

1
-Dcom.sun.management.jmxremote.rmi.port=${APP_JMX_PORT} -Djava.rmi.server.hostname=${hostname}

위 옵션이 없이 그냥 Linux OS 에서 실행하고 VisualVM 같은 JMX Visualize 툴을 사용해서 접속을 할 때는 잘 되었습니다. “rmi” 라는 포트가 이슈가 있는거 같은데요 옵션을 추가적으로 주지 않을 경우 default 를 사용하게 되는데 이 port 가 docker container 안에서만 열러게 됩니다. 그래서 docker container 와 host OS 의 port 간의 mapping 과정이 없었기 때문에 실제접속은 되지 않게 됩니다. 그래서 위 두 옵션을 적용하게 되면 default 값이 아닌 주어진 값을 사용할 수 있게 되어 host OS 외부에서 JMX 모니터링을 수행할 수 있게 됩니다.

정말 간단한 Tip 이어서 민망하지만 그래도 내가 고생하면 나 말고 한 사람이라도 고생할 수 있다는 생각에 그 누군가가 될 지 모를 분에게 도움이 언젠가 되길 바라면서 글을 작성해보았습니다. 변변치 않은 글 읽어주셔서 감사드립니다. 그럼 다음 글은 뭘 쓸지 또 고민에 들어가야겠네요 ^^;


Popit은 페이스북 댓글만 사용하고 있습니다. 페이스북 로그인 후 글을 보시면 댓글이 나타납니다.