Tech News

제목1인 기술 스타트업의 아키텍쳐 스택2021-04-12 21:47
작성자 Level 10

The Architecture Behind A One-Person Tech Startup (anthonynsimon.com) 


- 스트레스 없이, 느릿하게 SaaS를 운영하는 1인 개발자의 아키텍쳐 설명

- 여러개의 프로젝트를 동시에 운영하는 인프라를 구성했음

- 자신이 최근에 만든 PanelBear 라는 SaaS를 기준으로 설명

ㅤ→ 가장 작은 VPS에서 SQLite + Django로 시작

ㅤ→ 6개월간의 이터레이션을 통해, EKS 위에서 Django 모노리스 + Postgres + ClickHouse(분석) + Redis(캐싱) + Celery(예약 작업)

ㅤ→ 대부분 자동화 : 오토스케일링, ingress, TLS 인증서, failover, 로깅, 모니터링 등

ㅤ→ 이 설정을 여러개의 프로젝트에서 사용하므로, 비용을 줄이고 실험들을 정말 쉽게 시작할 수 있음

ㅤ→ 인프라 관리에는 거의 시간이 들지않음 (한달에 0~2시간).

ㅤ→ 대부분의 시간은 기능 개발, 고객 지원, 비즈니스를 성장시키는데 사용


- AWS에서 Kubernetes를 사용하지만 꼭 이게 필요한 건 아님. 다만, 본인은 익숙하기에 안정적으로 운영할 수 있다고 생각.

ㅤ→ 참을성 있는 팀(에러를 같이 참고 막아줄)에서 이 도구를 몇년간 사용하며 배웠음

ㅤ→ "쿠버네티스는 단순한 걸 복잡하게 만들지만, 복잡한 것을 단순하게 만들기도 함"


- 자동 DNS, SSL 및 로드밸런싱

ㅤ→ CloudFlare Proxy 에서 AWS L4 NLB(Network Load Balancer) 로 모든 트래픽 전달

ㅤ→ Request가 들어오면 LB가 k8s 클러스터 노드중 하나로 포워드

ㅤ→ 이 노드들은 여러개의 AZ(Availability Zone) 에 걸쳐져 있는 프라이빗 서브넷에 있음

ㅤ→ k8s 가 요청할 서비스를 알아내는 것은 ingress-nginx(Nginx 클러스터) 가 함

ㅤ→ nginx가 트래픽 전달전에 RateLimiting 및 트래픽 쉐이핑 규칙을 적용

ㅤ→ PanelBear의 경우 앱 컨테이너는 Uvicorn 에서 서빙되는 Django

ㅤ→ Terraform/K8s 간에 몇개의 설정파일이 있고 그걸 대부분의 프로젝트가 공유

ㅤ→ 새 프로젝트 배포 할때 20 라인 정도의 ingress 설정으로 가능


- 자동 롤아웃 및 롤백

ㅤ→ 마스터에 푸시할때마다 GitHub Actions 로 CI 파이프라인 실행

ㅤ→ 코드베이스 검사, Docker-Compose로 완전환 환경을 만들어 E-to-E 테스트

ㅤ→ 검사 통과시 ECR(AWS의 Docker Registry)로 푸시되는 새 Docker 이미지를 빌드

