Kubernetes-Masterclass | LBC, Ingress & Service Account(SA) & Webhook Service & Ingress Class

김주혁's avatar
Aug 20, 2024
Kubernetes-Masterclass | LBC, Ingress & Service Account(SA) & Webhook Service & Ingress Class
 

AWS Load Balancer Controller(LBC) Ingress

 
AWS 로드 밸런서 컨트롤러를 설치합니다. 이 컨트롤러는 Kubernetes에서 ALB(Application Load Balancer)와 NLB(Network Load Balancer)를 관리하는 데 사용됩니다.
 

1. AWS 로드 밸런서 컨트롤러 개요

  • 변경 사항: 이전에는 AWS ALB Ingress 컨트롤러가 사용되었으나, 이제는 AWS 로드 밸런서 컨트롤러로 이름이 변경되고 재설계되었습니다.
  • 지원 기능: 이 컨트롤러는 애플리케이션 로드 밸런서(ALB)뿐만 아니라 네트워크 로드 밸런서(NLB)도 생성할 수 있습니다.
  • Ingress 및 서비스 객체: ALB를 생성하려면 Kubernetes의 Ingress 객체를 사용하고, NLB를 생성하려면 서비스 객체에 NLB를 나타내는 주석을 추가해야 합니다.

2. 컨트롤러의 필요성 및 특징

  • 최신 Ingress API 지원:
    • 이전의 ALB Ingress 컨트롤러는 최신 Ingress API인 networking.k8s.io/v1을 지원하지 않습니다.
    • Kubernetes 1.22 v 이후로 ALB Ingress 컨트롤러는 더 이상 지원되지 않고 사용 중단 될 예정입니다.
    • 따라서 최신 AWS Load Balancer Controller를 활용해야 합니다. AWS 로드 밸런서 컨트롤러는 최신 Ingress API를 지원합니다.
  • 기능 확장: 이 컨트롤러는 최신 Kubernetes 기능을 활용하며, EKS 클러스터에서 최신 Ingress 및 로드 밸런서 기능을 사용할 수 있도록 합니다.

3. AWS 로드 밸런서 컨트롤러 Deployment

  1. 네임스페이스
      • kube-system 네임스페이스: AWS 로드 밸런서 컨트롤러와 관련된 모든 리소스는 EKS 클러스터의 kube-system 네임스페이스에 생성됩니다.
  1. 서비스 계정
      • AWS Load Balancer Controller Service Account:
        • 이 서비스 계정은 EKS 클러스터 내에서 AWS 로드 밸런서 컨트롤러를 위한 주요 계정입니다.
        • IAM 정책 및 역할: 로드 밸런서 컨트롤러가 AWS 리소스를 생성, 업데이트, 삭제할 수 있도록 IAM 정책IAM 역할을 정의합니다. 이 IAM 역할은 AWS Load Balancer Controller Service Account에 주석으로 추가됩니다.
  1. 컨트롤러 배포
      • 컨트롤러를 배포하면 관련된 파드가 생성됩니다. 이 파드들은 EKS 클러스터 내에서 ALB와 NLB를 생성하고 관리할 수 있는 권한을 갖습니다.
      • 이 컨트롤러 배포에는 로드 밸런서 컨트롤러 파드들이 있는데, 이 파드들은 EKS Cluster에서 AWS 서비스인 ALB를 생성할 능력을 가지고 있습니다.
        • 이러한 작업이 가능한 이유는 로드 밸런서 컨트롤러에 부여된 권한(IAM) 때문입니다.
  1. 기타 생성 리소스
      • Service Account: AWS 로드 밸런서 컨트롤러에 필요한 권한을 부여받는 계정입니다.
      • AWS Load Balancer Controller Deployment: 로드 밸런서 컨트롤러의 주 배포 리소스입니다.
      • AWS Load Balancer Controller Webhook Cluster IP Service: 웹훅 서비스로, 클러스터 내의 이벤트를 처리합니다.
      • AWS Load Balancer TLS Service: 로드 밸런서와 관련된 TLS 비밀(Secret)을 관리합니다.
  1. 연결 및 권한
      • 서비스 계정은 Deployment와 연결되며, 이 Deployment는 파드와도 연결됩니다.
      • 따라서, 로드 밸런서 컨트롤러는 EKS 클러스터 내에서 Application Load Balancer (ALB)와 Network Load Balancer (NLB)를 생성하고 관리할 수 있는 권한을 가집니다.

4. 컨트롤러의 동작 방식

  • Kubernetes API 감시: 컨트롤러는 Kubernetes API 서버에서 Ingress 이벤트를 감시하며, Ingress 리소스가 생성될 때 이를 감지하여 ALB를 생성합니다.
  • AWS 리소스 생성: Kubernetes에서 Ingress 매니페스트를 배포하면, AWS에서 애플리케이션 로드 밸런서(ALB) 또는 네트워크 로드 밸런서(NLB)가 생성됩니다.
 

 

AWS Application Load Balancer (ALB)

 

