EKS Prefix Mode/Delegation
개요
가장 보편적인 형태의 다음의 AWS EKS환경에서는
Managed Node Group*이 Amazon VPC CNI*를 통해 네트워크 설정이 이루어지며 인스턴스 타입 별로 지정된 숫자의 최대 파드 수량*을 한계로 가지게 됩니다.
Managed Node Group* : 관리형 노드 그룹
Amazon VPC CNI* : Amazon EKS Cluster에 있는 Pod 네트워킹용 Networking Plugin
지정된 숫자의 최대 파드 수량* : 일정한 연산식에 의해서 정해지며 타입 별로 이미 계산된 산정표가 존재합니다.
기본적인 지정 수량은 낮은 파드 밀도*를 가지며,
이런 낮은 밀도로 인하여 저사양 & 다량의 서버로 구성된 Microservices*로 갈수록 비효율적인 비용 구조를 만듭니다.
낮은 파드 밀도* : 단일 인스턴스에 적은 수량의 파드만 할당할 수 있음을 표현하는 관용어입니다.
저사양 & 다량의 서버로 구성된 Microservices* : 블루/그린 배포, 파드 수평 확장 등을 고려하면 파드 총량의 50~60% 미만으로 유지하는 것이 좋습니다.
본 문서는 파드 지정 수량을 넘어 높은 파드 밀도를 가지는 Amazon EKS Prefix Mode (Linux)에 대해서 소개합니다.
# SPEC
EKS Cluster 1.30
Amazon VPC CNI 1.18.x
Managed Node Group
본문에 앞서
최초에는 kubectl*, aws-cli* 등을 사용하여 실습을 진행하였습니다.
kubectl* :
aws-cli* :
하지만 사내에서는 대부분의 인프라를 Terraform으로 관리하고 있기 때문에, Terraform을 통해서 실습을 진행하였습니다.
본 문서는 범용성 높은 가이드를 위해서 kubectl, aws-cli를 기준으로 작성되었음을 안내드립니다.
기본값
본 챕터는 AWS EKS Networking의 최소한의 기본 지식을 포함하고 있습니다.
Managed Node Group 파헤치기
AWS EKS에서 t3.medium 1개 규격의 Managed Node Group을 생성하면, 단일 노드 총 3개의 ENI*가 할당된 것을 볼 수 있습니다. 또한 1개의 ENI는 1개의 PrivateIPAddress*를 가지고 있어 최종적으로 3개의 PrivateIPAddress를 가지게 됩니다.
aws-cli 작성 필요
ENI* : Elastic Network Interfaces
PrivateIPAddress* : 프로덕션 환경에 맞춰서 PrivateEndpoint를 가지는 EKS Cluster 구성을 완료하였다면, ManagedNode는 PrivateIPAddress만을 할당 받습니다.
또한 각각의 PrivateIPAddress에 대해서 지정된 수량 만큼의 SecondaryAddress*를 가지는 것도 확인할 수 있습니다.
aws-cli
이러한 방식을 Secondary IPv4 Address 방식이라고 부릅니다.
Secondary IPv4 Address 작용 방식
앞서 t3.medium은 3개의 ENI와 이에 대응되는 3개의 PrivateIPAddress를 가지고 있습니다. 아래 그림에서 slot1 에 적혀있는 slot1 : 10.0.0.20, 10.0.0.30, 10.0.0.40이 이에 해당합니다. 각각의 ENI에 할당된 slot2,3,4 : 10.0.0.101, ~ 10.0.0.32 가 실제로 파드에 할당되는 IPAddress입니다.
Secondary IPv4 Address과 파드 최대량
Secondary IPv4 Address를 사용하는 경우,
Node에 할당가능한 파드의 최대 수량은 다음과 같습니다.
ENI * (IP *- 1) + 2
즉, 앞서 설명한 t3.medium을 기준으로 하면 다음과 같은 수량이 나옵니다.
3 * ( 6 - 1 ) + 2 = 15 + 2 = 17*
실제로는 매번 연산을 하기 보다는 Kubelet/ENI Max Pods 등을 참고하여 진행하게 됩니다.
MaxPods 확인하기
실제로 Secondary IPv4 Address 방식을 사용할때,
EKS ManagedNodeGroup의 MaxPods를 확인할 수 있습니다. [Ref]
kubectl get nodes -o=custom-columns=NAME:.metadata.name,CAPACITY:.status.capacity.pods
NAME CAPACITY
ip-0-0-0-0.ap-northeast-2.compute.internal 17
ip-0-0-0-0.ap-northeast-2.compute.internal 17
ip-0-0-0-0.ap-northeast-2.compute.internal 17
개선안
Secondary IPv4 Address 방식은 파드 밀도가 낮다는 단점이 있습니다. 이 문제를 해결하기 위한 것이 Prefix Mode(Linux)입니다.
Prefix Mode 간단 소개
EKS Prefix Mode는 NodeGroup의 Prefix Delegation*을 통해서 ENI에 IPv4/IPv6 CIDR 범위를 할당할 수 있습니다.
Prefix Delegation* : 이 기능을 사용하여 접두사(Prefix)가 할당하면 인스턴스에서 여러 IP 주소가 필요한 컨테이너 및 네트워킹 어플리케이션을 포함한 애플리케이션의 관리를 확장하고 간소화 할 수 있습니다.
Prefix Mode 활성화 확인
다음과 같은 명령어를 통해서 Prefix Mode 활성화 여부를 확인할 수 있습니다.
kubectl describe daemonset aws-node -n kube-system | grep -i delegation
p.s. EKS Node 조회
kubectl get pods --selector=k8s-app=aws-node -n kube-system
Prefix Mode 활성화 요구사항
Prefix Mode를 사용하기 위해서는 Amazon VPC CNI가 1.9 버전보다 높아야 합니다. 아래 명령어를 통해서 Amazon VPC CNI 버전을 확인할 수 있습니다.
Windows PowerShell
kubectl describe daemonset aws-node --namespace kube-system | Select-String "Image" | %{ $_.ToString().Split('/')[1] }
Linux/MacOS Terminal
kubectl describe daemonset aws-node --namespace kube-system | grep "Image" | awk -F'/' '{print $2}'
Prefix Mode/Delegation 활성화
다음으로 Prefix Delegation을 활성화 할 수 있습니다.
kubectl set env daemonset aws-node -n kube-system ENABLE_PREFIX_DELEGATION=true
또한 WARM_PREFIX_TARGET*을 활성화합시다.
kubectl set env ds aws-node -n kube-system WARM_PREFIX_TARGET=1
Prefix Mode/Delegation 확인
다음으로 Prefix Deleagtion을 확인할 수 있습ㄴ다.
aws ec2 describe-instances \
--query 'Reservations[*].Instances[].{InstanceId: InstanceId, Prefixes: NetworkInterfaces[].Ipv4Prefixes[]}'
또한 WARM_PREFIX_TARGET 적용 내역도 볼 수 있습니다.
kubectl describe daemonset aws-node -n kube-system | grep -i WARM
AWS Console에서도 Prefix Delegation이 활성화된 Node(EC2)의 첫 번째 ENI에 IPv4 Prefix가 할당된 것을 볼 수 있습니다.
수정 사항이 적용되었다면, t3.medium을 기준으로 아래와 같이 MaxPods가 변경됨이 기대됩니다.
AS-IS : 17
TO-BE : 110
하지만 다음의 구문으로 테스트를 진행하면 Running Pods의 수량이 17에서 더이상 증가하지 않는 것을 알 수 있습니다.
echo "apiVersion: apps/v1
kind: Deployment
metadata:
name: pause-pods-prefix
namespace: prefix-delegation
spec:
replicas: 150
selector:
matchLabels:
run: pause-pods-prefix
template:
metadata:
labels:
run: pause-pods-prefix
spec:
containers:
- name: reserve-resources
image: registry.k8s.io/pause
" > prefix-delegation.yaml
kubectl create ns prefix-delegation
kubectl apply -f prefix-delegation.yaml
watch -n 1 "kubectl get pods | grep -E 'Running' | wc -l"
Prefix Mode is not working
Prefix Mode가 적용되지 않는 이유는 allocatable 설정값이 여전히 17이기 때문입니다. [Ref]
EKS NodeGroup allocatable 확인
그 이유는 EKS NodeGroup의 각 Node에 allocatable 설정값이 여전히 17이기 때문입니다.
아래 명령어를 통해서 allocatable 값을 확인할 수 있습니다.
kubectl get node -o yaml | grep allocatable -A7
allocatable:
cpu: 1930m
ephemeral-storage: "18181869946"
hugepages-1Gi: "0"
hugepages-2Mi: "0"
memory: 3364612Ki
pods: "17"
capacity:
EKS NodeGroup allocatable 변경
EKS Node의 allocatable 변경하기 위해서 레퍼런스에서는 SSH로 접속해서 bootstrap.sh 파일의 인자에 maxPods를 110으로 전달할 것으로 소개되어 있었습니다. 하지만 이 방식으 아래와 같은 이유로 자사와 적합하지 않았습니다.
운영망 전체에서 EKS NodeGroup에는 EC2 KeyPair를 사용하지 않고 있음
신규로 배포되는 서버가 생길 때마다 수동으로 SSH로 접속해서 값을 변경해야함
구조적으로 안정성이 높다고 보기 어려움
이 중에 1, 2번의 문제점으로 인해서 다른 해결방법이 필요했습니다.
EKS Managed NodeGroup UserData
Node(EC2)가 처음 켜질때 MaxPods 값을 반영하도록 접근법을 바꿨습니다. 이에 따라 Launch Template에 사용자 데이터를 확인해보았습니다.
Managed NodeGroup의 경우 아래와 같은 NodeConfig이 있는 것을 확인할 수 있습니다.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="//"
--//
Content-Type: application/node.eks.aws
---
apiVersion: node.eks.aws/v1alpha1
kind: NodeConfig
spec:
cluster:
apiServerEndpoint: {{ EKS HTTPS ENDPOINT }}
certificateAuthority: {{ EKS CertificateAuthority }}
cidr: {{ EKS CIDR Block }}
name: {{ EKS Cluster Name }}
kubelet:
config:
maxPods: {{ NodeGroup MaxPods }}
clusterDNS:
- {{ CLUSTER DNS }}
flags:
- {{ … }}
--//--
Nitro Instance에서 vCPU30개 미만인 인스턴스의 최대 파드 숫자는 110개로 제한이 됩니다. 따라서 t3.medium의 maxPods도 110으로 설정하면 됩니다.
maxPods: 110
이후 Managed Node Group에서 LaunchTemplate의 개정을 1에서 2(신규 개정)으로 변경해야 합니다.
최종적으로 Managed Node Group의 최소 수량을 늘리고 기존의 Node에서 신규 Node로 파드를 옮기면 작업이 완료됩니다.
Secondary IPv4 Address vs Prefix Mode : MaxPods
t3.medium을 기준으로 두 방식을 비교해봅시다.
전체적으로 Prefix Mode(Linux) 방식이 더 높은 파드 밀도를 가지는 것을 알 수 있습니다.
구분 | Secondary | Prefix |
---|---|---|
ENI | 3개 | 1개 |
Secondary | 9개 | 0개 |
Prefix Delegation | 0개 | 3개 |
MaxPods | 17개 | 110개 |
Secondary IPv4 Address vs Prefix Mode : Network Hop
당연히 방식의 네트워크 기술이 사용되었기 때문에 Network Hop*도 다르게 나올 것이라고 생각했습니다. 결론부터 말하면 Prefix Mode가 더 적은 경로의 Network Router를 지난다는 점을 알게 되었습니다.