CloudFormation으로 ALB 액세스 로그 설정해 보기

CloudFormation으로 ALB 액세스 로그 설정해 보는 방법을 정리해 봤습니다.
2023.04.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다. 이번에는 CloudFormation으로 ALB 액세스 로그 설정해 보는 방법을 정리해 봤습니다.

액세스 로그

Elastic Load Balancing은 로드 밸런서에 전송된 요청에 대한 자세한 정보를 캡처하는 액세스 로그를 제공합니다. 각 로그에는 요청을 받은 시간, 클라이언트의 IP 주소, 지연 시간, 요청 경로 및 서버 응답과 같은 정보가 포함되어 있습니다. 이러한 액세스 로그를 사용하여 트래픽 패턴을 분석하고 문제를 해결할 수 있습니다.

액세스 로그는 다음과 같은 로그 정보를 담고 있습니다.

  • 요청을 받은 시간
  • 클라이언트의 IP 주소
  • 지연 시간
  • 요청 경로
  • 서버 응답
bucket[/prefix]/AWSLogs/aws-account-id/elasticloadbalancing/region/yyyy/mm/dd/aws-account-id_elasticloadbalancing_region_app.load-balancer-id_end-time_ip-address_random-string.log.gz

액세스 로그의 경우 S3 버킷에 다음과 같은 경로에 저장됩니다.

보다 상새한 내용은 아래 문서를 참고해 주세요.

Management Console에서 액세스 로그 활성화

ALB를 생성할 때 액세스 로그를 설정하는 것은 불가능합니다.

ALB를 생성할 때 설정할 수 있는 부분은 다음과 같습니다.

  • 로드 밸런서 이름
  • 체계(내부 로드밸런서, 외부 로드밸런서)
  • IP 주소 유형
  • 네트워크 매핑
  • 보안 그룹
  • 타겟 그룹
  • 리스너
  • AWS Global Accelerator 설정 유무

등을 설정할 수 있지만, 액세스 로그를 설정할 수는 없습니다.

액세스 로그를 설정하기 위해, ALB를 생성한 다음「속성」→「편집」을 클릭합니다.

이어서 모니터링에서 액세스 로그를 활성화할 수 있습니다.

CloudFormation으로 액세스 로그 활성화

# ------------------------------------------------------------#
# Create S3 Bucket
# ------------------------------------------------------------# 
Resources:
  ALBLogsBucket:
    Type: "AWS::S3::Bucket"
    Properties:
      BucketName: !Sub ${SystemName}-${EnvName}-aws-alb-logs-bucket
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      LifecycleConfiguration:
        Rules:
          - Id: !Sub ${SystemName}-${EnvName}-aws-alb-logs-lifecycle
            Status: Enabled
            ExpirationInDays: 90
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${EnvName}-aws-alb-logs-bucket
        - Key: Env
          Value: !Sub ${EnvName}
