• yundream
  • 2019-06-20 06:27:36
  • 2018-05-18 17:05:45
  • 84233

Contents

CloudWatch

CloudWatch
  1. AWS 클라우드 리소스와
  2. AWS에서 실행되는 애플리케이션을 위한 모니터링 서비스다.
나는 특히 2번에 관심이 많다. 애플리케이션 로그는 보통 ELK 스택을 이용하기 마련이다. ELK는 매우 훌륭한 툴이긴 한데, 인프라 구성이 다양해 지면서 통합관리하는데 어려움을 느끼고 있다.

예컨데 EC2 기반으로만 한다면, 인스턴스 실행시에 FileBeat, LogStash를 전개하도록 하면 되니 별 문제가 없겠다. 하지만 ECS, Fargate 정도가 되면 사용하기가 힘들어진다. ECS, Fargate 와 같은 경량의 컨테이너에 FileBeat와 LogStash를 설치하는 것은 엄청난 자원 낭비다. ECS 같은 경우에는 그나마 인스턴스를 제어 할 수 있으니, 인스턴스에 LK를 설치하고 컨테이너 볼륨에 로그를 남기는 식으로 수집할 수 있겠으나 번거롭다.

"기능이 좀 떨어지더라도 애플리케이션의 형태에 관계 없이 로그를 수집"할 수 있는 솔류션을 찾아야 했고, CloudWatch를 선택했다. CloudWatch의 장점은 아래와 같다.
  • AWS ElasticSearch, Kinesis, S3 등 AWS의 다른 서비스로 로그를 전송 할 수 있다.
  • 컨테이너, 람다, EC2 등 방식에 상관 없이 동일한 로깅방법을 사용 할 수 있다.
  • 관리가 필요 없다.
모든게 귀찮다. 이 녀석으로 해보자.

CloudWatch에 대한 오해

CloudWatch 서비스 소개시 보여주는 화면이 시스템/네트워크 카운트 그래프라서, 카운트기반의 모니터링 도구라고 생각 할 수 있다. 물론 훌륭한 모니터링 도구이지만 그 이상의 기능을 제공한다. CloudWatch는 AWS위에서 실행되는 애플리케이션들의 로그를 수집하고 전송하는 중앙 로그 관리 시스템으로 사용 할 수 있다. 예를 들자면 아래와 같은 일을 할 수 있다.
  • NginX, MongoDB, Apache 등의 애플리케이션이 만드는 로그들
  • EC2 운영체제가 만드는 syslog와 같은 시스템 로그들
  • CloudTrail 이벤트 로그들
  • Lambda 펑션 로그들
  • 기타 직접 개발한 애플리케이션이 남기는 모든 종류의 로그들

CloudWatch의 기본 구성 요소

CloudWatch를 사용하기 전에 몇 가지 중요 컨셉을 짚고 넘어가자. CloudWatch 로그는 Log GroupsLog Streams로 구성이 된다.
  • 로그 그룹 : 로그 스트림의 그룹이다. 이 그룹에 있는 로그스트림은 보존기간, 모니터링과 접근제어 설정들을 공유한다. 웹 서버, 애플리케이션 서버, 데이터베이스로 구성된 웹 서비스가 있다고 가정해보자. 애플리케이션 종류에 따라서 보존기간, 접근제어 설정들이 달라질 거다. 웹 서버를 위한 로그그룹, 데이터베이스를 위한 로그그룹들을 따로 운영할 수 있을 것이다.
  • 로그 스트림 : AWS 문서를 보면 동일한 소스를 공유하는 로그 이벤트 시퀀스라고 설명하고 있다. 로그 그룹은 여러 개의 로그스트림을 가질 수 있다. 그냥 간단하게 로그파일이라고 보면 된다. 예를 들어 NginX 로그 스트림은 nginx_20180505_{instance_id} 와 같은 형식의 로그를 만들 수 있을 것이다.

Create log group 명령을 이용해서 "myWebApp"이라는 이름의 log group을 만들었다.
  • Expire Events After : 로그의 저장기간을 설정한다. 기본 설정은 Never Expire로 무기한 저장된다.
  • Metric Filters : 로그 데이터에 대한 검색 및 필터링 룰을 설정 할 수 있다. 이 설정을 이용해서 로그에 대한 카운터를 남긴다거나, 검색할 단어(404, 502와 같은)의 패턴을 정의 할 수 있다. 이러한 필터를 이용해서 로그 데이터를 그래프로 처리하는 등의 작업을 할 수 있다.

