AWS-CICD

[Troubleshooting ] EventBridge 규칙을 통해 Lambda 함수 호출, 함수 실행 권한 및 환경 설정 문제 해결하기

backend 따라쟁이 2025. 4. 16. 23:33

 

EventBridge 규칙에서 Lambda함수 호출에 실패할때 조치 방법

  1. EventBridge 규칙(Rule) 설정 확인:
    • 이벤트 패턴(Event Pattern): CodeDeploy 배포 성공 이벤트(CodeDeploy Deployment State Change, detail.state가 SUCCESS인 경우)를 정확히 필터링하도록 이벤트 패턴이 올바르게 정의되었는지 확인합니다. 실제 CodeDeploy 성공 시 발생하는 이벤트 구조와 비교해보세요. AWS 콘솔의 CloudWatch Logs Insights나 EventBridge의 이벤트 버스 모니터링 기능을 통해 실제 전달된 이벤트 내용을 확인하면 패턴 작성에 도움이 됩니다.
    • 대상(Target) 설정: 규칙의 대상으로 설정된 Lambda 함수가 올바른지, 그리고 대상 설정이 **활성화(Enabled)**되어 있는지 확인합니다. 실수로 비활성화되어 있을 수 있습니다.
    • 규칙 상태(Rule Status): EventBridge 규칙 자체가 활성화(Enabled) 상태인지 확인합니다.
  2. IAM 권한 확인 (가장 흔한 원인 중 하나): ☜ 나는 이게 문제였더라고!  
    • EventBridge가 Lambda 함수를 호출하려면 적절한 권한이 필요합니다. 일반적으로 EventBridge가 Lambda 함수를 대상으로 지정할 때 AWS 콘솔에서 자동으로 **리소스 기반 정책(Resource-based Policy)**을 Lambda 함수에 추가해줍니다.
    • Lambda 함수 권한 확인:
      • AWS Lambda 콘솔에서 해당 함수로 이동합니다.
      • '구성(Configuration)' 탭 아래의 '권한(Permissions)' 섹션으로 이동합니다.
      • '리소스 기반 정책' 섹션을 확인합니다.
      • eventbridge.amazonaws.com 서비스 주체(principal) 또는 해당 EventBridge 규칙의 ARN이 lambda:InvokeFunction 작업을 수행할 수 있도록 허용하는 정책문(statement)이 있는지 확인합니다. 예를 들어 다음과 유사한 정책이 있어야 합니다:
      • JSON
        {
          "Sid": "AllowEventBridgeInvoke",
          "Effect": "Allow",
          "Principal": {
            "Service": "events.amazonaws.com"
          },
          "Action": "lambda:InvokeFunction",
          "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:YOUR_FUNCTION_NAME",
          "Condition": {
            "ArnLike": {
              "AWS:SourceArn": "arn:aws:events:REGION:ACCOUNT_ID:rule/YOUR_RULE_NAME"
            }
          }
        }
        
      • 만약 이 정책이 없거나 잘못 설정되었다면, EventBridge는 Lambda 함수를 호출할 권한이 없어 실패하게 됩니다. EventBridge 규칙의 대상을 제거했다가 다시 추가하면 콘솔이 이 정책 생성을 시도할 수 있습니다. 또는 AWS CLI나 SDK를 사용하여 직접 추가할 수도 있습니다 (aws lambda add-permission 명령어 사용).
  3. Lambda 함수 실행 로그 및 오류 확인:
    • EventBridge가 Lambda를 호출했더라도, Lambda 함수 자체에서 초기화 오류나 실행 중 오류가 발생하여 즉시 실패했을 수 있습니다. 이 경우 호출되지 않은 것처럼 보일 수 있습니다.
    • CloudWatch Logs 확인:
      • 해당 Lambda 함수와 연결된 CloudWatch Log Group으로 이동합니다.
      • CodeDeploy 성공 이벤트가 발생한 시점 근처에 새로운 로그 스트림이나 로그 항목이 있는지 확인합니다.
      • START, END, REPORT 로그 외에 에러 메시지나 스택 트레이스가 있는지 확인합니다. 특히 함수 핸들러 설정 오류, 코드 내 오류, 타임아웃 등을 확인하세요.
  4. EventBridge 규칙 모니터링 확인:
    • CloudWatch Metrics에서 EventBridge 관련 지표를 확인합니다.
    • 해당 EventBridge 규칙(Rule)의 이름으로 필터링하여 다음 지표를 확인합니다:
      • TriggeredRules: 규칙의 이벤트 패턴과 일치하는 이벤트가 발생하여 규칙이 트리거되었는지 횟수를 보여줍니다. 이 값이 증가한다면 이벤트 패턴 매칭은 성공한 것입니다.
      • InvocationAttempts: EventBridge가 Lambda 함수 호출을 시도한 횟수입니다.
      • FailedInvocations: Lambda 함수 호출 시도가 실패한 횟수입니다. 이 값이 증가한다면 권한 문제나 Lambda 함수 자체의 문제(예: 함수가 존재하지 않음, 리소스 기반 정책 누락 등)일 가능성이 높습니다.
  5. Lambda 함수 구성 확인:
    • Lambda 함수의 핸들러 설정이 올바른지, 런타임은 적절한지 등 기본적인 구성 사항을 다시 한번 확인합니다.
    • Lambda 함수의 제한 시간(Timeout) 설정이 너무 짧게 되어 있어 이벤트 처리 중 타임아웃되는 것은 아닌지 확인합니다.