1. AWS 애플리케이션 로드 밸런서(ALB) 개요

  • ALB의 정의: ALB는 차세대 고급 로드 밸런서로, HTTP/HTTPS 트래픽의 라우팅을 담당하며, 다양한 라우팅 기능을 제공합니다.
  • 주요 기능:
    • 라우팅
      • 경로 기반 라우팅: 특정 URL 경로에 따라 트래픽을 여러 애플리케이션으로 라우팅할 수 있습니다.
        • /app1, /app2, /usermgmt ….
      • 호스트 기반 라우팅: 도메인 이름에 따라 트래픽을 다른 애플리케이션으로 라우팅할 수 있습니다.
      • 다양한 라우팅 조건: HTTP 헤더, HTTP 메서드, 쿼리 매개변수, 소스 IP 주소 등의 조건을 기반으로 라우팅을 설정할 수 있습니다.
    • Redirection
      • 리디렉션 및 사용자 정의 응답: ALB는 요청을 다른 URL로 리디렉션하거나, 사용자 정의 HTTP 응답을 반환할 수 있습니다.
    • Lambda 함수와 통합: ALB는 AWS Lambda 함수를 타겟으로 설정할 수 있으며, 서버리스 애플리케이션과의 통합을 지원합니다.
    • 사용자 인증: ALB는 회사 또는 소셜 아이덴티티를 통한 사용자 인증을 지원하며, 이를 통해 애플리케이션에 대한 접근을 제어할 수 있습니다.
    • 컨테이너화된 애플리케이션 지원:
      • ALB는 AWS ECS와의 통합을 지원하며, 컨테이너 기반 애플리케이션의 로드 밸런싱을 제공합니다.
      • ECS와의 통합을 아웃 오브 박스로 제공합니다.(기본 제공 기능)
    • 상태 확인:
      • 각 서비스의 상태를 독립적으로 모니터링할 수 있습니다.
      • 타겟 그룹 레벨에서 상태 확인이 가능합니다.
    • IP 기반 타겟 등록: ALB는 VPC 내부와 외부에서 IP 주소를 통해 타겟을 등록할 수 있습니다.

2. ALB Ingress 컨트롤러(ALB IC)

  • 역할: ALB Ingress Controller는 Kubernetes 클러스터에서 Ingress 리소스를 생성할 때, 애플리케이션 로드 밸런서와 필요한 AWS 리소스를 자동으로 생성하고 관리합니다.
  • ALB IC는 EKS 클러스터에서 Ingress 리소스가 생성될 때, Application Load Balancer와 필요한 AWS 리소스를 생성하는 작업을 트리거 합니다.
    • Ingress 주석: kubernetes.io/ingress.class=alb 주석을 사용해 ALB Ingress 컨트롤러를 트리거합니다.
    • 위 주석 이름과 함께 ALB IC가 Ingress 리소스와 함께 생성됩니다.
  • 트래픽 모드:
    • 인스턴스 모드: Ingress 컨트롤러가 클러스터의 노드를 ALB의 타겟으로 등록합니다.
      • EKS 클러스터 내의 워커 노드가 ALB의 타겟으로 등록된다는 것을 의미합니다.
      • 이 모드에서는 ALB에 도달한 트래픽이 Kubernetes의 NodePort로 라우팅됩니다.
        • ALB ⇒ NodePort ⇒ Port로 Proxy, 이는 Application 앞에 NodePort 서비스를 생성할 때 ALB가 먼저 NodePort 서비스로 라우팅한 후 그 서비스가 포트로 라우팅되는 것을 의미합니다.
      • 이 방식은 ALB Ingress manifest의 기본 트래픽 모드로, 기본 값 입니다.
      • Ingress manifests에 alb.ingress.kubernetes.io/target-type: instance 주석을 추가하여 명시적으로 지정할 수 있습니다.
    • IP 모드: Kubernetes 서비스의 포트가 직접 ALB의 타겟으로 등록됩니다.
      • ALB에 도달하는 트래픽은 서비스의 Port로 직접 라우팅됩니다.
      • Fargate를 사용하는 경우에는 반드시 IP 모드를 사용해야 합니다.
        • Fargate 노드는 NodePort 서비스를 지원하지 않기 때문에(서버리스 개념) 백그라운드에서 생성된 노드에 대한 제어가 불가능합니다.
        • 관리 노드 그룹을 사용할 때는 인스턴스 모드나 IP 모드 중 하나를 선택하는 개념입니다.
      • 인스턴스 모드에서는 EKS 워커 노드가 ALB 타겟으로 등록 됐지만, IP 모드에서는 Port가 ALB의 타겟으로 등록됩니다.
      • alb.ingress.kubernetes.io/target-type: IP를 사용하여 지정할 수 있습니다.

3. ALB Ingress 컨트롤러의 작동 원리

  1. Ingress 이벤트 감시:
      • 컨트롤러는 Kubernetes API 서버에서 Ingress 이벤트를 감시합니다. Ingress 리소스가 요구 사항을 충족하면, 생성되면 필요한 AWS 리소스를 생성합니다.
  1. AWS 리소스 생성:
      • 애플리케이션 로드 밸런서: Ingress 리소스가 생성되면, AWS에서 애플리케이션 로드 밸런서가 생성됩니다.
        • 이 로드 밸런서는 ELB v2 유형을 가집니다.
        • IAM 권한을 부여할 때 ELB v2도 포함되야 한다는 점에서 중요한 사항입니다.
      • 타겟 그룹: 각 Kubernetes 서비스에서 Ingress 리소스에 정의된 각 서비스에 대해 타겟 그룹이 생성됩니다. 이는 매니페스트에 정의된 서비스와 연결됩니다.
        • manifests에 정의된 Application 관련 NodePort 서비스가 생성되며 이에 따라 정의된 Port도 마찬가지로 생성됩니다.
      • 리스너와 규칙: ALB에서 트래픽을 수신할 리스너(예: 포트 443)가 생성되며, Ingress 매니페스트에 정의된 경로 기반 및 호스트 기반 라우팅 규칙이 설정됩니다.
 

