Docker와 Coder 그리고 Citizen

해당 포스트는 Kubernetes Advanced Network Study 3기에 참가하여 1주차 과제와 연관하여 작성했습니다.

주어진 요구사항

IDC에서 클라우드로의 마이그레이션을 진행하며 요구사항이 하나 전달되었습니다.

“Jupyter Notebook을 사용하는데 기존에 VM에 Jupyter Notebook을 사용했지만, 자원문제로 매번 재부팅하는 문제가 있어요. 여기에다가 A 사용자가 B 사용자의 데이터를 건들수도 있고, 그렇다고 망분리 VDI를 사용하자니 VDI 사양이 그렇게 좋지 않아서요. 어떻게 방법이 없을까요?”

생각하다보니 Visual Studio Code의 코드를 OSS화 해서 Hosting이 가능하도록 한 툴이 생각났습니다. Code-Server 하지만, 이 툴은 개인이 사용하도록 하는 것이기 때문에, 사용자 격리와 보안부서의 요구사항이 Audit 관련된 부분이 해결되지 않습니다. 그래서 누군가는 Code-Server를 호스팅할수 있도록 하지 않았을까? 하고 찾아보니 Coder 라는 툴이 보이게 되었습니다.

일단 설치를 하면서 요건을 되짚어보다

Coder를 확인해보니 Terraform 기반으로 필요한 리소스(AKS/GKE/EKS, Docker 등) 개인에게 격리된 개발환경을 제공하는 것을 확인했습니다.

우선, 공식 홈페이지에 있는 정보로 설치합니다.

curl -L https://coder.com/install.sh | sh

이후에 무엇이 필요한지 요건을 되짚어 보았습니다.

요건은 앞에서 기재했던 Jupyter Notebook 뿐만 아니라, 코드 에디터(가능한 VSCode 쪽으로), VSCode가 가능하다면 Extenstion도 설치하고, Nodejs, Anaconda, JDK도 사전에 설치되어서 Spark, Airflow 등의 작업할수 있는게 추가되었습니다.

그래서 Coder에 있는 여러 템플릿 중에 Docker Template을 가지고 DockerFile을 수정하기 시작합니다.

요구사항이 잔뜩 담겨버린 DockerFile을 만들고야 말았습니다…!

FROM ubuntu:22.04

RUN sed -i s%archive.ubuntu.com%repo.domain.com/repo%g /etc/apt/sources.list \
    && sed -i s%security.ubuntu.com/ubuntu%repo.domain.com/repo/ubuntu-sec%g /etc/apt/sources.list \
    && apt-get update \
	  && apt-get install -y wget curl git golang python3 python3-pip python-is-python3 sudo vim	wget gnupg bzip2 libaio1 unzip openjdk-11-jdk \
	  && wget http://repo.domain.com/repo/oracle_client/instantclient-basic-linux.x64-21.11.0.0.0dbru.zip -O /opt/instantclient-basic-linux.zip \
	  && unzip /opt/instantclient-basic-linux.zip -d /opt/oracle/ \
	  && sh -c "echo /opt/oracle/instantclient_21_11 > /etc/ld.so.conf.d/oracle-instantclient.conf" \
    && ldconfig \
    && wget http://repo.domain.com/src/nodesource.list -O /etc/apt/sources.list.d/nodesource.list \
	  && curl -s http://repo.domain.com/src/nodesource.gpg | gpg --dearmor | tee /usr/share/keyrings/nodesource.gpg >/dev/null \
	  && echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list \
	  && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg \
	  && apt-get update \
	  && apt-get install -y nodejs google-cloud-cli \
	  && rm -rf /var/lib/apt/lists/* \
	  && wget http://repo.domain.com/repo/anaconda/Anaconda3-2024.02-1-Linux-x86_64.sh -O /tmp/anaconda.sh \
    && bash /tmp/anaconda.sh -b -p /usr/local/anaconda3 \
    && groupadd anaconda3 \
	  && chgrp -R anaconda3 /usr/local/anaconda3 \
	  && chmod 770 -R /usr/local/anaconda3 \
	  && rm /tmp/anaconda.sh

ARG USER=coder
RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \
	&& echo "${USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/${USER} \
	&& chmod 0440 /etc/sudoers.d/${USER} \
	&& adduser ${USER} anaconda3
USER ${USER}
WORKDIR /home/${USER}

참고

이와 같은 DockerFile이 작성된 이유는 간단합니다. 컨테이너는 레이어로 이루어져 있으며, DockerFile의 FROM/RUN/ARG 등 구문들 모두가 하나의 레이어라고 보면 됩니다. 그렇기에 (역슬레시)와 &&을 통해서 최대한 하나의 명령어로 작성하는것이 컨테이너의 용량을 줄일수 있는 하나의 방법이 됩니다. 여기에 가장 좋은 예시로는 Nginx의 DockerFile이 되겠네요. 링크

벽에 또 막혔네요

자, 이렇게 해서 Coder를 통한 VSCode를 제공할수 있게 되었습니다! 는 일단 제외하고, 이렇게 하다보니 모든걸 Private한 환경에서 처리해야했습니다.

Coder가 Terraform 기반이다보니 Terraform Private Registry가 필요하게 되었습니다. 공식문서를 확인해보니 Terraform Registry API 문서가 있고, 이 문서를 보니 직접 구현을 해야하네요.

그래서 또, 누군가는 이걸 OSS로 만들었을거라고 생각하며 찾았습니다. Citizen 이었습니다. 어, 그런데 확인해보니 업데이트가 22년도 이고, 작업은 23년(구성당시)이고, OS에 Native하게 하려니 여러가지 문제가 발생합니다.

그래서 Citizen의 Container를 이용하기로 했습니다.

커스텀 이미지도 만들어보고, 여러 방면으로 하다가 결정한 것은, 기본 컨테이너를 가져오되, Data는 Host에 저장하여 컨테이너가 재시작되어도 데이터는 유지되도록 했습니다.

어떻게든 완성은 했어요

이렇게해서 Docker, Coder, Citizen의 합작으로 팀내 구성원들에게 VDI의 사양의 영향없이 빵빵한 스펙의 서버에서 자원을 나누어 사용하며 아름다운 격리까지…!

이후에 1년이 넘은 지금까지 망분리 VDI에서 개발해야하는 팀원분들은 매우 잘 쓰고 있습니다(다행이도요).