CloudNet@ Team Study/EKS Workshop 4th Cohort

Check EKS deployment and control plane information

"Everything about infra" 2026. 3. 17. 03:43

 

안녕하십니까.

 

CloudNet@ 팀 'Gasida' 님이 진행하시는 스터디 내용 중,

EKS를 직접 배포한 후에 제어부, 시스템 파드 정보, add-on 등 정보를 확인하고

학습하는 시간을 갖도록 하겠습니다.

 

 

01. EKS 실습 코드 배포

이전 포스팅에서 배포 명령을 입력해둔 후 Terraform 배포 코드에 대해서 알아보았습니다.

이어서 시작해보자면, 아래와 같이 배포가 완료되었고 실제로 확인해보도록 하겠습니다.

 

 

위와 같이 문제없이 complete 된 상황이여서 간단하게 Console 에서도 확인 해보겠습니다.

 

 

네, Cluster 와 NodeGroup을 제외하고도 지정된 리소스들이 정상적으로 생성이 되었습니다.

 

만약 자격 증명 설정을 하지 않았다면 아래와 같이 AWS API를 호출하지 못하여 에러가 발생합니다.

 

📌 자격 증명 설정

aws eks update-kubeconfig --region ap-northeast-2 --name myeks

실제로 aws api를 호출하여 정보를 읽어올 수 있는 것을 확인하였습니다.

 

📌 rename context 설정

kube config 정보를 확인하였을 때 name이 ARN 형식으로 되어있는 것을 아래와 같이 확인 가능합니다.

  • contexts: 부분 아래에 name: 부분이 보시다 싶이 ARN 형식으로 되어있습니다.
  • 이렇게 되면 context를 변경할 때 ARN full name으로 변경을 해야합니다.
# rename 전
kubectl config use-context arn:aws:eks:ap-northeast-2:093359840099:cluster/myeks

# rename 후
kubectl config use-context myeks

이런식으로 쉽게 context를 변경하기 위해 아래와 같이 rename 작업 까지 해주시면 됩니다.

# k8s config 확인 및 rename context
cat ~/.kube/config | grep current-context | awk '{print $2}' kubectl config rename-context $(cat ~/.kube/config | grep current-context | awk '{print $2}') myeks
cat ~/.kube/config | grep current-context

 


02. EKS 제어부 정보 확인

eks 클러스터 정보 확인

kubectl cluster-info

Kubernetes control plane is running at https://E2F77ED0429BBB82740C7C2A9EBCF47E.gr7.ap-northeast-2.eks.amazonaws.com
CoreDNS is running at https://E2F77ED0429BBB82740C7C2A9EBCF47E.gr7.ap-northeast-2.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
  • kubectl이 EKS API Server에 정상적으로 연결되어 있다는 의미.
  • URL이 ~/.kube/config의 server 값과 동일하며, E2F77ED0429... 부분이 클러스터 고유 ID를 의미.
  • CoreDNS is running 상태를 보아 클러스터 내부 DNS 서비스인 CoreDNS가 정상 동작을 의미.

 

Endpoint 확인

CLUSTER_NAME=myeks
aws eks describe-cluster --name $CLUSTER_NAME | jq

실제로 terraform에서 배포했던 리소스들에 대한 엔드포인트가 JSON 형태로 출력됩니다.

어떤 리소스들이 배포가 되었는지 AWS Console에서 같이 비교해도 좋을 것 같습니다.

 

dig를 조회하였을 때 출력되는 IP 소유 확인

APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
dig +short $APIDNS

13.209.169.249
3.34.7.35
  • 해당 IP들은 EKS Control Plane에 할당된 공인 IP입니다. 즉, AWS가 관리하는 인프라 IP
  • 내가 관리할 수 있는 영역은 Data Plane의 EC2 인스턴스이며, EKS는 AWS가 관리하므로 AWS Managed VPC에 해당 출력되는 IP들이 생성되어 있으며 우리한테는 보이지 않는 영역입니다.
  • terrform에서 옵션을 'endpointPublicAccess: true'로 설정하여 control plane이 public endpoint를 가짐.

그렇다면, 왜 IP가 2개일까? EKS는 기본적으로 API Server를 HA로 구성(Multi-AZ 분산)하기 때문.

 

eks 노드 그룹 정보 확인

aws eks describe-nodegroup --cluster-name $CLUSTER_NAME --nodegroup-name $CLUSTER_NAME-node-group | jq