CREATE IAM & Service Account(SA)

1. IAM 정책 생성

  1. IAM 정책 파일 다운로드
      • 최신 버전의 IAM 정책 파일을 다운로드합니다.
      • IAM policy latest.json 파일을 Visual Studio Code에서 열어 필요한 권한을 확인합니다.
        • iam
          { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iam:CreateServiceLinkedRole" ], "Resource": "*", "Condition": { "StringEquals": { "iam:AWSServiceName": "elasticloadbalancing.amazonaws.com" } } }, { "Effect": "Allow", "Action": [ "ec2:DescribeAccountAttributes", "ec2:DescribeAddresses", "ec2:DescribeAvailabilityZones", "ec2:DescribeInternetGateways", "ec2:DescribeVpcs", "ec2:DescribeVpcPeeringConnections", "ec2:DescribeSubnets", "ec2:DescribeSecurityGroups", "ec2:DescribeInstances", "ec2:DescribeNetworkInterfaces", "ec2:DescribeTags", "ec2:GetCoipPoolUsage", "ec2:DescribeCoipPools", "elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:DescribeLoadBalancerAttributes", "elasticloadbalancing:DescribeListeners", "elasticloadbalancing:DescribeListenerCertificates", "elasticloadbalancing:DescribeSSLPolicies", "elasticloadbalancing:DescribeRules", "elasticloadbalancing:DescribeTargetGroups", "elasticloadbalancing:DescribeTargetGroupAttributes", "elasticloadbalancing:DescribeTargetHealth", "elasticloadbalancing:DescribeTags", "elasticloadbalancing:DescribeTrustStores" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "cognito-idp:DescribeUserPoolClient", "acm:ListCertificates", "acm:DescribeCertificate", "iam:ListServerCertificates", "iam:GetServerCertificate", "waf-regional:GetWebACL", "waf-regional:GetWebACLForResource", "waf-regional:AssociateWebACL", "waf-regional:DisassociateWebACL", "wafv2:GetWebACL", "wafv2:GetWebACLForResource", "wafv2:AssociateWebACL", "wafv2:DisassociateWebACL", "shield:GetSubscriptionState", "shield:DescribeProtection", "shield:CreateProtection", "shield:DeleteProtection" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ec2:AuthorizeSecurityGroupIngress", "ec2:RevokeSecurityGroupIngress" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ec2:CreateSecurityGroup" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ec2:CreateTags" ], "Resource": "arn:aws:ec2:*:*:security-group/*", "Condition": { "StringEquals": { "ec2:CreateAction": "CreateSecurityGroup" }, "Null": { "aws:RequestTag/elbv2.k8s.aws/cluster": "false" } } }, { "Effect": "Allow", "Action": [ "ec2:CreateTags", "ec2:DeleteTags" ], "Resource": "arn:aws:ec2:*:*:security-group/*", "Condition": { "Null": { "aws:RequestTag/elbv2.k8s.aws/cluster": "true", "aws:ResourceTag/elbv2.k8s.aws/cluster": "false" } } }, { "Effect": "Allow", "Action": [ "ec2:AuthorizeSecurityGroupIngress", "ec2:RevokeSecurityGroupIngress", "ec2:DeleteSecurityGroup" ], "Resource": "*", "Condition": { "Null": { "aws:ResourceTag/elbv2.k8s.aws/cluster": "false" } } }, { "Effect": "Allow", "Action": [ "elasticloadbalancing:CreateLoadBalancer", "elasticloadbalancing:CreateTargetGroup" ], "Resource": "*", "Condition": { "Null": { "aws:RequestTag/elbv2.k8s.aws/cluster": "false" } } }, { "Effect": "Allow", "Action": [ "elasticloadbalancing:CreateListener", "elasticloadbalancing:DeleteListener", "elasticloadbalancing:CreateRule", "elasticloadbalancing:DeleteRule" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "elasticloadbalancing:AddTags", "elasticloadbalancing:RemoveTags" ], "Resource": [ "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*", "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*", "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*" ], "Condition": { "Null": { "aws:RequestTag/elbv2.k8s.aws/cluster": "true", "aws:ResourceTag/elbv2.k8s.aws/cluster": "false" } } }, { "Effect": "Allow", "Action": [ "elasticloadbalancing:AddTags", "elasticloadbalancing:RemoveTags" ], "Resource": [ "arn:aws:elasticloadbalancing:*:*:listener/net/*/*/*", "arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*", "arn:aws:elasticloadbalancing:*:*:listener-rule/net/*/*/*", "arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*" ] }, { "Effect": "Allow", "Action": [ "elasticloadbalancing:ModifyLoadBalancerAttributes", "elasticloadbalancing:SetIpAddressType", "elasticloadbalancing:SetSecurityGroups", "elasticloadbalancing:SetSubnets", "elasticloadbalancing:DeleteLoadBalancer", "elasticloadbalancing:ModifyTargetGroup", "elasticloadbalancing:ModifyTargetGroupAttributes", "elasticloadbalancing:DeleteTargetGroup" ], "Resource": "*", "Condition": { "Null": { "aws:ResourceTag/elbv2.k8s.aws/cluster": "false" } } }, { "Effect": "Allow", "Action": [ "elasticloadbalancing:AddTags" ], "Resource": [ "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*", "arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*", "arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*" ], "Condition": { "StringEquals": { "elasticloadbalancing:CreateAction": [ "CreateTargetGroup", "CreateLoadBalancer" ] }, "Null": { "aws:RequestTag/elbv2.k8s.aws/cluster": "false" } } }, { "Effect": "Allow", "Action": [ "elasticloadbalancing:RegisterTargets", "elasticloadbalancing:DeregisterTargets" ], "Resource": "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*" }, { "Effect": "Allow", "Action": [ "elasticloadbalancing:SetWebAcl", "elasticloadbalancing:ModifyListener", "elasticloadbalancing:AddListenerCertificates", "elasticloadbalancing:RemoveListenerCertificates", "elasticloadbalancing:ModifyRule" ], "Resource": "*" } ] }
  1. IAM 정책 생성
      • AWS CLI를 사용하여 IAM 정책을 생성합니다.
      • 명령어 예시:
        • aws iam create-policy \ --policy-name AWSLoadBalancerControllerIAMPolicy \ --policy-document file://iam_policy_latest.json
      • 생성된 IAM 정책의 ARN을 기록해 둡니다. 이 ARN은 이후 단계에서 사용됩니다.
        • arn:aws:iam::{id}:policy/AWSLoadBalancerControllerIAMPolicy
 

