← 목록으로AWS

Windows 서버 프로세스 원격 모니터링 (SSM + Lambda + DynamoDB)

AWS SSM을 활용해 Windows 서버의 Java 프로세스 실행 상태를 원격으로 확인하고, 연속 실패 시 Slack/SMS/Email 다중 알람을 발송하는 서버리스 모니터링 구축

AWSMonitoringPythonAutomation
2024-10-28

배경

운영 환경의 Windows FTP 서버에서 FileReceiver(Java 프로세스)가 실행 중이어야 파일 수신이 정상 동작합니다. 그러나 서버 재부팅이나 프로세스 비정상 종료 시 FileReceiver가 내려간 상태로 방치될 수 있어, 이를 자동으로 감지하는 모니터링이 필요했습니다.

Windows 서버는 CloudWatch Agent만으로는 특정 Java 프로세스의 실행 여부를 확인할 수 없으므로, AWS Systems Manager(SSM)를 통한 원격 PowerShell 실행 방식을 채택했습니다.


아키텍처

EventBridge (5분 주기: rate(5 minutes))
    ↓
Lambda (Python)
    ├── SSM SendCommand → Windows 서버에 PowerShell 원격 실행
    ├── SSM GetCommandInvocation → 실행 결과 수집
    ├── DynamoDB → 직전 상태 저장 (연속 실패 카운트)
    │
    └── 연속 실패 N회 이상 시 알람 발송
        ├── Slack (Incoming Webhook)
        ├── SMS (SNS Topic, Tokyo Region)
        └── Email (SES SendEmail)

SSM 원격 PowerShell 실행

Windows 서버 사전 준비

대상 Windows 서버에 SSM Agent가 설치/등록되어 있어야 합니다.

# SSM Agent 설치 확인
Get-Service AmazonSSMAgent

실행할 PowerShell 스크립트

javaw.exe 프로세스 중 FileReceiver.jar를 실행 중인 프로세스를 탐지합니다.

$procs = Get-WmiObject Win32_Process -Filter "Name = 'javaw.exe'" |
         Select-Object ProcessId, CommandLine |
         Where-Object { $_.CommandLine -match "FileReceiver.jar" }
 
if ($procs) {
    Write-Output "UP: FileReceiver detected. PIDs: $($procs.ProcessId -join ', ')"
    exit 0
} else {
    Write-Output "DOWN: FileReceiver not detected."
    exit 2
}
  • exit 0 → UP (정상)
  • exit 2 → DOWN (프로세스 미감지)

명확한 종료 코드를 반환하도록 래핑하여 Lambda에서 판단할 수 있게 합니다.


Lambda 핵심 로직

SSM 명령 실행 및 결과 수집

import boto3, time
 
ssm = boto3.client('ssm')
 
def check_instance(instance_id, command):
    # 1. SSM SendCommand로 PowerShell 원격 실행
    cmd = ssm.send_command(
        InstanceIds=[instance_id],
        DocumentName='AWS-RunPowerShellScript',
        Parameters={'commands': [command]},
        TimeoutSeconds=60,
    )
    command_id = cmd['Command']['CommandId']
 
    # 2. 결과 수집 (터미널 상태까지 폴링)
    inv = wait_for_terminal(command_id, instance_id)
 
    status = inv.get('Status')
    response_code = inv.get('ResponseCode')
    output = inv.get('StandardOutputContent', '')
 
    is_up = (response_code == 0 and 'UP:' in output)
    return is_up, status, response_code, output

폴링 (SSM 전파 지연 고려)

def wait_for_terminal(command_id, instance_id, max_wait=45):
    deadline = time.time() + max_wait
    while time.time() < deadline:
        try:
            inv = ssm.get_command_invocation(
                CommandId=command_id,
                InstanceId=instance_id,
            )
            if inv['Status'] in ('Success', 'Failed', 'TimedOut', 'Cancelled'):
                return inv
            time.sleep(1.0)
        except ssm.exceptions.InvocationDoesNotExist:
            time.sleep(1.0)  # SSM 전파 지연
    raise TimeoutError("SSM command timed out")

연속 실패 감지 (DynamoDB)

DynamoDB에 인스턴스별 직전 상태와 연속 실패 횟수를 저장합니다.

ddb = boto3.client('dynamodb')
 
def update_state(table, instance_id, is_up):
    prev = ddb.get_item(
        TableName=table,
        Key={'host': {'S': instance_id}}
    ).get('Item', {})
 
    prev_fails = int(prev.get('fails', {}).get('N', '0'))
    fails = 0 if is_up else prev_fails + 1
 
    ddb.put_item(
        TableName=table,
        Item={
            'host': {'S': instance_id},
            'status': {'S': 'up' if is_up else 'down'},
            'fails': {'N': str(fails)},
            'ts': {'S': datetime.utcnow().isoformat() + 'Z'},
        }
    )
    return fails

