UzukiLive 서버 현황

Vultr VC2가 같은 가격에 SSD 용량을 추가로 제공한다는 사실을 이제 깨달은 나머지(…) 전체적으로 UzukiLive 서버를 유지보수 하면서 작업을 진행했는데, 차후 서버를 옮길 필요가 있을 때 참고를 해야 할 경우가 있어서 업데이트 겸에 정리를 진행했습니다.

UzukiLive 서버란?

UzukiLive 서버는 소유중인 도메인인 ‘uzuki.live’ 라는 도메인 이름에서 파생된 서버 이름이고, Uzuki 라는 이름의 모티브는 ‘アイドルマスターシンデレラガールズ’ 의 메인 캐릭터인 ‘島村卯月'(Uzuki Shimamura) 에서 가져왔습니다.

이 서버는 2018. 12. 22 ~ 2018. 12. 25 일에 진행된 ‘UzukiLive 새 인스턴스 확장 이전'(https://pyxispub.uzuki.live/?p=1463) 으로 생성된 서버로, 기존 Vultr VC2 1Core 2GB , Vultr VC2 2Core 4GB 인스턴스를 합치고 새로 생성한 서버입니다. 리전은 Tokyo로 등록되어 있습니다.

이 서버의 목적은 개인 운용 목적의 서버로 블로그 서버 + 메일 서버 + 클라우드 서버 기능을 포함하며, 기타 안드로이드 개발에 필요한 Jenkins CI + JFrog Artifactory를 포함합니다.

그 외, 서버를 원할하게 관리하기 위한 Monitoring 스택 (cAdvisor + NodeExporter + Prometheus + Grafana) 을 구현하여 실제 프로덕션 환경에서 최소한으로 관리할 수 있는 능력에 대한 연습 서버이기도 합니다.

도메인은 NameCheap, Inc에서 등록되었고, DNS 네임서버는 dnsever에서 관리되고 있습니다.

서버 구조 개요

UzukiLive는 Vultr Cloud Compute (VC2) 의 4 CPU 8 GB 160GB SSD 기반의 클라우드에 Ubuntu 18.04.2 LTS + Docker 18.09.5 버전으로 실행중인 서버로, 현재 약 21개의 도커 인스턴스가 실행되고 있습니다.

  • Nginx – Proxy-pass, SSL (Let’s Encrypt) 연결을 위한 서비스
  • Service Layer
    • WordPress – PyxisPub 발행을 위한 워드프레스 서비스
    • Jenkins – Android 및 Docker CI/CD 작업을 위한 Jenkins 서비스
    • Artifcatory – 비공개 그레들 아키펙트 배포 및 기존 아키펙트 레포지토리에 대한 캐시 서비스
    • OwnCloud – 개인 저장용 클라우드 서비스
    • Rainloop – 메일 서버를 위한 프론트엔드 UI
  • Internal Layer
    • Docker-mailserver – 개인 이메일 ([email protected]) 및 부가 이메일 서비스를 위한 메일 서버 (IMTP(POP3)/SMTP 구현 포함)
    • Shadowbox – Jigsaw 가 개발하는 Outline 의 기반 컨테이너
    • Redis – Redis 데이터베이스, OwnCloud 전용
    • MariaDB – MariaDB 데이터베이스, WordPress 전용
    • pure-ftpd – (S)FTP 제공
    • Adminer – MariaDB에 대한 web admin
  • Monitor Layer
    • cAdvisor – 도커 엔진, 컨테이너, 이미지 등에 대한 데이터를 수집하는 모니터링 도구
    • NodeExporter – 호스트 서버를 모니터링 하는 도구
    • Prometheus – 컨테이너로부터의 데이터를 받기 위한 중간 매개체 도구
    • Grafana – 여러 데이터 제공자로부터 데이터를 받아 그래프로 보여주는 도구
    • AlertManager – Prometheus로부터 데이터를 전달받아 이벤트가 발생되었을 때 정해놓은 알림 룰을 통해 전송하는 도구
    • PushGateway – Prometheus 에 일회성/배치 작업에 대한 통계를 전송하도록 하는 도구

모든 레이어는 단일 uzukilive-network 네트워크로 엮여져있으며, 각 레이어마다 내부 통신을 위한 네트워크가 별도로 구성되어 있습니다.

외부에 포트 노출이 필요한 Nginx, MailServer, ShadowBox, pure-ftpd 을 제외하고는 내부 포트를 통해 통신하게 되며, 내부간 통신이 필요할 경우 uzukilive-network 네트워크와 각 레이어마다 할당된 네트워크를 통해 구현하게 됩니다.

Service Layer와 Grafana는 실제 외부에서 접근 가능한 서비스들이지만 이 포트들은 외부에 노출되지 않고 Nginx를 통해 Proxy-pass하게 됩니다. 즉, Nginx가 각 서비스에 접근하기 위한 게이트웨이로 작용하게 되어 서브도메인으로 구분하게 됩니다.