웹 애플리케이션에서의 로깅

NginX의 엑세스 로그를 남겨볼 생각이다.

EC2에서 발생하는 로그를 CloudWatch로 보낼 수 있는 세 가지 방법이 있다.
  1. AWS CLI를 호출하는 스크립트 파일을 실행해서 로그를 푸시 할 수 있다. 주기적으로 보내야 하므로 cron과 같은 운영체제 툴을 통해서 실행해야 한다.
  2. AWS SDK에서 제공하는 CloudWatch Logs SDK를 이용해서 애플리케이션에서 직접 로그를 푸시 할 수 있다.
  3. EC2에 설치된 로그 관리 에이전트를 이용해서 로그를 푸시 할 수 있다.
3번 방법을 사용하는 걸 추천한다. 로그 에이전트는 백그라운드에서 실행되며, 로그 파일을 모니터링 하면서 CloudWatch로 로그를 자동으로 전송한다. 3번 방법을 사용하기 위해서 아래의 두 가지를 준비해야 한다.
  1. CloudWatch 서비스에 접근해서 로그 스크림에 기록 할 수 있도록 권한을 설정해야 한다.
  2. 로그 처리를 위한 설정을 해야 한다. 이 경우 Nginx Access log와 애플리케이션 로그의 위치, 로그 그룹과 로그 스트림 설정이 필요하다.
EC2의 경우 IAM Role 을 이용해서 CloudWatch로의 접근을 설정 할 수 있다. IAM Role을 설정하는 대신에 IAM 자격증명파일(credential)을 EC2에 구성하는 방법도 있지만 추천하지 않는다.

나는 아래와 같이 IAM Role을 만들었다.
  1. IAM 콘솔을 오픈한다.
  2. 탐색창에서 Role을 선택한다.
  3. Create role를 클릭한다. 나는 EC2-Cloudwatch_logs 라는 이름의 role을 만들었다.
  4. Permissons에서 정책을 설정한다.
Permissons 정책은 아래와 같다.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:DescribeLogStreams"
            ],
            "Resource": [
                "arn:aws:logs:*:*:*"
            ]
        }
    ]
}
  • logs:CreateLogGroup : 로그그룹을 만들 수 있게 허용한다.
  • logs:CreateLogStream : 로그스트림을 만들 수 있게 허용한다.
  • logs:PutLogEvents : 로그를 전송 할 수 있돌고 허용한다.
  • logs:DescribeLogStreams : 로그 스트림정보를 확인 할 수 있게 허용한다.
이제 EC2 인스턴스를 만든다. 이 인스턴스는 EC2-Cloudwatch_logs Role로 실행하자.

aws cli로 테스트

실행한 인스턴스는 EC2-Cloudwatch_logs롤에 설정된 권한을 가지고 있다. 하지만 이 권한을 어느 리전에서 실행할지는 알려줘야 한다. "~/.aws/config"에 리전 정보를 입력하자.
$ cat ~/.aws/config 
[default]
region=ap-northeast-2
output=json
이제 aws cli 명령은 ap-northeast-2(서울)리전에서 실행된다. mytest라는 이름의 로그 스트림을 만들어보자.
$ aws logs create-log-stream --log-group-name myWebApp --log-stream-name mytest 
이제 이 mytest로 로그를 보내보자.
$ aws logs put-log-events --log-group-name myWebApp \
--log-stream-name mytest \
--log-events timestamp=1526984256000,message="hello world"
{
    "nextSequenceToken": "49582407152534913318350154521760445497433807242173352642"
}
웹 콘솔에서 로그를 확인 할 수 있을 것이다.

awslogs 설치

젠킨스에서의 빌드 결과를 CloudWatch로 보내야 하는 경우를 생각해 보자. 이런 배치작업은 aws cli를 이용해서 로그를 전송하는게 편한 방법이다. 하지만 NginX의 access.log와 같은 파일에 추가되는 내용을 CloudWatch로 보내는데 aws cli를 사용하기는 힘들다. 이 경우에는 aws에서 제공하는 로그 에이전트인 awslogs를 사용해야 한다. 먼저 awslogs 로그 드라이버를 설치하고 활성화 해야 한다. 아래와 같이 설치하자. amazon linux 를 기준으로 테스트했다.
$ sudo yum install -y awslogs
awslogs에 대한 설정을 해야 한다.
$ cat /etc/awslogs/awscli.conf 
[plugins]
cwlogs = cwlogs
[default]
region=ap-northeast-2
서비스를 재 시작 한다.
$ sudo service awslogs start

