티스토리 뷰

권한과 클러스터 내부 구성 요소를 갖췄으니 다음해야할 것은 외부 인터넷 망과의 연결이다.

 

우선, 안정적으로 트래픽을 받기 위해서는 로드밸런싱이 필수다. 

 

AWS에서는 AWS 로드밸런서 컨트롤러를 통해 ALB(Application Load Balancer)를 프로비저닝하고,

 

이를 EKS 클러스터 내부의 Ingress 리소스와 연결하여 로드밸런싱 기능을 지원한다.

 

이를 통해 외부 트래픽이 ALB를 통해 EKS 클러스터 내의 서비스로 효율적으로 라우팅되고 분산된다.

 

AWS 로드밸런서 컨트롤러란?

AWS Load Balancer Controller는 Kubernetes 클러스터의 AWS Elastic Load Balancer를 관리합니다. 컨트롤러를 사용하여 클러스터 앱을 인터넷에 노출할 수 있습니다. 컨트롤러는 클러스터 Service 또는 Ingress 리소스를 가리키는 AWS 로드 밸런서를 프로비저닝합니다. 다시 말해 컨트롤러는 클러스터의 여러 포드를 가리키는 단일 IP 주소 또는 DNS 이름을 생성합니다. 컨트롤러는 Kubernetes Ingress 또는 Service 리소스를 감시합니다. 이에 대한 응답으로 해당 AWS Elastic Load Balancing 리소스를 생성합니다. Kubernetes 리소스에 주석을 적용하여 로드 밸런서의 특정 동작을 구성할 수 있습니다.
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/aws-load-balancer-controller.html

 

서두에 AWS 로드밸런서 컨트롤러의 역할을 정리해뒀다.

 

아래 그림은 AWS 로드밸런서 컨트롤러의 동작 방식을 정리한 그림이다.

 

 

Terraform 코드

AWS 로드밸런서 컨트롤러는 EKS 내부의 리소스로 헬름 차트를 통해서 배포된다.

 

그전에 쿠버네티스 내에서 AWS 리소스에 접근하는 것이기 때문에 IRSA를 지정해줘야한다.

 

Variables

자주 쓰이는 값들을 변수 지정, 헬름차트를 이용해 배포한다.

variable "alb_chart" {
  type        = map(string)
  description = "AWS Load Balancer Controller chart"
  default = {
    name       = "aws-load-balancer-controller"
    namespace  = "kube-system"
    repository = "https://aws.github.io/eks-charts"
    chart      = "aws-load-balancer-controller"
    version    = "1.5.5"
  }
}

 

ALB Controller IRSA

locals {
  alb_name = "${local.cluster_name}-alb"
}

module "alb_controller_irsa" {
  source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"

  role_name = "${local.cluster_name}-${var.aws_lb_chart.name}"

  attach_load_balancer_controller_policy = true

  oidc_providers = {
    one = {
      provider_arn               = local.oidc_provider_arn
      namespace_service_accounts = ["kube-system:${var.aws_lb_chart.name}"]
    }
  }
}

iam-role-for-service-accounts-eks 모듈로 attach_load_balancer_controller_policy 옵션을 true로 주면 필요한 iam 역할들을 알아서 지정해준다.

 

oidc provider는 따로 가져와줘야함

 

ALB Controller SA

resource "kubernetes_service_account" "alb_controller" {
  metadata {
    name      = var.alb_chart.name
    namespace = var.alb_chart.namespace

    annotations = {
      "eks.amazonaws.com/role-arn" = module.aws_load_balancer_controller_irsa.iam_role_arn
    }
  }
}

alb에게 할당할 service account.

 

어노테이션에 위에서 만들었던 irsa를 전달한다.

 

Ingress

쿠버네티스 Ingress의 역할을 잠깐 정리하고 가면,

 

Ingress는 들어온 요청이 어떤 서비스(쿠버네티스 리소스인 서비스를 지칭)로 라우팅이 되야하는지 작성되어 있는 명세다.

 

Ingress가 원하는 서비스로 라우팅되고, 로드밸런싱 기능까지 지원하려면 인그레스 컨트롤러(Ingress Controller)가 필요하다.

 

아래 그림이 Ingerss와 Ingress Controller에 대해 잘 설명하고 있다.

 

출처 : https://kubetm.github.io/k8s/08-intermediate-controller/ingress/

 

Ingress Controller는 클라우드 벤더마다 다르게 작성된다. 예를들어 구글은 GKE 인그레스라고 부른다.

 

예전에는 AWS도 AWS ALB Ingress Controller라는 이름이었다.

 

최근에 AWS Load Balancer Controller로 브랜드가 변경되었다고 한다.

