SSH에서 REST로: Slack EMR 데이터 파이프라인 현대화 이야기

Slack 엔지니어링 블로그에 소개된 흥미로운 아키텍처 마이그레이션 사례가 있습니다. SSH 기반 데이터 플랫폼을 REST 기반으로 전환하여, 보안 취약점을 해결하고 동시에 인프라 현대화를가속한 이야기입니다. 700개 이상의 프로덕션 잡을 3분기 만에 무중단 이전한 과정이 꽤 실용적인 교훈을 제공합니다.
배경: 2017년에 만들어진 SSH 기반 플랫폼
2017년경 Slack은 Airflow를 사용해 EMR 클러스터에서 잡을 실행하는 가장 직접적인 경로로 SSH 방식을 채택했습니다. Airflow의 SSHOperator로 EMR 마스터 노드에 접속한 뒤 spark-submit 같은 명령을 실행하는 구조였죠.
시간이 지나면서 팀마다 다양한 용도에 맞춰 커스텀 SSH 기반 Operator를 자체 제작했습니다. Spark뿐 아니라 MapReduce, AWS CLI, 커스텀 Python 스크립트까지 — 결과적으로 프로덕션 환경에 700개 이상의 SSH 기반 잡이 누적되었습니다.
SSH 방식이 만든 문제들
직접 SSH 접속으로 클러스터에 접속하는 방식은 생각보다 많은 비용을 지불하게 만듭니다.
보안 측면:
• 컴퓨트 클러스터로의 직접 SSH 접속이 공격 표면 확대
• 오케스트레이션 워커 전반에 걸친 키 배포 및 회전으로 운영 부담 증가
• 세분화된 감사를 위해 여러 시스템 로그를 상관 분석해야 함
• 전용 보안 그룹과 커스텀 설정으로 권한 관리 복잡
운영 측면:
• 잡이 EMR 마스터 노드에서 직접 실행되어 리소스 경합 발생
• Kubernetes Pod 재시작 시 SSH 연결이 끊어지면서 잡 실패
• 장시간 잡이 연결 종료 후에도 실행되어 좀비 프로세스화
• 연결 끊김 시 잡 성공/실패 여부를 확인할 신뢰적 수단 부재
현대화 차단:
• SSH 의존성 때문에 Spark on Kubernetes 및 EMR on EKS 전환 불가
• 마지막 메인 계정 EMR 클러스터를 자식 계정으로 옮기지 못해 Whitecastle 이니셔티브 미완료
• 적절한 잡 모니터링과 가시성 구현 불가
REST 기반 잡 제출의 기본 개념
SSH 접속의 본질적 한계를 이해하면 REST 대안이 왜 효과적인지 자연스럽게 이해됩니다. SSH는 상태 유지형 직접 연결이라, Pod 재시작이나 연결 끊김발생시 명령이 계속 실행되거나 실패해도 재접속해서 상태를 확인할 신뢰적 수단이 없습니다.
반면 YARN, Trino, Snowflake 등 현대 컴퓨트 엔진은 HTTP API로 잡을 제출합니다:
• POST 잡 요청 → 잡 ID 반환
• GET 잡 상태 조회 → 실행/완료/실패 확인
• DELETE 잡 → 정상 취소
잡의 수명주기를 서버 측에서 관리하기 때문에, 클라이언트가 재시작해도 잡은 계속 실행되며 상태 조회도 가능합니다.
돌파구: YARN Distributed Shell
Hadoop 워크로드(MapReduce, Spark, Hive)는 YARN이 리소스 매니저이자 REST API를 제공합니다. 그러나 aws s3 sync, hadoop distcp 같은 임의 셸 명령을 실행하는 300개 이상의 CLI 기반 잡에는 즉시 사용 가능한 REST API가 없었습니다.
Slack 엔지니어링 팀이 발견한 해결책은 의외로 단순했습니다. YARN에 이미 포함된 org.apache.hadoop.yarn.applications.distributedshell.ApplicationMaster를 활용하면 임의의 셸 스크립트를 YARN 컨테이너 안에서 실행할 수 있었습니다.
동작 방식:
1. 명령 스크립트를 S3에 업로드 (예: aws s3 sync /tmp/data/ s3://bucket/output/)
2. Distributed Shell 설정으로 YARN에 제출 — application-type을 MAPREDUCE로 지정, 환경변수에 스크립트 위치 포함
3. YARN이 컨테이너 할당, 스크립트 다운로드 후 실행
YARN이 메모리, vCore 등 리소스 제한, 컨테이너 격리, 재시도와 장애 허용, 정상 취소, YARN UI 기반 로깅까지 관리합니다. 이 결정으로 Hadoop 워크로드뿐 아니라 aws s3 sync, hadoop distcp, 커스텀 Python 스크립트까지 모두 YARN 컨테이너에서 실행 가능해졌습니다.
솔루션: Quarry REST 게이트웨이
Quarry는 Slack이 자체 개발한 REST 기반 잡 제출 게이트웨이입니다. EMR/YARN, Trino, Snowflake 등 여러 컴퓨트 엔진에 잡을 제출하기 위해 만들어졌으며, 인증·신뢰성·가시성 문제를 이미 해결한 상태였습니다.
Quarry의 핵심 기능:
• 인증: SSH 키 대신 서비스 간 토큰 사용
• 잡 제출: YARN, Trino, Snowflake에 REST API로 전송
• 상태 추적: 잡 상태를 서버 측에서 모니터링
• 수명주기 관리: REST API 기반 정상 취소 및 정리
• 가시성: 모든 잡 제출에 대한 구조화된 로그, 메트릭, 트레이싱
아키텍처 변화:
이전: Airflow → SSH Connection → EMR Master Node → Execute Command이후: Airflow → Quarry REST API → YARN ResourceManager → EMR Container
Airflow Operator는 SSH 연결 대신 Quarry에 HTTP 요청을 보내고, Quarry가 YARN에 제출 후 상태를 폴링합니다. Airflow Pod가 재시작해도 잡은 유지되며, Quarry가 연결을 보존합니다.
마이그레이션 여정
8개 독립 데이터 리전에 걸친 700개 이상의 프로덕션 잡을 이전해야 했습니다. 각기 다른 네트워크 구성과 데이터 주권 요구사항, 검색 인덱싱 같은 무중단 필수 워크로드까지 존재하는 상황입니다.
5단계 접근법:
1. PoC: 파일럿 잡으로 Quarry 기반 접근 검증, dev 환경 테스트
2. 보안 검토: 보안 팀과 협업해 자격증명 제거 계획 수립
3. OKR 기반 실행: Key Result로 지정해 경영진 가시성 확보, 80% 마이그레이션 달성
4. 대량 마이그레이션: 여러 팀이 병렬로 잔여 워크로드 전 리전 이전
5. 최종 정리: 모든 레거시 SSH Operator 폐기, 100% 달성
마이그레이션 수치:
• 7개 Operator 유형에 걸쳐 700개 이상 잡 이전
• 8개 독립 데이터 리전에 적용
• 5개 팀이 새 Operator로 전환
• 비즈니스 핵심 서비스 무중단
• 초기 파일럿부터 100% SSH 제거까지 3분기 소요
직면한 도전들
도전 1: Virtual Memory Check 실패

데이터 export DAG 마이그레이션 중 SSH에서는 정상이던 잡이 vmem 체크 오류로 실패하기 시작했습니다.
원인: SSH는 마스터 노드에서 직접 실행되어 YARN 리소스 강제를 우회했습니다. Quarry는 잡을 정상적으로 YARN에 제출하므로 가상 메모리 한도를 초과한 컨테이너가 거부된 것이죠.
해결: AWS 모범 사례에 따라 전 클러스터에서 vmem 체크를 비활성화했습니다. yarn.nodemanager.vmem-check-enabled: false — Linux 가상 메모리 회계가 신뢰할 수 없고, 물리 메모리 한도로 충분하다는 AWS 권고에 부합합니다.
교훈: SSH는 다수의 문제를 가려왔습니다. 정상 YARN 제출로 전환하면 이전엔 보이지 않던 리소스 한도 이슈가 나타날 수 있으니, dev 환경에서 충분히 테스트해야 합니다.
도전 2: 네트워크 분리와 EKM 연결 문제
dev 검색 인프라 잡을 dev 클러스터에서 staging 분석 클러스터로 이전할 때 EKM(Enterprise Key Management) 연결 타임아웃이 발생했습니다. 오류 메시지는 Unable to execute HTTP request: Connect to sts.amazonaws.com:443 failed: connect timed out였죠.
원인: 원래 클러스터는 키 관리 엔드포인트로의 네트워크 라우팅이 구성되어 있었지만, 더 엄격한 네트워크 세그먼트에 있는 staging 분석 클러스터는 동등한 연결성이 없었습니다. 잡 설정에 명시되지 않은 네트워크 토폴로지 종속성이 노출된 것이죠.
해결: 검색 인프라 작업을 dev 서비스로 라우팅이 가능한 dev ETL 클러스터로 이동했습니다. 프로덕션 Hive 카탈로그가 필요한 작업은 staging에 유지하면서, dev ETL 클러스터를 스케일업해 추가 워크로드를 수용했습니다.
교훈: 네트워크 토폴로지가 매우 중요합니다. 어떤 클러스터에서 어떤 잡을 돌릴지 결정하기 전에 네트워크 분리·계정 경계를 이해해야 합니다.
도전 3: 멀티 리전 복잡성
데이터 주권 요구로 8개 독립 데이터 리전에서 EMR 클러스터를 운영합니다. SSH 폐기는 사실상 8개 병렬 마이그레이션을 의미했고, 각각 고유한 복잡성이 따랐습니다.
복잡성 요소:
• 설정 관리: 리전마다 별도 Quarry 설정, 클러스터 엔드포인트, 네트워크 라우팅 규칙 필요
• 테스트 부담: 모든 코드 변경을 8개 리전 전체에서 검증
• 순차 배포: 동시 배포 불가, 리전 단위 점진 롤아웃
• 리전별 이슈: 네트워크 구성, 데이터 주권 규칙, 클러스터 버전 차이
대응 방식:
• 단일 파일럿 리전(주로 US)에서 먼저 검증
• 리전별 설정 요구사항 문서화
• 리전 인식 가능한 Quarry Operator 구축
• 점진적 롤아웃과 리전별 학습 반영
• 리전별 마이그레이션 진행 상황 별도 추적
교훈: 멀티 리전 인프라는 단순히 N배가 아니라 리전별 고유 장애 모드까지 N배 어려움입니다. 교차 리전 조율과 리전별 디버깅에 충분한 시간을 배정해야 합니다.
결과: 100% SSH 제거 달성
모든 프로덕션 잡이 Quarry를 통한 REST 기반 제출로 전환되었습니다.
보안적 성과:
• 8개 독립 데이터 리전 전 프로덕션 EMR 클러스터에서 SSH 접근 제거, 공격 표면 대폭 축소
• SSH 키 배포를 서비스 간 토큰 인증으로 대체, REST API 로깅으로 정상적 감사 추적 확보
• 모든 잡 제출이 Quarry를 통한 구조화 로그 보유
• 마지막 AWS 메인 계정 EMR 클러스터를 자식 계정으로 이전, Whitecastle 이니셔티브 완수
• 특수 보안 그룹과 복잡한 권한 관리 제거로 컴플라이언스 단순화
운영적 개선:
• 마스터 노드 리소스 경합 제거, 모든 비 Hadoop 잡이 분산 YARN 컨테이너에서 적절한 리소스 할당으로 실행
• Kubernetes Pod 재시작에도 잡이 유지되어 잡 신뢰성 대폭 향상, 좀비 프로세스 사라짐
• REST API를 통해 정상 종료 가능
• Quarry API로 구조화된 잡 상태·로그·메트릭 제공, 잡 수명주기 전체 추적 가능
미래 기반:
• SSH 의존성 제거로 Spark on Kubernetes 마이그레이션 가능
• REST 기반 아키텍처가 클라우드 네이티브 관행과 정합
• 복잡한 SSH 설정 대비 단순하고 유지보수 쉬운 Quarry Operator로 팀 온보딩 용이
• Airflow를 EMR 인프라 세부사항과 디커플링, 모든 잡 제출을 Quarry로 표준화
학습된 교훈
잘 작동한 점:
1. 점진적 마이그레이션: Dev → GovDev/CommDev → Prod 순차 롤아웃과 Operator 타입별 이전으로 단계별 학습 누적
2. 강한 팀 협업: Search, Analytics, Data Engineering, ML, Marketing 등 다영역 협력, 신속한 코드 리뷰와 공용 채널 소통
3. 분석 기반 진행 추적: 전 리전 마이그레이션 진행 대시보드 구축, Airflow 데이터베이스 쿼리로 잔여 SSH 기반 작업 식별
다시 한다면 달리할 점:
1. 네트워크 토폴로지 사전 매핑 필요: EKM 연결 같은 네트워크 분리 이슈를 후반에 발견했습니다. Whitecastle 계정 경계와 네트워크 라우팅을 클러스터 마이그레이션 전에 문서화해야 합니다.
2. 리소스 한도 테스트 조기 수행 필요: vmem 체크 이슈가 후반에 발생했습니다. 초기 파일럿 단계부터 SSH 대비 YARN 리소스 한도 테스트를 포함해야 합니다.
3. Operator 제한에 대한 사전 소통 강화: 최종 단계에서 SSHOperator 신규 사용을 제한했을 때 일부 팀이 인지하지 못했습니다. Airflow 사용자 전체에 대한 사전 공지가 필요합니다.
대규모 마이그레이션 모범 사례
1. 마이그레이션 전에 모니터링부터 구축: 잔여 작업을 항상 파악할 수 있는 대시보드를 조기에 마련합니다. Airflow DB 쿼리를 활용하면 잔여 작업을 지속적으로 파악할 수 있습니다.
2. 다중 환경 테스트: Dev, CommDev, GovDev에서 테스트해 환경별 이슈를 프로덕션 이전에 포착합니다. 특히 계정 경계 간 테스트로 네트워크 분리 이슈를 사전에 발견할 수 있습니다.
3. 점진적 Operator 폐기: CrunchExecOperator, S3SyncOperator 등 한 번에 하나씩 폐기합니다. 각 단계가 자체 테스트·검증 포함된 미니 프로젝트로 운영하면 속도는 느리지만 위험이 크게 완화됩니다.
Slack의 이 사례는 단순한 기술 마이그레이션을 넘어, 레거시 시스템을 현대화할 때 필요한 접근 방식에 대한 통찰을 제공합니다. 점진적 실행, 팀 협업, 데이터 기반 의사결정이 결합되어야 대규모 마이그레이션이 성공할 수 있다는 것을 보여줍니다.
특히 네트워크 토폴로지와 리소스 한도처럼 이전에는 보이지 않던 숨은 비용이 마이그레이션 과정에서 어떻게 드러나는지, 그리고 그것을 어떻게 처리해야 하는지에 대한 실용적인 교훈은 많은 팀이 참고할 만한 가치가 있습니다.
📚 출처
• SSH에서 REST로: 보안 중심의 Slack EMR 데이터 파이프라인 현대화
• 원문: slack.engineering
📚 출처
'자동화&툴 리뷰' 카테고리의 다른 글
| WhisperSubTranslate v2.0 — 오프라인 영상 자막 추출 및 번역 데스크톱 앱 완벽 가이드 (0) | 2026.05.25 |
|---|---|
| LLM이라면, 이것을 읽어 주세요 — Anna's Archive와 웹 표준의 탄생 (0) | 2026.05.24 |
| Phosphene - Apple의 비디오 배경화면을 macOS Tahoe에서原生復刻 (0) | 2026.05.24 |
| Firefox의 Web Serial 지원 발표 — 개발자가 알아야 할 핵심 정리 (0) | 2026.05.23 |
| Show GN: Codex Relay - 모바일에서 코덱스 Terminal, Browser, Git, File Viewer, Markdown 탑재 완벽 가이드 (0) | 2026.05.22 |