2. IAM 역할 및 서비스 계정 생성

  1. eksctl 명령어로 IAM 역할 및 서비스 계정 생성
      • eksctl을 사용하여 IAM 역할과 Kubernetes 서비스 계정을 생성하고 연결합니다.
      • 명령어 예시:
        • eksctl create iamserviceaccount \ --cluster=eksdemo \ --namespace=kube-system \ --name=aws-load-balancer-controller \ --attach-policy-arn=arn:aws:iam::arn \ --override-existing-serviceaccounts \ --approve
      • <region>은 AWS 리전을, <cluster-name>은 EKS 클러스터 이름을, <policy-arn>은 생성한 IAM 정책의 ARN을 입력합니다.
  1. 서비스 계정 확인
      • 명령어 예시:
        • eksctl get iamserviceaccount --cluster eksdemo
      • AWS load balancer controller라는 이름의 서비스 계정이 생성되었는지 확인합니다.
      • iam 역할의 ARN을 Kubernetes 서비스 계정에 추가합니다.
  1. 클라우드 포메이션 스택 확인
      • eksctl 명령어는 클라우드 포메이션 스택을 생성하여 IAM 역할과 서비스를 설정합니다. 이 스택의 상태를 확인하여 작업이 완료되었는지 검토합니다.
 

AWS LoadBalancer Controller Install & Helm

 

1. Helm 설치

  1. Helm 설치 방법
      • macOS: brew install helm 명령어를 사용하여 설치합니다.
        • brew install helm helm version
      • Windows: Chocolatey를 사용하여 choco install kubernetes-helm 명령어로 설치합니다.
        • choco install kubernetes-helm
      • Linux: Helm 바이너리를 다운로드하고, 설치 스크립트(gethelm.sh)를 사용하여 설치합니다.
  1. Helm 설치 확인
      • Helm이 설치된 후, helm version 명령어를 사용하여 설치된 버전을 확인합니다.
      • 예시: Helm v3.8.0 설치 확인.

2. AWS 로드 밸런서 컨트롤러 설치 전 준비

  1. 중요 사항
      • EC2 노드 IMDS 제한 또는 Fargate 사용 시:
        • Helm 설치 명령어에 리전 코드VPC ID를 명시해야 합니다.
      • U.S. West 2 외의 리전에서 배포 시:
        • ECR 이미지 저장소를 해당 리전의 엔드포인트로 설정해야 합니다.
  1. Helm 차트 저장소 추가
      • helm repo add eks https://aws.github.io/eks-charts 명령어를 사용하여 EKS 차트 저장소를 추가합니다.
        • // 설치되지 않은 경우 "eks" has been added to your repositories // 설치된 경우 "eks" already exists with the same configuration, skipping
      • helm repo update 명령어로 저장소를 업데이트하여 최신 버전으로 동기화합니다.
        • helm repo update Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "eks" chart repository Update Complete. ⎈Happy Helming!⎈

3. AWS 로드 밸런서 컨트롤러 설치

  1. 설치 명령어 구성
      • AWS-load-balancer-controller 패키지를 설치하며, 주요 설정은 다음과 같습니다:
        • Namespace: kube-system
        • 클러스터 이름: 예시에서는 EKS-demo-one
        • 서비스 계정: 이미 생성된 aws-load-balancer-controller 계정을 사용
        • 리전 코드: us-east-1
        • VPC ID: AWS EKS VPC ID
  1. 설치 명령어 실행
      • Helm 설치 명령어를 복사하여 실행합니다.
      • 명령어가 성공적으로 실행되면, AWS 로드 밸런서 컨트롤러가 설치됩니다.
      helm install aws-load-balancer-controller eks/aws-load-balancer-controller \ -n kube-system \ --set clusterName=eksdemo \ --set serviceAccount.create=false \ --set serviceAccount.name=aws-load-balancer-controller \ --set region=ap-northeast-2 \ --set vpcId=vpc-0acc1c37d73dd23ab \ --set image.repository=602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon/aws-load-balancer-controller NAME: aws-load-balancer-controller LAST DEPLOYED: Mon Aug 19 22:59:16 2024 NAMESPACE: kube-system STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: AWS Load Balancer controller installed!
 

