이번 글에서는 오픈소스로 만들어가는 현재 팀의 서비스를 보다 쉽게 설치할 수 있도록 도와주는 launchpad를 개발하게된 내용에 대해서 이야기 하고자 한다.
이번에 개발한 launchpad
는 말그대로 run command 한번으로 infra부터 application까지 알아서 설치해주고 곧장 우리의 서비스를 이용할 수 있는 환경을 만들어주는 command-line-interface이다.
나는 현재 팀에 지금까지의 System engineer
경험을 살려 인프라 자동화 관련 개발에 참여하기 위해 합류했다. 때문에 나는 현재 backend
파트에서 주로 서비스 운영 및 자동화 개발에 주로 참여하고 있다.
이러한 이유로 처음 합류했을때 설치하기 복잡한 우리의 서비스를 설치 스크립트 한번으로 설치하고 바로 사용할 수 있도록 만들어 달라는 요구를 받았다.(마치 openstack의 devstack처럼.)
우리 서비스는 cloud-native한 서비스이고, kubernetes 기반이기 때문에 terraform을 이용해 EKS를 띄우고, helm과 kubectl을 install해서 가이드에 따라 배포하기만 하면 된다.
다만 eks 이외에도 잡아줘야할 설정이 많고, 우리 서비스는 EKS 이외의 infra resource는
최대한 kubernetes controller를 이용하도록 되어있기에 부가적으로 필요한 설정이 많다.
먼저, 내가 직접 설치해보면서 필요했던 것 들에 대해 아래와 같이 리스트업 했다.
그리고, 아래가 기존 설치 방법을 겪어보면서 그려본 flow chart이다.
기본적으로 우리 서비스는 SaaS이기도 하지만, 오픈소스이기 때문에 개인적으로 설치해서 사용해보고자 하는 유저들에게는 관련 도구 설치부터 필요한 json file까지 다 준비하라고 하기에는.... 상당히 설치하기 싫을 정도의 양이었다.
가장 먼저 생각이 든건 역시 terraform이었다. 이것은 aws provider뿐만 아니라 kubernetes, helm provider도 제공하고 있기 때문에 기존 설치 과정에 대한 내용을 코드로 정의하고 이것을 제공하기만 하면 땡일 것 같았다.
terraform을 이용해 설치를 하게 되었을때, 아래와 같은 flow chart를 그려볼 수 있었다.
이것만으로도 처음 내용과 비교했을때 신경써야할 부분도 적었고, 설치 과정도 단순해졌다.
더군다나, EKS 같이 설정해줘야 할 것이 많은 resource에 대해서는 EKS terraform module이 이미 존재하기 때문에 많은 시간을 들여 terraform code를 작성할 필요도 없었다.
https://github.com/terraform-aws-modules/terraform-aws-eks다만 마음에 걸리는 것은 terraform code를 작성할때 개인적으로 최대한 작은 단위로 나누는 것을 선호하는데 이렇게 되니 또 유저가 각각 module을 돌면서 apply를 해줘야 할 판이었다.
terraform을 최대한 module 단위로 쪼개는 이유에 대해서는 이것을 많이 사용해보신 고수분들께서도 그러하겠지만, 모놀리틱하게 선언된(?) 인프라가 점점 커짐에 따라 더욱 안전하고 편리하게 관리하기 위해 여러 단위로 나누는 것이 일반적이라 생각한다.
https://learn.hashicorp.com/tutorials/terraform/organize-configuration
terraform으로도 충분하다 생각했지만, 목표는 언제 어디서든 한번의 execute로 서비스가 쨘~
이었기 때문에 더 고민해봐야 했다.
그래서 생각한 것이 terraform으로 우리 서비스를 구성하는 것 들을 module처럼 만들고 차례대로 apply하도록 script를 만들어 interface처럼 제공하면 좋겠다! 라는 생각이었다.
종종 사용하던 python으로 만들어볼까 했지만, 언제 어디서든 한번의 execute로 서비스가 쨘~
이라는 것은, 환경에 구애받지 않고 동일한 행동으로 동일한 결과를 내야했기에 후보에서 탈락 시켰다.
python을 이용하면 유저들은 python 버전도 맞춰줘야하고, requirements package도 설치해야 했기에...
그래서 생각한 것이 shell-script로 만드는 것이었다, 다만 이렇게 되면 요구되는 os package(jq라던가..)가 있기 마련이고 유저의 local 환경마다 설치된 os package의 버전이 다르거나 설치가 안된 경우가 있을 수 있기 때문에 docker를 입히기로(?) 했다.
이렇게 하면 docker로 인해 OS 환경이 통일되는 것은 물론, 미리 필요한 intall tool을 얹어두기만 하면 유저들은 환경을 신경쓰지 않고 언제 어디서든 서비스를 구축할 수 있을 것이라 생각했다.
shell을 이용해 여차저차 만들었다. 그런데 만드는 과정에서 usage message부터 로직상 예외처리 등등 처리해줘야 할게 많은데 shell을 이용해서 한땀한땀 구현하다보니 너무 바보 같았다 힘들었다.
사실 아직 개발에 대한 통찰이 부족해 언어에 대한 구체적인 특징 등을 잘 이해하고 선택한 것은 아니었지만, golang이 shell보다 간결하고 깔끔한 문법을 제공하고, 바이너리 형태의 결과물을 제공한다는 것이 마음에 들어 사용해보기로 했다.
앞서 언급했지만 지금까지 서버 운영만 하다보니(사실 핑계다) 개발에 대한 이해도라던가, 언어 선택에 대해서 많이 신경쓰지 않았다. 일단 해보고 싶었다.
그렇다고 공부하고나서 만드는건 시간이 걸릴 것 같았고, 나는 빨리 결과물을 내고 싶었기 때문에 때문에 무작정 tutorial을 보면서 개발을 시작했다.
또한 launchpad
는 command-line-interface로서 서비스를 쉽게 설치할 수 있는 옵션을 제공해야했기 때문에 이러한 컨셉을 구현해낼 수 있도록 cobra라는 library를 사용했다.
CLI 개발을 지원하는 library는 여러가지가 있겠지만 사실 정확한 비교를 하고 선택한 것은 아니고, 앞서 내가 생각하는 컨셉을 구현하기 위해 이걸로 충분하다고 생각해서 곧장 사용해보기로 했다.
cobra가 말하는 자신들의 컨셉은 아래와 같은데 APPNAME VERB NOUN --ADJECTIVE.
처럼
문장을 읽고 직관적으로 interact
하는 방법을 알 수 있다는 것이 좋았다.
Cobra is built on a structure of commands, arguments & flags.
Commands represent actions, Args are things and Flags are modifiers for those actions.
The best applications read like sentences when used, and as a result, users intuitively know how to interact with them.
The pattern to follow is APPNAME VERB NOUN --ADJECTIVE. or APPNAME COMMAND ARG --FLAG
A few good real world examples may better illustrate this point.
In the following example, 'server' is a command, and 'port' is a flag:
hugo server --port=1313
In this command we are telling Git to clone the url bare.
git clone URL --bare
그렇게 한쪽 모니터로는 document를, 다른 한쪽 모니터로는 IDE를 보면서 아래와 같은 결과물을 개발했다. Cobra library에 따라 개발하기만 했는데 다행히 흉해보이지는 않는 것 같다.
github: spaceone-dev/launchpadinstall 이외에도 helm chart의 변경이 있으면
upgrade
작업도 가능하도록 만들었다.
불필요해진 경우destroy
를 하면 모든 리소스를 회수해주고 data도 모두 제거해준다.
Install and Management SpaceONE
Set the variable before installing SpaceONE.
Usage:
launchpad [command]
Available Commands:
completion generate the autocompletion script for the specified shell
deploy Deploy SpaceONE
destroy Destroy SpaceONE
help Help about any command
install Install SpaceONE
upgrade Upgrade SpaceONE
Flags:
-h, --help help for launchpad
Use "launchpad [command] --help" for more information about a command.
사용법은(README)
또한 SpaceONE launchpad
는 아래와 같이 3가지의 설치 타입을 제공한다.
1,2번의 경우 AWS 상에 설치가 되므로 AWS account를 요구하지만
3번의 경우 이미 Kubernetes cluster가 있는 경우 SpaceONE application만 배포하도록 했다.
(이에 따라 On-prem 환경에서 Cluster를 운용하는 유저도 우리 서비스를 설치해볼 수 있다.)
이렇게 해서 처음 생각했던 것 처럼 쉽게 우리의 서비스를 설치해줄 수 있는 결과물이 나왔다.
하지만 그 과정이 좋지 못했고 스스로도 아쉬운 것이 많았다.
물론 기본적으로 개발 역량이 아직은 부족한 탓에 오히려 잘한 것을 찾으라는 것이 더 어렵겠지만,
그렇기에 반드시 수행했어야 하는 것을 해내지 못했다.
나는 운영 script를 만들 정도로만 개발을 해왔다. 때문에 소프트웨어 또는 운영 도구를 만드는 것에 대해서는 배경 지식도 경험도 부족하다.
그렇기 때문에 더더욱 개발을 진행하면서 프로그램 설계, 에러 처리, log 처리, Coding style 등에 대해서 팀내 개발자들에게 리뷰를 요청하고 피드백을 수용하며 나아갔어야했다.
내가 모르니 알려주세요 가 아닌 나는 이렇게 생각했는데 당신들은 어떠한가.
라는 입장을 던질 줄 알아야했고 프로그램 설계시, 이런 접근 방법으로 시작하는 것이 좋다
등의 여러 피드백을 받으며 부족한 점이 구체적으로 무엇인지 알려고 노력했어야 했다.
보통 우리 서비스를 구축하기 위해 EKS Cluster 구축부터, DB 구축, Application 배포, Application 초기화 등의 작업을 거치면 약 4~50분 정도의 시간이 소요된다.
이러한 내용을 지금까지 일일히 직접 배포해가면서 테스트했다.
더 효율적인 테스트 방법이 없었을까? 라고 생각하려 하지 않았고, 그렇기에 많은 시간을 버려가며 개발했다.
test code 작성에 대해서 공부할 필요가 있는 것 같다.
2021년 앞으로 System engineer의 미래는 어두울거야
라고 생각하며 개발팀에 합류해 개발자라고 불리고 있지만 현재 만들고 있는 것을 보면 부끄러울 때가 많다.
이번 개발에 대해서도 전반적으로 무지성하게 접근했던건 아닌가 라는 생각이 든다. 앞으로 많이 깨져봐야 할 일이다.