# ------------------------------------------------------------#
# Set S3 Bucket Policy
# ------------------------------------------------------------# 
  ELBLogBucketPolicy:
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket: !Ref ALBLogsBucket
      PolicyDocument:
        Id: "AWSCFn-AccessLogs-Policy-20180920"
        Version: "2012-10-17"
        Statement:
          - Sid: "AlbLogs"
            Effect: "Allow"
            Action:
              - "s3:PutObject"
            Resource: !Sub arn:aws:s3:::${ALBLogsBucket}/AWSLogs/${AWS::AccountId}/*
            Principal:
              AWS:
                - "582318560864"

먼저 CloudFormation에서 S3 버킷을 생성하고, Policy를 설정합니다.

# ------------------------------------------------------------#
#  internet-facing ALB
# ------------------------------------------------------------#
  InternetFacingALB: 
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    Properties: 
      Name: !Sub ${SystemName}-${EnvName}-web-alb
      Tags: 
        - Key: Name
          Value: !Sub ${SystemName}-${EnvName}-web-alb
        - Key: Env
          Value: !Sub ${EnvName}
      Scheme: "internet-facing"
      LoadBalancerAttributes: 
        - Key: "deletion_protection.enabled"
          Value: true # trueに変更
        - Key: access_logs.s3.enabled
          Value: true
        - Key: access_logs.s3.bucket
          Value: !Ref ALBLogsBucket
        - Key: "idle_timeout.timeout_seconds"
          Value: 60
      SecurityGroups:
        - Fn::ImportValue: !Sub ${EnvName}-alb-sg
      Subnets: 
        - Fn::ImportValue: !Sub ${EnvName}-public-subnet-1a
        - Fn::ImportValue: !Sub ${EnvName}-public-subnet-1c
      Type: application
  ALBListenerHTTPSWeb001:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      Port: 443
      Protocol: HTTPS
      Certificates:
        - CertificateArn: !Ref LoadBalancerCertificateARN
      DefaultActions:
        - TargetGroupArn: !Ref TargetGroupWeb001
          Type: forward
      LoadBalancerArn: !Ref InternetFacingALB

ALB를 생성하는 부분에서는「Key: access_logs.s3.enabled」를 활성화 하고,「Key: access_logs.s3.bucket」에 로그를 저장할 S3 버킷을 설정합니다.

AWSTemplateFormatVersion: "2010-09-09"
Description:
  Create ALB or S3 Bucket
# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------# 
Parameters:
  SystemName:
    Description: "System name of each resource names."
    Type: String
    Default: "test"
  EnvName:
    Description: "Environment name of each resource names."
    Type: String
    Default: "prd"
  HostZoneId:
    Description: FQDN of the hosted zone
    Type: AWS::Route53::HostedZone::Id
    Default: "xxxxxxxxxxxxxxxx" #Route53 HostedZone ID
  SubDomain:
    Description: FQDN of the certificate
    Type: String
    Default: "xxxxxxxxxxxxxx" #domain address to be used
  LoadBalancerCertificateARN:
    Type: String
    Default: "xxxxxxxxxxxxxxxxxxxx" #certificate ARN
    Description: Enter certificate ARN; Use ACM to create a certificate before creating this stack
# ------------------------------------------------------------#
# Create S3 Bucket
# ------------------------------------------------------------# 
Resources:
  ALBLogsBucket:
    Type: "AWS::S3::Bucket"
    Properties:
      BucketName: !Sub ${SystemName}-${EnvName}-aws-alb-logs-bucket
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      LifecycleConfiguration:
        Rules:
          - Id: !Sub ${SystemName}-${EnvName}-aws-alb-logs-lifecycle
            Status: Enabled
            ExpirationInDays: 90
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${EnvName}-aws-alb-logs-bucket
        - Key: Env
          Value: !Sub ${EnvName}
# ------------------------------------------------------------#
# Set S3 Bucket Policy
# ------------------------------------------------------------# 
  ELBLogBucketPolicy:
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket: !Ref ALBLogsBucket
      PolicyDocument:
        Id: "AWSCFn-AccessLogs-Policy-20180920"
        Version: "2012-10-17"
        Statement:
          - Sid: "AlbLogs"
            Effect: "Allow"
            Action:
              - "s3:PutObject"
            Resource: !Sub arn:aws:s3:::${ALBLogsBucket}/AWSLogs/${AWS::AccountId}/*
            Principal:
              AWS:
                - "582318560864"
# ------------------------------------------------------------#
#  Target Group
# ------------------------------------------------------------#
  TargetGroupWeb001: 
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties: 
      VpcId: 
        Fn::ImportValue: !Sub ${EnvName}-vpc
      Name: !Sub ${SystemName}-${EnvName}-web001-tgp
      Protocol: HTTP
      Port: 80
      HealthCheckProtocol: HTTP
      HealthCheckPath: "/"
      HealthCheckPort: "traffic-port"
      HealthyThresholdCount: 5 # 正常の閾値
      UnhealthyThresholdCount: 2 # 非正常の閾値
      HealthCheckTimeoutSeconds: 5 # タイムアウト
      HealthCheckIntervalSeconds: 60 # 間隔
      Matcher: 
        HttpCode: 200 # 成功コード
      Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${EnvName}-web001-tgp
        - Key: Env
          Value: !Sub ${EnvName}
      TargetGroupAttributes: 
        - Key: "stickiness.enabled"
          Value: false
      Targets: 
        - Id: 
            Fn::ImportValue: !Sub ${EnvName}-web
          Port: 80
# ------------------------------------------------------------#
#  internet-facing ALB
# ------------------------------------------------------------#
  InternetFacingALB: 
    Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
    Properties: 
      Name: !Sub ${SystemName}-${EnvName}-web-alb
      Tags: 
        - Key: Name
          Value: !Sub ${SystemName}-${EnvName}-web-alb
        - Key: Env
          Value: !Sub ${EnvName}
      Scheme: "internet-facing"
      LoadBalancerAttributes: 
        - Key: "deletion_protection.enabled"
          Value: true # trueに変更
        - Key: access_logs.s3.enabled
          Value: true
        - Key: access_logs.s3.bucket
          Value: !Ref ALBLogsBucket
        - Key: "idle_timeout.timeout_seconds"
          Value: 60
      SecurityGroups:
        - Fn::ImportValue: !Sub ${EnvName}-alb-sg
      Subnets: 
        - Fn::ImportValue: !Sub ${EnvName}-public-subnet-1a
        - Fn::ImportValue: !Sub ${EnvName}-public-subnet-1c
      Type: application
  ALBListenerHTTPSWeb001:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      Port: 443
      Protocol: HTTPS
      Certificates:
        - CertificateArn: !Ref LoadBalancerCertificateARN
      DefaultActions:
        - TargetGroupArn: !Ref TargetGroupWeb001
          Type: forward
      LoadBalancerArn: !Ref InternetFacingALB
# ------------------------------------------------------------#
#  Route53
# ------------------------------------------------------------#
  DnsRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId: !Sub ${HostZoneId}
      Comment: "DNS for ALB"
      Name: !Sub ${SubDomain}
      Type: A
      AliasTarget:
        HostedZoneId: !GetAtt 'InternetFacingALB.CanonicalHostedZoneID'
        DNSName: !GetAtt 'InternetFacingALB.DNSName'

전체 코드는 다음과 같습니다. S3 버킷 생성 후, 액세스 로그 설정 뿐만 아니라 https 설정도 하고 있는 상태입니다.

액세스 로그 확인

CloudFormation을 생성한 다음, ALB를 확인해 보면, 액세스 로그가 활성화 되어 있는 것을 확인할 수 있습니다.

S3 버킷에서는 AWSLogs라는 객체가 생성되고「ELBAccessLogTestFile」파일이 생성된 것을 확인할 수 있습니다.

여기서 ALB에 몇 번 액세스를 시도해 보면, 날짜 별로 로그 파일이 생성됩니다.

본 블로그 게시글을 보시고 문의 사항이 있으신 분들은 클래스메소드코리아 (info@classmethod.kr)로 연락 주시면 빠른 시일 내 담당자가 회신 드릴 수 있도록 하겠습니다 !