이 때, http로 접속하였을 경우 https로 리다이렉트하는데, 이 https에 대한 인증서는 Let’s Encrypt를 통해 발급되었습니다.

서버 업데이트 내역

2019.04.28 이후 내역을 정리합니다.

  • 2019.04.28
    • 사양 업그레이드 – VC2 4core 8GB 100GB SSD -> VC2 4core 8GB 160GB SSD
    • 아키펙트 레포지토리 캐시 서버 cron 개선 – 매 정각 12시마다 336시간 동안 사용되지 않은 아키펙트 삭제 -> 매 정각 12시마다 168시간 동안 사용되지 않은 아키펙트 삭제
    • 사용하지 않는 Expose된 포트 제거
    • cAdvisor, Prometheus, AlertManager, PushGateway 등이 어떠한 경로를 통하여 외부에서 접근이 가능한 우회 방법 방지
    • 사용하지 않는 A 레코드 정보 제거

새 인스턴스로 확장 이전과 후기

이번 연휴(2018. 12. 22 ~ 2018. 12. 25) 동안 지금까지 운영해오던 UzukiLive 서버를 확장이전 하여 새롭게 환경을 구축하게 되었습니다.

기존 인스턴스와 문제점

기존 환경은 이렇게 설정되어 있습니다.

  • Vultr VC2 1core 2GB (UzukiLive 인스턴스) -> 블로그, nextcloud. 도커로 되있지 않음
  • Vultr VC2 2core 4GB (Artifactory 인스턴스) -> Artifactory, Jenkins. 도커로 되어있음

