토스 기술 블로그 정리 - 레거시 인프라 작살내고 하이브리드 클라우드 만든 썰
출처 https://toss.tech/article/payments-legacy-9
이 글은 토스 기술 블로그를 읽고 정리 + 이해가 부족한 부분을 기록하기 위함이다. 용어의 추가 설명도 포함되어 있다. 원본의 글을 옮겨 적은 부분도 있다.
한 줄 요약
OpenStack 기반 프라이빗 클라우드 구축해서 퍼블릭(AWS)과 Active-Active 하이브리드 클라우드(다중 Pod/클러스터)로 운영 관련 글.
기존 인프라
라우팅을 네트워크 장비에서 하지 않고 각각의 서버에 라우팅 형태가 들어있었다. 네트워크 장비는 라우팅에 관여를 하지 않고 있었다.
새로운 경로가 추가될 때마다 관련된 모든 서버에 반영이 필요함을 의미하고 관리가 어려워진다.
첫 해결 시도
기존 서비스는 유지하면서 새로운 기술은 퍼블릭 클라우드를 이용해서 서비스 운영
문제점
클라우드 비용 증가
퍼블릭 클라우드와 온프레미스의 레거시 인프라 간 DR 구성은 아키텍처의 차이 때문에 쉽지 않은 일
DR구성: 재해복구(DR, Disaster Recovery) 체계
DR은 보통 한쪽 인프라에 장애가 나면 다른 쪽으로 트래픽을 옮겨서 서비스를 지속시키는 구조인데, 이게 제대로 작동하려면 두 인프라가 비슷한 구조로 서로 대응(매핑)될 수 있어야 한다.
- 전용회선도 이용할 수 없음
전용회선은 회사(온프레미스 데이터센터)와 특정 거래처, 예를 들어 은행이나 카드사, VAN사 같은 결제 관련 기관들 사이를 물리적으로 직접 연결하는 통신 회선
토스의 결론
- 프라이빗 클라우드 + 퍼블릭 클라우드 새로운 프라이빗 클라우드를 구축한다.
프라이빗 클라우드는 AWS나 Azure 같은 클라우드 서비스를 저희가 소유한 데이터 센터에 직접 구축하는 것을 의미. 가장 큰 장점은 클라우드 서비스의 모든 구성 요소들에 대한 통제권을 저희가 거의 100% 가져갈 수 있다.
최종 목표: 하이브리드 클라우드
- 사용이 쉽고 빠르게 스케일 아웃이 가능한 퍼블릭 클라우드의 장점
- 세부적인 구성 요소들까지 모두 컨트롤이 가능한 프라이빗 클라우드의 장점
프라이빗 클라우드가 만족해야할 3가지 구성
- 애자일한 인프라
- 유연성
- 오픈소스 기반
OpenStack
- 오픈소스로 개발된 클라우드 플랫폼
- AWS나 Azure 같은 퍼블릭 클라우드가 제공하는 기능들(가상 서버, 네트워크, 스토리지, 로드밸런서 등)을 회사가 직접 소유한 데이터센터 안에서 똑같이 구현할 수 있게 해주는 소프트웨어
자동화
모든 자원의 라이프사이클 관리를 앤서블(Ansible)과 테라폼(Terraform) 코드를 이용하여 자동화
모니터링
CMDB - Configuration Management Database(구성 관리 데이터베이스) 회사가 보유한 IT 자원들(서버, 네트워크 장비, VM 인스턴스, 로드밸런서, 그리고 이들 간의 관계와 설정 정보 등)을 한곳에 모아서 기록해두는 데이터베이스
Zabbix는 오래되고 널리 쓰이는 전통적인 인프라 모니터링 도구. 서버의 CPU, 메모리, 디스크, 네트워크 상태 같은 하드웨어/시스템 레벨의 메트릭을 수집하고, 임계치를 넘으면 알람을 보내는 기능에 강점이 있다. 온프레미스 환경에서 특히 많이 쓰인다.
Prometheus는 클라우드 네이티브 환경, 특히 쿠버네티스와 잘 어울리는 모니터링 도구. 애플리케이션이나 서비스가 노출하는 메트릭을 주기적으로 수집(pull 방식)해서 저장하고, 이를 기반으로 알람 규칙을 설정할 수 있다. 컨테이너나 마이크로서비스 환경의 모니터링 표준처럼 자리 잡은 도구이다.
Mimir는 Prometheus와 호환되는 메트릭 저장소인데, Prometheus 자체는 대규모/장기간 데이터를 저장하는 데 한계가 있어서, Mimir 같은 도구를 붙여서 여러 Prometheus에서 모인 메트릭을 대규모로, 장기간 저장하고 조회할 수 있게 확장해주는 역할을 한다. (Grafana Labs에서 만든 도구)
고가용성 전략
- 완전히 독립된 OpenStack 클러스터 2개를 구성
- Active-Active로 운영하다가 특정 OpenStack 클러스터에 장애가 있을 경우 트래픽 인입을 제거하는 게 가장 빠르게 서비스 가용성을 유지할 수 있는 방법
k8s 구성 전략
- 컨트롤 플레인: K8S 클러스터 자체를 관리하고 제어하는 역할
- 데이터 플레인: 애플리케이션이 동작하는 공간
Cluster API
Cluster API는 K8S 클러스터 자체를 K8S의 리소스로 관리하는 툴킷
- CAPO(Cluster API Provider for OpenStack)
- OCCM(OpenStack Cloud Controller Manager) Cluster API가 OpenStack과 연동할 수 있게 해주는 연결 컴포넌트
네트워크 민첩성
NetDevOps라는 방법론
서버나 애플리케이션을 코드로 관리하는 DevOps 방식을, 네트워크 장비 운영에도 그대로 적용한다는 개념
Configuration 모듈화
네트워크 장비 하나의 설정을 하나의 큰 덩어리(모놀리식)로 관리하는 대신, 서비스별로 쪼개서 독립된 모듈 형태로 저장
새로운 서비스가 생기면 해당 모듈만 추가하고, 서비스가 없어지면 그 모듈만 제거하면 되니까 관리가 훨씬 단순하고 안전
템플릿화 및 자동 배포
설정 모듈들을 장비마다 따로따로 관리하는 게 아니라, 파이썬 코드로 하나의 템플릿을 만들어두고, 네트워크 관리 시스템이 각 장비에 맞는 값(파라미터)만 채워 넣어서 자동으로 배포하는 방식
최종 구성
총 3개의 독립된 OpenStack 클러스터를 구성
1
2
3
4
5
6
7
관리 1
- K8S 클러스터 관리를 위한 Cluster API
- 모니터링 시스템
- 보안 툴
- 가용성을 위한 쿼럼 노드 등
프로덕션 운영 2
하이브리드 클라우드
퍼블릭 클라우드와 IDC 합쳐서 총 4개의 가용 영역을 구성 각 클라우드에서도 완전히 독립된 2개의 서비스 운영 -> 고가용성 확보
동일한 역할의 구성 요소를 동일 계위에 배치해서 운영 효율성 확보
클라우드는 다르지만 아키텍처는 통일함
- L4는 IP 주소나 포트 같은 낮은 수준의 정보만 보고 단순하게 트래픽을 분산하는 방식
- L7은 HTTP 요청의 URL 경로나 헤더 같은 애플리케이션 레벨의 내용까지 들여다보고 좀 더 똑똑하게 라우팅하는 방식
애플리케이션 인프라 현대화
OpenStack의 경험을 AWS와 유사하게 하려고 함
클라우드 리소스 매핑
EC2 <–> NOVA(OpenStack에서 가상 서버(VM)를 만들고 관리하는 컴포넌트) NLB(AWS의 L4 로드밸런서) <–> OpenStack의 Octavia ECR(Elastic Container Registry, AWS에서 컨테이너 이미지를 저장/관리하는 서비스) <–> 오픈소스 Harbor ALB <–> F5사의 BigIP EKS <–> Kubernetes Cluster API를 이용해 OpenStack 위에 쿠버네티스 클러스터를 구성
배포 시스템 확장
빌드된 컨테이너 이미지를 AWS ECR과 OpenStack Harbor 양쪽으로 업로드하고, AWS EKS 클러스터 2개와 OpenStack OKS 클러스터 2개에 동시에 배포한 뒤, Istio와 Argo Rollout을 기반으로 점진적인 트래픽 전환이 이루어지도록 배포 시스템을 확장
- Argo Rollout은 쿠버네티스에서 카나리(canary) 배포나 블루/그린 배포처럼 점진적인 배포 전략을 관리해 주는 컨트롤러
- Istio는 서비스 메시(service mesh)로, 실제로 트래픽을 세밀하게 나눠서 라우팅하는 역할
Argo Rollout이 “지금은 새 버전에 20%를 보내라”고 지시하면, 이를 실제 네트워크 레벨에서 구현해 요청을 정해진 비율대로 기존 버전과 새 버전 파드에 분산시켜 주는 것이 Istio
클라우드 부하 분산
저희는 AWS에서 사용 중이던 Global Accelerator 구성을 변경해 AWS와 OpenStack 간 트래픽 부하 분산에 우선 적용해서 Active-Active 클라우드 운영의 시작을 빠르게 할 수 있었습니다.
Global Accelerator: AWS의 글로벌 네트워크 가속/고정 진입점 서비스로, 사용자를 가장 가까운 AWS 엔드포인트로 라우팅하고 여러 백엔드에 트래픽을 분산해 주는 서비스
Global Accelerator는 원래도 AWS 리소스로 트래픽을 분산하는 데 쓰이던 것인데, 이 설정을 조정해서 AWS와 OpenStack 사이의 트래픽 분산에도 우선 적용한 것
로그 수집 및 분석
기존에는 OpenStack에서 발생하는 로그까지 전부 AWS 쪽 Elasticsearch로 보내는 구조였다.
나중에 AWS와 OpenStack(IDC)을 잇는 전용회선 구간에 로그 트래픽이 몰리면서 병목 현상이 발생했다.
해결방법은 AWS와 OpenStack 각각에 별도의 Elasticsearch 클러스터를 두는 것
각 클라우드에서 발생한 로그는 같은 클라우드 안의 Elasticsearch에 저장하도록 바꾼 것
로그 저장소를 나누면 “AWS와 OpenStack을 통합해서 한눈에 보고 분석하기”가 어려워질 수 있는데, 이 부분은 Elasticsearch의 Cross Cluster 기능(서로 다른 Elasticsearch 클러스터를 연결해서 마치 하나처럼 검색·조회할 수 있게 해주는 기능)으로 해결
Elasticsearch는 대량의 텍스트/로그 데이터를 빠르게 저장하고 검색할 수 있게 해주는 오픈소스 검색 및 분석 엔진
“이 단어가 포함된 문서를 다 찾아줘” 같은 검색 작업이나, 대량의 로그를 실시간에 가깝게 저장하고 집계·분석하는 데 특히 강점
OpenStack에서 AWS 리소스 접근
AWS Roles Anywhere
_저희는 AWS 의 Roles Anywhere 서비스를 이용해 IAM Role을 사용할 수 있는 환경을 구현하기로 했습니다. _
원래는 AWS VPC 바깥(즉 OpenStack처럼 AWS가 아닌 외부 환경)에서 AWS 리소스에 접근하려면 IAM에서 Access Key(고정된 아이디/비밀키 형태의 인증 정보)를 발급받아 코드나 서버에 심어두는 방식이었다.
문제는 이 Access Key가 유출되면 그대로 AWS 계정이 뚫릴 수 있다는 점이라, 보안 사고 위험이 계속 커지는 방식이다.
Roles Anywhere는 AWS 외부에 있는 서버나 애플리케이션도, 사전에 등록된 신뢰 관계를 통해 신원을 증명하면, 고정된 Access Key 없이 짧은 시간만 유효한 임시 토큰을 발급받아 IAM Role의 권한처럼 사용할 수 있게 해준다.
OpenStack 위의 서버나 컨테이너가 AWS S3 같은 리소스에 접근할 때, 유출 위험이 큰 고정 Access Key 대신, 매번 짧게 유효한 임시 토큰을 발급받아 쓰도록 만들었다.
Roles Anywhere 보안 강화
AWS Roles Anywhere는 퍼블릭 서비스이기 때문에 OpenStack에서 발급된 AWS IAM 임시 키가 공용 인터넷망에서 사용되지 않도록 차단할 필요가 있었습니다.
이 문제를 막기 위해 도입한 것이 Session Policy와 aws:VpcSourceIp 조건
Session Policy는 IAM Role이 발급하는 임시 자격 증명(토큰)에 “이 세션에서는 이런 조건 하에서만 권한을 쓸 수 있다”는 추가 제약을 걸어주는 정책
aws:VpcSourceIp는 IAM 정책에서 쓸 수 있는 조건 키(condition key) 중 하나로, “이 요청이 특정 VPC를 통해 들어온 것인지, 그리고 그 안에서도 어떤 사설 IP 대역에서 들어온 것인지”를 검사할 수 있게 해준다.
적용한 방법
Roles Anywhere Profile(임시 키 발급 설정)에 “발급된 임시 키는 aws:VpcSourceIp 조건에 맞는, 즉 미리 허용한 사설 네트워크 경로를 통해 들어온 요청에서만 사용 가능하다”는 제약을 걸어두었다.
설령 이 임시 키가 외부로 유출되더라도 공용 인터넷에서 그 키로 AWS API를 호출하면 조건에 맞지 않아 거부되고, 오직 지정된 사내 네트워크(Private Link 경로) 안에서만 실제로 동작하게 된다.