Load Balancer Controller & Webhook Service

 

1. AWS 로드 밸런서 컨트롤러 설치 확인

  1. 배포 상세 정보 확인:
    1. kubectl -n kube-system get deployment aws-load-balancer-controller kubectl -n kube-system describe deployment aws-load-balancer-controller
      • 배포의 이름을 사용하여 자세한 정보를 확인합니다.
      • 여기에는 설치된 컨트롤러의 버전, Helm 차트 버전, 선택자 레이블, 사용된 포트, 서비스 계정, TLS 인증서 등의 정보가 포함됩니다.
        • Labels를 통해 다음의 정보를 얻을 수 있습니다.
          • app.kubernetes.io/instance=aws-load-balancer-controller app.kubernetes.io/managed-by=Helm app.kubernetes.io/name=aws-load-balancer-controller app.kubernetes.io/version=v2.8.2 // load balancer controlelr version helm.sh/chart=aws-load-balancer-controller-1.8.2 // helm chart version
        • Selector 를 통해 다음의 정보를 얻을 수 있습니다.
          • app.kubernetes.io/instance=aws-load-balancer-controller, app.kubernetes.io/name=aws-load-balancer-controller
        • StrategtyType 또한 확인할 수 있습니다.
          • StrategyType: RollingUpdate RollingUpdateStrategy: 25% max unavailable, 25% max surge
        • Containers의 Argument를 통해 다음을 확인할 수 있습니다.
          • Args: --cluster-name=eksdemo --ingress-class=alb --aws-region=ap-northeast-2 --aws-vpc-id=
        • Container를 보면 Port가
          • Ports: 9443/TCP, 8080/TCP
            인데 일반적으로 9443은 TLS/SSL 트래픽을 처리하는데 사용된다. 그리고 아래쪽으로 좀 더 내려보면
            Volumes: cert: Type: Secret (a volume populated by a Secret) SecretName: aws-load-balancer-tls Optional: false
            이런 정보가 있는데 이는 로드밸런서 컨트롤러가 9443 포트에 수신 대기하면서 TLS (SSL) 통신을 처리하고, 이 때문에 TLS 인증서가 필요하며 해당 인증서는 Secret으로 관리되다가 Volumes으로 마운드되어 Ingress Controller가 사용할 수 있게 된다는 것을 의미합니다.
           

2. 웹후크 서비스 확인

  1. 서비스 상태 확인:
    1. kubectl -n kube-system get svc aws-load-balancer-webhook-service ClusterIP 웹훅 클러스터 아이피 <none> 443/TCP 23m kube-dns ClusterIP 디엔에스 아이피 <none> 53/UDP,53/TCP,9153/TCP 29h
      • kube-system 네임스페이스에서 실행되는 모든 서비스를 나열합니다.
      • AWS 로드 밸런서 웹후크 서비스가 포트 443에서 수신 대기하고 있는지 확인할 수 있습니다.
  1. 서비스와 배포의 선택자 레이블 확인:
    1. kubectl -n kube-system get svc aws-load-balancer-webhook-service -o yaml // 서비스 선택자 확인 kubectl -n kube-system get deployment aws-load-balancer-controller -o yaml // 배포 선택자 확인
      webhook service
      apiVersion: v1 kind: Service metadata: annotations: meta.helm.sh/release-name: aws-load-balancer-controller meta.helm.sh/release-namespace: kube-system creationTimestamp: "2024-08-19T13:59:17Z" labels: app.kubernetes.io/component: webhook app.kubernetes.io/instance: aws-load-balancer-controller app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: aws-load-balancer-controller app.kubernetes.io/version: v2.8.2 helm.sh/chart: aws-load-balancer-controller-1.8.2 prometheus.io/service-monitor: "false" name: aws-load-balancer-webhook-service namespace: kube-system resourceVersion: "283699" uid: uid spec: clusterIP: ip clusterIPs: - ips internalTrafficPolicy: Cluster ipFamilies: - IPv4 ipFamilyPolicy: SingleStack ports: - name: webhook-server port: 443 protocol: TCP targetPort: webhook-server selector: app.kubernetes.io/instance: aws-load-balancer-controller app.kubernetes.io/name: aws-load-balancer-controller sessionAffinity: None type: ClusterIP status: loadBalancer: {}
      load balancer controller
      apiVersion: apps/v1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "1" meta.helm.sh/release-name: aws-load-balancer-controller meta.helm.sh/release-namespace: kube-system creationTimestamp: "2024-08-19T13:59:17Z" generation: 1 labels: app.kubernetes.io/instance: aws-load-balancer-controller app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: aws-load-balancer-controller app.kubernetes.io/version: v2.8.2 helm.sh/chart: aws-load-balancer-controller-1.8.2 name: aws-load-balancer-controller namespace: kube-system resourceVersion: "283814" uid: uid spec: progressDeadlineSeconds: 600 replicas: 2 revisionHistoryLimit: 10 selector: matchLabels: app.kubernetes.io/instance: aws-load-balancer-controller app.kubernetes.io/name: aws-load-balancer-controller strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: annotations: prometheus.io/port: "8080" prometheus.io/scrape: "true" creationTimestamp: null labels: app.kubernetes.io/instance: aws-load-balancer-controller app.kubernetes.io/name: aws-load-balancer-controller spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchExpressions: - key: app.kubernetes.io/name operator: In values: - aws-load-balancer-controller topologyKey: kubernetes.io/hostname weight: 100 containers: - args: - --cluster-name= - --ingress-class=alb - --aws-region= - --aws-vpc-id= image: 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon/aws-load-balancer-controller:v2.8.2 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold: 2 httpGet: path: /healthz port: 61779 scheme: HTTP initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 name: aws-load-balancer-controller ports: - containerPort: 9443 name: webhook-server protocol: TCP - containerPort: 8080 name: metrics-server protocol: TCP readinessProbe: failureThreshold: 2 httpGet: path: /readyz port: 61779 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 10 resources: {} securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true runAsNonRoot: true terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /tmp/k8s-webhook-server/serving-certs name: cert readOnly: true dnsPolicy: ClusterFirst priorityClassName: system-cluster-critical restartPolicy: Always schedulerName: default-scheduler securityContext: fsGroup: 65534 serviceAccount: aws-load-balancer-controller serviceAccountName: aws-load-balancer-controller terminationGracePeriodSeconds: 10 volumes: - name: cert secret: defaultMode: 420 secretName: aws-load-balancer-tls status: availableReplicas: 2 conditions: - lastTransitionTime: "2024-08-19T13:59:38Z" lastUpdateTime: "2024-08-19T13:59:38Z" message: Deployment has minimum availability. reason: MinimumReplicasAvailable status: "True" type: Available - lastTransitionTime: "2024-08-19T13:59:17Z" lastUpdateTime: "2024-08-19T13:59:38Z" message: ReplicaSet "aws-load-balancer-controller-567f5dff44" has successfully progressed. reason: NewReplicaSetAvailable status: "True" type: Progressing observedGeneration: 1 readyReplicas: 2 replicas: 2 updatedReplicas: 2
      • 예시: 서비스 Selector Lables가 app.kubernetes.io/instanceapp.kubernetes.io/name이고, Deployment과 Selector Lable과 일치해야 합니다.
 