그리고 메일 서버의 경우 Zoho 플랫폼을 빌려 사용하였고, 처음에 삽질을 너무 크게 한 나머지 uzuki.live 로 접속하면 SSL 에러가 발생하곤 했습니다.
그 외 문제점이라고 하면 FTP를 쉽게 사용할 수 없거나, 너무 설정이 여기저기 있어 확장하려고 해도 쉽지 않았습니다. (오죽하면 인스턴스를 두개 생성해서 관리를 했지만요… (._. )

당연히 비용도 비용이니 좋지 않은 사양에 월 30달러나 지불해야 한다는 것은 이해가 가지도 않긴 합니다.

따라서 이번 연휴때 계획을 잡고 신규 인스턴스에 전부 이전하기로 결정했습니다.

신규 인스턴스

신규 인스턴스는 Vultr의 VC2 4core 8GB, 100GB SSD 입니다. 이전 사양보다 약 2(Artifactory 인스턴스 기준) ~ 4(UzukiLive 인스턴스 기준)배 이상 사양이 증가하였습니다.

사양을 대폭 올린 이유로는 Jenkins 때문인데, 2core 4GB 사양에서 gradle 빌드를 두 개 이상 돌리는 순간 컨테이너가 메모리 부족으로 죽어버리는 대참사가 발생하여, 빌드를 두 개 이상 동시에 돌리더라도 문제가 없도록 구성하였습니다.

신규 인스턴스는 모든 요소가 Docker에 의해 관리되는 Dockerize 환경을 사용할 것이고, 아래 범주로 서비스를 관리할 예정입니다.

  • Reverse Proxy -> nginx
  • Stack: Infra -> adminer, pure-ftpd, docker-telegram-notifier
  • Stack: Blog -> MariaDB + WordPress
  • Stack: Build-Automation -> Jenkins, Artifactory
  • Stack: Mail -> docker-mailserver(IMAP/SMTP) + rainloop (Web UI)
  • Stack: Intro -> uzukilive-intropage
  • Stack: Octobox -> Octobox + Redis + PostgreSQL

그러면, 각 범주마다 설명을 약간 추가하면서 기능을 소개하려 합니다.

Reverse Proxy + SSL

기존 UzukiLive 에서도 사용했던 Nginx를 사용하고, 여기에 LetsEncrypt를 이용하여 모든 외부용 서비스에 SSL를 제공할 계획입니다.

보통 nginx-proxy + letsencrypt-companion 조합으로 사용하지만 이 조합의 경우 docker 소켓에 붙어 일정 시간마다 스캔을 해서 추가하는 방식으로 되어있어, 그거보다는 좀 더 귀찮지만 하나의 설정 파일(conf)로 존재하는 것이 좋다고 생각되었습니다.

따라서 새 서비스를 연동할 때 마다 아래의 명령어를 통해 인증서를 발급받았습니다.

docker run -it --rm -v /data/cert:/etc/letsencrypt -v /data/cert-data:/data/letsencrypt certbot/certbot certonly --webroot --webroot-path=/data/letsencrypt -d uzuki.live

저 방법을 사용하기 위해서는 일정의 예제 conf 파일을 만들어 nginx를 가동시킬 필요가 있는데, 샘플 nginx 파일을 만들고 DONAME_NAME 만 교체해서 생성하도록 했습니다.

server {
    listen      80;
    listen [::]:80;
    server_name uzuki.live;

    location / {
        rewrite ^ https://$host$request_uri? permanent;
    }

    location ^~ /.well-known {
        allow all;
        root  /data/letsencrypt/;
    }
}

Stack: Infra

여기에는 3개의 서비스가 들어가는데, adminer 는 MySQL/MariaDB의 정보를 보거나 수정할 수 있는 프로그램으로 phpmyadmin 대체용입니다

그 다음으로 pure-ftpd는 FTP 서버로 /home/pyxis 경로에 접근하여 데이터를 주고 받을 수 있게 설정했습니다.

마지막으로 docker-telegram-notifier 는 미리 만들어둔 Telegram bot로 컨테이너의 시작/중지 등의 상태를 보내줍니다.

가령 Jenkins가 시작되었다면 아래의 메세지를 보내줍니다.

Started container jenkins
Image: windsekirun/jenkins-android-docker:1.0.2
Container ID: ae8f526e8b42d216146fb68ee49f6506631259780f3c75195718786da6245cb6
오늘도 약 400개의 메세지를 받아내는 우즈키(..)

Stack: Blog

여기에는 2개의 서비스가 들어가는데, 워드프레스와 그 DB로 MariaDB를 선택했습니다. 기존 인스턴스에는 MySQL로 되어있고, 이 데이터를 그대로 가져갈 필요가 있었습니다.
따라서 PostgreSQL 보다는 MariaDB를 선택했습니다.

주소는 기존의 blog.uzuki.live 에서 pyxispub.uzuki.live 로 변경했는데, 기존 주소로 들어가면 새로운 주소로 리다이렉션 되도록 기존 인스턴스의 nginx 단을 수정했습니다.

기존 인스턴스는 2주 뒤인 1월 11일쯤에 제거될 예정입니다.

Stack: Build-Automation

여기에는 2개의 서비스가 들어가는데, 각각 Gradle Repository용 Artifactory와 Jenkins가 들어갑니다. 이 두개 서비스에 대해서는 일전 블로그 글로 설명한 적이 있으므로 별도로 설명할 것은 없다고 생각됩니다.

다만 아주 잉여롭지만 봇을 만든 겸에 빌드 시작 / 결과를 알려주는 별도의 Jenkins 호환용 그루비 스크립트를 작성해서 적용했습니다

Stack: Mail

기존 메일([email protected]) 는 Zoho Mail에서 수신/발신하도록 되어있어 내 것이 아니기도 한 존재였습니다.
따라서 이번 인스턴스에는 IMAP/SMTP 서버를 직접 구축하여 메일을 수신/발신할 수 있도록 설정하였습니다.

…다만, vultr가 SMTP 포트인 25번을 막아버리는 바람에 일단은 Gmail에 의존하여 발신하도록 설정하였으나 좀 더 Postfix를 공부하여 수정할 계획입니다.

메인 화면
글쓰기 화면

웹 메일 UI는 rainloop를 사용하였고, 특출나게 UI가 세련된 건 아니지만 나름대로 들어갈 기능은 전부 포함되어 있습니다.

Stack: Intro

물론 반응형입니다.

CSS Toolkit인 타키온(https://tachyons.io/) 을 이용하여 5~10분만에 대충 만든 인트로 페이지로, 이 서버에서 제공하는 서비스의 링크와 Github, Telegram, Contact 링크를 포함합니다.

물론, 이 인트로 페이지(라고 해도 HTML 1개 + CSS 1개) 도 docker 이미지를 만들어서 제공했으며, 도커 이미지는 https://github.com/WindSekirun/uzukilive-intropage 입니다.

Stack: Octobox

Octobox 라고 하는 Github의 알림을 관리하는 서비스가 있는데, 이 서비스가 self hosted로 하면 프라이빗 프로젝트까지 포함되어 설치하게 되었습니다.

이 서비스의 자세한 설명은 공식 홈페이지 (https://octobox.io/) 를 들어가는 것이 편리합니다.

마무리

일전에도 Jenkins나 Artifactory를 도커로 활용하고 있었지만 이번 기회를 통해 도커를 통한 관리가 얼마나 확장성과 자유성을 가져주는지 깨달았습니다.

개인 목적으로는 나름대로 규모가 있고, 따로 설치하라고 한다면 아마 멘탈 여러번 나가서 쉽게 던졌을텐데, 명령어 한 두줄 만으로 모든 것을 설정할 수 있다는 것이 큰 장점인 것 같습니다.

컨테이너가 14개가 되다보니 docker-compose로 각 스택별로 모아 필요한 스택만 켜고 끄고 할 수 있게 설정해두니, 패치할 때도 다운타임이 5~10분 내로 할 수 있다는 것도 좋았습니다.

열심히 가동되는 컨테이너(들)

그러면, 새로운 인스턴스와 새로운 환경에서 남은 6일, 앞으로 다가올 2019년에도 PyxisPub와 이 주인장(._. … )을 잘 부탁드립니다.