요약 및 추천 접근법:

  1. EventBridge 규칙 설정 (패턴, 대상, 활성화 상태) 재확인.
  2. Lambda 함수 권한 탭에서 리소스 기반 정책 확인 (가장 중요!). eventbridge.amazonaws.com 또는 규칙 ARN에 대한 lambda:InvokeFunction 권한이 있는지 확인합니다.
  3. CloudWatch에서 EventBridge 규칙의 FailedInvocations 지표 확인.
  4. CloudWatch에서 Lambda 함수의 로그 확인. (오류가 있는지, 아예 로그 자체가 없는지)

이 단계들을 차례대로 점검해보시면 문제의 원인을 파악하고 해결하는 데 도움이 될 것입니다. 만약 위의 방법으로도 해결되지 않는다면, 사용하신 이벤트 패턴이나 Lambda 리소스 기반 정책의 구체적인 내용을 공유해주시면 좀 더 자세히 살펴볼 수 있습니다.

 

♨ Lambda 함수가 호출되었는데, Lambda 함수 실행 중 타임아웃이 발생할 경우 조치 방법

Lambda 함수 실행 중 타임아웃은 codedeploy.list_deployment_instances API 호출 부분에서도 충분히 발생할 수 있습니다. 특히 "Target instance IDs:", instance_ids 로그가 출력되기 전에 타임아웃이 발생했다면, 해당 API 호출 또는 관련 로직(페이지네이션 루프 포함) 수행 중에 설정된 제한 시간을 초과했을 가능성이 매우 높습니다.

