Slack/쿠버네티스

3 개의 포스트

slack4분 읽기큐레이션 요약

SSH에서 REST로: Slack EMR 데이터 파이프라인의 보안 주도 현대화

Slack은 700개가 넘는 EMR 데이터 파이프라인을 직접 SSH로 실행하던 구조에서 REST 기반 작업 제출 방식으로 전환했다. SSH는 보안 공격 표면, 키 관리, 장애 복구, 작업 관측성 측면에서 한계가 있었고 Spark on Kubernetes와 AWS 계정 분리 같은 현대화도 가로막았다. Slack은 YARN REST API와 YARN Distributed Shell을 활용해 8개 데이터 리전의 작업을 중단 없이 마이그레이션하고 SSH를 완전히 제거했다. ## SSH 기반 파이프라인의 확산 - 2017년경 Airflow가 EMR 마스터 노드에 SSH로 접속해 명령을 실행하는 방식으로 데이터 파이프라인을 구축했다. - 단순한 `SSHOperator` 패턴이 확산되면서 다음과 같은 작업까지 SSH로 실행됐다. - Spark 및 MapReduce 작업 - AWS CLI 명령 - 사용자 정의 Python 스크립트 - 2024년에는 700개 이상의 운영 작업이 SSH 기반으로 실행되고 있었다. - 검색 인덱싱, 분석, 비즈니스 인텔리전스 등 핵심 데이터 처리도 이 구조에 의존했다. ## SSH의 보안 및 운영상 문제 - **보안 위험** - 오케스트레이션 워커가 EMR 클러스터에 직접 SSH 접속해야 해 공격 표면이 커졌다. - SSH 키를 여러 워커에 배포하고 주기적으로 교체해야 했다. - 세밀한 감사 추적을 위해 여러 시스템의 로그를 상호 연관해야 했다. - 보안 그룹과 사용자 권한 설정이 복잡해졌다. - **운영 장애** - 작업이 EMR 마스터 노드에서 직접 실행되어 리소스 경쟁이 발생했다. - Kubernetes Pod가 재시작되면 SSH 연결이 끊겨 작업이 실패했다. - 연결이 끊긴 뒤에도 작업이 계속 실행되는 ‘좀비 작업’이 남을 수 있었다. - 연결 단절 후 작업의 성공·실패 상태를 안정적으로 확인하기 어려웠다. - **인프라 현대화 차단** - Spark on Kubernetes와 EMR on EKS 도입을 시작할 수 없었다. - 메인 AWS 계정의 EMR 클러스터를 자식 계정으로 이전하는 Whitecastle 프로젝트가 지연됐다. - 신뢰할 수 있는 작업 모니터링과 관측성을 구현하기 어려웠다. ## REST 기반 작업 제출의 장점 - SSH는 클라이언트와 서버 사이의 상태ful 연결을 유지해야 한다. - REST 방식에서는 작업의 생명주기를 서버가 관리한다. - `POST`: 작업을 제출하고 작업 ID를 받음 - `GET`: 작업 ID로 실행·완료·실패 상태를 조회 - `DELETE`: 필요할 때 작업을 취소 - Airflow나 Kubernetes Pod가 재시작되어도 작업 자체는 서버에서 계속 실행될 수 있다. - 클라이언트가 작업 상태를 다시 조회할 수 있어 연결 단절에 강하다. - 작업 취소, 리소스 관리, 로그 확인 등도 실행 엔진의 표준 기능으로 처리할 수 있다. ## YARN Distributed Shell을 활용한 해결책 - Spark는 Livy REST API, Hive는 HiveServer2를 사용할 수 있어 상대적으로 이전이 쉬웠다. - 반면 MapReduce와 `aws s3 sync`, `hadoop distcp` 같은 300개 이상의 임의 CLI 작업은 바로 사용할 REST API가 없었다. - 검토한 대안은 다음과 같았다. - 원격 명령 실행용 커스텀 래퍼 서비스 - Ansible이나 Salt 같은 원격 실행 프레임워크 - YARN에 새로운 작업 유형을 직접 개발 - 이러한 방법은 별도 보안 계층과 운영 인프라를 구축·유지해야 해 복잡도가 높았다. - YARN의 **Distributed Shell**은 임의의 셸 스크립트를 YARN 컨테이너에서 실행할 수 있도록 했다. - 기존 YARN REST API를 그대로 사용 - YARN의 인증·인가 체계 활용 - 별도 보안 서비스 불필요 - 오픈소스 표준 기반 - 컨테이너 리소스와 작업 생명주기 관리 지원 ## Distributed Shell의 실행 흐름 - 실행할 셸 스크립트를 S3에 업로드한다. - 예: `s3://bucket/command.sh` - 스크립트는 `aws s3 sync` 같은 임의 명령을 포함할 수 있다. - YARN REST 요청에 Distributed Shell의 `ApplicationMaster`와 스크립트 위치를 지정한다. - YARN이 컨테이너를 할당하고 S3에서 스크립트를 내려받아 실행한다. - 실행 과정에서 YARN이 다음을 담당한다. - 메모리와 vCore 등 리소스 제한 - 컨테이너 격리 - 재시도와 장애 복구 - 정상적인 작업 취소 - YARN UI를 통한 로그 및 상태 확인 ## 마이그레이션의 의미 - YARN Distributed Shell을 통해 REST API가 없던 CLI·MapReduce 작업까지 동일한 실행 모델로 통합할 수 있었다. - 작업 제출과 실행을 SSH 연결에서 분리해 클라이언트 재시작과 네트워크 단절에 대한 안정성을 높였다. - 700개 이상의 작업을 8개 데이터 리전에 걸쳐 중단 없이 이전하면서 SSH 의존성을 제거했다. - 결과적으로 보안 강화뿐 아니라 Kubernetes 기반 실행 환경, AWS 계정 분리, 표준화된 모니터링으로 나아갈 기반을 마련했다. 실용적으로는 원격 서버에 직접 접속해 명령을 실행하기보다, 작업 ID·상태 조회·취소를 제공하는 서버 측 실행 모델을 사용하는 것이 바람직하다. 특히 기존 작업이 단순 CLI 스크립트라면 복잡한 신규 실행 서비스를 만들기 전에 YARN Distributed Shell처럼 기존 플랫폼의 표준 기능을 우선 검토할 수 있다.

