[AWS EKS] (31) EKS 스터디 12주차 ( EKS 규모에 따른 네트워킹 구조 )
CloudNet@팀의 EKS 스터디 AEWS 2기에 작성된 자료를 토대로 작성합니다.
- Kubernetes의 애플리케이션 네트워킹 변화 과정
- Gateway API의 등장
- Amazon VPC Lattice
한 개의 Kubernetes 클러스터를 사용할 때
- 단일 클러스터 내부에 배포되는 Kubernetes 서비스들은 클러스터 내부의 DNS 인 CoreDNS 및 Ingress 리소스를 통해서 내부 서비스 간 통신 및 외부로의 통신을 모두 네이티브하게 구현할 수 있음.
- 사용되는 방법들
- 기본 Service 리소스로 시작
- NodePort, ClusterIP, LoadBalancer 타입의 서비스 구현
- Ingress 활용
- 경로 기반 라우팅으로 서비스 구조화 및 관리 개선
- SSL/TLS 종단점 제공을 통한 보안 강화
- 단순한 내부 통신과 외부 노출 기능에 중점
여러 개의 Kubernetes 클러스터를 사용할 때
- 애플리케이션이 진화하고, 조직이 발전하면서 서비스들이 독자적인 VPC 및 Kubernetes 클러스터에 운영되기 시작하면서 클러스터 운영자들은 이런 VPC 간 / 클러스터 간의 애플리케이션 네트워킹에 대해서 고민하게 됨.
- 애플리케이션 끼리 통신을 하기 위해선 가장 먼저 내가 통신하고 싶은 서비스 혹은 마이크로 서비스가 어디에 있는지를 아는 것이 선행 되어야 함 → Service Discovery
- Service Discovery
- 서비스의 IP 주소 및 포트 정보를 동적으로 관리
- 각 서비스 인스턴스를 지속적으로 Health Check
- 서비스 관련 메타데이터와 구성 정보를 저장하고 관리
Service Discovery 패턴
1. 클라이언트 사이드 : 클라이언트가 직접 서비스 레지스트리를 쿼리하여 서비스 위치를 찾는 방식(예: Netflix Eureka, Spring Cloud)
2.서버 사이드 (로드 밸런서가 서비스 레지스트리를 쿼리하고 클라이언트 요청을 적절한 서비스로 라우팅)
3. 두 개 이상의 여러 VPC 사이에서는?
AWS의 경우에는 VPC Peering, PrivateLink, AWS Transit Gateway 등의 다양한 옵션을 통해 각 VPC를 연결
Service Mesh
마이크로 서비스가 늘어나면서 네트워크 복잡성 증가 및 공통 기능 적용(서킷브레이커, 재시도 로직, 타임아웃, 인증 등)의 요구사항 이 생김 → Service Mesh
Service Mesh
- AWS AppMesh, Istio, Linkerd 등으로 트래픽 관리, 보안, 관찰성 강화
- 마이크로서비스 간 통신의 복잡성 추상화
- 서비스 디스커버리와 로드밸런싱의 고도화 및 자동화 (서비스 메시는 서비스 디스커버리를 기반으로 함)
- 컨테이너 애플리케이션 앞에 AWS AppMesh, Istio, Linkerd 등의 사이드카 프록시 컨테이너를 배치
- 컨테이너 애플리케이션으로 들어오고 나가는 모든 트래픽은 프록시 컨테이너를 통해 라우팅 되는 방식
- 프록시 컨테이너의 역할
- 데이터 영역
- 사이드카가 요청을 가로챔 → 요청을 별도의 네트워크 연결로 캡슐화 → 소스 프록시와 대상 프록시 간에 안전하고 암호화된 채널을 설정
- 서비스 간 로우 레벨 메시징을 처리
- 서킷 브레이킹, 요청 재시도와 같은 기능을 구현하여 복원력을 높이고 서비스 성능 저하를 방지
- 제어 영역
- 메시 내의 모든 서비스를 추적하는 서비스 레지스트리 기능 수행
- 신규 서비스 자동 검색 기능 및 비활성 서비스 제거 기능 수행
- 지표, 로그, 분산 추적 정보와 같은 텔레메트리 데이터의 수집 및 집계
- 데이터 영역
이러한 방식의 애플리케이션 네트워킹의 한계점
Ingress와 Service Discovery, Service Mesh는 Kubernetes에서 트래픽 라우팅을 관리하는 대표적인 방식이었지만, 다음과 같은 한계점을 가지고 있었습니다.
Ingress의 한계
- HTTP, HTTPS와 같은 L7 트래픽에 최적화 되어있어 gRPC 및 TPC, UDP와 같은 비 L7 프로토콜에 대한 라우팅 기능이 제한적이었습니다.
- 고급 기능(인증, 속도 제한 정책, 고급 트래픽 관리 등)을 사용하려면 벤더별(AWS, NGINX, HAProxy 등) 사용자 정의 어노테이션이 필요하여 이식성과 표준화에 한계가 존재했습니다.
Service Mesh의 한계
- 주로 동-서 트래픽(서비스 간 내부 통신)에 초점을 맞추어 설계되어 북-남 트래픽(외부-내부 통신)에 대한 기능이 제한적이였습니다.
- Amazon EKS의 경우, VPC Peering 및 TGW가 필요 → 점점 늘어나는 설정들과 네트워크 리소스들
- 여러 AWS 계정을 사용할 경우, 각각 교차 계정 액세스 설정이 필요 → 권한 관리의 어려움
- 사이드카 프록시 배포가 필수적이며, 멀티 VPC 클라우드 환경에서 네트워크 복잡도가 증가하였습니다. (멀티 클러스터, 멀티 메시의 수많은 프록시 운영 및 관리의 어려움)
또한, 클라우드 환경에서 점차 마이크로 서비스가 확장되고 인프라 구성이 복잡해짐에 따라 아래와 같은 요구사항도 생겨났습니다.
- 다양한 팀 간의 책임 분리(인프라 담당자, 애플리케이션 개발자, DevOps 엔지니어 등)가 필요해졌습니다.
- 여러 VPC 또는 멀티 클러스터 환경에 걸친 리소스들을 일관되게 관리해야 했습니다.
- 다양한 컴퓨팅 형태(인스턴스, 컨테이너, 서버리스 등)를 통합적으로 관리할 수 있는 네트워킹 레이어가 필요했습니다.
Gateway API의 등장
이러한 한계를 극복하기 위해 SIG-NETWORK 커뮤니티에서 Gateway API가 고안되었습니다.
Gateway API는 다음과 같은 목표를 가지고 설계되었습니다.
- 역할 기반 설계: 인프라 관리자, 클러스터 운영자, 애플리케이션 개발자 각각의 요구사항을 반영할 수 있도록 설계되었습니다.
- 범용성: HTTP, HTTPS, gRPC 등 다양한 프로토콜을 지원하고 확장성 있게 설계되었습니다.
- 표준화: Kubernetes Ingress와 같이 포터블한 표준 API가 되도록 설계되었습니다.
- 확장성: 멀티 클러스터 환경 및 다양한 VPC 간의 원활한 네트워크 통합이 가능하도록 설계되었습니다.
Gateway API의 주요 구성요소
Gateway API는 계층적 구조로 설계되어 인프라 관리자와 애플리케이션 개발자의 역할과 책임을 명확히 구분합니다. 주요 구성 요소는 다음과 같습니다.
- 공통 구성을 가진 게이트웨이 집합을 정의하며, 이 클래스를 구현하는 컨트롤러에 의해 관리됩니다.
- 게이트웨이는 각기 다른 컨트롤러에 의해 다양한 구성으로 구현될 수 있습니다. 게이트웨이는 반드시 해당 클래스를 구현하는 컨트롤러의 이름을 포함하는 GatewayClass를 참조해야 합니다.
- 외부 트래픽을 수신하고 내부 서비스로 라우팅하는 진입점을 정의합니다.
- 하나 이상의 Route 리소스와 연결될 수 있습니다.
- 트래픽을 특정 서비스로 매핑하는 프로토콜 별 규칙을 정의합니다.
- HTTPRoute, TLSRoute, TCPRoute, UDPRoute, GRPCRoute 등이 있습니다.
- Gateway 리소스에 연결되어 트래픽을 대상 서비스로 전달합니다.
이 계층적 구조를 통해 인프라 관리자는 GatewayClass와 Gateway를 관리하며 전체 인프라의 일관성을 유지하고, 애플리케이션 개발자는 다양한 Route를 통해 자신의 애플리케이션에 대한 세부 라우팅 규칙을 독립적으로 정의할 수 있습니다.
AWS는 이러한 계층적 구조를 Amazon VPC Lattice와 통합하여 제공함으로써, 클라우드 네이티브 환경에서의 네트워킹 요구사항을 효과적으로 충족시킵니다.
Amazon VPC Lattice란
Amazon VPC Lattice 는 AWS에서 제공하는 완전관리형 애플리케이션 네트워킹 서비스로, 다양한 컴퓨팅 환경에서 애플리케이션 서비스를 연결, 보호 및 모니터링하는 통합 솔루션입니다. VPC Lattice는 단일 VPC 내에서는 물론, 계정 간 여러 VPC에 걸쳐 서비스를 연결하는 데 활용할 수 있습니다.
현대적 애플리케이션은 마이크로서비스 아키텍처를 통해 여러 개의 소규모 모듈형 서비스로 분할되어 개발되는 추세입니다. 이러한 접근 방식은 개발 속도와 확장성 측면에서 많은 이점을 제공하지만, 다양한 마이크로서비스 간의 효율적인 연결과 관리에 대한 새로운 네트워킹 문제를 야기합니다. Amazon VPC Lattice는 이러한 과제를 해결하기 위해 네트워크 액세스, 트래픽 관리, 모니터링에 대한 일관된 정책을 정의하여 EC2 인스턴스, EKS 컨테이너, Lambda 서버리스 함수 등 다양한 컴퓨팅 서비스 간에 간단하고 표준화된 연결 방식을 제공합니다.
Amazon VPC Lattice 주요 구성 요소
Amazon VPC Lattice는 Service, Service Network, Auth Policy, Service Directory의 네 가지 핵심 구성 요소로 이루어져 있습니다. 각 구성 요소의 특징과 역할을 살펴보겠습니다. 자세한 내용은 이 문서를 참조해주세요.
Service
Service
Service는 특정 작업이나 기능을 수행하는 독립적으로 배포가능한 소프트웨어 단위입니다. 이는 어떤 Amazon Virtual Private Cloud(VPC)나 계정에도 존재할 수 있으며, 다양한 유형의 컴퓨팅 환경(가상머신, 컨테이너, 서버리스 함수)에서 실행할 수 있습니다. 서비스 구성은 다음과 같은 요소로 이루어집니다.
- 리스너 : 리스너에서는 Service가 트래픽을 받아들일 포트와 프로포콜을 정의합니다. 지원되는 프로토콜은 HTTP/1.1, HTTP/2, gRPC이며, TLS가 활성화된 Service의 경우 HTTPS도 포함됩니다.
- 규칙 : 리스너의 기본 구성 요소로, 요청을 대상 그룹의 대상들로 전달합니다. 각 규칙은 우선 순위, 하나 이상의 작업, 그리고 리스너가 클라이언트 요청을 라우팅하는 기준이 되는 하나 이상의 조건으로 구성됩니다.
- 대상 그룹 : 애플리케이션이나 서비스를 실행하는 리소스들의 집합으로, 이를 대상 이라고도 합니다. 대상은 EC2 인스턴스, IP주소, Lambda 함수, 또는 Kubernetes Pod가 될 수 있습니다.
Service는 다음과 같은 특징을 갖습니다.
- 고유한 VPC Lattice 도메인 네임 제공
- 리스너를 통해 들어오는 연결 처리
- 특정 경로나 헤더 값에 기반한 라우팅 규칙 정의
- EC2, ECS, Lambda 등 다양한 AWS 컴퓨팅 서비스를 대상으로 설정 가능
- 상태 확인을 통한 트래픽 안정성 보장
Service Network
Service Network는 VPC Lattice의 핵심 구성 요소로, 여러 서비스를 논리적으로 그룹화하고 이들 간의 통신을 관리합니다. 하나 이상의 VPC를 Service Network에 연결하여 해당 네트워크 내의 서비스 간 통신을 가능하게 합니다.
Service Network의 주요 특징은 다음과 같습니다.
- 여러 VPC와 서비스를 단일 네트워크로 통합
- 계정 간, 리전 간 서비스 연결 지원
- 중앙 집중식 액세스 제어 및 모니터링 제공
- VPC 연결을 통한 Service Network 내 서비스에 대한 접근 관리
Auth Policy
Auth Policy는 VPC Lattice 서비스에 대한 액세스를 제어하는 IAM 기반 정책입니다. 이를 통해 특정 IAM 보안 주체나 역할이 서비스에 접근할 수 있는지 여부를 세밀하게 제어할 수 있습니다.
Auth Policy의 주요 기능은 다음과 같습니다.
- IAM 기반의 세분화된 접근 제어
- 서비스 레벨 또는 서비스 네트워크 레벨에서 적용 가능
- HTTP 메소드, 경로, 헤더 등을 기준으로 조건부 액세스 규칙 설정
- AWS 리소스 간의 안전한 통신 보장
Service Directory
Service Directory는 모든 VPC Lattice 서비스를 중앙에서 검색하고 관리할 수 있는 카탈로그입니다. 개발자와 운영팀이 사용 가능한 서비스를 쉽게 찾고 접근할 수 있도록 지원합니다.
Service Directory의 핵심 기능은 다음과 같습니다.
- 사용 가능한 모든 서비스의 중앙 집중식 카탈로그 제공
- 서비스 메타데이터 및 설명 관리
- 서비스 검색 및 필터링 기능
- 접근 가능한 서비스에 대한 가시성 제공
Amazon VPC Lattice의 장점
- 여러 VPC, EC2 인스턴스, 컨테이너, 서버리스로 구성한 애플리케이션의 네트워크 구성을 중앙 집중화 할 수 있습니다.
- 별도의 사이드카 프록시를 구성할 필요가 없습니다. (+ 완전 관리형 서비스)
- 복잡한 네트워크 구성을 단순화 해서 쉽게 사용할 수 있습니다.
- IAM 및 SigV4를 통해 각 애플리케이션으로의 보안 구성을 손쉽게 적용 할 수 있습니다.
- CloudWatch, S3, Kinesis Data Firehose를 통해 쉽게 로깅, 트래픽 패턴 분석 등을 수행할 수 있습니다.
사용 사례 #1 : 단일 리전의 애플리케이션 간 연결
사용 사례 #2 : 온프레미스에서 AWS에 배포된 애플리케이션으로 접근하는 경우
사용 사례 #3 : 여러 AWS 리전에 걸친 애플리케이션 간의 연결
사용 사례 #4 : 다중 계정 간 애플리케이션의 연결
VPC Lattice Pattern
이 패턴에서는 Terraform을 활용하여 클라이언트 애플리케이션이 한 곳에서 실행되고 서버 애플리케이션이 다른 곳에서 실행되는 두 개의 별개의 VPC를 배포합니다. 서버 애플리케이션은 EKS 클러스터 내에 배포되며 두 애플리케이션 간의 연결을 설정하는 Amazon VPC Lattice를 통해 클라이언트 애플리케이션에 노출됩니다. 또한 Amazon Route53 및 External DNS Add-on을 사용하여 노출된 서비스에 대한 사용자 지정 도메인 이름을 구성하는 방법을 보여줍니다.
- 아래 명령을 통해 실습용 코드를 clone 해주세요. 이 프로젝트의 디렉터리는 실습하기 편한 곳으로 설정해주세요.
git clone https://github.com/aws-ia/terraform-aws-eks-blueprints.git
# 터미널을 통해 terraform-aws-eks-blueprints 프로젝트의
# /patterns/vpc-lattice/client-server-communication 디렉터리로 이동
cd terraform-aws-eks-blueprints/patterns/vpc-lattice/client-server-communication
- main.tf 파일 내의 29번째 라인에서 region 값을 ap-northeast-2로 수정해주세요.
아래 명령을 순차적으로 실행하여 실습 인프라를 프로비저닝 해주세요.
terraform init
1. client vpc
terraform apply -target="module.client_vpc" -auto-approve
2. cluster vpc
terraform apply -target="module.cluster_vpc" -auto-approve
3. route 53
terraform apply -target=aws_route53_zone.primary -auto-approve
terraform apply -target="module.client_sg" -auto-approve
terraform apply -target="module.endpoint_sg" -auto-approve
terraform apply -target="module.client" -auto-approve
terraform apply -target="module.vpc_endpoints" -auto-approve
terraform apply -target="module.eks" -auto-approve
terraform apply -target="module.addons" -auto-approve
# 모든 모듈
# helm install 까지
terraform apply -auto-approve
1. ec2
2. eks
3. nodegroup
client.tf 파일을 살펴보겠습니다.
이 파일에서는 VPC Lattice를 통해 EKS Cluster의 애플리케이션으로 요청을 전달하는 클라이언트 역할을 하는 리소스에 대한 명세가 작성되어 있습니다.
client 모듈에서는 프로비저닝 할 EC2 인스턴스에 대한 명세가 적혀있습니다.
- 인스턴스 유형은 t2.micro 입니다.
- AmazonSSMManagedInstanceCore IAM Role을 설정합니다.
- client_sg 모듈을 참조하여 Security Group을 설정합니다.
이어서 vpc_endpoints 모듈에서는 client에서 Systems Manager를 사용하기 위한 VPC Endpoint를 구성하기 위한 명세가 적혀있습니다.
- VPC Endpoint에서 구성할 서비스는 ssm, ssmmessages, ec2messages 입니다.
- 적용할 서브넷은 client_vpc 모듈을 참조하여 private_subnets을 대상으로 합니다.
- endpoint_sg 모듈을 참조하여 Security Group을 설정합니다.
그 다음으로는 client의 EC2 인스턴스와 VPC Endpoint에서 사용할 각각의 Security Group(모듈 client_sg 및 endpoint_sg)에 대한 명세가 적혀있습니다.
- client_sg 모듈에서는 EC2 인스턴스의 Egress 설정이 명세되어 있습니다.
- endpoint_sg 모듈에서는 client_vpc의 모듈을 참조하여 private_subnets_cidr_blocks 값에 대해 443 포트를 허용하는 Ingress 설정이 명세되어 있습니다.
마지막으로, client_vpc 모듈에서는 이 모든 client를 위한 리소스가 구성될 VPC에 대한 내용이 명세되어 있습니다.
- client vpc에 대한 cidr 값은 main.tf 내에 명세되어있는 client_vpc_cidr 값을 참조합니다.
- 가용영역(azs) 값도 마찬가지로 main.tf 내에 명세되어있는 azs 값을 참조합니다.
- terraform의 cidrsubnet 함수는 주어진 대역 내에서 새 비트 수에 따른 서브네팅을 수행합니다.
VPC Lattice를 통한 Client to Server 통신 테스트
아래 그림과 같이 client라는 이름의 EC2 인스턴스를 선택하고, 상단의 Connect 버튼을 클릭합니다.
Session Manager로 접근합니다.
AWS에서는 Systems Manager Session Manager 라는 기능을 통해 인바운드 포트를 열고 배스천 호스트를 유지 관리하거나
SSH 키를 관리할 필요 없이 IAM 기반으로 EC2 인스턴스에 안전하게 쉘에 접속할 수 있습니다.
- 통신 테스트
client에서 cluster의 server pod로 요청이 잘 수행되는지 명령을 수행해보겠습니다. 이 과정에서 VPC Lattice로 구성된 서비스 네트워크를 사용해보겠습니다.
아래 그림처럼 한 쪽에는 client의 터미널을, 다른 한 쪽에는 kubectl 명령을 수행할 터미널을 준비해주세요.
- curl - 명령어 (client)
- log 확인 (cluster쪽)
kubectl logs -f deployment/server -n apps --all-containers=true --since=1m
Amazon VPC Lattice 확인
Amazon VPC Lattice Serivce 확인
왼쪽 메뉴바에서 PrivateLink and Lattice > Lattice services 를 찾아 클릭합니다.
그럼 아래와 같이 VPC Lattice Service를 조회할 수 있습니다.
Amazon VPC Lattice Target Group 확인
VPC Lattice Service의 세부 항목 중, Routing 섹션을 클릭하면 아래와 같은 Listener 규칙과 함께 대상 그룹을 확인할 수 있습니다. 대상 그룹의 세부 내용을 보기 위해서 아래 그림과 같이 Listener rules > Action > Forward to 순서로 찾아 대상 그룹을 클릭합니다.
Amazon VPC Lattice Target Group 확인
아래는 대상 그룹 상세 페이지 입니다. 여기의 대상그룹 섹션을 보면
POD 의 IP address와 Port 번호를 통해 VPC Lattice Service로의 라우팅 대상을 안내하고 있습니다.