타임아웃이 발생하는 주요 원인들은 다음과 같습니다.

  1. 네트워크 연결 문제 (가장 흔한 원인 중 하나): ☜ 나는 이게 문제였더라고!  
    • Lambda 함수가 VPC 내부에 있는 경우:
      • Private Subnet: Lambda 함수가 인터넷 아웃바운드 액세스가 없는 Private Subnet에 있고, NAT Gateway나 CodeDeploy용 VPC 엔드포인트(Interface Endpoint)가 설정되어 있지 않으면 AWS API(CodeDeploy 엔드포인트)에 연결할 수 없습니다. 이 경우 boto3 클라이언트는 응답을 기다리다가 결국 Lambda 함수의 타임아웃 시간에 도달하게 됩니다.
      • Security Group / NACL: Lambda 함수에 연결된 보안 그룹의 아웃바운드 규칙이나 서브넷의 네트워크 ACL이 HTTPS (포트 443) 트래픽을 차단하고 있을 수 있습니다. CodeDeploy API 엔드포인트로의 통신이 막히면 타임아웃이 발생합니다.
      • VPC 엔드포인트 설정 오류: CodeDeploy용 VPC 엔드포인트를 사용 중이라면, 라우팅, 보안 그룹, 엔드포인트 정책 등이 올바르게 설정되었는지 확인해야 합니다.
    • 해결 방안:
      • Lambda 함수가 VPC 내에 있다면, 네트워크 구성을 점검하세요 (NAT Gateway, Internet Gateway, 라우팅 테이블, 보안 그룹, NACL).
      • CodeDeploy용 VPC 엔드포인트 설정을 확인하거나, 없다면 생성을 고려해 보세요. (VPC 엔드포인트 사용 시 NAT Gateway 불필요)
      • 보안 그룹 아웃바운드 규칙에서 포트 443이 열려 있는지 확인하세요.
  2. 매우 많은 수의 인스턴스 및 페이지네이션:
    • CodeDeploy 배포 대상 인스턴스가 수백, 수천 대로 매우 많을 경우, list_deployment_instances API는 여러 페이지의 결과를 반환합니다. 코드의 while 루프는 모든 페이지를 다 가져올 때까지 반복해서 API를 호출합니다.
    • 각 API 호출마다 약간의 시간이 소요되는데, 페이지 수가 너무 많으면 이 시간들이 누적되어 Lambda 함수의 전체 타임아웃 시간을 초과할 수 있습니다. 특히 Lambda 함수의 타임아웃 설정이 짧을 경우(예: 기본값 3초 또는 수십 초) 발생 가능성이 높습니다.
    • 해결 방안:
      • Lambda 함수의 타임아웃 설정을 늘려보세요. (예: 1분, 5분 등). 임시로 늘려서 코드가 완료되는지 확인하면, 단순히 시간이 부족했던 것인지 다른 문제인지 판단하는 데 도움이 됩니다.
      • 정말로 많은 인스턴스를 처리해야 하고 시간이 오래 걸린다면, Step Functions 등을 사용하여 작업을 분할하거나 다른 아키텍처를 고려해야 할 수도 있습니다.
  3. CodeDeploy API 응답 지연 또는 일시적 문제:
    • 드물지만 AWS CodeDeploy 서비스 자체의 일시적인 성능 저하나 문제로 인해 API 응답이 느려져 타임아웃이 발생할 수도 있습니다.

문제 해결 방법 상세(Lambda 함수가 VPC 내부에 있는 경우):

Lambda 함수가 VPC 내부에 있을 때 타임아웃이 발생한다면 네트워크 연결 문제일 가능성이 높습니다. 다음 단계를 순서대로 점검해 보세요.

1단계: Lambda 함수 VPC 구성 확인

  • 어떤 VPC, 서브넷, 보안 그룹에 연결되어 있는지 확인합니다.
  • 작업: AWS Lambda 콘솔 > 해당 함수 선택 > '구성(Configuration)' 탭 > 'VPC' 메뉴로 이동합니다.
  • 여기에 명시된 **VPC ID, 서브넷 ID(들), 보안 그룹 ID(들)**을 메모해 둡니다.

2단계: 서브넷 유형 확인 (Public vs Private)

  • Lambda 함수가 연결된 서브넷들이 인터넷에 직접 연결될 수 있는 Public Subnet인지, 아니면 인터넷 연결을 위해 다른 경로(NAT 게이트웨이 등)가 필요한 Private Subnet인지 확인합니다.
  • 작업:
    • AWS VPC 콘솔 > '서브넷(Subnets)' 메뉴로 이동합니다.
    • 1단계에서 확인한 서브넷 ID 각각을 선택합니다.
    • '라우팅 테이블(Route table)' 탭을 확인하여 연결된 라우팅 테이블 ID를 확인합니다.