원문 읽기(새 탭에서 열림)
slack3분 읽기큐레이션 요약

셰프 인프라 개선: 방해받지 않는 안전

Slack은 Chef Policyfiles로 전환하는 대신, 기존 cookbook과 role을 유지하면서 EC2 프로비저닝 구조를 개선하는 방식을 선택했다. 단일 프로덕션 환경을 `prod-1`부터 `prod-6`까지 분리하고, 카나리와 단계적 릴리스 트레인을 도입해 잘못된 변경의 영향 범위를 줄였다. 그 결과 대규모 확장이나 배포 중에도 문제를 조기에 발견하고 안전하게 롤백·수정할 수 있는 경로를 마련했다. ## Policyfiles 대신 기존 구조 개선 - Policyfiles를 도입하면 roles와 environments를 대체하고 여러 팀의 cookbook을 수정해야 했다. - 장기적으로는 안전성이 높아질 수 있지만, 단기적으로는 수십 개 팀의 대규모 작업과 새로운 변경 위험이 발생했다. - Slack은 기존 cookbook과 role을 변경하지 않고 EC2 프레임워크를 보강하는 방향을 택했다. ## 단일 프로덕션 환경의 위험 - 기존에는 모든 인스턴스가 하나의 `production` Chef environment를 공유했다. - 인스턴스별 cron 작업을 가용 영역(AZ)마다 분산해 Chef 실행 시점을 staggered 방식으로 조정했다. - 이 방식은 잘못된 변경이 전체 노드에 동시에 적용되는 것을 막아 주었지만, 새로 생성된 노드는 즉시 최신 변경을 가져갔다. - 따라서 대규모 scale-out 중 잘못된 cookbook 버전이 수십~수백 개의 새 노드에 한꺼번에 적용될 수 있었다. ## `prod-1`~`prod-6` 환경 분리 - 단일 production environment를 다음과 같이 6개 bucket으로 나눴다. - `prod-1` - `prod-2` - `prod-3` - `prod-4` - `prod-5` - `prod-6` - 서비스 팀은 계속 인스턴스를 “prod”로 실행하지만, 실제 Chef environment는 인스턴스의 AZ에 따라 결정된다. - 노드가 여러 환경에 균등하게 분산되므로 하나의 변경이 전체 프로덕션에 미치는 blast radius가 줄어든다. - 각 environment를 독립적으로 업데이트할 수 있어 특정 AZ 그룹만 대상으로 변경을 검증할 수 있다. ## Poptart Bootstrap의 역할 - Slack의 기본 AMI에는 부팅 시 실행되는 `Poptart Bootstrap` 도구가 포함되어 있다. - 주요 역할은 다음과 같다. - Chef node object 생성 - 필요한 DNS 레코드 설정 - 부팅 성공·실패 결과를 Slack 채널에 알림 - 환경 분리를 위해 노드의 AZ ID를 검사하고 해당 노드를 `prod-1`~`prod-6` 중 하나에 자동 배정하도록 확장했다. - 서비스 팀이 별도의 프로비저닝 방식을 학습하거나 cookbook을 수정하지 않아도 인프라 구조 변경을 적용할 수 있었다. ## 카나리 환경 `prod-1` - `prod-1`은 카나리 프로덕션 환경으로 사용된다. - 새 cookbook 변경이 있으면 매시간 최신 버전을 배포한다. - sandbox와 dev를 거친 변경을 실제 프로덕션 환경에서 작은 규모로 먼저 실행한다. - 모든 production 환경을 통과한 뒤에야 테스트하는 방식보다, 변경이 도입된 시점과 장애 발생 시점의 거리가 짧아 원인 추적이 쉽다. - 누적된 대규모 변경이 아니라 비교적 작은 단위의 artifact를 검증할 수 있다. ## `prod-2`~`prod-6`의 릴리스 트레인 - `prod-2`부터 `prod-6`까지는 순차적인 release train 방식으로 업데이트된다. - 새 버전을 `prod-2`에 배포하기 전, 기존 버전이 `prod-2`에서 `prod-6`까지 성공적으로 진행됐는지 확인한다. - 각 환경의 배포가 완료되어야 다음 단계가 진행되므로 회귀 문제가 전체 프로덕션으로 확산되는 것을 방지한다. - 여러 production environment가 항상 일정한 버전 순서를 유지하도록 설계되어 있다. ## 시간 기반 배포 흐름 - 매시 정각에 최신 cookbook 변경을 sandbox에 반영한다. - 이후 Kubernetes CronJob이 dev 환경으로 변경을 진행한다. - 매시 30분부터 production rollout이 시작된다. - 예를 들어 artifact A가 생성되면: - 정각: sandbox와 dev가 A로 업데이트 - 30분: `prod-1`이 A를 받아 카나리 테스트 - 이후: `prod-2`부터 `prod-6`까지 단계적으로 A를 적용 - 그 사이 새 변경으로 artifact B, C가 생성되더라도 기존 릴리스 트레인의 진행 상태를 고려해 순차적으로 배포한다. 실용적으로는 기존 배포 시스템을 전면 교체하기보다, 환경 분리·카나리·단계적 rollout처럼 변경의 영향 범위를 줄이는 장치를 먼저 도입하는 것이 효과적이다. 특히 대규모 인프라에서는 새 노드가 어떤 버전을 자동으로 받는지와, 실패한 변경이 어디까지 확산될 수 있는지를 별도로 통제해야 한다.

