CMS 세팅 (워커 등 분리)

2018. 8. 2. 17:09알고리즘 문제풀기/기타 주제

Ubuntu 16.04 상에서 세팅하는 과정이다.

DB 및 AWS를 운영하는 메인 서버 한 대와, 하위 서버 여러 대로 이루어진 구성이다.
일반적으로는 워커(Worker)를 담당할 채점기 컴퓨터를 따로 두는 편이다. 각각의 채점기 컴퓨터에서는 워커 서비스를 세 개 정도(코어 갯수 - 1) 켜서 사용한다.

또, 참가자(contestant)가 굉장히 많은 경우, 참가자에게 홈페이지를 그려주는 contest web server(CWS) 서버 역시 분리할 필요가 생기기도 한다.
그 경우에도 마찬가지로 CWS를 담당하는 컴퓨터를 따로 둔다.

또, 랭킹을 표시하는 ranking web server(RWS)를 따로, 그리고 여러 개 둘 필요가 생기기도 한다. 채점 및 점수 매기기가 완료될 때마다 모든 RWS 쪽으로 채점 결과를 전송하게 된다.

이외의 서비스, 즉 Postgres DB 서버를 운영하고, 관리자용 admin web server(AWS)를 운영하고, 채점 및 점수 매기는 과정(evaluation service, scoring service)을 총괄하고, 로그를 남기고, 프린팅 등을 처리하는 모든 과정은 하나의 컴퓨터에서 처리할 만 하다.


1.

모든 컴퓨터에서, 필요한 패키지를 설치한다.

sudo apt-get install build-essential openjdk-8-jre openjdk-8-jdk fpc \
    postgresql postgresql-client gettext python2.7 \
    iso-codes shared-mime-info stl-manual cgroup-lite libcap-dev

sudo apt-get install python-dev libpq-dev libcups2-dev libyaml-dev \
libffi-dev python-pip


2.

모든 컴퓨터에서, CMS를 가져오고 prerequisites의 설치를 진행한다.

myungwoo/cms를 가져온다고 하면

<메인 서버>

git clone --single-branch -b koi-cms --recursive https://github.com/myungwoo/cms
cd cms
sudo ./prerequisites.py install

그리고 여전히 메인 서버에서, 모든 하위 서버들의 IP에 대해서 scp로 CMS 폴더를 통째로 보내준다. (git clone보다 빠르기 때문에)

scp ../cms $ip:~/cms -r

이제 각각의 하위 서버에서도 설치를 실행해준다.

<하위 서버>

cd cms
sudo ./prerequisites.py install


3.

모든 서버에서, 파이썬 virtual env를 만들고 CMS의 install을 진행한다.

virtualenv -p python2 ~/venv
source ~/venv/bin/activate
pip install -r requirements.txt
python setup.py install


4.

메인 서버에서, postgres DB를 세팅한다.

<메인 서버>

sudo su - postgres
createuser --username=postgres --pwprompt cmsuser

위의 커맨드에서, DB 접속 비밀번호를 입력한다.

<메인 서버>

createdb --username=postgres --owner=cmsuser cmsdb
psql --username=postgres --dbname=cmsdb --command='ALTER SCHEMA public OWNER TO cmsuser'
psql --username=postgres --dbname=cmsdb --command='GRANT SELECT ON pg_largeobject TO cmsuser'
cmsInitDB

또, Worker나 CWS 등이 이 Postgres에 접속할 수 있어야 하기 때문에, postgres 설정을 바꿔주어야 한다.

<메인 서버>

sudo vim /etc/postgresql/9.5/main/postgresql.conf

59번줄?에, listen_addresses = '127.0.0.1,192.168.0.x'와 같은 부분을, 하위 서버들의 IP 주소로 채운다.
또 HBA 관련 설정을 채워야 한다.

sudo vim /etc/postgresql/9.5/main/pg_hba.conf

모든 하위 서버에 대해서, host cmsdb cmsuser <하위 서버의 IP 주소>/32 md5 와 같은 식으로 한 줄씩 추가해준다.


5.

모든 서버에서, 설정 파일을 수정한다. 이 역시 메인 서버에서 수정하고 그를 scp로 deploy 하는게 편하다.

<메인 서버>

cp config/cms.conf.sample config/cms.conf
vim cms.conf

세팅해야 할 것

