Supervisor이란?
전통적(?)으로 Docker 컨테이너는 실행시에 1개의 프로세스를 실행한다. 예를 들어, Apache 데몬이나 SSH 서버의 데몬과 같은 것이 있다. 그러나 컨테이너 내에서 여러 개의 프로세스를 실행하고 싶을 경우가 있을 것이다. 이러한 소망을 실현시킬 수 있는 몇 가지 방법이 있다.
프로세스 관리 툴을 설치해 컨테이너의 CMD 명령으로 단순히 Bash 스크립트를 사용할 수 있도록 하면되는데, 이 때의 프로세스 관리 툴 중 하나가 Supervisor이다. Supervisor을 사용해, 컨테이너 내의 여러 개의 프로세스를 관리할 수 있다. 프로세스의 재실행도 가능하다.
즉 Docker시점에서 본다면, "Docker Container상에서는 Process가 Foreground로 실행되지 않으면 Container는 종료한다"는 Container의 제약이 있는데, 1개의 Container상에서 여러 개의 프로세스(예를 들어 Node+Mongo나 Fluentd+Elasticsearch등)을 작동시키고 싶다, 지속화하고 싶을 때 Supervisor이라는 Tool을 사용한다는 것이다.
참고로 Supervisor의 공식 사이트는 여기이다.
Supervisor은 가동시키고 싶은 서비스를 "/ect/supervisord.conf" 파일에 기재한다. 아래서는 httpd데몬과 vsfpd데몬을 동시에 가동싶은 경우의 파일 예이다.
# cat supervisord.conf
[supervisord]
nodaemon=true
[program:httpd]
command=/usr/sbin/httpd -k start
[program:vsftpd]
command=/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf
위의 설정 예에서 httpd와 vsfpd의 실행시에 관련된 처리를 1개의 supervisord.conf 파일에 기재하고 있으나, 서비스마다 설정 파일을 나눠서 작성해, /ect/supservisord.conf 파일을 통해 서비스마다의 설정 파일을 로드하는 방법도 존재한다.
이번 포스팅에서는 supervisor의 설치와 실행에 대해 알아본 후, Docker에 어떻게 적용하는지에 대해 알아 볼 생각이다.
Supervisor의 설치
※ 설치 부분과 관련해서 참고한 포스팅의 환경이 CentOS6.4였으므로, 운영체제에 따라 차이가 있을 것으로 예상됩니다.
※ 설치~실행 확인 부분에 관련해 참고한 포스팅에서는 GrowthForecast와 HRForcasf를 사용하기 위한 흐름을 설명하고 있으니, 적절히 다른 프로그램으로 바꿔서 설정해주세요.
설치
설치 방법은 크게 두 가지가 있다.
1) EPEL 리포지토리를 이용해 설치
2) python패키지 매니저(pip/easy_install)의 사용해 설치
1번의 방법으로는 이전 버전을 받을 가능성이 있기 때문에, 따라서 최신 버전을 바로 사용하고 싶다면 2번을 방법을 사용한다.
1) EPEL 리포지토리를 이용해 설치
supervisord 자체 및 supervisord 관리 스크립트는 /etc/init.d에 들어가, service 커맨드로 관리할 수 있다.
yum install supervisor
참고로 CentOS의 경우 EPEL 리포지토리가 기본적으로 유효화되지 않으므로 등록되어 있지 않은 경우 설치 전에 아래의 커맨드를 실행하다.
rpm --import http://apt.sw.be/RPM-GPG-KEY.dag.txt
rpm -ivh http://apt.sw.be/redhat/el6/en/x86_64/rpmforge/RPMS/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm
2) python패키지 매니저(pip/easy_install)의 사용해 설치
sudo easy_install supervisor
# 혹은
sudo pip install supervisor
기본 conf파일 생성
EPEL 리포지터리로 설치한 경우 자동으로 /etc/supervisord.conf가 생기지만, 수동으로 생성하고자하면 아래의 커맨드를 사용한다.
sudo echo_supervisord_conf > /etc/supervisord.conf
include 컨피그 파일용 디렉토리 생성
EPEL 리포지터리로 설치한 경우 자동으로/etc/supervisord.d가 생성되어 있으므로, 아래의 커맨드를 사용하자.
sudo mkdir /etc/supervisord.d
supervisord 로그 파일
supervisord 자체가 뱉어내는 로그 파일의 조정을 해야한다. 디폴트의 컨피그 파일에는 로그 파일 위치가 /tmp/supervisord.log인데 원하는 경우 /etc/supervisord.conf를 수정하면 된다.
[supervisord]
# 로그 디렉토리
;logfile=/tmp/supervisord.log
logfile=/var/log/supervisor/supervisord.log
로그 출력처의 디렉토리를 생성하고, 내친 김에 log rotation의 설정도 해두자.
sudo mkdir /etc/supervisord.d
sudo sh -c "echo '/var/log/supervisor/*.log {
missingok
weekly
notifempty
nocompress
}' > /etc/logrotate.d/supervisor"
pid, include의 설정
이와 관련된 설정도 /etc/supervisord.conf에서 할 수 있다.
pid 파일은 /var/run 아래에 생성되게 하고, /etc/supervisord.d/ 아래의 설정 파일을 include할 수 있게 했다.
[supervisord]
# ...중략
# pid파일
;pidfile=/tmp/supervisord.pid
pidfile=/var/run/supervisord.pid
# ...중략
# include섹션이 주석처리되어 있으므로, 주석 처리르 지우고 아래와 같이 수정했다.
[include]
files = supervisord.d/*.ini
supervisord 자체의 시스템 서비스 등록(CentOS6버전)
init 스크립트는 작성해두신 분이 있어 그 내용을 참고했다.
https://github.com/Supervisor/initscripts
sudo curl -o /etc/rc.d/init.d/supervisord https://raw.githubusercontent.com/Supervisor/initscripts/master/redhat-init-equeffelec
sudo chmod 755 /etc/rc.d/init.d/supervisord
sudo chkconfig --add supervisord
supervisord의 컨피그 파일
/ect/supervisord.conf를 아래와 같이 편집했다.
[inet_http_server]
port=127.0.0.1:9001
[supervisorctl]
serverurl=unix:///var/tmp/supervisor.sock
serverurl=http://127.0.0.1:9001
web 관리 컨솔을 개방하여, 동시에 root이외의 유저로 부터 클라이언트 커맨드를 사용할 수 있도록 허가했다.
프로세스 관리 등록
당시 설치한 supervisor는 version3으로 2버전에서는 컨피그 파일이 특히 로그 출력 부분이 약간 다를 수 있다.
아래에서는 Job의 표준 출력 로그 저장 디렉토리를 /var/log/supervisor/jobs로 하였다. 또한 로테이션 설정도 아래와 같이 해두는 것이 적당하다.
GrowthForecast 등록의 예
[program:GrowthForecast]
command=/usr/local/bin/growthforecast.pl --enable-float-number --data-dir /data/gf ; 실행 커맨드
user=monadmin ; 실행 유저
autorestart=true ; 프로세스 다운시에 자동 재실행
stdout_logfile=/var/log/supervisor/jobs/GrowthForecast-supervisord.log ; 표준 출력 로그
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=5
stdout_capture_maxbytes=1MB
redirect_stderr=true ; 에러 출력을 표준 출력으로 리다이렉트
이것을 /ect/supervisord.d/GrowthForecast.ini에도 작성해뒀다.
HRForecast 등록의 예
/opt/HRForecast 디렉토리에 설치하고 있다.
[program:HRForecast]
command=perl hrforecast.pl --config config.pl ; direcotry로 부터의 상대경로로 OK。
user=monadmin
directory=/opt/HRForecast ; 설치 디렉토리가 있는 경우 여기에
autorestart=true
stdout_logfile=/var/log/supervisor/jobs/HRForecast-supervisord.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=5
stdout_capture_maxbytes=1MB
redirect_stderr=true
이 내용도 동일하게 /etc/supervisord.d/HRForecast.ini에도 작성해뒀다.
실행 확인
sudo service supervisor start
/var/log/supervisor아래의 로그를 체크해두는 것이 좋을 것이다. 이번에 했던 설정의 경우, 설정한 프로세스(GrowthForecast나 HRForecast)의 stdout/err도 출력된다.
실행 후에는 root이외로부터 클라이언트 커맨드의 supervisorctl를 파악해보고자한다. 커맨드 라인의 관리 인터페이스에들어가면, 커맨드를 입력하면 문제 없다는 가정하에 아래와 같은 내용이 출력된다.
[monadmin@myhost]% supervisorctl
GrowthForecast RUNNING pid 24955, uptime 0:12:00
HRForecast RUNNING pid 24956, uptime 0:12:00
supervisor>
CLI콘솔 상에서는 start|stop|restart [프로세스명], status으로 관리 프로세스의 목록을 확인할 수 있다. CLI콘솔에 들어가지 않아도 supervisorctl {start|stop|restart|status} [프로세스 명] 등으로도 확인할 수 있다.
root가 아니어도 되므로, 유저 레벨로 관리할 수 있는 데몬이 됐다.
Supervisor를 Docker에 적용하기
※ 여기서부터는 nginx를 supervisor상에서 움직여보고 싶은 경우를 상정해, Docker에 적용한 내용에 대한 포스팅을 참고한 것 입니다.
기본적인 사용법
nginx를 supervisor상에서 움직여보고 싶은 경우, Dockerfile을 작성하면 다음과 같다.
FROM ubuntu:14.04
#Install nginx
RUN apt-get update && apt-get -y install nginx curl
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
#Install Supervisor and config
RUN apt-get install -y supervisor
RUN touch /etc/supervisord.conf
RUN echo '[supervisord]' >> /etc/supervisord.conf
RUN echo 'nodaemon=true' >> /etc/supervisord.conf
RUN echo '[program:nginx]' >> /etc/supervisord.conf
RUN echo 'command=nginx' >> /etc/supervisord.conf
EXPOSE 80
CMD /usr/bin/supervisord -c /etc/supervisord.conf
[supervisord]와 nodaemon=true는 필수 항목으로, nodaemon =True로 supervisor 자체가 foreground 프로세스로써 다뤄져 Docker container의 종료를 예방하는 역할을 한다. command=에서는 Container상에서 nginx가 단체로 계속해서 움직일 경우에 작성해야만 하는 command를 작성한다.
Dockerfile은 간결하게 작성해 컨피그 파일과 구분하는 것이 좋다. supervisord.conf파일에는 아래의 내용을 작성해, /etc/ 이하에 배치하도록 Dockerfile쪽에 작성하면 OK이다.
[supervisord]
nodaemon=true
[program:nginx]
command=nginx
여러 개의 프로세스를 움직일 경우의 사용법
Elasticsearch + Fluentd와 supervisor상에 움직이고 싶은 경우는 다음과 같이 Dockerfile을 작성하면 될 것이다.
FROM ubuntu:14.04
RUN apt-get update -y
#Install Elasticsearch
ENV ELASTICSEARCH_VERSION elasticsearch-1.4.4
RUN apt-get install -y curl openjdk-7-jdk
RUN mkdir /opt/elasticsearch
RUN curl -sL "https://download.elasticsearch.org/elasticsearch/elasticsearch/${ELASTICSEARCH_VERSION}.tar.gz" | tar xz -C /opt/elasticsearch --strip=1
#Install Fluentd and plugins
RUN apt-get install -y libcurl4-openssl-dev git-core build-essential ruby-dev
RUN curl -L http://toolbelt.treasuredata.com/sh/install-ubuntu-trusty-td-agent2.sh | sh
COPY td-agent.conf /etc/td-agent/td-agent.conf
RUN ulimit -n 65536
#Install Supervisor and config
RUN apt-get install -y supervisor
RUN touch /etc/supervisord.conf
RUN echo '[supervisord]' >> /etc/supervisord.conf
RUN echo 'nodaemon=true' >> /etc/supervisord.conf
RUN echo '[program:elasticsearch]' >> /etc/supervisord.conf
RUN echo 'command=/opt/elasticsearch/bin/elasticsearch' >> /etc/supervisord.conf
RUN echo '[program:td-agent]' >> /etc/supervisord.conf
RUN echo 'command=/usr/sbin/td-agent' >> /etc/supervisord.conf
# expose port for elasticsearch
EXPOSE 9200
# expose port for fluentd
EXPOSE 24224
CMD /usr/bin/supervisord -c /etc/supervisord.conf
Docker에서 Supervisor사용시에 주의해야할 설정
각 프로세스의 표준 출력
Supervisor은 기본적으로 각 프로세스로 부터의 표준 출력을 받아내어 file로 작성한다. 따라서 Supervisor을 경유하여 각 프로세스를 움직이는 경우에 각 프로세스의 표준 출력 내용을 확인할 수 없다.
file이 아닌 표준출력을 작성해내고 싶다면, stdout_logfile를 /dev/fd/1에 설정하면 된다. 예를 들어, 아래와 같이 설정하면, td-agent의 프로세스로부터 출력된 표준 출력은 (Supervisor를 경유하여) 시스템 전체의 표준 출력에 Route된다.
[supervisord]
nodaemon=true
[program:elasticsearch]
command=/opt/elasticsearch/bin/elasticsearch
[program:td-agent]
command=/usr/sbin/td-agent
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
참고자료
https://qiita.com/taka4sato/items/1f59371ead748d88635a
https://qiita.com/yushin/items/15f4f90c5663710dbd56
https://techracho.bpsinc.jp/morimorihoge/2017_06_05/40936
https://www.itmedia.co.jp/enterprise/articles/1602/17/news004_2.html
'IT > 기초 지식' 카테고리의 다른 글
[Linux] expect를 이용한 Linux 커맨드 입력 자동화 (0) | 2021.10.20 |
---|---|
[Singularity] Singularity + headless VNC + Pipenv를 사용한 강화학습 환경 만들기(gym, pybullet) (0) | 2021.10.14 |
[Docker] Docker 이미지를 오프라인에서도 사용하는 방법 (0) | 2021.10.13 |
[Docker/Singularity] Docker, Singularity의 차이 (0) | 2021.10.12 |
[Docker] Docker 컨테이너에 네트워크 액세스하기(docker run -p 옵션) (0) | 2021.10.12 |