원문 읽기(새 탭에서 열림)
slack4분 읽기큐레이션 요약

안전한 배포: 변경

Slack은 고객 영향의 대부분(73%)이 배포를 비롯한 Slack 내부 변경에서 발생한다는 분석을 바탕으로 Deploy Safety Program을 시작했다. 이 프로그램은 자동 감지·복구, 영향 범위 제한, 안전장치와 문화 개선을 통해 고객 영향 시간을 줄이는 것을 목표로 했으며, 2025년 1월에는 정점 대비 고객 영향 시간이 90% 감소했다. 핵심은 특정 배포 시스템만 엄격하게 관리하는 대신, 모든 배포 방식에 반복 적용 가능한 안전 패턴을 구축하면서 개발 속도도 유지하는 것이다. ## 변화가 안정성에 미치는 영향 - Slack이 고객 업무에서 더욱 중요한 제품이 되면서 안정성에 대한 기대 수준이 높아졌다. - 고객 대상 장애의 73%가 Slack 내부 변경으로 발생했으며, 특히 코드 배포가 주요 원인이었다. - 장애 영향은 시스템마다 달랐고, 고객이 사용하는 기능에 따라 피해 정도도 달라졌다. - Slack에는 수백 개의 내부 서비스와 여러 배포 시스템이 있어, 단일한 배포 방식만 개선해서는 문제를 해결하기 어려웠다. - 기존에는 개별 서비스나 배포 시스템에 수동 절차를 추가하는 방식이 많았지만, 이는 개발 속도와 엔지니어링 사기를 떨어뜨렸다. - 고객은 약 10분을 넘는 중단을 단순한 “일시적 문제”가 아닌 심각한 장애로 인식하는 경향이 있었다. ## Deploy Safety의 목표 초기에는 중요도가 높은 서비스 전체를 대상으로 다음과 같은 North Star 목표를 세웠다. - 배포로 인한 영향 시간 단축 - 자동 감지 및 복구: 10분 이내 - 수동 감지 및 복구: 20분 이내 - 영향 심각도 감소 - 전체 플릿의 10%에 도달하기 전에 문제가 있는 배포 감지 - 개발 속도 유지 - 안정성을 높이되 변화와 혁신의 속도를 희생하지 않음 이 목표는 이후 모든 배포 시스템과 프로세스에 적용되는 Deploy Safety Manifesto로 확장됐다. 단순한 운영 절차가 아니라 자동화, 배포 안전장치, 조직 문화의 변화를 함께 추진한 것이 특징이다. ## 고객 영향 시간을 측정하는 지표 Slack은 프로그램의 성과를 측정하기 위해 다음 지표를 정의했다. - **고심각도 및 일부 중간 심각도 변경 유발 장애로 인한 고객 영향 시간** - 장애 심각도는 현재 또는 예상되는 고객 영향을 나타내지만, 실제 최종 영향과 항상 일치하지는 않는다. - 따라서 중간 심각도 장애는 실제 고객 영향 수준을 기준으로 별도 선별해야 했다. - 이 지표는 고객 감정을 직접 측정하는 값이 아니라, 고객 경험을 추정하는 실용적인 대리 지표다. Slack은 다음 세 요소 사이의 연결이 완벽하지 않다는 점도 인정한다. - 고객의 실제 만족도 - Deploy Safety 프로그램 지표 - 개별 프로젝트 지표 따라서 지표를 설계할 때 결과를 측정할 수 있는지, 무엇을 측정하는지 명확한지, 주관적 판단이 일관적인지, 실제 고객 피드백과 계속 비교되는지를 중요하게 봤다. ## 투자할 프로젝트를 고르는 방법 프로그램 초기에는 어떤 프로젝트가 가장 큰 효과를 낼지, 효과가 언제 나타날지 알기 어려웠다. 장애 데이터는 과거 결과를 보여주는 후행 데이터였지만 고객은 이미 현재 문제를 겪고 있었기 때문이다. 이에 따라 Slack은 다음과 같은 투자 전략을 사용했다. - 초기에는 여러 영역에 폭넓게 투자하고 빠르게 실행 - 이미 고객 피해가 확인된 영역을 우선 개선 - 성과가 확인된 프로젝트와 패턴에 추가 투자 - 효과가 낮은 영역의 투자는 축소 - 결과에 따라 바뀔 수 있는 짧고 유연한 로드맵 운영 프로젝트는 주로 다음 중 하나 이상의 목표에 기여하도록 설계했다. - 배포 과정에서 문제를 더 일찍 감지 - 자동 복구 시간 단축 - 수동 복구 시간 단축 - 격리 경계를 설계해 장애의 확산 범위와 심각도 축소 ## Webapp 배포 개선 사례 변경 유발 장애의 가장 큰 원인으로 Webapp backend가 지목되면서 단계적인 개선이 진행됐다. - 자동 메트릭 모니터링 구축 - 자동 알림과 수동 롤백으로 고객 영향 여부 검증 - 자동 배포 및 자동 롤백 도입 - 자동 롤백을 통해 고객 영향 시간을 10분 이하로 유지하는 성과 확인 - 추가 메트릭 모니터링과 수동 롤백 최적화 - Frontend 수동 롤백 기능 추가 - 중앙 집중식 배포 오케스트레이션 시스템으로 패턴 확대 - Slack Bedrock과 Kubernetes를 넘어 여러 배포 시스템에 메트릭 기반 배포와 자동 복구 적용 이 과정을 통해 Webapp backend와 frontend, 일부 인프라 배포가 훨씬 안전해졌으며 분기별로 계속 개선되는 결과를 보였다. ## 반복 가능한 안전 패턴 Slack의 접근 방식은 처음부터 완벽한 시스템을 설계하는 것이 아니었다. - 문제를 해결할 수 있는 작은 프로젝트를 먼저 시도 - 실제 고객 영향과 지표 변화를 통해 효과 검증 - 성공한 방식을 다른 서비스와 배포 시스템에 복제 - 결과가 낮은 영역은 투자를 줄이고 새로운 접근을 시도 즉, Deploy Safety는 하나의 도구나 배포 시스템을 도입하는 프로젝트가 아니라, 측정과 실험을 반복해 조직 전체에 안전한 변경 방식을 확산하는 프로그램이다. 실무적으로는 모든 배포를 수동 승인으로 막기보다, 고객 영향과 직접 연결된 메트릭을 기반으로 조기 감지·자동 롤백·영향 범위 제한을 구축하는 것이 효과적이다. 또한 안정성 지표를 정기적으로 실제 고객 피드백과 비교하고, 효과가 입증된 안전 패턴을 다른 시스템에 재사용해야 개발 속도와 안정성을 함께 확보할 수 있다.

원문 읽기(새 탭에서 열림)