출력해보니, 아래와 같이 JSON 형태로 출력이 되었는데 각 옵션들을 확인해보자.

 

1) status / health 정보

  • 노드 그룹의 현재 상태를 나타내며, 문제가 발생하면 health.issues 배열에 에러가 기록됨.
status value 의미
ACTIVE 정상 동작 중
CREATING 생성 중
CREATE_FAILED 생성 실패
DEGRADED 일부 노드 문제

 

2) scalingConfig - 노드 수 제어

  • 노드 수를 결정하는 핵심 설정이며, Terraform 코드에서 정의한 대로 배포가 되었음.
    • desired_size : 평시 유지할 노드 수
    • minSize ~ maxSize : Cluster Autoscaler가 조절 가능한 범위
    • desiredSize는 minSize와 maxSize 사이 값이어야 한다.

3) capacityType - 비용과 직결

의미 비용 적합 워크로드
ON_DEMAND 안정적, 중단 없음 정가 프로덕션 핵심 서비스
SPOT AWS가 회수 가능 최대 90% 절감 배치, 비핵심 서비스

 

4) updateConfig - 업그레이드 안정성

  • 노드 그룹 버전 업그레이드 시 한 번에 교체하는 노드의 비율을 의미한다.
  • 현재 설정은 33이며, 노드 2대 기준으로 33%이므로 1대씩 순차 교체를 의미함.

5) nodeRole - 노드에 부여된 IAM Role

  • Terraform 코드에 IAM Role을 직접 작성하지 않았지만 EKS 모듈이 자동으로 생성함.

실제로 확인해보았을 때 위와 같은 Role을 자동으로 부여하였음을 알 수 있다. (EKS 내부 통신에 필요한 권한)

 

노드 정보 확인 (OS와 컨테이너 런타임)

kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
kubectl get node -owide

  • 레이블 기반으로 노드 정보를 확인하였을 때 인스턴스 타입, 용량 유형, AZ를 확인할 수 있다.
  • '-o wide' 명령으로 노드 상세 정보를 확인할 수 있으며, 내 외부 IP, OS 이미지, containerd 버전 등 확인 가능.

인증 정보 확인

kubectl get node -v=6

인증 정보는 어디에서 API를 호출하는지, 보안 설정이나 로컬 환경에 따라 달라지는 것 같다.

  • Config loaded from file: /Users/sunghwan/.kube/config : 내 로컬 macOS의 /kube/config 참조

또한 round_trippers.go:632 (kubernetes/client-go 라이브러리 내부 파일) 확인

  • kubectl을 로컬에서 https get 요청 → eks api server에서 200OK 반환, 응답 속도는 399ms

 

 토큰 기반 통신 구조 확인

aws eks get-token --cluster-name $CLUSTER_NAME --region $AWS_DEFAULT_REGION

kubectl이 EKS API Server에 접근할 때 사용하는 임시 인증 토큰을 발급하는 명령어 입니다.

  • kubectl이 kind, apiVersion 형식을 읽어서 인증 토큰을 추출하며 kubectl 명령 실행 시 자동으로 호출함.
  • expirationTimestamp에 출력되는 시간이 토큰 만료 시간이며, 발급 후 15분 후에 만료된다.
    • 만료 되면 kubectl이 자동으로 재발급하여 연결 유지.

token은 base64로 인코딩 되었는데, 반대로 디코딩을 해볼까?

파라미터 별 의미를 아래와 같이 나열해보겠습니다.

  • Action=GetCallerIdentity : STS에게 "이 자격 증명이 누구냐?"라고 묻는 API
    • EKS가 이걸 호출해서 "어떤 IAM User/Role이 요청했는지" 확인함.
  • X-Amz-Credential : 사용자 IAM Access Key ID, 서명 날짜, 리전, 서비스, 서명 버전 등 정보 출력
  • X-Amz-Date : 토큰이 발급된 시각
  • X-Amz-Expires=60 : 60초 후 이 URL이 만료됨 (URL자체는 60초, EKS 토큰은 15분동안 캐싱)
  • X-Amz-Algorithm=AWS4-HMAC-SHA256 : AWS Signature Version 4 방식으로 서명
  • X-Amz-Signature : 내 Secret Access Key로 서명한 값을 의미 (위변조 방지용)

 

즉, 이해를 돕기 위해 EKS 인증 서명 방식을 풀어보자면 아래와 같습니다.

 

