Amazone Elastic Kubernetes Service(이하 EKS)를 설치해보고 EKS가 어떻게 구성되는지 살펴보겠습니다.
개인적으로 Azure를 자주 사용하기 때문에 AKS(Azure Kubernetes Service)와 어떤 차이가 있는 지도 간략하게 설명하겠습니다.
목차
- 환경 개요
- EKS 생성하기
- 웹 콘솔 살펴보기
- 주요 컴포넌트 비교
- 노드 비교
- 리소스 정리
1. 환경 개요
Windows 11의 WSL(Windows Subsystem for Linux) 환경에서 실습을 진행합니다. 버전 정보는 아래를 참고 부탁드립니다.
> wsl --version
WSL 버전: 2.3.26.0
커널 버전: 5.15.167.4-1
WSLg 버전: 1.0.65
MSRDC 버전: 1.2.5620
Direct3D 버전: 1.611.1-81528511
DXCore 버전: 10.0.26100.1-240331-1435.ge-release
Windows 버전: 10.0.22631.4751
> wsl --status
기본 배포: Ubuntu
기본 버전: 2
> wsl --list
Linux용 Windows 하위 시스템 배포:
Ubuntu(기본값)
참고로 Windows 11환경에서 WSL 을 구성하는 것은 아래를 참고하시면 됩니다.
https://learn.microsoft.com/ko-kr/windows/wsl/install
오래되서 잘 기억나지 않지만, 저는 예전에 wsl을 설치를 해서 아래와 같은 방식을 사용 했던 것 같기도 합니다.
2. EKS 생성하기
EKS의 배포 방식에는 AWS 콘솔을 이용한 방식, eksctl
을 이용한 방식, IaC 도구(terraform 등)를 이용한 방식이 있습니다.
eksctl를 통해서 클러스터를 생성하는 것이 가장 간단하지만, 내부적으로 CloudFormation을 이용하여 EKS클러스터와 노드그룹 2가지 stack을 만들어 생성을 진행하는 방식이라 속도가 느립니다. 반면 terraform을 사용하는 경우는 AWS API로 직접 생성을 요청하여 eksctl
보다는 빠르다고 합니다.
해당 포스트에서는 eksctl
을 통해서 클러스터를 구성하려고 합니다.
이를 위해서 기본적으로 AWS CLI
, eksctl
, kubectl
과 같은 도구를 먼저 설치하겠습니다.
https://docs.aws.amazon.com/eks/latest/userguide/setting-up.html
AWS CLI 설치
AWS에서 제공하는 가이드에 따라 AWS CLI를 설치합니다.
https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
*참고로 wsl 기본적으로 unzip이 없어서 apt install unzip -y
를 먼저 수행해야 합니다.
아래와 같이 나오면 정상입니다.
# sudo ./aws/install
You can now run: /usr/local/bin/aws --version
# aws --version
aws-cli/2.23.13 Python/3.12.6 Linux/5.15.167.4-microsoft-standard-WSL2 exe/x86_64.ubuntu.20
또한 aws configure
를 수행해 필요한 정보를 입력해야만 이후 eksctl 사용이 가능합니다.
kubectl 설치
이미 kubernetes를 자주 사용하기 때문에 언젠가 설치한 kubectl이 설치되어 있어 이 부분은 생략하겠습니다.
아래에서 알맞은 OS 유형을 바탕으로 설치를 진행하시면 됩니다.
eksctl 설치
마지막으로 eksctl
을 설치합니다.
https://eksctl.io/installation/#for-unix
# for ARM systems, set ARCH to: `arm64`, `armv6` or `armv7`
ARCH=amd64
PLATFORM=$(uname -s)_$ARCH
curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$PLATFORM.tar.gz"
# (Optional) Verify checksum
curl -sL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_checksums.txt" | grep $PLATFORM | sha256sum --check
tar -xzf eksctl_$PLATFORM.tar.gz -C /tmp && rm eksctl_$PLATFORM.tar.gz
sudo mv /tmp/eksctl /usr/local/bin
이런식으로 결과가 나오면 됩니다.
# eksctl version
0.203.0
EKS 클러스터 생성
eksctl을 통해 클러스터를 생성하고 삭제하는 가이드는 아래를 참고할 수 있습니다.
https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html
## 생성
eksctl create cluster --name my-cluster --region region-code
## 삭제
eksctl delete cluster --name my-cluster --region region-code
참고: region-code
https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/using-regions-availability-zones.html
아래 블로그를 보면 다양한 옵션을 통해 클러스터를 생성할 수 있음을 알 수 있습니다.
https://learnk8s.io/terraform-eks#three-popular-options-to-provision-an-eks-cluster
예를 들어, Node type, Node 개수, 노드 min/max(Cluster Autoscaler)를 조정할 수 있습니다.
eksctl create cluster \
--name learnk8s-cluster \
--node-type t2.micro \
--nodes 3 \
--nodes-min 3 \
--nodes-max 5 \
--region eu-central-1
이를 보다 규격화 해서 아래와 같은 형태로 cluster.yaml
파일을 생성하고 eksctl create cluster -f cluster.yaml
와 같이 실행하는 방법도 있습니다.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: learnk8s
region: eu-central-1
nodeGroups:
- name: worker-group
instanceType: t2.micro
desiredCapacity: 3
minSize: 3
maxSize: 5
간단한 테스트를 위한 목적이라면 eksctl 에 옵션을 추가하는 방식으로 사용할 수 있겠지만, yaml에 환경 구성을 저장해 놓고 재활용할 수 있는 장점이 있을 것 같습니다.
본 포스트에서는 테스트 목적이므로 eksctl
에 옵션을 추가하여 클러스터를 생성하도록 하겠습니다.
AWS_DEFAULT_REGION=ap-northeast-2
CLUSTER_NAME=myeks1
eksctl create cluster \
--name $CLUSTER_NAME \
--region $AWS_DEFAULT_REGION \
--nodegroup-name ${CLUSTER_NAME}-nodegroup \
--node-type t3.medium \
--node-volume-size=30 \
--version 1.31 \
--ssh-access \
--external-dns-access \
--verbose 4
참고로 기존에 생성된 ssh key(~/.ssh/id_rsa.pub)를 활용하므로, 생성된 ssh key가 없는 경우에는 ssh key-gen을 미리 수행하시면 됩니다.
ssh-keygen -t rsa -b 4096
eksctl
수행 로그를 바탕으로 진행과정을 살펴보겠습니다.
## 이와 같은 로그로 시작합니다.
2025-02-06 21:52:29 [ℹ] eksctl version 0.203.0
## eksctl에서 클러스터와 managed nodegroup을 위해 2개의 CloudFormation stacks을 만드는 것을 알 수 있습니다.
2025-02-06 21:52:29 [ℹ] will create 2 separate CloudFormation stacks for cluster itself and the initial managed nodegroup
## eksctl-myeks1-cluster를 stack을 배포합니다.
2025-02-06 21:52:31 [ℹ] deploying stack "eksctl-myeks1-cluster"
## 어느정도 시간이 지나면 myeks1의 컨트롤 플레인이 생성이 완료된 것을 알 수 있습니다.
2025-02-06 22:00:32 [▶] completed task: create cluster control plane "myeks1"
## Addon을 설치합니다. 이 과정에서 metrics-server, kube-proxy, vpc-cni, coredns 와 같은 컴포넌트 들이 설치됩니다.
2025-02-06 22:00:33 [ℹ] creating addon
2025-02-06 22:00:33 [▶] addon: &{metrics-server v0.7.2-eksbuild.1 [] map[] {false false false false false false false} map[] <nil> false true [] [] []}
..
## 노드 그룹에 대한 stack 배포를 시작합니다.
2025-02-06 22:02:37 [ℹ] deploying stack "eksctl-myeks1-nodegroup-myeks1-nodegroup"
## 노드 그룹 생성이 완료 되었습니다.
2025-02-06 22:05:13 [✔] created 1 managed nodegroup(s) in cluster "myeks1"
## kubeconfig 를 저장합니다.
2025-02-06 22:05:13 [✔] saved kubeconfig as "/root/.kube/config"
## myeks1 클러스터의 생성이 종료 되었습니다.
2025-02-06 22:05:15 [✔] EKS cluster "myeks1" in "ap-northeast-2" region is ready
대략 생성 요청 이후 15분 내에 완료가 되었습니다. terraform으로 수행하는 경우는 시간이 더 단축될 수 있으므로 이후 다시 확인을 해봐야할 것 같습니다
AKS의 경우는 보통 5분 내에 생성이 완료되어 생성 시간 자체는 AKS가 빠른 느낌입니다.
또한 수행 과정을 살펴보면 kubeconfig를 직접 설정해 주는 것을 알 수 있습니다. 이로써 eksctl
로 클러스터를 생성하면 바로 kubectl
을 사용할 수 있습니다.
반면, AKS에서는 클러스터 생성 후 az aks get-credentials
와 같은 명령어로 kubeconfig를 가져올 수 있습니다.
3. 웹 콘솔 살펴보기
EKS를 생성할 때 기본적으로 생성되는 리소스를 확인하기 위해서 웹 콘솔을 접근 해봅니다.
앞서 설명한 바와 같이 eksctl
은 CloudFormation을 사용하는데 이를 웹 콘솔에서 확인하실 수 있습니다.
생성된 EKS로 들어와서 정보를 확인해 봅니다.
현재 버전과 언제까지 유효한지, 그리고 클러스터 상태와 업그레이드 인사이트(업그레이드에 충족한 상태인지 검증하는 기능으로 보임), 노드 상태 문제를 한 눈에 볼 수 있는 점이 인상적입니다.
클러스터 정보 아래에 탭으로 다양한 클러스터 정보를 확인해볼 수 있습니다. 이 중 몇가지를 살펴보겠습니다.
[개요] 탭에서 API Server 엔드포인트 정보를 확인할 수 있습니다. (혹시나 보안 이슈를 우려하여 실제 정보는 캡처하지 않았습니다)
EKS의 API Server 엔드포인트를 확인하며 신기한 점은 이 엔드포인트에 대해서 dns query를 하면 2개의 IP가 응답을 합니다. API Server가 2개가 있다는 의미는 아니고, NLB에서 2개의 IP를 응답해 주는 것이라고 합니다.
# dig +short xxx.gr7.ap-northeast-2.eks.amazonaws.com
3.35.116.125
3.35.119.23
노드에 진입하여 확인해 볼 때도 kubelet과 kube-proxy가 각 다른 API Server 엔드포인트로 연결한 것을 알 수 있습니다.
# kubectl get no
NAME STATUS ROLES AGE VERSION
ip-192-168-32-233.ap-northeast-2.compute.internal Ready <none> 24m v1.31.4-eks-aeac579
ip-192-168-67-87.ap-northeast-2.compute.internal Ready <none> 24m v1.31.4-eks-aeac579
# kubectl node-shell ip-192-168-32-233.ap-northeast-2.compute.internal
[root@ip-192-168-32-233 /]# ss -tnp | egrep "kubelet|kube-proxy"
ESTAB 0 0 192.168.32.233:59018 3.35.119.23:443 users:(("kubelet",pid=2901,fd=20))
..
ESTAB 0 0 192.168.32.233:51418 3.35.116.125:443 users:(("kube-proxy",pid=3122,fd=9))
그리고 [컴퓨팅] 탭을 확인해보면 노드그룹이 EC2 Auto Scaling Group을 통해서 제공되며, 2개의 노드가 생성된 것을 알 수 있습니다.
[네트워킹] 탭을 보면 노드가 배포된 VPN와 서브넷 정보를 확인할 수 있습니다.
여기서 중요한 부분은 API 서버 엔드포인트 엑세스와 퍼블릭 액세스 소스 허용 목록입니다.
API 서버 엔드포인드 엑세스는 EKS에서 API 서버를 퍼블릭 혹은 프라이빗으로 제공하는지 여부이고, 퍼블릭인 경우 퍼블릭 엑세스 소스 허용 목록에서 접근을 허용할 IP를 등록해 줄 수 있습니다.
퍼블릭으로 설정된 클러스터에서는 최소한 접근 허용 목록을 지정하는 것이 보안적으로 안정적입니다.
EKS는 API 서버 엔드포인트를 퍼브릭
/퍼블릭 및 프라이빗
/프라이빗
세 가지 유형으로 제공하고 있습니다. 여기서 상단의 엔드포인트 엑세스 관리
를 눌러보면 상세한 정보를 확인하실 수 있습니다.
이를 그림으로 살펴보면 더 쉽게 이해할 수 있습니다.
먼저 Public을 살펴보면 kubectl과 같이 API 서버를 접근할 때 퍼블릭 엔드포인트로 접근하게 되며 또한 워커 노드의 접근도 퍼블릭 엔드포인트로 접근합니다.
출처: https://www.youtube.com/watch?v=bksogA-WXv8&t=5s
두번째 유형은 Public and Private 형태입니다.
kubectl과 같이 API 서버를 접근할 때 퍼블릭 엔드포인트로 접근하게 되는 것은 동일합니다. 반면 워커 노드는 API Server에 대한 dns query에 대해서 Route 53의 Private Hosted Zone을 통해 EKS owned ENI으로 응답을 받게되어 프라이빗한 연결을 제공합니다.
출처: https://www.youtube.com/watch?v=bksogA-WXv8&t=5s
세번째 유형은 Private 입니다.
이 구성에서는 API Server 엔드포인트를 퍼블릭으로 노출하지 않기 때문에 kubectl 과 같은 접근과 노드의 접근 모두가 EKS Owned ENI를 통해서 이뤄 집니다.
보다 자세한 내용은 아래의 문서를 참고하시기 바랍니다.
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/cluster-endpoint.html
이러한 API 서버 엔드포인트에 대한 보안 강화는 AKS에서도 유사하게 구현되어 있습니다.
먼저 API 서버 엔드포인트 Public을 Public Cluster로 생각할 수 있으며, Authorized IP range(https://learn.microsoft.com/ko-kr/azure/aks/api-server-authorized-ip-ranges?tabs=azure-cli)를 통해 API 서버로의 접근을 제한할 수 있습니다.
또한 API 서버 엔드포인트 Private 에 대응하는 Private Cluster(https://learn.microsoft.com/en-us/azure/aks/private-clusters?tabs=default-basic-networking%2Cazure-portal)를 구성하는 방식을 제공하고 있습니다.
다만 EKS에서 설명하는 API 서버 엔드포인트 Private에서 다른 AWS 서비스를 접근하는 경우에도 VPC Endpoint가 필요하다는 언급이 있는 것을 볼 때, EKS의 Private의 의미는 워커 노드 관점에서 외부로의 접근을 Isolated하겠다는 중의적인 표현이 있는 것 같습니다.
반대로 AKS의 Private cluster는 단순히 API 서버를 Private 하게 제공한다는 의미만 담고 있습니다. 다른 서비스로의 접근은 해당 서비스에서 Private endpoint 방식으로 구성을 하거나 해야하고, 또한 워커 노드의 환경 자체를 Isolated하기 위해서는 UDR(User-defined Routing)을 통해 Firewall을 이용하는 방식을 취할 수 있습니다.
한편 AKS에서도 최근 Network Isolated Cluster를 Public Preview 로 제공하고 있습니다. 이는 워커 노드 환경에서 외부 접근을 Isolated 하는 방식을 제공합니다.
https://learn.microsoft.com/en-us/azure/aks/concepts-network-isolated
마지막으로 [추가 기능] 탭에서는 AddOn을 확인해볼 수 있습니다.
주요 컴포넌트 비교 절에서 확인하겠지만 AKS는 kube-proxy, cordns, metrics-server 와 같은 컴포넌트를 시스템 컴포넌트 이야기하고 미리 설치되어 제공됩니다. 또한 이러한 컴포넌트는 보통 kubernetes 버전과 상응하여 자동으로 업그레이드 되는 방식을 취하고 있습니다.
EKS에서 확인을 해보면 이러한 컴포넌트들이 개별 AddOn으로 인식되며, 또한 개별 컴포넌트에 대해서 버전 업데이트
가 가능한 점에 차이가 있습니다.
추가 기능 가져오기
를 눌러보면 CSI Driver 와 같은 형태의 컴포넌트들도 AddOn으로 추가가 가능한 것을 알 수 있으며, 3rd Party에서 제공하는 AddOn도 AWS 마켓플레이스를 통해서 설치 가능한 것으로 보입니다.
Kubernetes 버전 별로 제공되는 AddOn에 차이가 있을 수 있으므로 아래의 명령을 통해서 확인하시기 바랍니다.
aws eks describe-addon-versions --kubernetes-version 1.31 --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output table
웹 콘솔에서 EKS 화면을 떠나 노드 중 한대를 확인해보겠습니다.
Private IP가 2개가 있습니다. 노드에서도 확인해보면 eth0, eth1 두개의 인터페이스가 있는 것을 알 수 있습니다. (아직 AWS를 잘 몰라서 왜 2개인지는 잘 모르겠네요..)
[root@ip-192-168-32-233 /]# ip -br -c a
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP 192.168.32.233/19 fe80::8f9:d9ff:febf:d407/64
enia4cb1502028@if3 UP fe80::e0bd:c3ff:feec:294c/64
enifc2da76e4e6@if3 UP fe80::88e6:29ff:fe17:10f8/64
eth1 UP 192.168.34.104/19 fe80::864:31ff:fea4:c503/64
Public IP도 하나 할당되어 있습니다. 노드에 할당된 파드에 진입해보니 해당 Public IP로 통신을 하는 것을 알 수 있습니다.
# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nettools-65789c8677-5l444 0/1 ContainerCreating 0 3s <none> ip-192-168-32-233.ap-northeast-2.compute.internal <none> <none>
nettools-65789c8677-j9dzp 1/1 Running 0 29s 192.168.86.177 ip-192-168-67-87.ap-northeast-2.compute.internal <none> <none>
nsenter-tpremx 1/1 Running 0 72m 192.168.32.233 ip-192-168-32-233.ap-northeast-2.compute.internal <none> <none>
# kubectl exec -it nettools-65789c8677-5l444 -- bash
[root@nettools-65789c8677-5l444 /]# curl ifconfig.me
52.79.138.69
아마 노드들이 Public Subnet을 사용하기 때문에 이런 구성이 된 것일 수도 있고, 혹은 컨셉이 다른 것일 수 있습니다만, AKS에서는 Instance Level Public IP(https://learn.microsoft.com/en-us/azure/aks/use-node-public-ips)를 별도로 지정하지 않는 이상 노드들은 Private IP로만 구성됩니다.
노드(파드)의 외부 통신의 방식은 클러스터의 Outbound-type을 통해서 지정되며 상세한 내용은 아래의 문서를 참고하실 수 있습니다.
https://learn.microsoft.com/en-us/azure/aks/egress-outboundtype
해당 인스턴스의 네트워크 인터페이스를 살펴보면 다수의 secondary IP가 할당된 것을 알 수 있습니다.
AWS는 VPC CNI로 파드의 IP Range가 VPC의 IP와 동일한 IP 대역을 사용합니다. 해당 노드에 배포된 파드들을 살펴보면 host network를 사용하지 않는 파드들이 사용하는 IP로 보입니다.
# kubectl get po -A -owide |grep ip-192-168-32-233
default nettools-65789c8677-5l444 1/1 Running 0 8m52s 192.168.47.31 ip-192-168-32-233.ap-northeast-2.compute.internal <none> <none>
default nsenter-tpremx 1/1 Running 0 81m 192.168.32.233 ip-192-168-32-233.ap-northeast-2.compute.internal <none> <none>
kube-system aws-node-fgrrx 2/2 Running 0 106m 192.168.32.233 ip-192-168-32-233.ap-northeast-2.compute.internal <none> <none>
kube-system coredns-9b5bc9468-dvv5c 1/1 Running 0 110m 192.168.49.120 ip-192-168-32-233.ap-northeast-2.compute.internal <none> <none>
kube-system kube-proxy-xpnsb 1/1 Running 0 106m 192.168.32.233 ip-192-168-32-233.ap-northeast-2.compute.internal <none> <none>
kube-system metrics-server-86bbfd75bb-wmk4d 1/1 Running 0 110m 192.168.42.2 ip-192-168-32-233.ap-northeast-2.compute.internal <none> <none>
마지막으로 노드의 네트워크 인터페이스와 EKS Owned ENI를 비교해보면 아래와 같이 요청자 ID
가 소유자 ID와다른 것을 알 수 있습니다. 즉 AWS에서 생성한 것이라는 것을 알 수 있습니다.
노드에서 EKS Owned ENI를 확인할 수 있는 방법이 있습니다.
kubectl exec나 kubectl logs와 같은 명령은 API 서버로 요청을 하여 노드에 실행 중인 파드나 로그를 보여줍니다. 그렇기 때문에 이 명령을 수행하는 순간은 API 서버에서 노드로의 접근으로 이뤄집니다.
아래와 같이 사전에 ss -tnp
를 수행하고, 세션1에서 kubectl exec
를 수행한 뒤, 다시 ss -tnp
를 수행해보면 EKS Owned ENI를 통한 연결이 확인됩니다.
참고로 AKS에서는 API 서버와 노드의 연결을 konnectivity
를 통해 제공한다는 차이가 있습니다.
4. 주요 컴포넌트 비교
앞서 생성한 EKS에서 배포된 파드를 바탕으로 기본 컴포넌트를 살펴보겠습니다.
# kubectl get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system aws-node-6mm9l 2/2 Running 0 119m
kube-system aws-node-fgrrx 2/2 Running 0 119m
kube-system coredns-9b5bc9468-dvv5c 1/1 Running 0 123m
kube-system coredns-9b5bc9468-pzm47 1/1 Running 0 123m
kube-system kube-proxy-4ml68 1/1 Running 0 119m
kube-system kube-proxy-xpnsb 1/1 Running 0 119m
kube-system metrics-server-86bbfd75bb-j888c 1/1 Running 0 123m
kube-system metrics-server-86bbfd75bb-wmk4d 1/1 Running 0 123m
metrics-server
, coredns
, kube-proxy
와 같은 컴포넌트가 있고, aws-node
가 있습니다.
aws-node
는 이미지를 살펴보면 AWS CNI와 Netowrk Policy Agent에 해당하는 컨테이너로 이루어져 있다는 걸 알 수 있습니다.
image: 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon-k8s-cni-init:v1.19.0-eksbuild.1
image: 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon/aws-network-policy-agent:v1.1.5-eksbuild.1
상당히 간결한 느낌입니다. 한편으로 필요한 기능이 있을 때 AddOn을 상당히 설치해야 한다는 의미이기도 합니다.
4GiB 인스턴스에서 대략 550Gib 정도를 kube-reserved로 사용하는 걸로 보입니다. 실행 파드가 적고, limit 설정도 안된 파드가 있어서 Allocated resources가 여유가 있습니다.
Capacity:
cpu: 2
ephemeral-storage: 31444972Ki
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 3943300Ki
pods: 17
Allocatable:
cpu: 1930m
ephemeral-storage: 27905944324
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 3388292Ki
pods: 17
...
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 350m (18%) 0 (0%)
memory 270Mi (8%) 570Mi (17%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-1Gi 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)
비교를 위해 AKS를 기본 생성하고, 배포된 컴포넌트를 살펴보겠습니다.
az group create --name aks-rg --location eastus
az aks create \
--resource-group aks-rg \
--name myaks1 \
--node-count 2
상대적으로 많은 컴포넌트가 설치되어 있는 것을 알 수 있습니다.
$ az aks get-credentials -g aks-rg -n myaks1
Merged "myaks1" as current context in /home/xx/.kube/config
$ kubectl get po -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system azure-cns-65cr5 1/1 Running 0 4m29s
kube-system azure-cns-zc944 1/1 Running 0 4m37s
kube-system azure-ip-masq-agent-7ccvx 1/1 Running 0 4m37s
kube-system azure-ip-masq-agent-fjkz5 1/1 Running 0 4m29s
kube-system cloud-node-manager-jg2p7 1/1 Running 0 4m37s
kube-system cloud-node-manager-rjh58 1/1 Running 0 4m29s
kube-system coredns-54b69f46b8-fsgqh 1/1 Running 0 4m15s
kube-system coredns-54b69f46b8-qsqnr 1/1 Running 0 5m13s
kube-system coredns-autoscaler-bfcb7c74c-dk26h 1/1 Running 0 5m13s
kube-system csi-azuredisk-node-hcmcn 3/3 Running 0 4m37s
kube-system csi-azuredisk-node-hzp7x 3/3 Running 0 4m29s
kube-system csi-azurefile-node-clzjj 3/3 Running 0 4m37s
kube-system csi-azurefile-node-gt9mj 3/3 Running 0 4m29s
kube-system konnectivity-agent-546bc6d8dc-5d9xs 1/1 Running 0 15s
kube-system konnectivity-agent-546bc6d8dc-j8pzd 1/1 Running 0 12s
kube-system kube-proxy-vs88d 1/1 Running 0 4m29s
kube-system kube-proxy-wtqth 1/1 Running 0 4m37s
kube-system metrics-server-7d95c7bd8d-rklw7 2/2 Running 0 4m7s
kube-system metrics-server-7d95c7bd8d-xsgn4 2/2 Running 0 4m7s
상대적으로 많은 파드들이 실행되어 Allocated resources를 많이 사용 중입니다. 이 때문에 AKS에서는 시스템 컴포넌트들과 사용자 워크로드를 분리하도록 권장하고 있습니다. 시스템 노드풀과 사용자 노드풀을 분리하는 방식을 취할 수 있습니다. 다만 이 경우에도 daemonset 유형의 파드(ex. CSI driver)들은 전체 노드에도 동일하게 생성됩니다.
Capacity:
cpu: 2
ephemeral-storage: 129886128Ki
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 7097596Ki
pods: 250
Allocatable:
cpu: 1900m
ephemeral-storage: 119703055367
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 5160188Ki
pods: 250
...
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 682m (35%) 2042m (107%)
memory 766Mi (15%) 4252Mi (84%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-1Gi 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)
7GiB 노드에서 1.9GiB 정도가 kube-reserved 로 예약되어 있습니다. AKS에서는 1.29 이상에서 kube-reserved 매커니즘에 상당한 개선이 있었습니다. 다만 default로 생성된 노드의 max-pods 가 250으로 설정되어 이 부분이 kube-reserved로 반영된 영향일 수 있습니다.
상세한 내용은 아래 문서를 참고할 수 있습니다.
https://learn.microsoft.com/en-us/azure/aks/node-resource-reservations#memory-reservations
특이한 점은 AWS의 AddOn들은 CPU limit을 지정하지 않고 있습니다. (자신감일까요..?)
5. 노드 구성 비교
노드 관점에서 정보를 비교해 보겠습니다.
EKS의 노드입니다. Amazon Linux 2를 사용하고 있고 containerd를 사용한다는 것을 알 수 있습니다. 인스턴스에 Public IP가 구성되어 있고, 아래 정보에서 EXTERNAL-IP가 표시되어 있습니다.
# kubectl get no -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ip-192-168-32-233.ap-northeast-2.compute.internal Ready <none> 137m v1.31.4-eks-aeac579 192.168.32.233 52.79.138.69 Amazon Linux 2 5.10.233-223.887.amzn2.x86_64 containerd://1.7.25
ip-192-168-67-87.ap-northeast-2.compute.internal Ready <none> 137m v1.31.4-eks-aeac579 192.168.67.87 15.165.15.152 Amazon Linux 2 5.10.233-223.887.amzn2.x86_64 containerd://1.7.25
AKS의 노드입니다. Ubuntu 22.0.4.5 를 사용하고 containerd를 사용합니다. 노드들은 default에서 Private IP만 구성되어 EXTERNAL-IP가 <none>으로 표시됩니다.
$ kubectl get no -owide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
aks-nodepool1-21558960-vmss000000 Ready <none> 4m19s v1.30.7 10.224.0.4 <none> Ubuntu 22.04.5 LTS 5.15.0-1079-azure containerd://1.7.25-1
aks-nodepool1-21558960-vmss000001 Ready <none> 4m27s v1.30.7 10.224.0.5 <none> Ubuntu 22.04.5 LTS 5.15.0-1079-azure containerd://1.7.25-1
EKS 노드에 진입하여 일반적인 구성을 살펴보겠습니다.
[root@ip-192-168-32-233 /]# hostname
ip-192-168-32-233.ap-northeast-2.compute.internal
[root@ip-192-168-32-233 /]# ip -br -c a
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP 192.168.32.233/19 fe80::8f9:d9ff:febf:d407/64
enia4cb1502028@if3 UP fe80::e0bd:c3ff:feec:294c/64
enifc2da76e4e6@if3 UP fe80::88e6:29ff:fe17:10f8/64
eth1 UP 192.168.34.104/19 fe80::864:31ff:fea4:c503/64
[root@ip-192-168-32-233 /]# stat -fc %T /sys/fs/cgroup/
tmpfs
AKS는 1.25 버전에서 cgroupv2를 default로 사용하고 있는 점에 차이가 있습니다.
root@aks-nodepool1-21558960-vmss000000:/# hostname
aks-nodepool1-21558960-vmss000000
root@aks-nodepool1-21558960-vmss000000:/# ip -br -c a
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP 10.224.0.4/16 metric 100 fe80::6245:bdff:fea7:ab7a/64
enP40656s1 UP
azvae85acd5c66@if4 UP fe80::a8aa:aaff:feaa:aaaa/64
azve6bd6a1fcff@if6 UP fe80::a8aa:aaff:feaa:aaaa/64
azv61ea7670b68@if8 UP fe80::a8aa:aaff:feaa:aaaa/64
root@aks-nodepool1-21558960-vmss000000:/# stat -fc %T /sys/fs/cgroup/
cgroup2fs
cgroupv2로 변경을 하는 경우, 애플리케이션 프레임워크에서 cgroupv2를 인지하지 못하는 상황에서 메모리 리포팅 버그나 OOM과 같은 이슈가 발생할 수 있습니다. 이러한 리스크로 인해서 아직 cgroupv2으로 전환을 하지 않은 것인지 분명하지는 않습니다.
일단 현 시점에는 노드 수준의 큰 차이점을 확인하기 어려워 기본적인 정보만 보는 수준에서 실습을 마무리 하겠습니다.
6. 리소스 정리
실습을 마무리하고 eksctl로 생성한 클러스터를 삭제합니다.
eksctl delete cluster --name $CLUSTER_NAME
마무리
해당 포스트는 AEWS(AWS EKS Workshop Study) 3기를 참여하면서 과제로 작성을 시작했습니다.
이번 주는 개인 환경을 세팅하고 EKS를 설치해 EKS의 기본적인 아키텍처와 구성 정보를 확인해봤습니다. 그 과정에서 AKS와 다양한 관점에서 비교를 해봤습니다.
한편으로 AWS를 사용할 일이 없었는데, 이번 과정을 통해서 AWS 콘솔이 어떤 식으로 정보를 노출하는지, CLI를 사용하는 방식 등을 이해할 수 있었습니다.
매주 다양한 주제에 대해서 EKS를 스터디할 계획이라, 각 주제별로 Azure의 구성이나 관점에 어떤 차이가 있는지 비교해 보도록 하겠습니다.