본문 바로가기
Dev/Go

4개의 region에 존재하는 5000개의 서버 경고 알림을 어떻게 실시간으로 수집할까?

by Sovereign 2024. 9. 17.

문제 상황

각 서버에서 발생하는 Alert 데이터를 수집하기 위해서는 자체적으로 Agent를 개발하는 방법과 상용 솔루션을 사용하는 방법이 존재했다. 기존 업무 환경은 약 5000개의 서버 중 80%에 해당되는 서버에 Zabbix가 설치되어 있었고 이를 바탕으로 데이터 수집을 고려했다.

 

데이터 수집을 위해 아래의 이미지와 접근 방법을 구상했다.

각 Region 내의 개별 서버에 Zabbix를 설치하고 발생한 Alert을 하나의 Slack Workspace로 전송한다.

 

운영팀과 협의해 각 Region과 유의미하게 분류해야 되는 서버들은 별도의 Slack Channel로 분류해서 메시지를 관리했다.

22개의 Slack Channel을 통해 각 서버에서 발생되는 Alert을 JSON 타입의 Original Message로 전송받았고, Slack RTM API를 사용하여 실시간으로 채팅 이벤트 수집할 수 있는 사실을 발견했다.

 

Slack 공식 문서를 살펴보니 "Real Time Messaging API"를 사용해 실시간 통신을 가능하게 할 수 있다.

 

Slack의 최신 권장 사항에 따르면 "Events API"를 사용하라고 하지만 VPN을 사용하는 보안 환경을 고려했을 때 "Real Time Messaging API"를 채택했다. 예를 들어 Webhook을 통해 외부에서 내부 서버로의 HTTP 요청을 받아야 하는 "Events API"는 VPN 또는 방화벽 설정에 따라 요청이 차단될 가능성이 있다.

 

우선 예제 코드를 보기 전 사용할 "Real Time Messaging API"에 대해 살펴보자.

 

 

 

Real Time Messaging API

Slack의 Real Time Messaging (RTM) API는 WebSocket을 기반으로 실시간으로 Slack과 통신할 수 있게 해주는 API다.

RTM API는 Slack의 서버와 클라이언트 애플리케이션 간에 양방향 연결을 설정하여 메시지와 이벤트를 실시간으로 주고받을 수 있는 환경을 제공한다.

 

 

RTM API 핵심 개념

RTM API는 WebSocket을 통해 Slack 서버와 클라이언트 애플리케이션 간에 실시간으로 통신한다. WebSocket 연결이 성립되면, Slack 서버에서 발생하는 모든 이벤트가 클라이언트로 즉시 전송된다. 이 연결을 통해 클라이언트는 Slack에서 발생하는 메시지, 상태 업데이트 등을 실시간으로 수신하고 처리할 수 있다.

 

RTM API를 통해 수신되는 이벤트는 Slack에서 발생하는 거의 모든 활동을 포함한다. 예를 들어, 사용자가 채널에 메시지를 작성하거나, 새로운 사용자가 채널에 참여하는 등의 이벤트가 실시간으로 전달된다. 각 이벤트는 JSON 형식으로 전달되며, type 필드로 이벤트 유형을 구분할 수 있다.

 

RTM 세션을 시작하려면 rtm.connect 메서드를 호출하여 WebSocket URL을 받는다. 이 URL은 30초 동안만 유효하다. 연결이 성공적으로 이루어지면 "hello" 이벤트를 첫 번째로 수신하게 되고 Slack에서 발생한 이벤트들이 지속적으로 전송된다.

 

RTM API는 기본적인 메시지 이벤트 외에도 채널 생성, 사용자 상태 변경, 파일 공유, 이모지 반응 등 Slack의 거의 모든 활동이 이벤트로 전달된다.

 

클라이언트는 WebSocket 연결을 통해 Slack으로 메시지를 보낼 수 있다. 전송되는 메시지는 고유의 ID를 가지며, 서버에서 응답이 올 때 이 ID를 통해 클라이언트는 어떤 메시지에 대한 응답인지 확인할 수 있다. 메시지 응답에는 성공 여부를 나타내는 ok 필드와 메시지의 타임스탬프가 포함된다.

 

 

RTM API의 동작 원리

 

단계 설명
1. WebSocket URL 요청 클라이언트는 rtm.connect API를 호출하여 Slack 서버로부터 WebSocket URL을 요청한다.
2. WebSocket URL 획득 Slack 서버는 클라이언트에 WebSocket 연결을 설정할 수 있는 URL을 응답으로 반환한다.
3. WebSocket 연결 설정 클라이언트는 반환된 URL을 사용하여 WebSocket 연결을 설정한다.
4. 초기 연결 이벤트 수신 WebSocket 연결이 성공적으로 설정되면 Slack 서버는 첫 번째 이벤트로 "hello" 이벤트를 보낸다.
5. 메시지 이벤트 수신 이후 Slack 서버는 사용자가 Slack 채널에서 작성한 메시지와 같은 다양한 이벤트를 클라이언트에 전송한다.
6. 메시지 이벤트 처리 클라이언트는 수신된 메시지 이벤트를 처리하거나 사용자 인터페이스에 반영한다.
7. Ping을 통한 연결 상태 확인 클라이언트는 주기적으로 ping 메시지를 보내 Slack 서버에 연결이 여전히 유효한지 확인한다.
8. Pong 응답 수신 Slack 서버는 클라이언트에 pong 응답을 보내 연결이 유지되고 있음을 알린다.
9. 에러 발생 만약 연결에 문제가 생기거나 WebSocket URL이 만료되면, Slack 서버는 에러 메시지를 클라이언트에 전송한다.
10. 재연결 시도 에러를 감지한 클라이언트는 재연결을 시도하여 Slack 서버와의 실시간 통신을 복구한다.

 

 

 

 

어떻게 해결했나

Slack Channel에서 데이터를 수집하는 예제 코드다.

RMT API 초기화, 메시지 이벤트 처리하는 구조를 참고하길 바란다. 수집한 데이터를 데이터베이스에 저장하는 로직은 별도로 구현하면 된다.

 

수집 전에 Zabbix에서 Alert의 상태를 포함한 JSON Original Message의 형식은 사용자가 직접 설정해야 된다. 참고 바란다.

특별한 알고리즘이 필요한 것은 아니나 사전에 설정된 메시지 이벤트를 조회해서 가공하는 로직이 꽤나 고민을 해야 된다.

 

 

참고. 수집한 데이터를 필터 및 그룹화 처리하는 흐름을 간략하게 표현하자면 아래와 같다.


출처

https://api.slack.com/legacy/rtm

 

Legacy: Real Time Messaging API

A websocket-based HTTP API for receiving a stream of data around a specific connected user. We strongly recommend using the Events API instead.

api.slack.com

https://tools.slack.dev/node-slack-sdk/events-api/

 

Events API | Node Slack SDK

@slack/events-api officially reached EOL on May 31st, 2021. Development has fully stopped for this package and all remaining open issues and pull requests have been closed.

tools.slack.dev