관리 메뉴

피터의 개발이야기

[kubernetes] Ingress 수정 후 검수기 전용회선 네트워크 오류 트라블 슈팅 정리 및 최신 CloudFormation temple 정보 추가 본문

Kubernetes/트러블슈팅&장애대응

[kubernetes] Ingress 수정 후 검수기 전용회선 네트워크 오류 트라블 슈팅 정리 및 최신 CloudFormation temple 정보 추가

기록하는 백앤드개발자 2022. 9. 28. 15:51
반응형

ㅁ 개요

 ㅇ 검수기 전용회선 네트워크 오류가 발생하였다.

 ㅇ Grafana 컨테이너를 추가하면서 Ingress 변경작업으로 인해 ALB 주소가 변경 되어 발생한 문제점이었다.

 ㅇ ALB 주소와 연결된 다른 설정부분을 설명하며, 해결과정에 대해서 정리하였다.

 

 

ㅁ 검수기 전용회선 네트워크 오류 확인 요청이 인입되어 네트워크  확인 작업

 ㅇ전체 네트워크 흐름에 따라 체크를 시작하였다. 

 ㅇ Route53의 레코드 확인, 문제 없음.

 

 

 ㅇ 로드밸런서도 활성화 상태이다. 

 ㅇ 접속 장애가 나고 있는 443 리스너의 대상그룹을 확인해야 한다

 

 

 

ㅇ Grafana 컨테이너 추가 작업 후 외부 접속을 위해 Ingress 수정 작업을 했던 시점에서 헬스케크에 문제점이 시작되었다.
 ㅇ 네트워크 인터페이스에서 해당 IP를 확인해 보았지만 검색이 되지 않았다.

 

 

ㅁ Grafana 컨테이너 추가에 따른 Ingress 작업

 ㅇ 외부에서 grafana로 접속이 가능하도록 ingress에 설정 정보를 추가하였다.

 

 

 ㅇ kubectl get ingress stg-grafana 명령어로 설정된 ingress 정보를 확인하였다.

 ㅇ 새로운 Address가 생성된 것을 확인하였다.

 

 

 ㅇ 새로운 Address는 로드 밸런서에서도 확인할 수 있었다.

 ㅇ ingress에 접속할 수 있는 Address가 변경이 되면서 문제가 발생한 것이다.

 ㅇ 더 구체적인 문제는 새로운 ALB가 구성되면서 그곳을 바라보는 IP가 변경된다는 점이다.

 ㅇ 이 부분에 대해서 좀 더 알아보았다.

 

 

ㅁ Application Load Balancer IP 변동

 ㅇ 로드밸런싱을 하는 주체도 IP가 존재한다. 하지만 이 IP의 경우 시간이 지남에 따라 변경이 된다.

 ㅇ AWS에서도 다음과 같은 경고를 주고 있다. 여기에

중요:
 Classic Load Balancer 및 Application Load Balancer의 IP 주소는 시간이 지남에 따라 변경됩니다. 이 정보를 사용하여 애플리케이션이 이러한 IP 주소를 가리키도록 정적으로 구성하지 마세요.

 ㅇ 이를 보안하기 위해 람다를 이용하여 주기적으로 변경된 IP를 수정하도록 되어 있었다.

 ㅇ 근본적인 이유는 Network Load Balancer에서 직접적으로 ALB에 연동하도록 지원해 주지 않았다.

 ㅇ 2021.9.27 이후 NLB -> ALB 직접 전달로 개선하면서 람다를 이용한 방법은 옛날 방식이 되었다. 

Application Load Balancer는 이제 네트워크 로드 밸런서와 직접 통합하여 AWS PrivateLink 및 고정 IP 주소를 활성화합니다.
게시된 날짜: Sep 27, 2021
Elastic Load Balancing은 이제 Network Load Balancer(NLB)에서 Application Load Balancer(ALB)로의 직접 트래픽 전달을 지원합니다. 이 기능을 통해 이제 AWS PrivateLink를 사용하고 ALB 기반 애플리케이션에 대해 고정 IP 주소를 노출할 수 있습니다.
ALB는 고급 요청 기반 라우팅을 제공하는 관리형 계층 7 프록시입니다. NLB는 계층 4에서 작동하며 PrivateLink 및 영역 고정 IP 주소에 대한 지원을 제공합니다. PrivateLink는 퍼블릭 인터넷에 트래픽을 노출하지 않고 애플리케이션에 대한 프라이빗 연결을 가능하게 하며 영역별 고정 IP 주소는 클라이언트의 네트워크 및 보안 구성을 단순화할 수 있습니다. 이번 출시 이전에 NLB를 ALB와 통합하려는 고객은 ALB IP 주소 변경을 관리하기 위해 AWS Lambda 함수와 같은 사용자 지정 메커니즘을 설정해야 했습니다. 이번 출시를 통해 ALB를 NLB의 대상으로 등록해 ALB IP 주소 변경을 능동적으로 관리할 필요 없이 NLB에서 ALB로 트래픽을 전달할 수 있으므로 PrivateLink 및 영역 고정 IP 주소를 비롯한 NLB의 이점을 ALB의 고급 요청 기반 라우팅과 연결해 사용자의 애플리케이션으로 트래픽을 로드 밸런싱할 수 있게 되었습니다. ALB 유형 대상 그룹은 모든 상용 AWS 리전 및 AWS GovCloud(미국) 리전의 NLB에 사용할 수 있습니다.
시작하려면 새 ALB 유형 대상 그룹을 생성하고 ALB를 등록하며, ALB 유형 대상 그룹으로 트래픽을 전달하도록 NLB를 구성하십시오. NLB에서 PrivateLink를 활성화하여 클라이언트에게 비공개로 서비스를 제공할 수도 있습니다. 자세한 내용은 블로그 게시물 및 NLB 설명서를 참조하십시오.

 

 