1) 로컬에 AWS IAM 자격증명을 기반으로 STS(Security Token Service)를 통해 내 신원 저장

  • 확인 명령어 : "cat ~/.aws/credentials"
  • aws_secret_access_key가 서명에 사용되는 키입니다.
  • aws_access_key_id는 IAM User 식별자 입니다.

2) 로컬에서 사용자가 kubectl 명령 실행

  • ~/.kube/config를 읽어서 인증 방식을 확인하며, exec 블록에 정의된 명령을 실행하여 토큰을 가져옴.

 

3) STS PreSigned URL 생성

  • AWS CLI가 로컬의 Secret Key로 STS URL에 서명을 생성한다 (위 디코딩 된 token 참조)
  • Secret Key 자체는 URL에 포함되지 않으며 서명값(Signature)만 전송된다.

4) token 생성

  • 서명된 STS URL을 Base64 인코딩해서 토큰으로 변환한다.

5) EKS API Server로 토큰 전송

  • kubectl이 토큰을 Authorization Header에 담아 EKS API Server로 전송한다.
  • 'kubectl get node -v=6'으로 실제 HTTP 요청에서 확인 가능함.
GET /api/v1/nodes
Host: E2F77ED0429BBB82740C7C2A9EBCF47E.gr7.ap-northeast-2.eks.amazonaws.com
Authorization: Bearer k8s-aws-v1.aHR0cHM6Ly9zdHMu...

 

6) EKS가 STS로 토큰 검증

  • EKS API Server가 토큰을 디코딩해서 STS URL을 직접 호출한다

7) 권한 확인 후 응답

  • EKS가 access entry를 조회해서 해당 IAM의 권한을 확인한다
    • terraform 배포 당시 "enable_cluster_creator_admin_permissions = true"로 인해 admin 권한 확인

 


03. 시스템 파드 정보 확인

 

3-1. Pods 정보 확인

kubectl get pod -n kube-system -o wide
kubectl get pod -A

현재 Pods 정보들을 확인하였을 때 coredns, kube-proxy, cni 등의 Pods들만 존재한다.

 

즉, Data plane 관련된 파드들만 떠있고 control plane 파드들은 보이지 않는다.

(kube-apiserver, etcd, kube-controller-manager, shceduler가 안보인다.)

 

이유는 EKS의 경우 Control Plane은 AWS가 완전히 관리하기 때문에 data plane 노드에서는 보이지 않습니다 !


3-2. kube-system 네임스페이스에 모든 리소스 확인

kubectl get deploy,ds,pod,cm,secret,svc,ep,endpointslice,pdb,sa,role,rolebinding -n kube-system

리소스들을 차례대로 아래와 같이 살펴보겠습니다.

  • deployment - coredns
    • 2개의 Pod가 2개 노드에 분산 배치 (고가용성)
    • Replica 수를 조절해서 DNS 성능 조절이 가능하다.
  • DaemonSet - node, kube-proxy
    • DaemonSet은 모든 노드에 1개씩 자동 배포된다.
    • 노드가 추가되면 자동으로 Pod 수도 추가됨 (노드 2대니까 각각 2개씩 떠 있는 것 확인)
    • aws-node는 Pod IP 할당하는 역할을 하며, kube-proxy는 iptables를 관리한다.

  • ConfigMap - 설정 저장소
    • amazon-vpc-cni : vpc-cni 설정
    • aws-auth : IAM 과 k8s간 권한을 맵핑해주는 역할 (NodeGroup의 IAM Role 확인)
    • coredns : DNS 설정
    • kube-proxy : iptables를 관리하는 kube-proxy 설정
    • kube-proxy-config : proxy 상세 설정 정보
    • kube-root-ca.crt : EKS 클러스터 CA 인증서

  • Service / Endpoint
    • kube-dns : Pod들이 DNS 조회할 때 '10.100.0.10'으로 요청을 보냄
      • kube-proxy가 iptables 규칙을 참조하여 kube-dns의 pods들로 트래픽 분산시킴.
    • eks-extension-metrics-api : AWS가 관리하는 Control Plane 영역의 IP
      • EKS가 매트릭을 수집하는 앤드포인트임.
  • PodDisruptionBudget
    • Node drain, upgrade 시 동시에 중단 가능한 core dns pod 수를 1개로 제한.
    • core dns는 2개 있으니 최소 1개는 항상 살아있도록 보장하는 설정.

  • ServiceAccount (총 40개 이상..) 
    • k8s 기본 Controller용 SA : deployment-controller, replicaset-controller etc..
      • 각 컨트롤러가 k8s API를 호출할 때 사용하는 계정이며, EKS에서는 AWS 관리 영역에서 사용됨
    • EKS 전용 SA : aws-node, tagging-controller, aws-cloud-provider etc..
      • vpc-cni pod, aws 리소스 태깅 및 클라우드 연동하는 계정이며, data plane에서 사용됨.

  • role.rbac (EKS 전용 Role)
    • eks:addon-manager : add-on 설치/관리
    • eks:authenticator : IAM 인증 처리
    • eks:coredns-autoscaler : core dns 자동 스케일링
    • eks:fargate-manager : Fargate 노드 관리
    • eks:network-policy-controller : 네트워크 정책 관리
    • eks:node-manager : 노드 라이프사이클 관리
    • eks:az-pooler : AZ 가용성 체크
  • 등 모든 Role 전부 AWS Control Plane이 k8s API를 호출하기 위해 필요한 권한을 정의함. (EKS 전용)

 