3단계: 라우팅 테이블 확인

  • Lambda 함수 서브넷에 연결된 라우팅 테이블이 인터넷 또는 CodeDeploy 서비스 엔드포인트로 트래픽을 보낼 경로를 가지고 있는지 확인합니다.
  • 작업:
    • AWS VPC 콘솔 > '라우팅 테이블(Route tables)' 메뉴로 이동합니다.
    • 2단계에서 확인한 라우팅 테이블 ID를 선택합니다.
    • '라우팅(Routes)' 탭 내용을 확인합니다.
    • 시나리오 A: NAT 게이트웨이 사용 예상 시 (가장 일반적) ☜ 난 이방법을 사용함.
      • 대상(Destination) 0.0.0.0/0 (모든 IPv4 트래픽)에 대한 경로가 있습니까?
      • 해당 경로의 대상(Target)이 **NAT 게이트웨이 ID (nat-xxxxxxxx)**로 지정되어 있습니까?
      • 만약 그렇다면: 4단계 (NAT 게이트웨이 확인)로 진행합니다.
      • 만약 경로가 없거나 대상이 잘못되었다면: 이것이 문제의 원인일 가능성이 높습니다. Private Subnet에서 외부 API를 호출하려면 0.0.0.0/0 트래픽을 NAT 게이트웨이로 보내는 경로가 필요합니다.
    • 시나리오 B: VPC 엔드포인트 사용 예상 시
      • CodeDeploy 서비스용 VPC 인터페이스 엔드포인트(com.amazonaws.<region>.codedeploy)를 사용하도록 의도했습니까?
      • 이 경우 0.0.0.0/0 경로는 필요 없거나 다른 용도로 사용될 수 있습니다. CodeDeploy로 가는 트래픽은 엔드포인트를 통해 라우팅됩니다.
      • 만약 그렇다면: 5단계 (VPC 엔드포인트 확인)로 진행합니다.
    • 시나리오 C: 퍼블릭 서브넷 사용 시 (Lambda에는 일반적이지 않음)
      • 대상 0.0.0.0/0의 대상(Target)이 **인터넷 게이트웨이 ID (igw-xxxxxxxx)**로 지정되어 있습니까?
      • 만약 그렇다면: 해당 서브넷은 퍼블릭 서브넷입니다. 이 경우 Lambda 함수 자체에 퍼블릭 IP가 할당되어야 외부 통신이 가능합니다 (기본 설정 아님). 일반적으로 Lambda는 Private Subnet + NAT/엔드포인트 조합을 사용합니다. 이 구성이 의도된 것이 아니라면 Private Subnet으로 변경하는 것을 고려하세요. 의도된 것이라면 6단계 (보안 그룹 확인)로 진행합니다.

4단계: NAT 게이트웨이 상태 및 구성 확인 (3단계 A 시나리오 해당 시) ☜ 상세한 해결방법 (주의 : NAT게이트웨이는 퍼블릿 서브넷, lambda 함수는 프라이빗 서브넷에 있어야함. 프라이빗 서브넷에서의 라우트에는 NAT 게이트웨이가 설정되어 있어야 하며, 퍼블릿 서브넷의 라우트에선 인터넷 게이트웨이가 설정되어 있어야 함.) 

  • 라우팅 테이블에서 확인한 NAT 게이트웨이가 정상적으로 작동하는지 확인합니다.
  • 작업:
    • AWS VPC 콘솔 > 'NAT 게이트웨이(NAT Gateways)' 메뉴로 이동합니다.
    • 라우팅 테이블에 있던 nat-xxxxxxxx ID를 찾습니다.
    • **상태(Status)**가 'available'인지 확인합니다.
    • NAT 게이트웨이에 탄력적 IP(Elastic IP) 주소가 할당되어 있는지 확인합니다.
    • NAT 게이트웨이가 위치한 서브넷을 확인합니다. 이 서브넷은 퍼블릭 서브넷이어야 합니다 (즉, 이 서브넷의 라우팅 테이블에는 0.0.0.0/0 -> igw-xxxxxxxx 경로가 있어야 함). 해당 서브넷의 라우팅 테이블도 확인합니다.