ㅤ→ k8s 클러스터에 flux 컴포넌트 ( https://fluxcd.io/ ) 가 알아서 클러스터내의 이미지를 동기화

ㅤ→ Flux 가 자동으로 Incremental Rollout 실행


- Horizontal Autoscaling

ㅤ→ CPU/메모리 사용량 기반으로 오토스케일링

ㅤ→ 클러스터의 노드당 Pod가 너무 많은 경우 자동으로 더 많은 서버를 생성해서 클러스터 용량을 늘리고 부하를 줄임. 일이 없을때는 축소

ㅤ→ Panelbear 의 경우 API Pod를 2개에서 8개까지 복제본을 자동 조정


- CDN을 이용해서 Static Asset 캐슁

ㅤ→ CloudFlare를 DNS에 설정해서, 모든 요청을 처리하고 DDoS 방지까지 처리

ㅤ→ Static 파일 서빙에는 Whitenoise ( https://github.com/evansd/whitenoise ) 를 사용해서 NGinx/Cloudfront/S3에 파일 업로드할 필요가 없음

ㅤ→ Panelbear 의 랜딩 같은 몇개의 정적 웹사이트에는 NextJS 를 사용


- 어플리케이션 데이터 캐슁

ㅤ→ 일정부분에서는 파이썬이 제공하는 인메모리 LRU 캐슁을 사용

ㅤ→ 대부분의 엔드포인트는 인 클러스터 Redis를 사용


- EndPoint 당 Rate Limiting

ㅤ→ nginx-ingress 에서 글로벌 레이트 리밋을 하지만, 가끔 엔드포인트/메소드 당 특정 리밋을 줄 필요가 있음

ㅤ→ Django Ratelimit 라이브러리를 사용해서 Django 뷰당 제한을 선언 가능

ㅤ→ Redis 를 백엔드로 사용해서 각 엔드포인트에 요청하는 클라이언트를 추적하도록 구성(IP가 아닌 클라이언트 키 기반 해시)


- App Administration

ㅤ→ Django 의 Admin Panel 이 기본적으로 데이터를 보고 편집하는 기능들을 지원

ㅤ→ 의심스러운 계정 접근 차단 / 공지 이메일 발송 / 계정 삭제 요청 처리등의 기능을 추가(처음엔 소프트 삭제후, 72시간내에 완전 삭제)


- 예약된 작업 실행

ㅤ→ SaaS에선 다양한 예약작업이 실행 : 고객에 대한 일일 보고서, 15분마다 사용 통계 계산, 직원들에게 보내는 지표 이메일 등

ㅤ→ Celery 워커 몇개와 Celery beat 스케줄러를 클러스터내에서 실행중. Redis를 태스크 큐로 사용

ㅤ→ 예약된 작업이 제대로 실행되지 않을때 SMS/Slack/Email 등으로 공지 받기 위해 HealthChecks.io 를 사용


- App Configuration

ㅤ→ 모든 설정은 환경변수를 이용. 구식이지만 이식 가능하고 잘 지원됨


- Keeping Secrets

ㅤ→ kubeseal 을 이용. 비대칭 암호화를 사용해서 Secret들을 암호화함. 암호 해독 키에 접근할 권한이 있는 클러스터만 암호 해독 가능

ㅤ→ 클러스터내의 Secret 들을 보호하기 위해 AWS KMS의 암호화 키를 이용


- 관계형 데이터 : Postgres

ㅤ→ 실험들을 위해 클러스터내에서 바닐라 Postgres 컨테이너를 운영하고, K8s Cronjob 으로 S3에 매일 백업을 수행

ㅤ→ 프로젝트가 성장하면 데이터베이스를 클러스터 내에서 RDS로 옮기고, AWS가 암호화된 백업 및 보안 업데이트등을 처리하게 함

ㅤ→ 보안을 강화하기 위해, AWS의 DB는 Private Network 에서만 접근 가능


- 컬럼 데이터 : ClickHouse

ㅤ→ PanelBear의 분석데이터를 효율적으로 저장하고 실시간 쿼리하기 위해 ClickHouse 를 사용

ㅤ→ 훌륭한 Columnar 데이터 베이스로, 엄청 빠르고 구조만 잘 잡으면 높은 압축률을 보임(스토리지 감소 = 수익 증가)

ㅤ→ K8s 클러스터내에서 ClickHouse 인스턴스를 자체 호스팅

ㅤ→ S3에 Columnar 데이터를 주기적으로 백업하는 CronJob 생성

ㅤ→ 재해시 S3에서 데이터를 수동으로 백업하고 복원하는 몇개의 스크립트


- DNS기반 서비스 디스커버리

ㅤ→ K8s 가 클러스터내의 DNS 레코드를 자동으로 관리해서 트래픽을 해당 서비스로 라우팅

ㅤ→ 오토스케일링중에도 건강한 pod 들과 연결되도록 자동으로 DNS 레코드를 동기화


- Version-Controlled Infrastructure

ㅤ→ Docker, Terraform, K8s manifest 를 단일 저장소(Infra Mono-Repo)에서 관리

ㅤ→ 간단한 명령으로 인프라 생성 및 삭제가 가능하고 버전 관리를 통해 재현가능


- Cloud Resource를 위한 Terraform

ㅤ→ 대부분의 클라우드 리소스는 Terraform 으로 관리

ㅤ→ 이를 통해 인프라 자원과 설정을 문서화 하고 추적이 가능


- App 배포를 위한 K8s manifest

ㅤ→ 인프라 모노 레포의 YAML 파일에 K8s Manifest 가 적혀있음

ㅤ→ cluster 와 apps 두개의 폴더로 분할

ㅤ→ cluster 에는 nginx-ingress, 암호화된 secret들, Prometheus 스크래퍼 처럼 클러스터 전체 서비스 관련 설정을 포함

ㅤ→ apps 에는 프로젝트당 하나의 네임스페이스에 정보들 저장


- 구독 및 결제

ㅤ→ Stripe Checkout 을 이용해서 모든 결제 처리

ㅤ→ 결제 정보 자체에 관여할 필요 없어서 제품에 집중 가능

ㅤ→ 고객 세션 만들고 Stripe의 페이지로 리디렉션 한뒤 WebHook 으로 결과받으면 끝


- Logging

ㅤ→ 로깅 에이전트를 쓰지 않고 간단히 stdout 에 로그출력하면 k8s 가 자동으로 로그를 수집하고 rotate도 수행

ㅤ→ FluentBit 등을 통해서 Elasticsearch/Kibana 등으로 보낼수 있겠지만, 간단히 유지하기 위해 아직은 하지 않음

ㅤ→ 로그 검사를 위해서는 CLI 도구인 stern 사용


- 모니터링 및 경고

ㅤ→ 처음에는 Prometheus / Grafana 를 자체호스팅 했지만, 클러스터 문제 발생시 경고시스템도 같이 중단 되어서 불편

ㅤ→ 그래서 New Relic 으로 변경

ㅤ→ 모든 서비스에는 자동으로 지표를 수집하고 Datadog, New Relic, Grafana Cloud 등으로 보낼수 있는 Prometheus Integration 이 있어서, New Relic 으로 이관시 그들이 제공하는 Prometheus Docker 이미지를 사용하는 것만으로 가능


- 오류 추적

ㅤ→ Sentry 를 이용해서 애플리케이션 오류를 수집

ㅤ→ Slack #alerts 채널을 이용해서 downtime, cron job failures, security alerts, performance regressions, application exceptions 등 모든 경고를 중앙 집중화


- Profiling 및 다른 좋은 것들

ㅤ→ 심층 분석이 필요할때는 cProfile 이나 snakeviz 같은 도구를 사용

ㅤ→ 로컬 머신에서는 Django Debug Toolbar 이용

G
M
T
Text-to-speech function is limited to 200 characters
댓글
자동등록방지
(자동등록방지 숫자를 입력해 주세요)