정리하자면 이렇다.
 
서비스 셀렉터와 레이블 셀렉터의 일치
 
  • 서비스 셀렉터: Kubernetes 서비스는 특정 파드로 트래픽을 라우팅하기 위해 레이블 셀렉터를 사용합니다. 이 레이블 셀렉터는 서비스와 연결된 포드의 레이블과 일치해야 합니다.
    • 여기서 사용할 서비스는 aws-load-balancer-webhook-service을 의미한다.
    • 즉, 웹훅 서비스는 특정 파드로 트래픽을 라우팅하기 위해 Lable Selector를 사용하늗네 이 레이블 셀렉터는 연결된 파드의 레이블과 일치해야 하고 여기서 파드는 Kubernetes Controller를 의미한다.
      • aws-load-balancer-controller-567f5dff44-frz9f 1/1 Running 0 34m aws-load-balancer-controller-567f5dff44-gp6t5 1/1 Running 0 34m
 
트래픽 포트 매핑
  • 443 포트: 일반적으로 HTTPS 트래픽이 들어오는 포트입니다.
  • 9443 포트: 설명에 따르면, AWS Load Balancer Controller는 이 포트에서 TLS를 통해 통신합니다. 따라서 포트 443에서 들어오는 트래픽은 컨트롤러의 포트 9443으로 전달되어야 합니다.
웹후크 서비스와 컨트롤러 포트 확인
  • 웹후크 서비스: 포트 443에서 수신 대기하고 있으며, AWS Load Balancer Controller가 이 포트에서 요청을 받는 웹후크 서비스와 상호작용합니다.
  • 컨트롤러 포트: AWS Load Balancer Controller의 포트 9443은 이 웹후크 서비스와 상호작용하는 데 사용됩니다. 즉, 포트 9443이 웹후크 서비스와의 연결을 위해 설정된 것입니다.
 