Application Load Balancer는 이제 네트워크 로드 밸런서와 직접 통합하여 AWS PrivateLink 및 고정 IP 주소를

Elastic Load Balancing은 이제 Network Load Balancer(NLB)에서 Application Load Balancer(ALB)로의 직접 트래픽 전달을 지원합니다. 이 기능을 통해 이제 AWS PrivateLink를 사용하고 ALB 기반 애플리케이션에 대해 고정 IP

aws.amazon.com

 

 

ㅁ Lambda Function 확인

 ㅇ 이 람다는 AWS Route53에서 kubenetes ingress로 트래픽을 전달하는 ALB의 유동 아이피를 갱신해주는 역할을 한다.

 ㅇ 12일에 ingress 작업을 하면서 에러가 발생하고 있었던 것을 확인 할 수 있다.

 

 

 ㅇ EventBridge에서 1분에 한번씩 Lambda가 실행되도록 설정되어 있음.

 ㅇ 1분에 한번씩 람다로 변경된 주소를 확인하여 target group의 IP를 업데이트를 해 주고 있었다.

 

 

 ㅇ 변경되는 Address 주소는 람다함수의 환경변수에 적용되어 있는데, 이 주소가 변경되면서 람다에러가 발생하였다.

 ㅇ 이 주소를 수정하였을 때에 아래의 그림처럼  target 그룹이 수정됨을 확인 할 수 있었다.

 

 ㅇ 참고로 람다 함수의 로그이다.

 

 

ㅁ Elastic Load Balancing가 kubernetes로 전송하는 트래픽의 소스 IP 찾는 법

 ㄴ 네트워크 인터페이스에서 조회하는 방법

 ㅇ AWS elb find load balancer IP 문서에서 안내를 하고 있다.

 ㅇ 로드밸런스 창에서 IP주소를 찾을 로드 밸런서를 찾는다.

 ㅇ k8s-stg-int 로 검색하면 현재 로드밸러스에 배정된 IP를 확인 할 수 있다.

 

 

 ㄴ 로드밸런스의 DNS 정보를 이용한 nslookup

  ㅇ 로드밸런스에서 DNS 정보를 확인한다.

 

 

 ㅇ nsloopup 명령어로 172.20.147.43, 172.20.209.185 주소를 확인 할 수 있다.

 

 

 

 

 

ㅁ 정리

Ingress 수정이 이루어졌는데,
   1) Int NLB 연결 대상인 ALB의 IP가 변경되면서 NLB 등록된 기존 IP Unhealthy 발생
     - 검수기 내부 구성 변경을 하는과정에서 ALB 재구성하면서 ALB 주소가 변경됨

   2) ALB는 AWS에서 주기적으로 IP를 변경하므로 이에 대한 자동대응을 위해 람다를 구성하여
       NLB대상 ALB 주소에 대한 변경IP를 확인하여 변경시 현행화하는 작업을 수행하나
       람다에 설정되어있던 ALB 주소가 재구성전  구 ALB 주소로 등록되어있어 신규 ALB 주소에 대한 IP변경시 업데이트 적용되지 못함

 

 

 

ㅁ StaticIP-LambdaFunction(2022.0928)

 ㅇ 마지막 최신 소스 및 설명은 여기

 

Using AWS Lambda to enable static IP addresses for Application Load Balancers | Amazon Web Services

Update: On September 27th, 2021, we launched Application Load Balancer(ALB)-type target groups for Network Load Balancer (NLB). With this launch, you can register ALB as a target of NLB to forward traffic from NLB to ALB without needing to actively manage