5-1. 20-32번줄의 각 서비스의 IP 주소를 설정한다.
Worker(, 그리고 CWS도 분리한다면 CWS)를 제외한 모든 서비스의 IP 주소는 메인 서버의 IP 주소로 설정한다.
포트는 대부분 그대로 쓰되, 한 컴퓨터에서 워커를 여러 대 켜는 경우 각 워커의 포트는 다르게 설정한다.

5-2. DB 접속 스트링 (45번줄)
"database": "postgresql+psycopg2://cmsuser:your_password_here@localhost/cmsdb 라고 되어 있는데,
"database": "postgresql+psycopg2://cmsuser:<4번에서 설정한 비밀번호>@<메인 서버의 IP주소>/cmsdb 가 되도록 바꾼다.

5-3. 81번줄 secret_key
랜덤한 16 bytes hexademical 스트링(즉, 32글자)으로 바꿔 주어야 한다.
다음 커맨드의 결과를 붙여넣자:
python -c "import random;print('%032x'%random.randrange(1<<128))"

5-#. 145번줄 rankings
RWS를 쓸 경우에만 설정한다.
"rankings": ["http://usern4me:passw0rd@localhost:8890/"]
RWS를 호스팅할 서버 주소와 포트를 넣고, 랭킹 서비스에서만 쓸 ID와 비밀번호로 채운다.
이 아이디와 비밀번호는, 대회 서버가 랭킹 서버에게 채점 결과를 전송하는 과정에서의 보안을 담당한다.
여기서, 만약 RWS 앞에 nginx를 놓을 계획이라고 하더라도, 여기에는 백엔드 역할의 서버의 주소와 포트를 넣어야 한다.

5-#. cms.ranking.conf

RWS를 쓸 경우에만 설정한다.

위에서 설정한 랭킹 서비스 전용 아이디와 비밀번호를 채워 넣는다.



수정을 마쳤으면 scp로 각 유저의 ~/cms/config/ 안에 복사해주고,

※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
※ cms.conf 등을 수정하고 나면, 꼭 다음 커맨드를 써야 반영된다!!!
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※

sudo ./prerequisites.py install


6.
관리자 계정을 만들고, AWS를 켜서 로그인한다.

관리자 계정에 로그인 할 수 있으면 절대 안 된다는 생각으로, 아이디와 비밀번호를 꼭 정성들여서 만들도록 하자.

<메인 컴퓨터>

cmsAddAdmin -p <패스워드> <아이디>
cmsAdminWebServer 0

AWS에서 컨테스트를 만들어주어야 한다. 그래야 cmsResourceService를 켤 수 있다.


7.
모든 컴퓨터에서 cmsResourceService를 켠다.
Resource Service만 켜면, 그 아이가 각자의 컴퓨터에서 켜야 하는 서비스를 모두 켜 줄 것이다.

cmsResourceService -a <컨테스트 번호>

이제 모든 setup이 끝났다.



번외 1.

nginx 프론트엔드를 세우려면, 먼저 nginx를 설치한다.
그리고 /etc/nginx/sites-enabled/default 의 내용을 싹 지우고, 채워준다.

HTTP 서버만 세우는 건 간단하다.
nginx 설정을 아래와 같이 해준다.