NginX Access Log 전송 설정

이렇게 해서 awslogs를 작동은시켰다.

이제 Nginx Access Log를 ClodWatch로 보내도록 해보자. 로그를 CloudWatch로 보내기 위해서는 아래의 정보들이 필요하다.
  1. 어떤 로그파일을 : /var/log/nginx/access.log
  2. 어떤 로그 그룹의 : myWebApp
  3. 어떤 이름의 로그 스트림으로 보낼 것인가.
이들 정보를 /etc/awslogs/awslogs.conf 파일어 넣어주면 된다.
[general]
state_file = /var/awslogs/state/agent-state

[NginxAccessLog]
file = /var/log/nginx/access.log
log_group_name = myWebApp
log_stream_name = {instance_id}
datetime_format = %d/%b/%Y:%H:%M:%S %z
initial_position = end_of_file
  • state_file : awslogs 에이전트는 로그파일에 로그가 추가되면, 해당 로그를 CW로 전송한다. awslogs 에이전트가 다시 시작할 경우, 마지막 읽은 지점이후의 내용을 CW로 전송 할 수 있어야 한다. 이를 위해서 로그파일에 대한 정보를 저장하고 있어야 한다. 이 파일의 위치를 설정한다. awslogs 에이전트가 시작하면 자동으로 이 파일을 만든다. 하지만 디렉토리를 만들어주지는 않으므로, 디렉토리까지는 만들어줘야 한다.
  • initial_position : 로그파일에 이미 로그가 쌓여있을 수가 있다. 처음부터 읽을 것인지, 아니면 마지막 줄 부터 읽을 것인지를 설정한다. start_of_file 과 end_of_file 중에 선택 할 수 있다.
  • log_stream_name : 보통 서비스는 분산환경에서 작동을 한다. 로그 파일도 여러 인스턴스에서 만들어질 수 있으므로 이를 식별 할 수 있어야 한다. 보통 instance_id 혹은 hostnam 등을 조합해서 로그 스트림 이름을 만든다. 로그 스트림이름이 없다면, awslogs가 자동으로 로그 스트림을 생성한다.
서비스를 재 시작 한다.
$ sudo service awslogs start
웹 콘솔에서 로그를 확인 할 수 있다.

정리

로깅 시스템의 주요 원칙은 아래와 같다.
  • 모든 로그를 수집 할 수 있는 능력이 있어야 한다.
  • 모든 로그를 분석 할 수 있는 능력이 있어야 한다.
  • 실시간으로 분석 할 수 있어야 한다.
  • 트랜드를 분석 할 수 있어야 한다.
  • 로컬 디스크 시스템과 로깅이 분리되야 한다.
  • 애플리케이션과 로깅을 분리 할 수 있어야 한다. : 로깅을 위해서 별도의 코드가 들어가지 않게 해야 한다는 의미다. 남기려는 로그를 표준출력하거나 디스크에 쌓아 놓으면, 알아서 수집되도록 만들어야 한다.
로깅 시스템은 위의 원칙을 따를 수 있도록 주의깊게 설계해야 한다. 즉 "표준 출력해주세요, 로그파일이 쌓이는 디렉토리 위치만 설정해 주세요" 이 한 마디로 수집툴, 분석툴을 제공 할 수 있어야 한다.

앞으로 할 일

  • ElasticSearch와 통합한다.
  • ElasticSearch를 통합하기 위해서 LogStash를 함께 사용하는 경우가 많은데, 복잡도를 증가시킨다. CloudWatch 로그 스트림을 ElasticSearch로 보내는 것을 테스트해봐야 한다.
  • 분석을 위해서는 S3에 저장돼야 한다. Cloudwatch의 로그 데이터를 S3에 저장 할 수 있는데, 정확히 살펴봐야 한다.
  • 분석툴을 살펴본다. CloudWatch Log Insight, QuickSight, Athena
  • 모니터링 대시보드를 설계 한다.
  • 결국 완전한 로그 시스템을 설계한다.