• 느리게 가는 도시의 빨리 사는 사람

    필자는 도시의 탈을 쓴 시골에 산다. 간신히 한 곳 있는 영화관에서 새로 나온 영화를 챙겨보고, 학생들의 문제집 판매량이 없다면 당장이라도 망할 것 같은 서점에서 한달에 한번 바뀌는 베스트셀러 책장을 들여다보며, 사용하는 노트북의 수리라도 받으려면 옆 도시까지 움직여야 하는. 그런 겨우겨우 도시라고 불릴 수 있는 곳에서 살고 있다.

    그래서 그런지, 언제나 북적거리고 바쁘게 움직이는 대도시를 동경한다. 높게 뻗은 건물들과 살아있는 듯 자연스럽게 연결되는 대중교통, 어디로 눈을 돌려도 밝게 빛나는 환한 조명은 지금도 내 심장을 쿵쿵 뛰게 만든다. 좋아하면 닮는다더니, 웃기게도 필자는 아무 급할 일 없는 이 작은 도시에서 언제부턴가 빠르게 움직이기 시작했다. 거리의 풍경을 눈에 담지 않았고, 움직이는 도중에도 자주 스마트폰을 만지작 거렸다. 항상 끼는 이어폰에서는 싫어도 몸을 움직이게 만드는 EDM이 흘러나왔다.

    느리게 가는 도시의 빨리 사는 사람이 되어버린 것이다.

    아무도 닥달하는 사람이 없는데, 스스로 생산적인 일을 하고 있지 않으면 어딘가 불안했다. 내가 가치없는 사람이 되는 것 같았다. 한동안 이런 상태를 별로 문제삼지 않았었는데, 최근에 들어서 ‘왜?’ 라는 질문이 자꾸 들었다. 한참을 곰곰히 생각해봤는데, 대답 대신 웃음이 피식 나왔다. 남들은 ‘타임 푸어’니 뭐니 하면서 일에서 벗어나고 싶어하는데, 나는 누구보다 시간이 풍족한데도 자꾸 스스로 족쇄를 채우려 하는 상황이 너무 아이러니했다. 더 이상 고민할 건 없었다.

    컴퓨터를 끄고 밖으로 나갔다. 항상 듣던 Dance Mix 대신 Chill Mix를 틀었다. 메시지가 온 스마트폰을 알고도 가만히 냅뒀다. 횡단보도의 신호등이 깜빡거려도 마음을 졸이지 않았다.

    나는 느리게 가는 도시의 느리게 사는 사람이다.

  • Portainer를 통한 Docker 초점잡기

    자, 2017년 마지막 날까지 까만 바탕에 하얀 글씨만 들여다보고 있는 당신을 위해 Portainer라는 가볍고 빠른 웹 기반 Docker 환경 관리 도구를 들고왔다.

    필자도 평소 꽤 CLI 환경을 애용하는 편이지만, 가끔은 눈으로 보이는 인터페이스가 미친듯이 끌린다. 마치 할리우드 해커가 된 것처럼 이쁘고 깔끔한 그래픽을 바라보며 폼 잡고 싶어진다. 그래서 로컬에서 구동하는 Docker를 사용할 때는 종종 Kitematic이라는 GUI 도구도 같이 사용했었는데, 원격 서버에서 구동되는 Docker를 사용할 때는 마땅한 도구를 찾지 못해 선택권 없이 CLI만 주구장창 사용했다. 사실 어지간한 도구들은 사용 전 이것저것 신경써야 할 것들도 많고 그 결과물도 썩 마음에 들지 않아 더 CLI를 선호했기도 한데, Portainer는 사전 설정도 간단하고 사용도 편해 상당히 만족하며 사용하고 있다.

    속살

    날씨도 추우니 빠르게 속살을 까고 내려가자. 아래는 Portainer 공식 웹페이지에서 제공하는 설치 과정이다. 일반적인 단일 노드 환경에서 Docker를 사용한다면, 아래 두 명령어면 충분하다. Portainer가 사용하는 데이터 볼륨을 만들고, 호스트의 /var/run/docker.sock 을 컨테이너와 직접 연결한 후 9000포트를 통해 외부와 커뮤니케이션 시켜준다.

    $ docker volume create portainer_data
    $ docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
    

    만약 다중 노드로 구성된 Docker Swarm 환경에서 Portainer를 사용하고 싶다면, 아래를 참고하면 된다.

    $ docker service create \
    --name portainer \
    --publish 9000:9000 \
    --replicas=1 \
    --constraint 'node.role == manager' \
    --mount type=bind,src=//var/run/docker.sock,dst=/var/run/docker.sock \
    portainer/portainer \
    -H unix:///var/run/docker.sock
    

    Easy peasy lemon squeezy는 바로 이럴 때 사용하는 말이다. 컨테이너 구동이 끝났다면, 브라우저에서 해당 노드의 IP + 9000포트로 접속하면 된다.


    간단한 계정 생성 과정을 거친 후, 위와 같이 Local과 Remote를 선택하는 창이 나오는데, 이름에서 유추할 수 있듯 Local은 Portainer가 설치된 시스템의 Docker 그 자체에 접근하는 것이고 (이를 위해 docker run-v 옵션을 통해 시스템의 /var/run/docker.sock을 마운트해 줬다.), Remote는 다른 곳에 위치한 Docker 머신을 관리할 수 있는 옵션이다.

    대부분의 경우 Docker가 돌아가는 시스템 그 자체에 Portainer를 설치했을 것이니, Local을 선택하자. 원격지 Docker 머신을 사용하고 싶은 경우, Docker 데몬의 API 주소 (원격 서버 주소 + 2375 혹은 2376)로 Endpoint를 설정하면 된다.


    모든 필요 설정을 마치면, 드디어 무언가 할 수 있는 콘솔창이 마중나온다. 이제 더 이상 설명할 건 없고, 하나하나 눌러보며 이전에 Docker CLI나 기타 GUI 도구로 진행했던 작업을 이어가면 된다. 혹시 단일 컨테이너로 실행했더라도 해당 시스템이 Docker Swarm의 Manager 노드일 경우 그 Swarm 클러스터의 전반적인 상태와 구조까지 시각화해서 보여주니 상당히 편하다.

    한가지 아쉬운 점이라면, 각 컨테이너의 리소스 사용량을 그래프화시켜 실시간으로 보여주는 기능도 있으면서 정작 상태 이상 알림 기능은 없어 본격적인 모니터링 용도로는 사용하기 애매하다는 것인데, 추후 업데이트에서 대응할 계획이 있다고 운영진이 공식 입장을 내놓았으니 이를 기다려봐도 좋을 것 같다.

    마치며

    사실 해가 가기 전 캐노니컬의 MAAS 솔루션 관련 포스트를 마무리하고 개고생한 2017년 넋두리 글이라도 쓸까 했는데, 생각보다 MAAS의 잔버그가 많아 모두 내년으로 미뤄버렸다. 그래도 어찌저찌 다른 글로 공백은 매웠으니 뭐 만족한다.

    몇시간 남지 않은 2017년 모두 잘 마무리 할 수 있길 바란다.

  • YateBTS를 사용하는 홈메이드 GSM 네트워크 구축하기

    이전 프로젝트 포스트 에서 온갖 폼은 다 잡아 놨으니, 이제 회수할 차례다. 지난 한 주간 틈날 때마다 방에서 전자파를 뿜어내며 시간을 보냈다. 네트워크 구축에 필요한 하드웨어도 배송 받았고, 어느 정도의 테스트도 끝마친 상태다. “모두를 위한 모바일 네트워크” 라는 프로젝트 취지에 맞게, 나 스스로가 국토를 뒤덮을 수 없으니 인터넷의 불특정 다수에게 과정을 공유하는 것이 맞다고 생각한다. 특히 이와 관련된 한국어 자료는 전무하다 싶을 정도니, 한국어 독자들에게는 분명 도움이 될 것이다.

    주의! 이 프로젝트와 관련 포스트를 참고해 발생한 모든 종류의 불이익은 독자에게 있습니다. 적합한 법적 절차를 거치지 않았을 경우, 외부와 격리된 테스트 환경에서만 운용하고 전파가 외부로 새어나가지 않도록 주의하여야 합니다.

    하드웨어 준비물

    • 라즈베리 파이 3 모델 B.

      국내 인터넷 쇼핑몰 등지에서 쉽게 구할 수 있는 최신 라즈베리 파이 모델이다. 원활한 작업을 위해 16GB 이상의 마이크로SD와 적절한 전력을 공급해줄 수 있는 충전 케이블 / 전원 공급원을 같이 준비하자.

      휴대성과 적은 전력 소모를 걱정하지 않는다면 기존에 가지고 있던 x86 데스크탑이나 노트북 등을 사용해도 좋다. 오히려 퍼포먼스 부분에서는 더 권장한다. 라즈베리 파이는 기본 성능 자체도 낮을 뿐더러 USB 3.0을 지원하지 않아 추후 네트워크 구축 후 데이터 패킷 통신 시 (GPRS) 간혈적인 병목 현상이 발생할 수 있다.

    • BladeRF x40

      필자는 몇해 전 킥스타터에서 성공적으로 모금을 마친 Nuand 사의 소프트웨어 정의 라디오 (SDR) 플랫폼 BladeRF x40를 구축에 사용했다. 비슷한 기능을 제공하는 장비 중 가장 저렴한 가격대와 안정적인 품질을 보여주니 개인적으로는 가장 추천한다. 한국에서 리셀링하는 업체는 프리미엄을 잔뜩 붙였으니 공식 홈페이지 에서 주문할 것. 한국 직배송도 지원한다.

      추가로, 수요층이 한정된 물건이라 서드파티 케이스를 구하기 힘드니 구매할 때 공식 홈페이지에서 케이스까지 같이 구매하는 편이 좋다. 물론 DIY 능력자라면 스스로 만들어 써도 된다.

    • SMA 규격을 준수하는 안테나

      본인의 용도에 맞게 적절한 출력을 보장하는 SMA 규격 안테나를 준비해두자. BladeRF는 전이중 통신 플랫폼이니 당연하지만 안테나 2개가 필요하다. Nuand 공식 홈페이지에서 BladeRF와 함께 판매하는 2dBi 출력의 안테나가 있으니 귀찮으면 같이 사도 무방하다. 다만, 눈물 나오게 빈약한 전파 커버리지는 감안해야 한다.

    기타 라즈베리 파이에 연결할 모니터나 키보드 등 작업에 도움을 줄 수 있는 물건들은 알아서 구비하길 바란다.

    가입자 식별에 사용하는 SIM 카드는 이번 포스트에서는 사용하지 않는다. 가입자 인증 기능을 구현하고 싶은 독자는 Amazon이나 AliExpress 등에서 공 SIM 카드를 별도로 구매하면 된다. 이런 제품이런 리더기 조합으로 맞추면 될 것이다.

    소프트웨어 작업

    라즈베리 파이의 OS는 라즈비안 Jessie Lite 마지막 릴리즈 를 사용한다. 사용할 YateBTS 소프트웨어가 Ubuntu 14.04 / Debian 8을 기반으로 하기 때문. 현재 업로드되는 최신 OS인 라즈비안 Stretch를 설치하면 소프트웨어 설치 과정 중간에 오류가 발생한다. YateBTS 프로젝트 자체도 정상적으로 유지되고 있고, 포럼도 활발한 상태인데 최신 OS 기반 대응은 해줄 생각을 안 하고 있어 아쉬울 따름이다. 그래도 아쉬운 사람이 발품 팔아야 하지 않겠나. 일단 그대로 따라가자.

    위에서 언급한 YateBTS는 적합한 트랜시버와 컴퓨터만 있다면 누구나 모바일 네트워크를 구축할 수 있게 해주는 오픈소스 프로젝트다. 우리는 적합한 트랜시버 (BladeRF) 와 덜 적합하지만 적당히 굴러는 가는 컴퓨터 (라즈베리 파이)를 이미 가지고 있으니 YateBTS를 사용해 당장 셀룰러 신호를 뿜어낼 수 있다.

    그리고 희소식 하나, BladeRF x40의 펌웨어와 YateBTS, 그리고 각종 필요한 유틸리티들을 자동으로 설치해주는 자동화 스크립트를 가져왔다. 혹시라도 이후 과정에 기다리고 있을 험난한 소프트웨어 설치 작업을 걱정하고 계셨던 분들이 있으시다면 안심하셔도 된다. 여러분이 할 일은 스크립트를 다운로드 받아 실행만 하면 된다.

    아래 과정을 통해 라즈베리 파이에서 스크립트를 실행해 보자.

    아래 과정에서 사용될 스크립트는 Matthew May와 Brendan Harlow님이 챔플레인 대학의 SEC-440(System Security) 학위 프로그램에 사용한 자동화 스크립트로 최신 YateBTS를 구동할 수 있도록 필자가 직접 커스터마이즈 하였습니다.

    //필자의 GitHub에서 스크립트 다운로드.
    wget https://raw.githubusercontent.com/kycfeel/dokupe/master/auto_yatebts_deploy.sh
    
    //다운받은 스크립트에 실행 권한 추가.
    chmod +x ./auto_yatebts_deploy.sh
    
    //sudo 권한으로 스크립트 실행.
    sudo ./auto_yatebts_deploy.sh
    

    이제 커피 한잔 마시며 기다리면 된다! 첫 실행 시 내 네트워크의 이름을 물어보는데 알아서 잘 입력해주고, 중간 BladeRF 펌웨어 설치 시 BladeRF가 연결되어 있지 않다면 USB로 연결해달라는 안내문만 하나 뜰 뿐, 완전히 자동으로 YateBTS가 설치되니 걱정 푹 놓고 있으면 된다. 성능이 떨어지는 라즈베리 파이 특성 상 소프트웨어 make 과정 등에서 상당한 시간을 소요하니, 인내심을 가지자.

    설치가 완료되었다면 라즈베리 파이 내 계정의 홈 폴더에 StartYateBTS.sh 라는 스크립트가 생성됬을 것이다. sudo ./StartYateBTS 명령어로 YateBTS를 실행해 보자. 자동으로 소프트웨어가 가동되고, BladeRF의 신호 송수신 LED가 깜빡거릴 것이다. 콘솔창의 화면에 MBTS Ready 라는 메시지가 나오면 가동 완료.

    고맙게도 YateBTS는 대부분의 네트워크 설정 과정을 GUI로 진행할 수 있도록 웹 인터페이스를 제공한다. 왜 생 Yate 엔진만 사용하지 않고 YateBTS를 같이 사용하는지 지금부터 피부로 느끼게 될 것이다. 생각보다 상당히 편하다. 같은 네트워크에 연결된 컴퓨터에서 브라우저를 키고 라즈베리_파이의_IP/nib 주소로 접속하면 된다. 아마 별 문제 없이 웹 인터페이스가 마중을 나올 거다.


    바로 웹 인터페이스의 BTS Configuration -> GSM 메뉴로 들어가서 가장 중요한 GSM 네트워크의 설정을 진행해보자.


    위 이미지는 필자의 세팅값인데, EGSM900 - #1000 (930.2 MHz) 규격으로 네트워크를 구축하고 있고, MCC와 MNC 코드는 각각 테스트 네트워크를 의미하는 001과 01로 설정되어 있다. 하단의 전파 최소 / 최대 강도는 모두 중간 수준인 35, 네트워크를 식별명은 프로젝트 이름을 그대로 따 dokupe로 설정했다.

    원할 경우, 바로 옆의 GPRS 메뉴로 넘어가 Enable 값에 체크만 해 주면 GSM 음성 통화 / SMS와 더불어 GPRS 데이터 통신도 가능해진다. 외부 인터넷 연결까지 생각한다면 GGSN 메뉴의 Firewall.Enable 값을 no firewall로 변경해주자.

    일반적인 GSM 네트워크는 우리에게도 익숙한 USIM (SIM) 카드를 통해 가입자를 식별한다. 혹시 설치 스크립트를 유심히 살펴봤다면 항목 중 pySIM 이라는 소프트웨어가 있었을 건데, 이게 바로 라즈베리 파이를 통해 SIM 카드를 프로그래밍 할 수 있게 해주는 도구다. 웹 인터페이스의 Subscribers -> Manage SIMs 메뉴를 통해 간단히 사용할 수 있지만, 이번에는 SIM 카드 없이 주변의 모든 GSM 대응 휴대전화가 네트워크에 연결할 수 있는 방법을 소개하려 한다. SIM 카드에 투자하는 추가 비용이 없는 것은 좋지만 출력이 높아질 경우 제 3자의 휴대전화가 내 네트워크에 자동 연결되어 버릴 수도 있으니 언제나 주의해야 한다. 테스트 환경에서만 사용할 것. 사실 지금 사용 가능한 공 SIM 카드와 리더기가 없다 읍읍

    그렇다고 복잡한 건 없고, 단순히 Subscribers -> List Subscribers 메뉴의 Regexp 값을 .* 으로만 고정하면 SIM 카드가 없어도 누구나 네트워크에 연결이 가능해진다. 이 정도면 만지면 이제 최소한의 네트워크 설정이 완료되었다.

    사용하기

    이제 휴대전화를 꺼내 수동 네트워크 검색 (또는 비슷한 기능을 하는 메뉴) 에 들어가 스캔을 돌려보면 KTKOR SK Telecom 등의 익숙한 통신사와 함께 Test PLMN 1-1 (혹은 비슷한 이름의) 처음 보는 통신사가 같이 검색될 것인데, 이게 우리가 만든 모바일 네트워크다.


    처음 스크립트를 돌릴 때 설정했던 네트워크 이름은 왜 안나오나 궁금해 할 수도 있는데, YateBTS의 커뮤니티 버전은 커스텀 네트워크 이름의 출력을 지원하지 않는 것 같다. 해외 포럼 등에서도 계속 오고가는 이야기이며, 틈날 때마다 리서치 중이니 혹시 우회 방법이나 대체 해결책이 보이면 글을 업데이트 하겠다. Test PLMN 1-1는 우리가 설정한 MNC, MCC 코드에 지정되어 있는 기본 네트워크 이름이다.

    정상적으로 휴대전화가 네트워크에 연결되었다면, 아래와 같이 몇초 지나지 않아 YateBTS 시스템에서 자동으로 보내는 문자메시지가 수신될 것이다. 웰컴 메시지는 Yate 시스템의 버전에 따라 얼마든지 형태가 달라질 수 있다. 혹시 내가 수신한 메시지의 양식이 다르더라도, 그 내용은 아주 비슷할 것이니 별 걱정하지 않아도 된다.


    상단의 웰컴 메시지는 Yate 6 기준 /usr/local/share/yate/scripts/nipc.js 파일 안의 sms_registration 변수 안에 담겨있다. 자유롭게 커스터마이즈 해보자!

    수신된 문자 메시지에는 내 모바일 네트워크에서의 고유 전화번호도 같이 적혀 있다. 이제 이 번호로 다른 기기들과의 전화 / 문자메시지를 주고받을 수 있다. 남는 휴대전화가 더 있다면, 네트워크에 연결해 서로 전화를 걸어보고 문자를 발송해 보자. 별 문제 없이 잘 진행될 것이다.

    IP를 할당받고 인터넷에 연결하는 일도 전혀 어려울 건 없다. 평소 휴대전화에서 데이터 네트워크에 접속하는 것처럼, 설정의 셀룰러 데이터 메뉴에서 데이터 통신을 허용해주기만 하면 된다. 평소에 보던 LTE나 3G 마크 대신 GPRS라는 안 익숙한 친구가 불쑥 튀어나올 것이다. 물론 기본 수십 ~ 수백 mbps 속도를 뽑아내는 LTE 네트워크를 사용하던 우리한테는 이 GPRS라는 친구는 영 미덥지 않다. 무려 이론상 최고 속도 114kbps를 보장해주는 2000년대 2.5G 기술이니까 말이다. 그래도 뭐, 일단 인터넷에 연결할 수 있다는 것 만으로도 감사하자. ‘불가능한 것’ 과 ‘불편한 것’ 의 차이는 어마어마하게 크다.

    결론

    독자분들 중 시대가 어느 시대인데, 왜 GSM 네트워크를 선택했냐고 궁금해하시는 분들도 분명 있을 것이다. 필자도 이왕 만들거 속도 빵빵한 LTE 네트워크를 사용할 수 있었으면 좋았겠지만 현실적으로 봤을 때, 그리고 우리 네트워크의 취지를 생각할 때 GSM과 GPRS 조합이 가장 적당하다고 판단했다.

    일단, GSM 이상의 모바일 네트워크 (UMTS 등)는 더 높은 하드웨어 사양을 요구한다. 다시말해, 라즈베리 파이로 구축하는 휴대용 네트워크는 어림도 없다는 소리다. 노트북이라는 대안이 있기는 하지만, 비용 측면이나 전력 소모량, 공간 사용 측면에서 비교가 되지 못한다. 하나 더 이유를 꼽자면, 오직 GSM 네트워크만 SIM을 통한 가입자 인증 없이 주변 모든 휴대기기를 네트워크에 연결시킬 수 있다. UMTS 이상 모바일 네트워크들은 필수적으로 사전에 사용자 정보를 SIM에 프로그래밍 해둬야 한다. 유사시 네트워크가 제 기능을 하기 위해서는 최대한 간단하고 편하게 사람들 사이에 퍼져야 한다. 평시에도 국내에서는 공 SIM 카드 자체를 구할 수 없을 뿐더러, 일일이 그 많고 많은 사람들을 위한 SIM 카드를 프로그래밍 하고, 또 나눠준다는 것 자체가 비현실적이다. 사용할 유저가 없는 네트워크는 유령 전파가 될 뿐이다.

    물론, 여유가 있다면 OpenBTS-UMTS 프로젝트나 openLTE 프로젝트 등을 참고해 GSM보다 빠르고 현대적인 네트워크를 얼마든지 구축할 수 있다. 관심이 있다면 해당 사이트를 잘 열람해보자. 필자도 시간과 자원이 남는다면, 이런 프로젝트들을 활용한 네트워크를 구축해보고, 글을 남길 의향이 있다.

    여기까지 따라오신 분들, 혹은 단순 흥미로 읽어내려가신 분들, 모두 수고하셨다. 이제 우리 손에 모바일 네트워크 하나쯤은 들고 집에 갈 수 있게 되었다. 각종 재난 상황에서, 또는 혹시라도 세상에 ‘네트워크는 공공재’ 라는 중요한 사실을 다시 각인시켜줄 필요가 있을 때, 오늘의 삽질이 결실을 맺을 수 있길 바란다.

  • 모두를 위한 모바일 네트워크, dokupe.

    IT 기술이 전 세계에 녹아들기 시작한 후로부터, 우리 일상의 온라인 서비스 의존도는 점점 더 높아지고 있다. 점점 더 많은 전화 통화와 메시지를 주고받으며, 점점 더 복잡한 일을 인터넷으로 처리한다. 하루가 다르게 지구를 뒤엎는 데이터 패킷의 양은 늘어나고 있다. 밀접한 네트워크 엑세스는 어느 순간 우리에게 너무나 당연한 것이 되었고, 한 순간이라도 네트워크 엑세스 없이 일상을 보낸다는 것은 상상하기 어려운 일이 되고 있다. 그런데, 이 ‘만약’ 이라는 상황은 언제나 예기치 못한 때 찾아온다. 단순히 자연재해나 정전 등이 원인이 될 수도 있고, 더 나아가서는 정치적인 목적을 위해 국가 주도로 네트워크 사용을 차단하거나 악의적인 집단에 의해 공격받아 장기간 사용 불능이 될 수도 있다. 비현실적적으로 느껴질 수도 있지만, 이미 세계의 여러 국가에서 경험했고, 일부는 지금도 경험하고 있는 상황이다.

    물론 해외 이야기까지 꺼내지 않더라도, 우리는 충분히 많은 네트워크 단절 사태를 경험했지 않은가. 지난 2011년 대규모 정전사태는 물론이고, 2014년 모 통신사의 가입자 확인 모듈 장애로 발생한 전국적인 통신 장애나, 2016년 발생한 경주 지진으로 해당 지역 일대의 통신망이 과부화된 일 등 기억을 되돌려보면 이미 다양한 원인으로 발생하는 통신 장애는 그리 낯선 것이 아니다.

    그럼 우리가 할 수 있는 일은 뭘까? 끔찍한 일이 터지지 않게 기도하며 정부와 통신사만 응원할 것인가? 하나의 방법이 될 수는 있지만, 필자는 조금 더 능동적인 솔루션을 생각하고 있다. 외부 단체나 자원에 의존하지 않으며, 익숙한 방식으로 기초적인 음성통화, 메시징, 데이터 통신이 가능한 모바일 네트워크를 만들어보려 한다. 이런 모바일 네트워크는 10여년 전에는 통신사의 전유물이였지만, 이제는 힘없는 개인도 충분히 들일 수 있을 정도의 (비교적) 저렴한 하드웨어와, 여러 오픈소스 소프트웨어들이 온라인에 공개되어 있다. 적당히 응용하면 전통적인 고정식 기지국을 넘어 라즈베리 파이 등의 소형 컴퓨터를 활용해 들고 다닐 수 있는 기지국을 만들 수도 있을 것이다.

    위에서는 예기치 못한 상황에서 사용할 수 있는 백업 네트워크의 역할을 강조해서 설명했지만, 더 나아가 개인적으로는 사회에 모종의 메시지를 남길 수 있지 않을까 생각하고 있다. 네트워크는 엄연히 공공재의 성격을 띠어야 한다. 일부 주도권을 가진 사람들이 자신들의 이익을 위해 타인의 정보 접근을 제한해서는 안된다는 말이다. 이미 망 중립성이라는 개념도 존재하지만, 유지/보수와 사업 이익의 문제점 등 현실의 벽 때문에 쉽게 실현되지는 않고 있다. 다만, 통신사들은 더 이상 네트워크가 단순히 자신들의 사업 아이템만은 아니라는 것을 상기할 필요가 있다. 마치 전기와 수도를 사용하는 것처럼, 네트워크는 사회적 계층에 상관없이 누구나 사용하는 필수 자원의 범위에 완전히 들어왔다. 외부적인 요인을 가져와 국민들의 정보 접근을 제한하게 된다면 이는 우리 모두의 교육에 대한 기회를 박탈하는 것과 같고, 보이지 않는 손으로 눈과 귀를 막아버리는 것과 같다. 사업 아이템과 공공재 사이의 균형을 맞추지 않는다면, 일개 개인이라도 직접 나서서 독자적인 통신망을 구축할 수 있다는 것을 보여주고 싶다. 더 나은 미래를 위해, 누군가는 움직여야 한다.

    앞으로의 진행 상황과 관련된 기술적인 내용들은 이 GitHub 페이지와 공식 프로젝트 페이지 에서 확인할 수 있을 것이다.

  • Jenkins로 Docker 이미지 배포 자동화하기

    오늘날 개발되고 상용화된 대부분의 서비스들은 어떤 천재 혼자 뚝딱 만들어 낸 것이 아니다. 다양한 특기를 가진 다양한 사람들이 함께 품어 만들어낸 불교의 사리 같은 것이다. 그리고 자연스럽게 가뜩이나 어려운 일의 중간 과정이 진짜 알맹이를 가로막지 않도록 여러 도구와 개념들이 등장했는데, 그 중 하나가 지속적으로 코드의 품질을 관리할 수 있고, 또 나아가 배포까지 이어질 수 있는 CI와 CD (Continuous Integration / Continuous Delivery)다. 내가 작성한 코드를 그대로 내 컴퓨터에서 테스트하고 사용한다면 아무 상관 없는 이야기겠지만, 여러 팀원이 함께 코드를 작성하는 환경에서는 각종 이슈와 신규 배포의 진행사항을 기록하는 일도 필요하고, 내가 사용하지 않는 개발환경을 요구하는 코드를 빌드할 일도 생긴다. 이런 여러가지 문제를 다 내려놓고. 일단 귀찮다. 하루이틀도 아니고 이 모든 일들을 매일 반복한다고 생각해보자. 말 그대로의 주객전도다.

    위에서 언급한 CI와 CD의 개념은 이런 문제들을 해결하기 위해 탄생했다. 그리고 가장 대중적인 도구로 Jenkins를 뽑을 수 있겠다. 이미 전세계 다양한 팀에서 Jenkins를 사용해 자신들의 코드를 자동 빌드하고, 테스트하고, 변경점을 기록하고 있다. 필자는 어딘가의 팀에서 개발자로 활동하고 있지 않지만, 평소 취미 목적으로 만드는 소프트웨어들을 개인 노트북에서 코딩해 Docker 이미지로 빌드한 후, Docker Hub 저장소를 통해 개인 서버들로 전송해 구동하는 과정을 자주 거치고 있어 귀차니즘을 참지 못하고 Jenkins에 손을 대게 되었다.

    DinD (Docker-in-Docker)


    지금부터 하나 재미있는 시도를 해보자. 바로 Jenkins를 Docker 컨테이너로 구동한 후, 그 컨테이너 안에 또 Docker 데몬을 구동해 도커 안의 도커 환경을 만들어 볼 거다. Jenkins 컨테이너가 자체적으로 Docker 이미지를 생성할 수 있게 만드는 거다. Git에 새로운 코드를 커밋하면 Jenkins가 이를 감지하고 자동으로 Docker 이미지를 생성해, 업로드까지 해주는 구성을 해보자.

    필자는 관련 정보를 검색하던 중 발견한 Seapy님의 Docker 이미지를 사용했다. Docker Hub에 공개된 여러 이미지들을 테스트해봤으나 이 이미지가 가장 깔끔하고 사용하기 편해 그대로 사용하고 있다. 다른 이미지를 사용할 예정이거나, 혹은 직접 이미지를 빌드해 사용하고 싶다고 해도 기본적인 설정 방법은 같으니, 참고하길 바란다.

    호스트 컴퓨터에서, 아래 명령어를 통해 이미지를 다운받고 실행해보자.

    docker run -p 연결할_포트번호:8080 -v 연결할/경로:/var/jenkins_home --privileged seapy/jenkins-dind:1.554.3
    

    위의 연결할_포트번호에는 웹 브라우저에서 접근 시 사용할 포트번호를, 연결할/경로에는 Jenkins 컨테이너의 /var/jenkins_home 폴더와 연결될 호스트 컴퓨터의 폴더 경로를 입력한다. Docker 컨테이너는 일반적으로 컨테이너가 변형될 경우 안의 데이터의 안전을 장담할 수 없는 구조라 이렇게 호스트 컴퓨터의 폴더를 연결해두면 컨테이너에 문제가 생겨도 데이터는 안전하게 지킬 수 있다.

    중간에 다른 문제가 발생하지 않았다면, 정상적으로 컨테이너가 구동되고 웹 브라우저로 Jenkins에 접근도 잘 될 것이다. 사용한 이미지가 조금 연식이 있어 (마지막 업데이트가 년단위 전이다…) Jenkins도 구버전이 구동되어 있을 것인데, 사실 이 상태로도 정상적인 사용은 가능하다. 귀찮은 사람은 이대로 사용하고, 최신 버전을 사용하지 못하면 온몸에 가시가 돋는 얼리어답터 분들은 docker execattach 명령 등을 통해 해당 컨테이너에 Java8를 설치한 후 웹 콘솔에서 업데이트 버튼을 누르면 된다. 최신 버전의 Jenkins는 Java8를 요구하는데, 이 이미지에 설치된 구버전은 Java7만 사용하고 있기 때문이다. 꼭 기억하길 바란다. 컨테이너는 일종의 프로세스 개념이라, Java8이 없어 다운받은 업데이트 파일을 정상적으로 구동하지 못할 경우 컨테이너가 그대로 꺼져버린다. 괜히 삽질하지 마시길.

    자, 그대로 사용하시던 혹은 업데이트를 하셨던, 이제 우리의 알맹이를 공략하자. Jenkins 웹 콘솔에서 새로운 Item 버튼을 타고 프로젝트 생성 페이지로 넘어가보자. 프로젝트 이름을 입력하고, Freestyle project를 누르면 된다.

    혹시 최신 버전의 Jenkins로 업데이트한 후, 새로운 Item 버튼을 누르면 빈 페이지만 보일 경우, Jenkins 관리 -> 플러그인 관리 메뉴에 들어가 External Job Monitor을 최신 버전으로 업데이트하면 된다. 이 버그리포팅을 참조하면 도움이 될 것이다.

    상세 구성을 할 수 있는 페이지가 나올건데, 소스 코드 관리 라는 항목에서 Git을 선택하고 자신의 저장소 URL과 인증 정보 등을 입력한다. 필자는 BitBucket을 연동할 생각이기에 그 아래 항목의 빌드 유발 항목에서 Build when a change is pushed to BitBucket 을 선택했다.

    필자처럼 BitBucket을 사용할 경우 프로젝트 생성 전 Jenkins 관리 -> 플러그인 관리 메뉴에서 BitBucket 플러그인을 미리 설치해둬야 한다. 설치하지 않을 경우 위 항목이 보이지 않는다.

    아래의 빌드 항목에는 직접 실행 가능한 쉘 명령어를 입력할 수 있는데, 아래처럼 이미지 생성 후 업로드하는 명령어를 지정하면 된다.

    docker build -t 저장소명/이미지명 .
    
    docker push 저장소명/이미지명
    


    모두 설정을 마쳤을 경우 아마 위 이미지와 비슷할 것이다. 저장을 눌러 빠져나오자.

    이제 테스트 타임이다! 코드에 변경점을 준 뒤 Git에 업로드한 뒤 두근두근 기다리면 된다. 정상적으로 과정을 따라왔다면, 아마 별 문제 없이 빌드와 배포 과정이 진행될 것이다.

    자동화 별 것 없네

    수고하셨다. 자동화 생각보다 별 것 없다. 여러분은 약간의 시간을 투자하여 매일 반복하는 지루한 작업을 줄인 참된 인간이 된 것이다. 이 글에서는 Docker 이미지의 자동 빌드 & 배포만 예시로 들었지만, 이 환경을 기반으로 어떤 종류의 자동화도 할 수 있으니 이제 본인 편의에 맞게 커스터마이징 해나가면 된다.

    Knock ‘em dead!