5단계: VPC 엔드포인트 상태 및 구성 확인 (3단계 B 시나리오 해당 시)

  • CodeDeploy용 VPC 인터페이스 엔드포인트가 올바르게 설정되었는지 확인합니다.
  • 작업:
    • AWS VPC 콘솔 > '엔드포인트(Endpoints)' 메뉴로 이동합니다.
    • 서비스 이름이 com.amazonaws.<region>.codedeploy 인 인터페이스(Interface) 유형의 엔드포인트를 찾습니다.
    • **상태(Status)**가 'available'인지 확인합니다.
    • 엔드포인트가 1단계에서 확인한 올바른 VPC에 연결되어 있는지 확인합니다.
    • '서브넷(Subnets)' 탭에서 Lambda 함수가 사용하는 서브넷 (또는 해당 가용 영역의 다른 서브넷)이 연결되어 있는지 확인합니다.
    • '보안 그룹(Security groups)' 탭에서 연결된 보안 그룹이 Lambda 함수의 보안 그룹으로부터 HTTPS (포트 443) 인바운드 트래픽을 허용하는지 확인합니다.
    • 엔드포인트 정책(Policy)이 설정되어 있다면, Lambda 함수의 실행 역할(IAM Role)이 codedeploy:ListDeploymentInstances 작업을 수행하도록 허용하는지 확인합니다. (기본값은 전체 허용)
    • VPC 설정에서 'DNS 호스트 이름 활성화' 및 'DNS 확인 활성화'가 모두 활성화되어 있는지 확인합니다.

6단계: Lambda 함수 보안 그룹의 아웃바운드 규칙 확인

  • Lambda 함수 자체에 연결된 보안 그룹이 외부로 나가는 트래픽을 허용하는지 확인합니다.
  • 작업:
    • AWS EC2 콘솔 > '보안 그룹(Security Groups)' 메뉴로 이동합니다.
    • 1단계에서 확인한 Lambda 함수에 연결된 보안 그룹 ID를 찾습니다.
    • '아웃바운드 규칙(Outbound rules)' 탭을 확인합니다.
    • HTTPS (포트 443) 트래픽을 대상 0.0.0.0/0 (NAT/IGW 사용 시) 또는 VPC 엔드포인트가 사용하는 IP 대역/보안 그룹 (VPC 엔드포인트 사용 시)으로 허용하는 규칙이 있는지 확인합니다. 가장 흔한 실수는 이 아웃바운드 규칙이 없거나 너무 제한적인 경우입니다.

7단계: 네트워크 ACL(NACL) 규칙 확인

  • 서브넷 수준의 방화벽인 NACL이 트래픽을 차단하고 있지 않은지 확인합니다. NACL은 상태 비저장(Stateless)이므로 인바운드와 아웃바운드 규칙을 모두 확인해야 합니다.
  • 작업:
    • AWS VPC 콘솔 > '네트워크 ACLs(Network ACLs)' 메뉴로 이동합니다.
    • Lambda 함수가 있는 서브넷과 (NAT 게이트웨이를 사용한다면) NAT 게이트웨이가 있는 서브넷에 연결된 NACL을 확인합니다.
    • Lambda 서브넷 NACL:
      • 아웃바운드 규칙: 대상 0.0.0.0/0 (또는 CodeDeploy 엔드포인트 IP 대역), 포트 443 (HTTPS)으로 나가는 TCP 트래픽을 허용하는 규칙이 있는지 확인합니다.
      • 인바운드 규칙: 소스 0.0.0.0/0 (또는 CodeDeploy 엔드포인트 IP 대역), 포트 범위 1024-65535 (Ephemeral ports)로 들어오는 TCP 트래픽을 허용하는 규칙이 있는지 확인합니다. (API 응답 트래픽)
    • NAT 게이트웨이 서브넷 NACL (NAT 사용 시): 유사하게 인바운드/아웃바운드 규칙을 확인합니다. (인터넷에서 오는 응답과 인터넷으로 나가는 요청)
    • 참고: 기본 NACL은 모든 트래픽을 허용합니다. 사용자 정의 NACL이 적용되어 있다면 규칙 번호 순서대로 평가되므로 주의 깊게 확인해야 합니다.