1. 로드 밸런서 컨트롤러 로그 확인

  1. 파드 나열:
    1. kubectl get pods -n kube-system aws-load-balancer-controller-567f5dff44-frz9f 1/1 Running 0 41m aws-load-balancer-controller-567f5dff44-gp6t5 1/1 Running 0 41m aws-node-tkg7k 2/2 Running 0 29h aws-node-zkbdc 2/2 Running 0 29h coredns-5b9dfbf96-mwmng 1/1 Running 0 29h coredns-5b9dfbf96-z8pml 1/1 Running 0 29h kube-proxy-2464v 1/1 Running 0 29h kube-proxy-xbm4n 1/1 Running 0 29h
      • 이 명령어를 사용하여 kube-system 네임스페이스에서 실행 중인 모든 파드를 나열합니다.
      • AWS 로드 밸런서 컨트롤러와 관련된 두 개의 파드를 확인할 수 있습니다.
  1. 파드 로그 확인:
    1. kubectl -n kube-system logs -f <POD-NAME> kubectl -n kube-system logs -f aws-load-balancer-controller-567f5dff44-gp6t5 {"level":"info","ts":"2024-08-19T13:59:20Z","msg":"version","GitVersion":"v2.8.2","GitCommit":"f39ae43121c3f4de0129dda483c10b17a687491d","BuildDate":"2024-08-09T20:18:06+0000"} {"level":"info","ts":"2024-08-19T13:59:20Z","logger":"setup","msg":"adding health check for controller"} {"level":"info","ts":"2024-08-19T13:59:20Z","logger":"setup","msg":"adding readiness check for webhook"} {"level":"info","ts":"2024-08-19T13:59:20Z","logger":"controller-runtime.webhook","msg":"Registering webhook","path":"/mutate-v1-pod"} {"level":"info","ts":"2024-08-19T13:59:20Z","logger":"controller-runtime.webhook","msg":"Registering webhook","path":"/mutate-v1-service"} {"level":"info","ts":"2024-08-19T13:59:20Z","logger":"controller-runtime.webhook","msg":"Registering webhook","path":"/validate-elbv2-k8s-aws-v1beta1-ingressclassparams"}
      • 각 파드의 로그를 실시간으로 확인할 수 있습니다.
      • 로그에 정보만 표시되는 경우, 문제가 없음을 의미합니다. 오류가 있을 경우, 로그에서 문제를 찾아볼 수 있습니다.

2. 서비스 계정 및 비밀 검토

  1. 서비스 계정 정보 확인:
    1. kubectl -n kube-system get sa aws-load-balancer-controller ------------------------ kubectl -n kube-system get sa aws-load-balancer-controller -o yaml apiVersion: v1 kind: ServiceAccount metadata: annotations: eks.amazonaws.com/role-arn: service account arn creationTimestamp: "2024-08-18T16:34:58Z" labels: app.kubernetes.io/managed-by: eksctl name: aws-load-balancer-controller namespace: kube-system resourceVersion: "76198" uid: uid ------------------------- kubectl -n kube-system get secret aws-load-balancer-tls kubernetes.io/tls 3 45m sh.helm.release.v1.aws-load-balancer-controller.v1 helm.sh/release.v1 1 45m -------------------------- kubectl -n kube-system get secret <GET_FROM_PREVIOUS_COMMAND - secrets.name> -o yaml
      • 서비스 계정의 상세 정보를 YAML 형식으로 확인합니다.
      • 여기에는 서비스 계정 이름, 네임스페이스, 주석으로 IAM 역할 등이 포함되어 있습니다.
       
      원래는 kubectl -n kube-system get sa aws-load-balancer-controller -o yaml 를 통해 secret을 확인할 수 있어야 하지만, 내 경우엔 확인할 수 없었습니다. 왜일까요?
       
      K8s 1.24 이후에는 Service Account 으로 Secret을 만드는 것이 기본 설정이 아닙니다. 강의에서는 Secret을 확인하여 만들고 있지만 최신버전(나의 경우 1.3) SA 생성 시 기본적으로 Secret 생성을 지원하지 않아 표시되지 않습니다.
       
      aws eks describe-cluster --name eksdemo --query "cluster.version" --output text // 1.30
       
      Kubernetes 1.24 이후 버전에서는 Secret을 수동으로 생성 해야 합니다 . 필드 token의 키 data는 자동으로 설정됩니다.
      apiVersion: v1 kind: Secret metadata: name: sa1-token annotations: kubernetes.io/service-account.name: sa1 type: kubernetes.io/service-account-token
      필요한 경우 비밀을 명시적으로 만드는 것이 모든 버전에서 권장되는 접근 방식입니다.
       
  1. 비밀 확인:
    1. kubectl -n kube-system get pods kubectl -n kube-system get pod <AWS-Load-Balancer-Controller-POD-NAME> -o yaml kubectl -n kube-system get deploy aws-load-balancer-controller -o yaml
      • 비밀의 YAML 형식을 확인하여 CA 인증서 및 토큰 정보를 포함한 내용을 검토합니다.
      • 물론 1.24 이후 버전에서는 확인할 수 없지만 이 CA 인증서 및 JWT 토큰은 매우 중요한데 그 이유는
        • 로드 밸런서 컨트롤러가 AWS Application Load Balancer를 생성할 때
        • Ingress manifests가 배포되면
        • k8s API 서버가 정보를 받고
        • 로드 밸런서 컨트롤러가 Ingress 이벤트를 감시하여
        • AWS Load Balancer를 생성하게 되는데
        • 이 때 EKS Cluster와 AWS Service 간의 인증 메커니즘이 필요하기 때문이며 이 때 사용하는 메커니즘이 JWT 토큰입니다.
        • 좀 더 자세하게 설명하면,
          • 기본적으로 IAM은 AWS Service에 접근할 수 있도록 하는 서비스 입니다.
          • EKS는 IAM에서 관리하는 인증과 권한 시스템을 통해 AWS 서비스에 접근할 수 있습니다.
          • 이를 통해 EKS는 AWS Service와 상호작용할 수 있는데, Cluster 내의 SA(Service Account)는 Container와 Application이 Cluster 내부에서 AWS Service와 통신할 때 사용되는 증명입니다.
          • 이 때 이 서비스 계정인 SA는 EKS 클러스터 내에서 토큰을 사용하여 AWS Service와 인증을 수행하게 되기 때문에 중요하다고 볼수 있습니다.
      • kubectl -n kube-system get pod <load balancer controller> -o yaml 를 통해 아래 정보를 확인할 수 있는데
        • env: - name: AWS_STS_REGIONAL_ENDPOINTS value: regional - name: AWS_DEFAULT_REGION value: ap-northeast-2 - name: AWS_REGION value: ap-northeast-2 - name: AWS_ROLE_ARN value: arn - name: AWS_WEB_IDENTITY_TOKEN_FILE value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token volumeMounts: - mountPath: /tmp/k8s-webhook-server/serving-certs name: cert readOnly: true - mountPath: /var/run/secrets/kubernetes.io/serviceaccount name: kube-api-access-fkxb2 readOnly: true - mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount name: aws-iam-token readOnly: true
          여기서 aws-iam-token를 통해 EC2 인스턴스의 값과 비밀 경로를 확인할 수 있습니다.
           
  1. 토큰 디코딩:
      • 비밀의 JWT 토큰을 디코딩하여 서비스 계정, 네임스페이스, 메타데이터 등의 정보를 확인합니다.
      • JWT 디코더를 사용하여 디코딩된 토큰을 검토하면, EKS 클러스터와 AWS 서비스 간의 인증 메커니즘을 이해하는 데 도움이 됩니다.

