'CloudWatch'에 해당하는 글 5건

AWS WAF setting

Server/AWS 2024. 11. 25. 02:53

웹 공격, 특히 DDoS 대응으로 방화벽을 설치하라고 한다. (난 안전불감증으로, WAF 설치의 필요성은 못느끼고 있다.)

AWS 에서는 WAF 라는 웹 어플리케이션 방화벽 서비스를 제공한다. 고급 사양으로는 DDoS 방어에 특화된 AWS Shield, 여러 계정/리소스 관리를 간소화 하는 AWS Firewall Manager 가 있지만 생략한다. (여유자금 있으면 쓰면됨)

십수 년 전 suhosin 사용했을 때도 그렇지만, 설정을 빡세게 할수록 방화벽의 기능을 십분 활용할 수 있지만, 그렇게까지 할 필요가 있나 싶다. 공격을 완벽하게 막기란 쉽지 않고, 까딱 잘못하면 정상적인 요청마저 거부할 수도 있고, 슬프지만 내가 개발한 서비스가 누군가의 타겟이 될 정도로 인기 있지도 않기 때문이다. 참고로 20년 동안 방화벽에 대한 필요성을 느낀 적이 단 한번도 없었다. 그래도 방화벽을 달아야 하는 상황이라 아주 기본적인 설정만 해보려고 한다.

WAF 는 기본적으로, AWS 리소스 일부를 보호할 수 있으며, HTTP(S) 요청에 대한 IP / 국가 / 헤더 / 요청횟수 등으로 접근 허용이나 거부를 할 수 있다. (SQL Injection / XSS 생략) 프론트 단의 CloudFront 와 백엔드의 API 서버 중 alb 에만 방화벽을 설치해 보았다. 가장 기본적인 규칙들만 몇 개 적용하고 Bot Control / Capcha 등은 사용하지 않았다.

 

 

1. 서버 접근 패턴 파악

 

우선은 방어 전략을 짜기 전에, 해당 서버에 로그를 수집하여 패턴을 파악해 봐야 한다. 물론 처음부터 빡세게 제한하는 것도 좋지만, 이미 운영중일 경우는 기존 서비스에 장애가 발생하지 않도록 면밀히 분석해야 한다.

 

다행스럽게도 서버 대부분은 해외IP 로부터 SQL Injection / XSS 접근이 전부여서 Source IP 가 해외인 접근만 차단하는 것으로 완벽 차단이 가능했다. 사실 그것보다는 DDoS 공격에 대비하는 것이 목표라, 해외IP 차단 + 국내IP 에서 초당 100개 요청시 IP 차단 하는 Rule 로 처리하기로 했다.  

 

 

 

 

2. Rule 세팅 및 리소스 적용

 

  • Rule : 제어 규칙 생성
  • Rule Group : 재사용 가능한 사용자 정의 Rule Group 을 생성할 수 있고, AWS Marketplace 에서 유/무료 관리형 규칙 그룹을 선택할 수도 있다. (규칙 수, 복잡도에 따라 요금 증가)
  • Web ACL(제어목록) : 특정 규칙집합을 만들고 AWS 리소스를 연결하여 요청 제어 수행
    ㄴ 기본동작 (Allow / Block) 설정
    ㄴ 규칙 우선순위는 화면 위에서 아래, 낮은 숫자에서 높은 숫자 순

 

 

 

 

3. 모니터링 및 알람 설정

모니터링으로 요청에 대한 규칙 및 필터링 확인을 마쳤다면, CloudWatch 에서 특정 메트릭(예: 차단된 요청 수 - BlockedRequests)이 기준치를 초과할 때 SNS 알림을 트리거하도록 설정하여 운영하도록 한다. (알람 세팅 생략...)

 

 

 

4. 요금

(예, 관리형 규칙X, 사용자 규칙 19)

  • 웹 ACL 요금 = 5.00 USD * 1 = 5.00 USD
  • 규칙 요금 = 1.00 USD * 19(규칙) = 19.00 USD
  • 요청 요금 = 1백만 건당 0.60 USD * 1천만 건 = 6.00 USD
  • 결합된 총 요금 = 월별 30.00 USD

WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