upstream cws {
    ip_hash;
    keepalive 500;
    server :<포트(보통 8888)>;
    server :<포트(보통 8888)>;
# ...
}
upstream aws {
    keepalive 5;
    server :<포트(보통 8889)>;
}
# rws를 안 쓰면 아래 줄은 필요 없다.
upstream rws {
    keepalive 500;
    server :<포트(보통 8890)>;
    server :<포트(보통 8890)>;
# ...
}
server {
    listen 80 default_server;
    server_name <서버 주소>; # cms.asdfzxcv.com, ioi, 혹은 192.168.0.200 등
    location ^~ /aws/ {
        proxy_pass http://aws/;
        include proxy_params;

        proxy_redirect http://$host/ /aws/;
        proxy_redirect https://$host/ /aws/;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        client_max_body_size 100M;
    }
# rws를 안 쓰면 아래 줄은 필요 없다.
location ^~ /rws/ { proxy_pass http://rws/; include proxy_params; proxy_redirect http://$host/ /rws/; proxy_redirect https://$host/ /rws/; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_buffering off; } location / { proxy_pass http://cws/; include proxy_params; proxy_http_version 1.1; proxy_set_header Connection ""; client_max_body_size 50M; } }


그리고 cms.conf 에서 num_proxies 를 찾아서 1로 만들어주어야 하고,

그 다음에는 또다시 sudo ./prerequisites.py install 을 돌려주어야 한다!!!!

꼭 까먹지 말자.



그리고 방화벽을 세운다.

sudo ufw allow 80
sudo ufw allow 5432
sudo ufw enable

HTTPS를 사용하고 싶다면, 80번을 443번으로 넘겨주는 server{}를 하나 만들고, self-signed certificate를 지정해준 후,
모든 참가자(contestant) 컴퓨터에 해당 CA를 신뢰할 수 있는 인증서로 배포해야 한다.


번외 2. 각종 커맨드 목록

cmsAddAdmin [-p PASSWORD] username
cmsAddParticipation [-c CONTEST_ID] [-i IP] [-d DELAY_TIME] [-e EXTRA_TIME] [-t TEAM] [--hidden] [--unrestricted] [-p PLAINTEXT_PASSWORD | -H HASHED_PASSWORD] [--bcrypt] uesrname
cmsAddUser [-t TIMEZONE] [-l LANGUAGES: comma-separated] [-p PLAINTEXT_PASSWORD | -H HASHED_PASSWORD] [--bcrypt] first_name last_name username
cmsRemoveContest [-c CONTEST_ID]
cmsRemoveParticipation [-c CONTEST_ID] username
cmsRemoveSubmissions [-c CONTEST_ID] [-u USERNAME] [-t TASK_NAME] [-s SUBMISSION_ID]
cmsRemoveTask task_name
cmsRemoveUser username


번외 3. 컴퓨터 환경 세팅

# 유저 추가하기

useradd=저수준이라고 까임
adduser 를 쓰자!

adduser [--home DIR] [--shell SHELL] [--no-create-home] user


# IP 칠 필요 없게 만들기

/etc/hosts에 IP주소와 대명사를 순서대로  한 줄에 띄어쓰기로 구분해서 써주면 된다.
127.0.0.1 대신 localhost를 쓸 수 있는 것도 이 파일 덕분이라고 생각하면 된다.


# 브라우저 홈 페이지 설정

Firefox 홈 페이지 설정 (모든 Firefox를 종료시킨 후에 하자!)

/usr/lib/firefox/mozilla.cfg 에 다음 내용: (첫 줄에 //가 꼭 필요하단다)

//
defaultPref("browser.startup.homepage", "data:text/plain,browser.startup.homepage=http://ioi")
pref("browser.startup.homepage", "http://ioi")

/usr/lib/firefox/defaults/pref/local-settings.js 에 다음 내용:

pref("general.config.obscure_value", 0);
pref("general.config.filename", "mozilla.cfg");

obscure value를 설정하지 않거나 디폴트 값 13으로 두면, mozilla.cfg를 ROT13 해서 읽으려고 하기 때문에 꼭 써주어야 한다.


Chrome 홈 페이지 설정

/opt/google/chrome/master_preferences 에 다음 내용:

{
"homepage": "http://ioi",
"homepage_is_newtabpage": false,
"browser": {
"show_home_button": true
},
"session": {
"restore_on_startup": 4,
"startup_urls": [
"http://ioi"
]
},
"bookmark_bar": {
"show_on_all_tabs": true
},
"sync_promo": {
"show_on_first_run_allowed": false
},
"distribution": {
"import_bookmarks": false,
"import_history": false,
"import_home_page": false,
"import_search_engine": false,
"ping_delay": 60,
"suppress_first_run_bubble": true,
"do_not_create_desktop_shortcut": true,
"do_not_create_quick_launch_shortcut": true,
"do_not_launch_chrome": true,
"do_not_register_for_update_launch": true,
"make_chrome_default": false,
"make_chrome_default_for_user": false,
"suppress_first_run_default_browser_prompt": true,
"system_level": true,
"verbose_logging": true
},
"first_run_tabs": [
"http://ioi"
]
}


얏호

'알고리즘 문제풀기 > 기타 주제' 카테고리의 다른 글

PS 계열 커뮤니티와 웹 사이트  (4) 2019.04.23
PS 토픽 모음  (1) 2019.04.21
Code::Blocks에서의 편한 설정  (0) 2016.01.13
CMS Green  (0) 2015.08.20
FFT in competitive programming  (1) 2015.07.18