톰캣에 특정 키워드가 포함된 에러로그가 발생됐을 때 슬랙으로 알림을 받기 위해 필요한 서비스들은 AWS 의 cloudwatch, sns, lambda 등 이다. 이 서비스들로 과정을 대충 설명하자면...
- cloudwatch 에 톰캣 로그를 남길 수 있다. 그리고 특정 키워드들의 필터링이 가능하다. 필터링 됐을때 경보(알림)이 가능하다.
- 경보 설정에서 SNS 로 알림을 전송할 수 있다.
- SNS 에 알림이 오면 슬랙에 메시지를 전달하는 Lambda 함수를 실행하게 하면 끝.
EC2 로그를 cloudwatch 로...
지표 필터(Metric Filter) 생성
경보를 처리할 SNS(Simple Notification Service) 생성
경보(Alarms) 생성
슬랙 웹훅(WebHooks URL) 생성
람다(Lambda) 생성
1. EC2 로그를 cloudwatch 로...
EC2 의 특정 로그를 cloudwatch 로 전달하기 위해서는 awslogs 가 설치되어 있어야 한다.
아래는 centos7 에서의 설치 및 설정 예이다. (OS 별로 설치 방법은 다름.)
# yum install awslogs No matches found # curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O # python ./awslogs-agent-setup.py --region ap-northeast-1 AWS Access Key ID [None]: ******************** AWS Secret Access Key [None]: **************************************** Path of log file to upload: /var/log/tomcat8/api.log Destination Log Group name: /project1/var/log/tomcat8/api.log Timestamp format: 3. %Y-%m-%d %H:%M:%S (2008-09-08 11:52:54) | cs |
curl 로 다운받아 setup 파일을 리전과 함께 실행하면 IAM 및 로그 관련 설정을 하게 된다.
AWS Key 는 CloudWatch Logs 에 대한 권한이 있는 IAM 정보를 적으면 되고,
EC2 의 어떤 로그 파일을 cloudwatch 로그 그룹으로 생성할 것인지 를 적으면 되고,
로그 파일의 datetime_format 을 선택하면 된다.
위에 설정한 항목들은 /var/awslogs/etc/awslogs.conf 파일에서 수정 및 추가가 가능하다.
... [/var/log/tomcat8/catalina.log] datetime_format = %d-%b-%Y %H:%M:%S file = /var/log/tomcat8/catalina.*.log buffer_duration = 5000 log_stream_name = {instance_id} initial_position = start_of_file log_group_name = /project1/var/log/tomcat8/catalina.log [/var/log/tomcat8/web.log] datetime_format = %Y-%m-%d %H:%M:%S file = /var/log/tomcat8/web.log buffer_duration = 5000 log_stream_name = {instance_id} initial_position = start_of_file log_group_name = /project1/var/log/tomcat8/web.log ... | cs |
설정을 마쳤으면 awslogs 데몬을 올리고 부팅시 시작되도록 설정한다.
# systemctl start awslogs # chkconfig awslogs on | cs |
여기까지 마쳤다면 cloudwatch log-group 에서 catalina.log 등의 로그를 확인할 수 있다.
설정 중 datetime_format 의 형식대로 로그의 라인을 구분하므로 이 부분을 정확하게 선택하지 않으면 cloudwatch 에서 로그를 볼 수 없을 것이다. 만약 awslogs 데몬이 시작된 후에도 cloudwatch 에 로그가 생성되지 않았다면 /var/log/awslogs.log 파일에서 에러 로그를 확인한다.
2. 지표 필터(Metric Filter) 생성
cloudwatch 특정 로그의 [지표 필터] 탭에서 지표 필터를 생성한다.
우리의 목적은 로그에서 에러 문구를 추출하는 것이므로 [패턴 필터링] 항목에는 필터링할 키워드를 나열한다. error 나 exception 등 원하는 것들을 나열하고 [패턴 테스트] 항목에서 테스트를 할 수 있다. (아래 예에서는 ERROR, Error, error 라는 키워드를 필터링 하였다.) 지표의 세부 정보까지 입력하면 지표 필터가 생성고, 이것은 cloudwatch 의 경보(Alarms) 에서 사용될 것이다.
3. 경보를 처리할 SNS(Simple Notification Service) 생성
SNS 메뉴의 토픽을 표준(standard) 및 default 설정으로 하나 생성한다.
이 토픽은 경보를 받아 람다로 전달될 것이다.
4. 경보(Alarms) 생성
다시 cloudwatch 의 경보(Alarms) 로 돌아와 경보를 생성한다. 이미 생성한 지표를 선택하고 1분안에 에러가 발생한다면, 이미 생성한 SNS 토픽으로 전달하도록 설정한다.
5. 슬랙 웹훅(WebHooks URL) 생성
특정 채널로 메시지를 전달 받기 위해서는 슬랙에서 별도의 WebHooks 를 생성하고 람다에 입력해 주어야 한다.
슬랙앱에서 [Administration]-[Manage Apps] 를 클릭하면 브라우저로 Manage 페이지가 열린다.
webhooks 이 없다면 상단 App 검색창에서 검색하여 [Incoming WebHooks] 를 install 하고 [Add to Slack] 을 클릭하여 WebHooks 를 생성한다.
Post to Cannel 항목에는 메시지를 전달받을 채널을 선택하면 되고 Webhook URL 은 람다에 입력해야 하므로 기록해 놓는다.
6. 람다(Lambda) 생성
SNS 에 알림이 발생하면 실행될 람다를 생성한다.
함수 생성 - Blueprints : cloudwatch-alarm-to-slack-python 를 선택.
구독할(위에 생성한) SNS 를 선택하고 약간의 코드 수정, 환경 변수 추가만 하면 슬랙으로 알림을 보낼 수 있다.
import boto3 import json import logging import os from base64 import b64decode from urllib.request import Request, urlopen from urllib.error import URLError, HTTPError # The base-64 encoded, encrypted key (CiphertextBlob) stored in the kmsEncryptedHookUrl environment variable #ENCRYPTED_HOOK_URL = os.environ['kmsEncryptedHookUrl'] # The Slack channel to send a message to stored in the slackChannel environment variable #SLACK_CHANNEL = os.environ['slackChannel'] #HOOK_URL = "https://" + boto3.client('kms').decrypt( # CiphertextBlob=b64decode(ENCRYPTED_HOOK_URL), # EncryptionContext={'LambdaFunctionName': os.environ['AWS_LAMBDA_FUNCTION_NAME']} #)['Plaintext'].decode('utf-8') HOOK_URL = os.environ['HOOK_URL'] logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): logger.info("Event: " + str(event)) message = json.loads(event['Records'][0]['Sns']['Message']) logger.info("Message: " + str(message)) alarm_name = message['AlarmName'] #old_state = message['OldStateValue'] new_state = message['NewStateValue'] reason = message['NewStateReason'] slack_message = { 'text': "%s state is now %s: %s" % (alarm_name, new_state, reason) } req = Request(HOOK_URL, json.dumps(slack_message).encode('utf-8')) try: response = urlopen(req) response.read() logger.info("Message posted") #logger.info("Message posted to %s", slack_message['channel']) except HTTPError as e: logger.error("Request failed: %d %s", e.code, e.reason) except URLError as e: logger.error("Server connection failed: %s", e.reason) | cs |
생성된 코드에서 기존 환경 변수인 kmsEncryptedHookUrl 과 slackChannel 을 사용하지 않고 HOOK_URL 을 직접 사용하는 코드로 변경한 것이다. 코드 수정 후 환경 변수 항목에 HOOK_URL 이름으로 WebHooks URL 을 입력하면 완성이다.
이제 톰캣 로그에 ERROR, Error, error 등의 키워드가 표시되면 슬랙으로 아래처럼 알림이 발송될 것이다.
로그 상세를 알람 메시지에 표시하고 싶었지만... 불가...