약 1년 정도 EKS fargate + grafana 로 모니터링과 알람을 사용했다. 이왕 설치했으니까, 나름 피곤한 세팅 해가면서, 이쁘게 커스텀 잘 해왔는데, 보안 점검때마다 EKS 와 plugin 을 최신버전으로 올리는 바람에 그 때마다 Node 날아가고 전부 새로 설치+세팅 해야 한다는 점... 한번은 그냥 기분 좋게 했었는데, 두번은 못하겠다. 이게 다 fargate 를 사용해서...? AWS 의 EKS 인 만큼, AWS 안에서 모니터링과 알람을 만드는 것이 옳다고 생각하고 방법을 찾아봤다.

 

CPU / MEM / Traffic 모니터링은 기본이고, 배포시(혹은 장애시) 슬랙 알림 전송이 목표이며, 유일하게 AWS CloudWatch Container Insights 를 찾았다.

 

Container Insights 는 ECS/EKS 의 EC2/Fargate 에서 컨테이너 어플리케이션의 지표 및 로그를 수집하고 집계할 수 있다. 일반적으로 워커노드의 kubelet 이 /metrics/cadvisor 엔드포인트에서 CPU, 메모리, 디스크, 네트워크 사용량 등의 리소스 지표를 노출하는데, EKS Fargate 네트워킹 구조상 이 kubelet 에 접근이 안되기 때문에 프록시 역할을 할 ADOT(AWS Distro for OpenTelemetry 수집기를 사용하여, 워커노드의 지표 및 로그(CPU, 메모리, 트래픽) 들을 CloudWatch 로 전달한다. 그럼에도 CloudWatch 의 [향상된 관찰 기능] 은 지원되지 않는다.

 

 

 

 

ADOT Pod 생성

 

1. fargate profile 생성

 

$ kubectl create namespace fargate-container-insights
namespace/fargate-container-insights created

 

 

2. 서비스 계정 생성

 

ADOT 수집기에는 성능 로그 이벤트를 CloudWatch로 보내려면 IAM 권한이 필요하다. AWS 관리형 정책 CloudWatchAgentServerPolicy 와 연결할 역할(EKS-Fargate-ADOT-ServiceAccount-Role)을 만들고, EKS 의 서비스계정(adot-collector) 을 생성하여 연결하는 스크립트이다. YOUR-EKS-CLUSTER-NAME 과 YOUR-EKS-CLUSTER-REGION 을 적절히 수정한다.

 

$ ##!/bin/bash
CLUSTER_NAME=YOUR-EKS-CLUSTER-NAME
REGION=YOUR-EKS-CLUSTER-REGION
SERVICE_ACCOUNT_NAMESPACE=fargate-container-insights
SERVICE_ACCOUNT_NAME=adot-collector
SERVICE_ACCOUNT_IAM_ROLE=EKS-Fargate-ADOT-ServiceAccount-Role
SERVICE_ACCOUNT_IAM_POLICY=arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy

$ eksctl utils associate-iam-oidc-provider \
--cluster=$CLUSTER_NAME \
--approve

$ eksctl create iamserviceaccount \
--cluster=$CLUSTER_NAME \
--region=$REGION \
--name=$SERVICE_ACCOUNT_NAME \
--namespace=$SERVICE_ACCOUNT_NAMESPACE \
--role-name=$SERVICE_ACCOUNT_IAM_ROLE \
--attach-policy-arn=$SERVICE_ACCOUNT_IAM_POLICY \
--approve

2023-11-27 22:09:08 [ℹ]  eksctl version 0.75.0
2023-11-27 22:09:08 [ℹ]  using region ap-northeast-2
2023-11-27 22:09:09 [ℹ]  1 iamserviceaccount (fargate-container-insights/adot-collector) was included (based on the include/exclude rules)
2023-11-27 22:09:09 [!]  serviceaccounts that exist in Kubernetes will be excluded, use --override-existing-serviceaccounts to override
2023-11-27 22:09:09 [ℹ]  1 task: {
    2 sequential sub-tasks: {
        create IAM role for serviceaccount "fargate-container-insights/adot-collector",
        create serviceaccount "fargate-container-insights/adot-collector",
    } }2023-11-27 22:09:09 [ℹ]  building iamserviceaccount stack "eksctl-test-addon-iamserviceaccount-fargate-container-insights-adot-collector"
2023-11-27 22:09:10 [ℹ]  deploying stack "eksctl-test-addon-iamserviceaccount-fargate-container-insights-adot-collector"
2023-11-27 22:09:10 [ℹ]  waiting for CloudFormation stack "eksctl-test-addon-iamserviceaccount-fargate-container-insights-adot-collector"
2023-11-27 22:09:26 [ℹ]  waiting for CloudFormation stack "eksctl-test-addon-iamserviceaccount-fargate-container-insights-adot-collector"
2023-11-27 22:09:43 [ℹ]  waiting for CloudFormation stack "eksctl-test-addon-iamserviceaccount-fargate-container-insights-adot-collector"
2023-11-27 22:09:43 [ℹ]  created serviceaccount "fargate-container-insights/adot-collector"

 

 

3. ADOT StatefulSet 배포

 

https://github.com/aws-observability/aws-otel-collector/blob/main/deployment-template/eks/otel-fargate-container-insights.yaml

 

파일을 다운받아, YOUR-EKS-CLUSTER-NAME 과 region=us-east-1 을 적절히 수정하여 배포한다.

 

$ kubectl apply -f eks-fargate-container-insights.yaml
clusterrole.rbac.authorization.k8s.io/adotcol-admin-role created
clusterrolebinding.rbac.authorization.k8s.io/adotcol-admin-role-binding created
configmap/adot-collector-config created
service/adot-collector-service created
statefulset.apps/adot-collector created

 

 

4. CloudWatch Log Group 확인

 

몇 분이 지나면 CloudWatch 로그 그룹에 로그가 쌓이는 것을 확인할 수 있다.
/aws/containerinsights/CLUSTER_NAME/performance

 

 

5. CloudWatch 대시보드 생성

 

Metrics > ContainerInsights 지표를 활용하여 CPU, 메모리, 트래픽 정도의 대시보드를 구현할 수 있다.
(배포 알림은 ContainerInsights 가 아닌 ALB target-group 의 HealthyHostCount 로 측정하였음. PromQL 가 없으니 잇몸으로...)

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Tomcat Log - Slack Alarm

Server/AWS 2020. 10. 28. 19:00

톰캣에 특정 키워드가 포함된 에러로그가 발생됐을 때 슬랙으로 알림을 받기 위해 필요한 서비스들은 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 등의 키워드가 표시되면 슬랙으로 아래처럼 알림이 발송될 것이다.




로그 상세를 알람 메시지에 표시하고 싶었지만... 불가...




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

ECS logs / alarms

Server/AWS 2018. 8. 27. 22:57

ECS 를 사용하면 인스턴스에 docker / ecs / container 등에 대한 로그가 생성된다. CloudWatch Logs 로 로그 정보를 전송하면 컨테이너의 로그 용량 관리를 하지 않아도 된다. 인스턴스에서 CloudWatch Logs 에 로그 정보를 전송하도록 구성할 수도 있지만, 인스턴스 수 조정이 빈번하다면 해당 에이전트를 계속해서 설치하고 구성하는 것이 번거로울 수 있다. 이 경우에는 ECS 의 Task 정의에서 awslogs 로그 드라이버를 활성화하여 CloudWatch Logs 를 설정하는 방법이 있다.



Awslogs 설정


CloudWatch Logs 에 로그를 쌓기 위해서는 로그가 분류될 로그 그룹을 만들어야 한다. CloudWatch 콘솔이나 AWS CLI 를 사용하던지 간편하게 ECS 콘솔의 Task 정의에서 로그 그룹을 생성한다. [Task define] - [Container] - [Storage And Logging] - [Auto-configure CloudWatch Logs] 체크. 이렇게 awslogs 로그를 활성화 하면 해당 컨테이너의 로그 설정들이 자동으로 세팅되며, 추가로 옵션을 사용할 수 있다.



해당 Task 정의를 배포하고 나면 CloudWatch Logs 에서 해당 컨테이너의 로그들을 확인할 수 있다.




CPU / Memory 초과 알림


Amazon ECS 는 서비스의 평균 CPU 및 메모리 사용량과 함께 CloudWatch 지표(Metrics) 를 게시하며, 이 지표를 사용하여 알람을 추가할 수 있다. 우선 SNS(Simple Notification Service) 에 해당 알림 전용으로 메일 받을 Topic 을 하나 생성한다. [CloudWatch] - [Alarms] 에서 알람을 생성하고 ECS-Metrics 에서 CPU 나 Memory 의 상한선을 설정한 후, [Send notification to:] 에 알림 받을 Topic 을 선택하면 CPU 나 Memory 가 상한선을 초과할 경우 알림을 수신할 수 있다.




Task 중단시 메일 알림


Task 가 중단 됐을 때 알림을 받기 위해 CloudWatch 이벤트에 Rule 을 설정할 수도 있다.

[CloudWatch] - [Events] - [Rules] 에서 Rule 을 하나 생성하고, [Event Pattern Preview] 항목에 [Edit] 를 클릭하여 다음 코드를 입력한다.


{
   "source": [
     "aws.ecs"
  ],
  "detail-type": [
     "ECS Task State Change"
  ],
  "detail": {
    "clusterArn": [
      "arn:aws:ecs:ap-northeast-1:870750012345:cluster/api",
      "arn:aws:ecs:ap-northeast-1:870750012345:cluster/web"
    ],
  "lastStatus": [
      "STOPPED"
    ],
    "stoppedReason" : [
      "Essential container in task exited"
    ]
  }
}
cs


마찬가지로 알림을 받을 수 있도록 Rule 의 Target 에 생성해 놓은 Topic 을 연결한다.

이제 ECS 의 api/web 클러스터의 Task 상태가 essential 컨테이너로부터 중단되어 STOPPED 로 변경되면 알림을 수신할 수 있다.

stoppedReason 을 작성하지 않으면 Task 가 STOPPED 로 변경될 때마다 알림을 수신할 수 있으며, 위 중단 이유를 제외하고도 특정 stoppedReason 을 지정할 수 있다.





WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

Lambda timeout

Daily/Prog 2017. 5. 11. 23:39

자정에 한 번만 실행되어야 하는 Lambda 함수가 세 번 실행됐다.

Lambda Schedule -> S3 upload -> RDS insert 이 프로세스에서 세 번 실행된 걸 확인한 것은 RDS.

S3 를 추적해 보았더니 역시나 세 번의 upload.

CloudWatch 의 로그를 보았더니 Lambda 세 번 실행.

왜 세 번 실행이 되었을까...


00:01:21 START RequestId: f647b0b7-35dc-11e7-b221-9f353cc1b3ea Version: $LATEST

00:01:36 END RequestId: f647b0b7-35dc-11e7-b221-9f353cc1b3ea

00:01:36 REPORT RequestId: f647b0b7-35dc-11e7-b221-9f353cc1b3ea Duration: 15002.00 ms Billed Duration: 15000 ms Memory Size: 512 MB Max Memory Used: 98 MB

00:01:36 2017-05-11T00:01:36.076Z f647b0b7-35dc-11e7-b221-9f353cc1b3ea Task timed out after 15.00 seconds


00:02:42 START RequestId: f647b0b7-35dc-11e7-b221-9f353cc1b3ea Version: $LATEST

00:02:57 END RequestId: f647b0b7-35dc-11e7-b221-9f353cc1b3ea

00:02:57 REPORT RequestId: f647b0b7-35dc-11e7-b221-9f353cc1b3ea Duration: 15001.92 ms Billed Duration: 15000 ms Memory Size: 512 MB Max Memory Used: 81 MB

00:02:57 2017-05-11T00:02:57.392Z f647b0b7-35dc-11e7-b221-9f353cc1b3ea Task timed out after 15.00 seconds


00:04:59 START RequestId: f647b0b7-35dc-11e7-b221-9f353cc1b3ea Version: $LATEST

00:05:13 # finish

00:05:13 END RequestId: f647b0b7-35dc-11e7-b221-9f353cc1b3ea

00:05:13 REPORT RequestId: f647b0b7-35dc-11e7-b221-9f353cc1b3ea Duration: 14197.01 ms Billed Duration: 14200 ms Memory Size: 512 MB Max Memory Used: 90 MB 


time out 문구가 눈에 띈다.

15 초로 설정되어 있는건 내가 걸어놨으니 그렇다 치고, S3 upload 는 캔슬되었어야지... 어이가 없네?

timeout 설정 늘려서 해결.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,