aws.amazon.com

 ㅇ 현재 LambdaFunction 정보

  - python: 2.7
  - dnspython 1.15
 ㅇ 최신? 마지막?

  - python: 3.8
  - dnspython 2.1.0

 ㅇ CloudFormation template 마지막 버젼은 여기

https://exampleloadbalancer-us-east-1.s3.amazonaws.com/blog-posts/static-ip-for-application-load-balancer/template_poplulate_NLB_TG_with_ALB_python3.json

 

{
  "Transform": "AWS::Serverless-2016-10-31",
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Template of Register Application Load Balancer as IP target for Network Load Balancer",
  "Parameters": {
    "InternalALBDNSName": {
      "Type": "String",
      "Default": "",
      "Description": "Enter the DNS name of your internal Application Load Balancer name. e.g.application-load-balancer.elb.us-east-1.amazonaws.com"
    },
    "NLBTargetGroupARN": {
      "Type": "String",
      "Default": "",
      "Description": "Enter the target group ARN which you want the Application Load Balancer to be registered to"
    },
    "S3BucketName": {
      "Type": "String",
      "Default": "",
      "Description": "Enter the S3 Bucket name that you want to store Application Load Balancer's node IP addresses"
    },
    "ALBListenerPort": {
      "Type": "String",
      "Default": "",
      "Description": "Enter the traffic listener port of your internal Application Load Balancer"
    },
    "MAXDNSLookupPerInvocation": {
      "Type": "Number",
      "Default": 50,
      "Description": "Please specify the max DNS lookup this function can perform per invocation"
    },
    "InvocationBeforeDeregistration": {
      "Type": "Number",
      "Default": 3,
      "Description": "Please specify how many invocations are needed before a IP is deregistered"
    },
    "CWMetricFlagIPCount": {
      "Type": "String",
      "Default": "True",
      "AllowedValues": [
        "True",
        "False"
      ],
      "Description": "Please specify if you want the Lambda function to create a CloudWatch metric to track IP count of your internal Application Load Balancer"
    },
     "SameVPC": {
      "Type": "String",
      "Default": "True",
      "AllowedValues": [
        "True",
        "False"
      ],
      "Description": "Please specify if your Network Load Balancer and the internal Application Load Balancer are in the same VPC. By default, it is set to True"
    },
    "Region": {
      "Type": "String",
      "Default": "us-east-1",
      "AllowedValues": [
        "us-east-1",
        "us-east-2",
        "us-west-1",
        "us-west-2",
        "eu-west-1",
        "eu-west-2",
        "eu-west-3",
        "eu-central-1",
        "ap-southeast-1",
        "ap-southeast-2",
        "ap-northeast-1",
        "ap-northeast-1",
        "ap-northeast-2",
        "sa-east-1",
        "ap-south-1",
        "ca-central-1"
      ],
      "Description": "Please specify the region where you want to create your Lambda function"
    }
  },
  "Mappings": {
    "RegionMap": {
      "ap-northeast-1": {
        "Bucket": "exampleloadbalancer-ap-northeast-1",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "ap-northeast-2": {
        "Bucket": "exampleloadbalancer-ap-northeast-2",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "ap-south-1": {
        "Bucket": "exampleloadbalancer-ap-south-1",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "ap-southeast-1": {
        "Bucket": "exampleloadbalancer-ap-southeast-1",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "ap-southeast-2": {
        "Bucket": "exampleloadbalancer-ap-southeast-2",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "ca-central-1": {
        "Bucket": "exampleloadbalancer-ca-central-1",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "eu-central-1": {
        "Bucket": "exampleloadbalancer-eu-central-1",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "eu-west-1": {
        "Bucket": "exampleloadbalancer-eu-west-1",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "eu-west-2": {
        "Bucket": "exampleloadbalancer-eu-west-2",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "sa-east-1": {
        "Bucket": "exampleloadbalancer-sa-east-1",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "us-east-1": {
        "Bucket": "exampleloadbalancer-us-east-1",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "us-east-2": {
        "Bucket": "exampleloadbalancer-us-east-2",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "us-west-1": {
        "Bucket": "exampleloadbalancer-us-west-1",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "us-west-2": {
        "Bucket": "exampleloadbalancer-us-west-2",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      },
      "eu-west-3": {
        "Bucket": "exampleloadbalancer-eu-west-3",
        "Key": "blog-posts/static-ip-for-application-load-balancer/populate_NLB_TG_with_ALB_python3.zip"
      }
    }
  },
  "Resources": {
    "LambdaFunction": {
      "Type": "AWS::Serverless::Function",
      "Properties": {
        "CodeUri": {
          "Bucket": {
            "Fn::FindInMap": [
              "RegionMap",
              {
                "Ref": "Region"
              },
              "Bucket"
            ]
          },
          "Key": {
            "Fn::FindInMap": [
              "RegionMap",
              {
                "Ref": "Region"
              },
              "Key"
            ]
          }
        },
        "Description": "Register Application Load Balancer to Network Load Balancer",
        "Handler": "populate_NLB_TG_with_ALB.lambda_handler",
        "Timeout": 300,
        "Role": {
          "Fn::GetAtt": [
            "LambdaIAMRole",
            "Arn"
          ]
        },
        "Runtime": "python3.8",
        "Environment": {
          "Variables": {
            "ALB_DNS_NAME": {
              "Ref": "InternalALBDNSName"
            },
            "NLB_TG_ARN": {
              "Ref": "NLBTargetGroupARN"
            },
            "S3_BUCKET": {
              "Ref": "S3BucketName"
            },
            "MAX_LOOKUP_PER_INVOCATION": {
              "Ref": "MAXDNSLookupPerInvocation"
            },
            "INVOCATIONS_BEFORE_DEREGISTRATION": {
              "Ref": "InvocationBeforeDeregistration"
            },
            "CW_METRIC_FLAG_IP_COUNT": {
              "Ref": "CWMetricFlagIPCount"
            },
            "ALB_LISTENER": {
              "Ref": "ALBListenerPort"
            },
            "SAME_VPC": {
              "Ref": "SameVPC"
            }
          }
        }
      }
    },
    "ScheduledRule": {
      "Type": "AWS::Events::Rule",
      "Properties": {
        "Description": "ScheduledRule",
        "ScheduleExpression": "rate(1 minute)",
        "State": "ENABLED",
        "Targets": [
          {
            "Arn": {
              "Fn::GetAtt": [
                "LambdaFunction",
                "Arn"
              ]
            },
            "Id": "TargetFunctionV1"
          }
        ]
      },
      "DependsOn": [
        "LambdaFunction"
      ]
    },
    "LambdaInvokePermission": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "FunctionName": {
          "Fn::GetAtt": [
            "LambdaFunction",
            "Arn"
          ]
        },
        "Principal": "events.amazonaws.com",
        "Action": "lambda:InvokeFunction",
        "SourceArn": {
          "Fn::GetAtt": [
            "ScheduledRule",
            "Arn"
          ]
        }
      }
    },
    "LambdaIAMRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": "lambda.amazonaws.com"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyName": "Lambda-ALBasTarget",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "LambdaLogging",
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": [
                    "arn:aws:logs:*:*:*"
                  ]
                },
                {
                  "Sid": "S3",
                  "Action": [
                    "s3:Get*",
                    "s3:PutObject",
                    "s3:CreateBucket",
                    "s3:ListBucket",
                    "s3:ListAllMyBuckets"
                  ],
                  "Effect": "Allow",
                  "Resource": "*"
                },
                {
                  "Sid": "ELB",
                  "Action": [
                    "elasticloadbalancing:Describe*",
                    "elasticloadbalancing:RegisterTargets",
                    "elasticloadbalancing:DeregisterTargets"
                  ],
                  "Effect": "Allow",
                  "Resource": "*"
                },
                {
                  "Sid": "CW",
                  "Action": [
                    "cloudwatch:putMetricData"
                  ],
                  "Effect": "Allow",
                  "Resource": "*"
                }
              ]
            }
          }
        ]
      }
    }
  }
}

 

 

ㅁ 함께 보면 좋은 사이트

 ㅇ 인그레스란?

 

인그레스(Ingress)

기능 상태: Kubernetes v1.19 [stable] 클러스터 내의 서비스에 대한 외부 접근을 관리하는 API 오브젝트이며, 일반적으로 HTTP를 관리함. 인그레스는 부하 분산, SSL 종료, 명칭 기반의 가상 호스팅을 제공

kubernetes.io

 ㅇNLB에서 ALB로 직접 트래픽을 전달

 

Application Load Balancer는 이제 네트워크 로드 밸런서와 직접 통합하여 AWS PrivateLink 및 고정 IP 주소를

Elastic Load Balancing은 이제 Network Load Balancer(NLB)에서 Application Load Balancer(ALB)로의 직접 트래픽 전달을 지원합니다. 이 기능을 통해 이제 AWS PrivateLink를 사용하고 ALB 기반 애플리케이션에 대해 고정 IP

aws.amazon.com

 ㅇ Using AWS Lambda to enable static IP addresses for Application Load Balancers

 

Using AWS Lambda to enable static IP addresses for Application Load Balancers | Amazon Web Services

Update: On September 27th, 2021, we launched Application Load Balancer(ALB)-type target groups for Network Load Balancer (NLB). With this launch, you can register ALB as a target of NLB to forward traffic from NLB to ALB without needing to actively manage

aws.amazon.com

 

반응형
Comments