resource "kubernetes_ingress_v1" "alb" {
  metadata {
    name = "alb"
    annotations = {
      "alb.ingress.kubernetes.io/load-balancer-name" = "${local.alb_name}"
      "alb.ingress.kubernetes.io/scheme"      = "internet-facing",
      "alb.ingress.kubernetes.io/target-type" = "ip"
    }
  }
  spec {
    ingress_class_name = "alb"
    rule {
      http {
        path {
          backend {
            service {
              name = "echo"
              port {
                number = 8080
              }
            }
          }
          path = "/*"
        }
      }
    }
  }
}

특별한 동작은 없고, 모든 요청이 echo라는 이름의 서비스의 8080포트로 전달되도록 했다.

 

AWS Load Balancer Controller helm chart

resource "helm_release" "alb_controller" {
  namespace  = var.alb_chart.namespace
  repository = var.alb_chart.repository
  name    = var.alb_chart.name
  chart   = var.alb_chart.chart
  version = var.alb_chart.version
  
  set {
    name  = "clusterName"
    value = local.cluster_name
  }
  set {
    name  = "serviceAccount.create"
    value = "false"
  }
  set {
    name  = "serviceAccount.name"
    value = kubernetes_service_account.aws_load_balancer_controller.metadata.0.name
  }
  set {
    name  = "region"
    value = data.aws_region.current.name
  }
  set {
    name  = "vpcId"
    value = data.terraform_remote_state.vpc.outputs.ps_vpc.vpc_id
  }
  depends_on = [kubernetes_service_account.aws_load_balancer_controller]
}

아래의 명령어로 조회했을 때, 잘 나오면 헬름차트 배포가 정상적으로 진행된 것이다.

> kubectl get pod -n kube-system
NAME                                            READY   STATUS    RESTARTS   AGE
aws-load-balancer-controller-7b464f85bc-gdczd   1/1     Running   0          4h50m
aws-load-balancer-controller-7b464f85bc-zjmh7   1/1     Running   0          3h21m

로드밸런서도 생성이되니까 콘솔에서 확인하는게 좋다.

 

만약 잘못 작성된 부분이 있으면 로드밸런서가 생성되지 않으니 참고.

 

서비스와 디플로이먼트

echo라는 이름을 갖는 서비스와 디플로이먼트를 만들었다.

resource "kubernetes_service" "echo" {
  metadata {
    name = "echo"
  }
  spec {
    selector = {
      "app.kubernetes.io/name" = "echo"
    }
    port {
      port        = 8080
      target_port = 8080
    }
    type = "NodePort"
  }
}

resource "kubernetes_deployment" "echo" {
  metadata {
    name = "echo"
  }
  spec {
    replicas = 1
    selector {
      match_labels = {
        "app.kubernetes.io/name" = "echo"
      }
    }
    template {
      metadata {
        labels = {
          "app.kubernetes.io/name" = "echo"
        }
      }
      spec {
        container {
          image = "k8s.gcr.io/echoserver:1.10"
          name  = "echo"
        }
      }
    }
  }
}

아래의 요청을 보내보면 잘 동작하는 것을 확인 할 수 있다.

 

도메인 발급을 받지 않은 상태라 로드밸런서로 바로 요청을 보냄

$ curl -k https://testbed-eks-alb-1334220614.ap-northeast-2.elb.amazonaws.com
Hostname: echo-d66985b48-cm47x
Pod Information:
        -no pod information available-
Server values:
        server_version=nginx: 1.13.3 - lua: 10008
Request Information:
        client_address=172.18.3.39
        method=GET
        real path=/
        query=
        request_version=1.1
        request_scheme=http
        request_uri=http://testbed-eks-alb-1334220614.ap-northeast-2.elb.amazonaws.com:8080/
Request Headers:
        accept=*/*
        host=testbed-eks-alb-1334220614.ap-northeast-2.elb.amazonaws.com
        user-agent=curl/7.81.0
        x-amzn-trace-id=Root=1-663b940a-42cb8b293167752c0b869fed
        x-forwarded-for=211.197.35.161
        x-forwarded-port=443
        x-forwarded-proto=https
Request Body:
        -no body in request-

 

마치며

일단 여기까지 큰 줄기가 끝났다.

 

쿠버네티스 클러스터 안에 파드를 하나 배포하고, 로드밸런서를 연결해 외부에서 접근할 수 있게끔 작업했다.

 

보안그룹, IAM, WAF, Cloud Front 등 모든 것들을 IaC로 관리할 수 있지만 가장 큰 줄기부터 짚고 넘어갈 예정이다.

 

이제부터는 쿠버네티스 관리 도구들인 Istio와 ArgoCD가 등장한다.

 

Istio는 어렵게 작업하진 않을 예정이고, ArgoCD로 GitHub를 연동해 배포까지 진행할 예정이다.

 

참고 사이트

https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.8/

https://lordofkangs.tistory.com/566

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함