1달 전 홈 서버를 구축해 보고 싶어서 사비로 맥미니를 구매했습니다.
8~9월에 일정이 많아서 많은 시간을 들이지는 못했지만, 추석 연휴까지 활용하여 어느 정도 구축을 완료했습니다.
자세한 내용은 추후에 정리할 계획입니다만, 진행 과정과 중간에 겪었던 어려움을 적어 보려고 합니다.
홈 서버, 맥미니를 선택한 이유
홈 서버를 구축해 보고 싶다는 생각은 올해 초부터 가지고 있었습니다.
DevOps에 관심을 가진 뒤로 저만의 고유한 서버를 구축해 보고 싶었고,
제가 운영 중인 사이드 프로젝트의 대부분은 데이터를 내부에 JSON 형식으로 두고 따로 서버를 두지 않고 있는데 시간이 지나면서 유지보수도 힘들어지고 여러 이유로 서버의 필요성을 느끼고 있었습니다.
그럼에도 홈 서버를 망설였던 이유는 가족과 함께 지내고 있어 소음이나 비용 문제가 걱정되기 때문이었습니다.
그러던 중 LinkedIn의 한 게시글을 보고 맥미니라면 전력 소모도 적고, 소음과 발열도 문제가 없겠다는 생각에 구매를 하게 되었습니다.
사양은 기본 사양에서 RAM만 16GB로 업그레이드하여 구매하였습니다.
현재 재직 중인 회사의 운영 서버와 비교해 보았을 때, 이 정도면 원하는 수준의 서버는 구축 가능하겠다는 판단을 내렸습니다.
구축 과정에서 겪은 어려움
macOS와 Kubernetes
macOS와 리눅스는 모두 UNIX 계열이지만, 서로 다른 운영체제라고 보아야 하고 특히 macOS가 M1/M2 칩을 채용한 뒤로는 호환 문제가 생각보다 많습니다. 관련된 문제를 Kubernetes를 설치할 때도 겪게 되었습니다.
통상적인 Kubernetes 설치 도구 대부분은 드라이버를 요구하는데, 보통 Docker Desktop을 많이 안내하고 있습니다. 하지만 너무 무거워서 가급적 사용하지 않고 싶었고, 특히 가장 참고자료가 많았던 minikube의 경우 Docker 드라이버를 사용하게 되면 외부망에 서비스를 노출하는 과정이 까다롭고 불편했습니다. 그 외 kind나 MicroK8s 등의 도구도 사용해 보았지만 만족스럽지 않았고, HyperKit 드라이버처럼 M1/M2 칩을 지원하지 않는 경우도 있었습니다.
결국 많은 시행착오 후 선택한 것은 이전에 만족스럽게 사용했던 Multipass + K3s였습니다.
그리고 다행히도 이전에 K3s 구축 과정을 기록해 두어서, 비교적 수월하게 Kubernetes를 세팅할 수 있었습니다.
결국 K3s를 포함해서 macOS에서 Kubernetes 환경을 구축하기 위해서는 Docker 또는 VM을 중간에 두어야 한다는 점이 만족스럽지는 않습니다.
하지만 단순 성능만으로 맥미니를 서버로 선택한 것이 아니었기 때문에, 감내해야 할 부분이라고 생각합니다.
나중에는 리눅스 서버를 꼭 구매해 봐야겠네요.
macOS와 Docker 빌드
Docker 이미지 빌드에는 GitHub Actions를 사용하였습니다. 맥미니 내부에서 수행할 수도 있지만, 리소스 사용을 최대한 줄이고 외부 리소스를 가능하면 활용하고 싶었습니다.
하지만 이 부분에서 문제가 생겼습니다.
GitHub Actions는 macOS에서 Docker 빌드 지원이 빈약해서 Ubuntu로 빌드를 수행해야 하는데, 둘의 CPU 아키텍처가 달라 개발 환경에서는 빌드와 실행이 잘 되는데 GitHub Actions에서 빌드한 이미지는 오류가 발생했습니다.
멀티 플랫폼을 지원하도록 Docker 빌드를 수행하는 방법이 공식 문서에 있었지만 실제로 적용해 보니 속도가 너무 느려 채택하지 않았고, 최종적으로는 Distroless 이미지를 사용하여 빌드된 파일을 맥미니와 호환되는 arm64
아키텍처 이미지에 이동시켜 실행하는 방법으로 해결하였습니다.
macOS와 Rust 빌드
홈 서버에 배포하기 위해 처음으로 만든 것이 파일 서버였습니다.
Rust를 사용했는데, 기능이 간단하고 이번 기회에 Rust를 써 보고 싶어서 채택하게 되었습니다.
다만 위에서 언급한 CPU 아키텍처의 차이로 인해 Rust 빌드 파일도 제대로 실행되지 않는 문제가 있었습니다.
조사해 보니 Rust도 플랫폼을 지정해서 빌드하는 방법이 있었고, 여러 시행착오를 거쳐 최종적으로는 한 블로그를 참고하여 빌드 스크립트를 새로 구성했습니다.
아래는 빌드에 성공한 Dockerfile
최종본입니다.
그 외
-
VM 내부 IP를 네트워크에 공개하고 공유기로 포트포워딩하기 위해 Multipass VM의 네트워크 설정이 필요했습니다. 공식 문서를 참고하였습니다.
-
외부에 도메인으로 서비스를 공개하기 위해 HTTPS 설정이 필요했는데, 기존에 소유하고 있던 도메인을 Cloudflare로 이관하고 cert-manager로 인증서를 관리하도록 하였습니다. Cloudflare는 상대적으로 약한 홈 서버의 보안을 강화시켜 줄 수 있어서 계속 사용할 것 같습니다.
-
Argo CD의 UI를 도메인으로 공개할 때 Redirection이 계속 발생하여 연결이 되지 않는 문제가 있었습니다. 수많은 이슈들에서 관련 내용들을 찾을 수 있었는데, 저는 결국 아래 설정을 추가하여 해결하였습니다.
-
추가로 공유기에서 맥미니에 고정 IP를 부여하거나, 포트포워딩 작업을 해야 하는데 이 부분은 검색을 통해 해결하였습니다. 설정법이 모두 다르기 때문에 여기서는 따로 설명하지 않겠습니다.
마치며
생각보다 어려움이 많았지만, 초기 설정을 완료했고 테스트용 파일 서버도 외부에 공개되어 있습니다.
최근 사이드 프로젝트에 시들했었는데, 홈 서버를 구매하면서 명확한 목표가 생기니 과정이 어려워도 계속 시도하게 되고 해결한 뒤에는 큰 성취감을 느끼게 되는 것 같습니다. 앞으로는 기존에 서비스하던 사이드 프로젝트들을 모두 홈 서버로 이관하고, 모니터링 시스템도 구축하여 완성도를 높일 계획입니다.
참고 자료
- Support amd64 on M1 with docker instance · Issue #2422 · canonical/multipass · GitHub
- Multi-platform image | Docker Docs
- Rust: Docker Image Optimization With Multi-stage Builds - DEV Community
- Cross-compilation in Rust (kerkour.com)
- How to add a network to an existing instance | Multipass documentation
- 오라클 클라우드 무료쿠버네티스 (K3S) 서버에 인증서 달기 - Hibernation IT
- Ingress Configuration - Argo CD - Declarative GitOps CD for Kubernetes (argo-cd.readthedocs.io)
- ERR_TOO_MANY_REDIRECTS · Issue #2953 · argoproj/argo-cd (github.com)