3. 로드 밸런서 컨트롤러 제거 (선택 사항)

  1. 로드 밸런서 컨트롤러 제거:
      • 명령어: kubectl delete -n kube-system deploy <로드 밸런서 컨트롤러 이름>
      • AWS 로드 밸런서 컨트롤러를 클러스터에서 제거하는 명령어입니다.
      • 이 단계는 필요하지 않다면 건너뛰어도 됩니다.
      helm uninstall aws-load-balancer-controller -n kube-system
 

Ingress Class

 

인그레스 클래스(IngressClass) 개념

문제 시나리오

  • Kubernetes 클러스터에서는 다양한 인그레스 컨트롤러가 동시에 운영될 수 있습니다. 예를 들어, EKS에서는 AWS ALB(Application Load Balancer) 인그레스 컨트롤러와 NGINX 인그레스 컨트롤러가 함께 사용될 수 있으며, AKS에서는 Azure Application Gateway 인그레스 컨트롤러가 사용될 수 있습니다.
  • 이와 같은 멀티 컨트롤러 환경에서는 특정 인그레스 리소스가 어떤 인그레스 컨트롤러에 의해 관리될지를 명확히 정의해야 합니다.

인그레스 클래스(IngressClass)

  • 정의: 인그레스 클래스는 Kubernetes 인그레스 리소스가 특정 인그레스 컨트롤러에 의해 처리되도록 매핑하는 Kubernetes 리소스입니다.
  • 목표: 여러 인그레스 컨트롤러가 존재하는 클러스터에서 인그레스 리소스와 컨트롤러 간의 명확한 연결을 설정합니다.

인그레스 클래스 리소스의 구성

  • API 버전: networking.k8s.io/v1
  • kind: IngressClass
  • metadata: 인그레스 클래스의 메타데이터를 정의하며, 주요 항목으로는 이름과 주석이 있습니다.
    • 예: name: my-aws-ingress-class
  • spec: 인그레스 클래스의 동작을 정의합니다.
    • controller: 인그레스 클래스가 연결될 인그레스 컨트롤러를 지정합니다. 예: ingress.k8s.aws/alb는 AWS ALB 인그레스 컨트롤러를 의미합니다.

기본 인그레스 클래스 설정

  • 주석: ingressclass.kubernetes.io/is-default-class를 통해 인그레스 클래스를 기본 클래스로 지정할 수 있습니다.
    • *true*로 설정된 경우, 해당 인그레스 클래스가 클러스터의 기본 인그레스 클래스로 간주됩니다. 이 경우, 인그레스 리소스가 별도로 인그레스 클래스를 지정하지 않더라도 자동으로 이 클래스를 사용합니다.
    • 기본 클래스로 설정되지 않은 경우, 인그레스 리소스의 spec.ingressClassName 필드를 사용하여 명시적으로 인그레스 클래스를 지정해야 합니다.

인그레스 리소스(Ingress Resource)

  • API 버전: networking.k8s.io/v1
  • kind: Ingress
  • metadata: 인그레스 리소스의 식별 정보와 메타데이터를 정의합니다.
    • 예: name: ingress-nginx-app
  • spec: 인그레스 리소스가 관리할 백엔드 서비스 및 트래픽 라우팅 규칙을 정의합니다.
    • defaultBackend: 기본 백엔드 서비스를 지정하며, 트래픽이 이 서비스로 전달됩니다.
    • rules: 호스트 및 경로에 기반하여 트래픽을 다양한 백엔드 서비스로 라우팅합니다.

인그레스 클래스와 인그레스 리소스 간의 연결

  • 명시적 연결: 인그레스 리소스의 spec.ingressClassName 필드를 통해 특정 인그레스 클래스를 지정하여 인그레스 컨트롤러와 연결할 수 있습니다.
  • 기본 클래스 사용: 기본 인그레스 클래스를 설정한 경우, spec.ingressClassName을 생략할 수 있으며, 클러스터에서 기본으로 정의된 인그레스 클래스가 자동으로 적용됩니다.
Share article
RSSPowered by inblog