3-3. 모든 파드의 컨테이너 이미지 정보 확인

kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c

현재 가용중인 모든 파드들에 대한 컨테이너 이미지 정보를 확인해본 결과,

전부 같은 ECR 계정에서 이미지를 가져옵니다.

 

602401143452.dkr.ecr.ap-northeast-2.amazonaws.com → AWS가 관리하는 공식 EKS ECR 계정 ID

즉, Docker Hub나 외부 레지스트리가 아닌 AWS 공식 ECR에서 직접 Pull 한 이미지임.

 

모두 AWS 공식 ECR에서 가져온 것이므로 AWS가 버전 관리 및 보안 패치를 담당한다.


 

3-4. kube-proxy 상세 정보 확인

kubectl describe pod -n kube-system -l k8s-app=kube-proxy
kubectl get cm -n kube-system kube-proxy -o yaml
kubectl get cm -n kube-system kube-proxy-config -o yaml

  • Priority Class
    • 메모리 부족 시 절대 evict되지 않는 최고 우선 순위임.
    • kube-proxy가 죽으면 노드 전체 네트워크가 마비되기 때문에.
  • IP = Node IP
    • kube-proxy는 노드 네트워크 스택을 직접 다루기 때문에 별도 Pod IP없이 노드 IP를 그대로 사용함.

  • HostPath 볼륨 마운트 : 노드의 실제 파일시스템을 직접 마운트 (iptalbes 규칙을 노드 커널에 직접 쓰기 때문)
    • /run/xtables.lock (rw) : iptables 잠금 파일
    • /lib/modules (ro) : 커널 모듈
    • /var/log (rw) : 로그 파일

  • Tolerations : op=Exists → 모든 taint 허용
    • 노드 상태가 나빠도 절대 쫓겨나지 않습니다.
    • 노드가 not-ready 상태여도 kube-proxy는 계속 실행돼야 네트워크 복구가 가능하기 때문에.

  • kube-proxy의 configmap 설정 (kubeconfig)
server: https://e2f77ed0429bbb82740c7c2a9ebcf47e.gr7.ap-northeast-2.eks.amazonaws.com
tokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token

kube-proxy가 EKS API Server에 접근하는 방식이며, ServiceAccount 토큰으로 인증합니다.
(아까 STS 방식과 다르게 내부 ServiceAccount 토큰을 사용함)

kubectl (외부) → STS 토큰으로 인증
kube-proxy (내부) → ServiceAccount 토큰으로 인증

 

  • kube-proxy-config (핵심 설정)
bindAddress: 0.0.0.0 → 모든 인터페이스에서 수신한다는 의미 (특정IP로 제한X)

contrack → Linux 커널의 연결 상태 추적 테이블을 의미하며,
Service 트래픽의 NAT 상태를 추적하는데 사용한다. (값이 너무 낮으면 대규모 트래픽 시 연결이 끊김)

 - maxperCore : CPU 코어당 최대 연결 추적 수
 - min : 최소 연결 추적 수
 - tcpEstablishedTimeout : TCP 연결 유지 시간
 - tcpCloseWaitTimeout : CLOSE_WAIT 타임아웃