8단계: (선택) EC2 인스턴스로 연결 테스트

  • 문제 진단을 돕기 위해, Lambda 함수와 동일한 VPC 서브넷 및 동일한 보안 그룹을 사용하는 EC2 인스턴스를 임시로 생성합니다.
  • 해당 인스턴스에 SSH로 접속하여 CodeDeploy 엔드포인트로 직접 연결 테스트를 수행합니다. 
  • Bash
     
    # 예시: 서울 리전
    curl -v https://codedeploy.ap-northeast-2.amazonaws.com
    
  • 여기서 연결이 성공하면 Lambda 환경 자체의 문제일 수 있고, 여기서도 실패하면 VPC 네트워크 경로 문제일 가능성이 높습니다.

이 단계들을 순서대로 차근차근 점검해 보시면 VPC 내부 Lambda 함수의 네트워크 연결 문제를 진단하고 해결하는 데 도움이 될 것입니다. 가장 먼저 Lambda 타임아웃 설정 증가보안 그룹 아웃바운드 규칙을 확인하는 것이 효과적인 경우가 많습니다.

 

♨ Lambda 함수가 호출되었는데, AccessDeniedException 오류가 발생할 경우 조치 방법

AccessDeniedException 오류는 Lambda 함수가 codedeploy:ListDeploymentInstances 권한이 없어서 발생한 것입니다. 이 오류를 해결하기 위해 아래 순서대로 조치하면 됩니다.


✅ 1단계: 오류 원인 파악

오류 메시지에 따르면, Lambda 함수가 사용하는 역할(myFunc-asg-update-role-n3ys1udk)에 codedeploy:ListDeploymentInstances 권한이 없습니다.

User: arn:aws:sts::...:assumed-role/myFunc-asg-update-role-n3ys1udk/myLambda-codedeploy is not authorized to perform: codedeploy:ListDeploymentInstances

✅ 2단계: Lambda 함수의 실행 역할(Role) 확인

  1. AWS Lambda 콘솔 접속
  2. 문제 발생한 Lambda 함수 선택 (myLambda-codedeploy)
  3. [구성] 탭 > 권한 > 실행 역할 클릭
    • 여기서 확인되는 IAM Role이 myFunc-asg-update-role-n3ys1udk인지 다시 한번 확인

✅ 3단계: 해당 IAM Role에 권한 추가

이제 해당 Role에 필요한 CodeDeploy 권한을 추가해야 합니다.

  1. IAM 콘솔 접속
  2. 역할(Roles)에서 myFunc-asg-update-role-n3ys1udk 검색하여 클릭
  3. [권한] 탭에서 정책 추가 버튼 클릭
  4. 인라인 정책 추가 또는 기존 정책 편집

🔧 정책(JSON) 예시:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codedeploy:ListDeploymentInstances",
                "codedeploy:GetDeploymentInstance",
                "codedeploy:GetDeployment",
                "codedeploy:GetDeploymentGroup"
            ],
            "Resource": [
                "arn:aws:codedeploy:ap-northeast-2:148761669753:deploymentgroup:SpringBootApp-1/app-deploy-1",
                "arn:aws:codedeploy:ap-northeast-2:148761669753:deployment:SpringBootApp-1/*"
            ]
        }
    ]
}

✅ 필요 시 "Resource": "*"로 설정해 우선 테스트해보고, 이후 최소 권한 원칙에 따라 리소스를 좁히는 것이 좋습니다.


✅ 4단계: 정책 저장 및 적용 확인

  1. 정책 저장 후, Lambda 함수에서 다시 테스트 이벤트 실행
  2. 동일한 AccessDeniedException이 발생하지 않으면 권한 적용 완료

✅ 5단계 (선택): CloudTrail로 추가 분석

혹시 다른 권한도 누락됐을 수 있으므로, CloudTrail에서 Lambda 호출 이력을 확인해 어떤 API 호출에 실패했는지 추가로 점검할 수 있습니다.


필요하시면 IAM 정책 생성 화면에서 어떤 버튼을 눌러야 하는지도 스크린샷 기반으로 도와드릴 수 있어요. JSON 정책 붙여넣기 창이 잘 안 보이는 경우 알려주세요!