연속 실패 N회(기본 2회) 이상일 때만 알람을 발송하여 일시적 오탐을 방지합니다.


다중 알람 채널

Slack (Incoming Webhook)

def notify_slack(webhook_url, message):
    payload = json.dumps({"text": message}).encode()
    req = urllib.request.Request(
        webhook_url,
        data=payload,
        headers={'Content-Type': 'application/json'},
    )
    urllib.request.urlopen(req, timeout=5)

SMS (SNS - Tokyo Region)

def send_sms(topic_arn, message):
    sns = boto3.client('sns', region_name='ap-northeast-1')
    sns.publish(
        TopicArn=topic_arn,
        Message=message[:120],  # SMS 길이 제한
        MessageAttributes={
            'AWS.SNS.SMS.SMSType': {
                'DataType': 'String',
                'StringValue': 'Transactional',
            }
        },
    )

Email (SES)

def send_email(sender, recipients, subject, body):
    ses = boto3.client('ses')
    ses.send_email(
        Source=sender,
        Destination={'ToAddresses': recipients},
        Message={
            'Subject': {'Data': subject, 'Charset': 'UTF-8'},
            'Body': {'Text': {'Data': body, 'Charset': 'UTF-8'}},
        },
    )

알람 조건

  • UP 상태일 때는 알람을 전송하지 않음
  • DOWN이 연속 N회 이상일 때만 Slack/SMS/Email 발송
  • SMS는 120자 이내로 truncate

Lambda 환경 변수

변수설명
INSTANCE_IDS대상 Windows 인스턴스 ID (쉼표 구분)
SLACK_WEBHOOK_URLSlack Incoming Webhook URL
SNS_TOPIC_ARN_SMSSMS용 SNS Topic ARN (Tokyo Region)
SES_FROM발신 이메일 주소
SES_TO_CSV수신 이메일 주소 (쉼표 구분)
DDB_TABLEDynamoDB 테이블 이름
FAIL_THRESHOLD연속 실패 임계치 (기본 2)
SSM_TIMEOUTSSM 명령 타임아웃 (기본 60초)
MAX_WAIT_SEC결과 폴링 최대 대기 (기본 45초)

IAM 역할

Lambda 실행 역할에 필요한 권한:

{
  "Effect": "Allow",
  "Action": [
    "ssm:SendCommand",
    "ssm:GetCommandInvocation",
    "dynamodb:GetItem",
    "dynamodb:PutItem",
    "ses:SendEmail",
    "sns:Publish",
    "logs:CreateLogGroup",
    "logs:CreateLogStream",
    "logs:PutLogEvents"
  ],
  "Resource": "*"
}

Standby 서버 자동 실행 설정

Active 서버뿐 아니라 Standby 서버에서도 재부팅 후 FileReceiver가 자동 실행되도록 Windows 작업 스케줄러를 설정합니다.

수동 실행 확인

# 관리자 PowerShell
cd C:\java\FileReceiver
C:\java\jre1.8.0_161\bin\javaw.exe -jar FileReceiver.jar
 
# 프로세스 확인
Get-Process javaw | Where-Object { $_.Path -like "*jre1.8.0_161*" }

작업 스케줄러 자동 실행

작업 스케줄러 (taskschd.msc) > 작업 만들기

일반 탭:
  이름: FileReceiver
  "가장 높은 권한으로 실행" 체크
  "사용자 로그온 여부와 관계없이 실행" 선택

트리거 탭:
  "컴퓨터 시작 시" 선택

동작 탭:
  프로그램: C:\java\jre1.8.0_161\bin\javaw.exe
  인수: -jar FileReceiver.jar
  시작 위치: C:\java\FileReceiver

재부팅 후 자동 실행 확인:

Get-Process javaw | Where-Object { $_.Path -like "*jre1.8.0_161*" }

트러블슈팅

Standby 서버 원격 접속 불가

보안 소프트웨어(방화벽)가 SSM Agent의 아웃바운드 통신을 차단하는 경우가 있었습니다. 방화벽 설정에서 SSM 관련 엔드포인트 통신을 허용하여 해결했습니다.


정리

  • SSM을 활용한 Windows 서버 Java 프로세스 원격 모니터링
  • EventBridge 5분 주기 트리거 → Lambda → SSM PowerShell 실행
  • DynamoDB로 연속 실패 카운트 관리, 오탐 방지
  • Slack/SMS/Email 다중 알람 채널 구성
  • Standby 서버 자동 실행 설정 (작업 스케줄러)
  • UP 상태에서는 알람 미발송으로 알림 피로 최소화