iptables: → 동기화 주기를 의미

 - syncPeriod : 30초마다 iptables 규칙 동기화
 - minSyncPeriod : 변경 감지 시 즉시 동기화
 - masqueradeAll : 전체 SNAT 비활성화
 - masqueradeBit : SNAT 마킹 비트

mode: "iptables" → Service에서 Pod 라우팅을 Linux iptables 규칙으로 구현한다는 의미.

 


 

3-5. Core DNS 상세 정보 확인

kubectl describe pod -n kube-system -l k8s-app=kube-dns
kubectl get cm -n kube-system coredns -o yaml
kubectl get pdb -n kube-system coredns -o jsonpath='{.spec}' | jq

  • Priority Class
    • 메모리 부족 시 일반 Pod보다 먼저 보호되는 높은 우선순위 (kube-proxy 보다 낮음)
    • core dns가 죽으면 클러스터 전체 DNS 조회가 불가능해져서 모든 서비스 간 통신이 마비되기 떄문
  • Pod IP
    • 노드 IP와 다른 별도의 Pod IP가 할당됨
    • vpc-cni가 VPC 서브넷 대역에서 직접 IP를 할당한다. (DNS 요청을 받아야 하므로 자체 IP 필요함)

  • VolumMount : kube-proxy와 다르게 hostPath 등 마운트 없음.
  • Toleration : op=Exists가 아닌 옵션을 제외하고 모든 taint 허용.
    • control-plane:NoSchedule : Control Plane 노드에도 배포 가능 (on-prem 환경 고려)
    • not-ready / unreachable for 300s : 노드에 문제가 생겨도 5분간 대기 후 다른 노드로 이동

  • Core Dns의 configmap 설정
.:53  → 모든 도메인에 대해 53번 포트로 수신
errors → DNS쿼리 처리 중 발생하는 에러를 로그로 출력

health {
       lameduck 5s → Pod 종료 시 5초간 헬스체크를 실패 상태로 반환해서 트래픽을 먼저 차단한 후 종료.
}
→ http://:8080/health 엔드포인트 활성화
→ describe Pod에서 봤던 Liveness Probe가 여기로 요청을 보냄

ready
→ http://:8181/ready 엔트포인트 활성화
→ describe Pod에서 봤던 Readiness Probe가 여기로 요청을 보냄

kubernetes cluster.local in-addr.arpa ip6.arpa {
    pods insecure
    fallthrough in-addr.arpa ip6.arpa
}
→ 클러스터 내부 DNS 도메인 처리의 핵심 플러그인
→ cluster.local : k8s 서비스 도메인 처리

forware . /etc/resolv/conf → cluster.local로 끝나지 않는 외부 도메인 쿼리를 상위 DNS로 전달

 

  • Core DNS의 PDB 설정
    • 자발적 중단(Voluntary Disruption)시 동시에 중단 가능한 Pod 수를 제한하는 정책.
    • 자발적 중단 예시 : node drain (upgrade, 점검 등) , deployment 롤링 업데이트 등.
    • 단, 하드웨어 장애같은 비자발적 중단은 PDB로 막을 수 없다!

 


 

04. add-on 정보 확인

클러스터에 설치된 Addon 목록을 확인해보자.

aws eks list-addons --cluster-name myeks | jq

{
    "addons": [
        "coredns",
        "kube-proxy",
        "vpc-cni"
    ]
}

 

현재 위와 같이 coredns, kube-proxy, vpc-cni의 추가 기능을 사용하는 것 확인해보았습니다.

 

아래와 같이 자세하게 볼 수도 있습니다.

# coredns
aws eks describe-addon --cluster-name myeks --addon-name coredns | jq

# kube-proxy
aws eks describe-addon --cluster-name myeks --addon-name kube-proxy | jq

# vpc-cni
aws eks describe-addon --cluster-name myeks --addon-name vpc-cni | jq

 

vpc-cni로 한번 살펴볼까요?

  • 현재 ACTIVE 상태이고, 문제 발생 시 health.issues에 에러가 기록됩니다.
  • 1.21.1 버전을 사용중이고, eksbuild.5는 AWS가 EKS용으로 빌드한 패치 번호를 의미합니다.
    • eks.tf에서 'most_recent = true'로 설정했기 때문에 k8s 1.32와 호환되는 최신 버전이 자동 선택됨.
  • kube-system의 네임스페이스에서 동작하는 것까지 확인이 가능합니다!

추가적으로 AWS Console → 클러스터 → 내 클러스터 선택 → 추가기능 에서도 확인이 가능합니다.