Post

AEWS 1주차 정리

Arch Linux에서 AWS CLI 설치 및 EKS 구축 구축 과정 기록

🔑 1. IAM User 생성

AWS IAM에서 관리 권한이 있는 사용자를 생성

  1. IAM 콘솔 접속

    AWS 콘솔에서 IAM 서비스로 이동

  2. 사용자 추가
    • 사용자 이름: eks-user (예시)
    • 권한 설정: AdministratorAccess (모든 권한 부여)
  3. 생성 완료

    생성된 IAM 사용자의 액세스 키를 안전하게 보관

Image

🔐 2. Access Key 발급

IAM 사용자(eks-user)의 Access Key를 생성하여 인증 정보 확보

  1. IAM 콘솔에서 사용자 선택
    • IAM → Userseks-user 선택
  2. Access Key 생성
    • Security credentials(보안 자격 증명) 탭 이동
    • Create access key 클릭
  3. Access Key 저장
    • 생성된 Access Key IDSecret Access Key를 안전한 곳에 보관
    • Secret Access Key는 이후 다시 확인할 수 없으므로 주의

Image Image

📥 3. AWS CLI 설치 및 설정

로컬 PC에서 AWS CLI를 설치하고 Access Key를 설정

1. AWS CLI 설치

Arch Linux에서 yay를 사용하여 AWS CLI v2 설치

1
yay -S aws-cli-v2

2. AWS CLI 인증 정보 설정

발급받은 Access Key를 사용하여 AWS CLI 설정

1
aws configure

입력값

  • AWS Access Key ID: 발급받은 Access Key ID
  • AWS Secret Access Key: 발급받은 Secret Access Key
  • Default region name: ap-northeast-2 (서울 리전, 원하는 리전 선택 가능)
  • Default output format: json 또는 yaml (기본값: json)

🔑 4. AWS CLI를 이용한 Key Pair 생성

AWS CLI를 사용하여 EC2 인스턴스에서 사용할 Key Pair 생성

1. Key Pair 생성

아래 명령어를 실행하여 Key Pair를 생성하고 .pem 파일로 저장

1
aws ec2 create-key-pair --key-name kp-aews --query "KeyMaterial" --output text > kp-aews.pem

2. 보안 설정 (권한 변경)

생성된 Key Pair 파일(.pem)의 권한을 변경하여 안전하게 보호

1
chmod 400 kp-aews.pem

💡 참고: kp-aews.pem 파일은 SSH 접속 시 사용되므로 안전하게 보관

📜 5. CloudFormation을 이용한 EKS 스택 배포

AWS CloudFormation을 사용하여 EKS 스택 배포

1. CloudFormation 스택 배포 실행

아래 명령어를 실행하여 CloudFormation을 통해 EKS 배포

1
2
3
4
5
6
# yaml 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/myeks-1week.yaml

# 배포
aws cloudformation deploy --template-file ~/Downloads/myeks-1week.yaml \
--stack-name myeks --parameter-overrides KeyName=kp-aews SgIngressSshCidr=$(curl -s [ipinfo.io/ip](http://ipinfo.io/ip))/32 --region ap-northeast-2

2. 배포 과정

  • myeks-1week.yaml 템플릿을 사용하여 EKS 스택 생성
  • KeyName=kp-aews: EC2 SSH 접속을 위한 Key Pair 지정
  • SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32: 현재 사용 중인 공인 IP에서만 SSH 접속 허용
  • -region ap-northeast-2: 서울 리전에 배포

3. 배포 완료 메시지 확인

배포가 정상적으로 완료되면 아래 메시지 출력

1
2
3
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - myeks

🖥️ 6. EC2 인스턴스에 SSH 접속

CloudFormation에서 생성된 EC2 인스턴스의 Public IP를 자동 조회하여 SSH 접속

1
ssh root@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)

기본 접속 정보

  • 사용자명: root
  • 비밀번호: qwe123

💡 이 정보는 CloudFormation 템플릿 파일에서 설정된 값

Image

🛡️ 7. IAM 사용자 자격 증명 설정 및 VPC 확인

AWS CLI를 사용하기 위해 IAM 사용자 자격 증명을 설정하고, EC2 인스턴스를 조회하여 VPC 정보 확인

1. 자격 증명 설정 필요 여부 확인

AWS CLI에서 EC2 인스턴스를 조회하려 하면, 자격 증명이 설정되지 않은 경우 아래 오류 발생

1
2
3
[root@myeks-host ~]# aws ec2 describe-instances

Unable to locate credentials. You can configure credentials by running "aws configure".

이 오류는 AWS CLI가 IAM 사용자 자격 증명(Access Key, Secret Key)을 찾을 수 없을 때 발생

2. AWS 자격 증명 설정

IAM 사용자 자격 증명을 설정하려면 아래 명령어 실행

1
2
3
4
5
[root@myeks-host ~]# aws configure
AWS Access Key ID [None]: XXXXXXXXXXXXXXXXXX
AWS Secret Access Key [None]: XXXXXXXXXXXXXXXXXX
Default region name [None]: ap-northeast-2
Default output format [None]: json

입력값

  • AWS Access Key ID: 발급받은 Access Key 입력
  • AWS Secret Access Key: 발급받은 Secret Access Key 입력
  • Default region name: ap-northeast-2 (서울 리전, 원하는 리전 선택 가능)
  • Default output format: json (필요 시 yaml 가능)

3. VPC 및 EC2 인스턴스 확인

IAM 자격 증명을 설정한 후, 다시 EC2 인스턴스를 조회하면 정상적으로 결과 출력

🌐 8. EKS 배포를 위한 VPC 정보 설정

EKS 배포에 필요한 VPC ID를 조회하고 환경 변수로 저장

1
2
3
4
[root@myeks-host ~]# export VPCID=$(aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq -r .Vpcs[].VpcId)
[root@myeks-host ~]# echo "export VPCID=$VPCID" >> /etc/profile
[root@myeks-host ~]# echo $VPCID
vpc-06b6b56c0362daea4

Image

🏗️ 9. EKS 배포를 위한 서브넷 설정

EKS 클러스터 배포에 필요한 퍼블릭 서브넷 ID를 조회하고 환경 변수로 설정

1. 퍼블릭 서브넷 ID 조회 및 환경 변수 설정

아래 명령어를 실행하여 퍼블릭 서브넷 ID를 조회하고 환경 변수에 저장

1
2
[root@myeks-host ~]# export PubSubnet1=$(aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet1" --query "Subnets[0].[SubnetId]" --output text)
[root@myeks-host ~]# export PubSubnet2=$(aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet2" --query "Subnets[0].[SubnetId]" --output text)

2. 설정 적용 및 유지

재부팅 후에도 유지되도록 /etc/profile에 추가

1
2
[root@myeks-host ~]# echo "export PubSubnet1=$PubSubnet1" >> /etc/profile
[root@myeks-host ~]# echo "export PubSubnet2=$PubSubnet2" >> /etc/profile

3. 설정 확인

환경 변수가 정상적으로 설정되었는지 확인

1
2
3
4
[root@myeks-host ~]# echo $PubSubnet1
subnet-03de214d67fde4926
[root@myeks-host ~]# echo $PubSubnet2
subnet-0f906344fd9149770

Image

🚀 10. EKS 클러스터 및 노드 그룹 배포

EKS 클러스터와 관리형 노드 그룹을 배포 (약 15분 소요)

1. 환경 변수 확인

설정된 환경 변수를 확인하여 올바르게 적용되었는지 확인

1
2
3
4
5
6
7
8
[root@myeks-host ~]# echo $AWS_DEFAULT_REGION
ap-northeast-2
[root@myeks-host ~]# echo $CLUSTER_NAME
myeks
[root@myeks-host ~]# echo $VPCID
vpc-06b6b56c0362daea4
[root@myeks-host ~]# echo $PubSubnet1,$PubSubnet2
subnet-03de214d67fde4926,subnet-0f906344fd9149770

2. 클러스터 배포 실행

아래 명령어를 실행하여 EKS 클러스터 및 관리형 노드 그룹 배포

1
2
eksctl create cluster --name $CLUSTER_NAME --region=$AWS_DEFAULT_REGION --nodegroup-name=$CLUSTER_NAME-nodegroup --node-type=t3.medium \
--node-volume-size=30 --vpc-public-subnets "$PubSubnet1,$PubSubnet2" --version 1.31 --ssh-access --external-dns-access --verbose 4

3. 배포 옵션 요약

  • 클러스터 및 관리형 노드 그룹 배포
  • t3.medium 인스턴스 사용, 30GB EBS 할당
  • 퍼블릭 서브넷에 배포
  • SSH 및 외부 DNS 액세스 허용

📡 11. EC2 인스턴스 생성 모니터링

EC2 인스턴스의 Public IP, Private IP, 인스턴스 상태를 실시간으로 모니터링

1. 실시간 모니터링

아래 명령어를 실행하여 EC2 인스턴스 상태를 실시간으로 확인

1
while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text ; echo "------------------------------" ; sleep 1; done

2. 현재 실행 중인 인스턴스 목록 조회

배포 완료 후 실행 중인 인스턴스를 확인하려면 아래 명령어 실행

1
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table

3. 배포 상태

배포중 (인스턴스가 생성되고 부팅 중)

Image 배포완료 (인스턴스가 정상적으로 실행됨)

Image

Image

🏢 12. EKS 클러스터 네임스페이스 및 엔드포인트 확인

EKS 클러스터의 네임스페이스를 설정하고, API 서버 엔드포인트 확인

1. 기본 네임스페이스 설정

EKS에서 기본 네임스페이스default로 변경

1
2
3
(eks-user@myeks:N/A) [root@myeks-host ~]# k ns default
Context "eks-user@myeks.ap-northeast-2.eksctl.io" modified.
Active namespace is "default".

2. EKS 클러스터 엔드포인트 확인

EKS API 서버의 엔드포인트 확인

1
2
(eks-user@myeks:default) [root@myeks-host ~]# aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint
https://F5010046882B83E478ED4CDA5EA08828.gr7.ap-northeast-2.eks.amazonaws.com

3. EKS API 서버 도메인의 IP 주소 조회

EKS API 서버의 도메인을 확인한 후 해당 도메인의 IP 주소 조회

1
2
3
4
(eks-user@myeks:default) [root@myeks-host ~]# APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
(eks-user@myeks:default) [root@myeks-host ~]# dig +short $APIDNS
3.37.179.56
3.37.34.120

설명

  • aws eks describe-cluster → 현재 배포된 클러스터의 API 서버 도메인 확인
  • dig +short → 해당 도메인의 공인 IP 주소 조회
  • 보통 NLB(Network Load Balancer)에 연결된 두 개의 고정 공인 IP를 확인할 수 있음

4. EKS API 서버에 직접 요청 (403 Forbidden 응답 확인)

EKS API 서버에 직접 요청 시 권한 부족(403 Forbidden) 오류 발생

1
2
3
4
5
6
7
8
9
10
11
(eks-user@myeks:default) [root@myeks-host ~]# curl -k -s $(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint)
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"/\"",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}

설명

  • API 서버는 인증되지 않은 요청을 거부 (403 Forbidden)
  • system:anonymous 사용자는 기본적으로 API 서버에 접근 권한 없음

5. EKS API 서버의 버전 정보 확인

API 서버의 /version 엔드포인트를 통해 클러스터의 Kubernetes 버전 정보 확인

1
https://f5010046882b83e478ed4cda5ea08828.gr7.ap-northeast-2.eks.amazonaws.com/version

Image

현재 API Server endpoint access는 Public으로 설정됨

Image

Auto Scaling groups 두 개가 배포됨

Image

설정한 값이 올바르게 반영됨

Image

🔍 13. EKS 노드 그룹 및 노드 정보 확인

EKS 클러스터의 노드 그룹 및 개별 노드 정보 조회

1. EKS 노드 그룹 정보 확인

EKS에 생성된 관리형 노드 그룹 확인

1
(eks-user@myeks:default) [root@myeks-host ~]# eksctl get nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup

출력

1
2
CLUSTER	NODEGROUP	STATUS	CREATED			MIN SIZE	MAX SIZE	DESIRED CAPACITY	INSTANCE TYPE	IMAGE ID	ASG NAME						TYPE
myeks	myeks-nodegroup	ACTIVE	2025-02-08T00:56:29Z	2		2	2			t3.medium	AL2_x86_64	eks-myeks-nodegroup-30ca7187-6636-6b8c-0211-b50c446338dd	managed

2. 개별 노드 정보 확인

EKS에 배포된 개별 노드의 세부 정보 조회

1
(eks-user@myeks:default) [root@myeks-host ~]# kubectl get node -owide

출력

1
2
3
NAME                                               STATUS   ROLES    AGE   VERSION               INTERNAL-IP     EXTERNAL-IP     OS-IMAGE         KERNEL-VERSION                  CONTAINER-RUNTIME
ip-192-168-1-206.ap-northeast-2.compute.internal   Ready    <none>   34m   v1.31.4-eks-aeac579   192.168.1.206   43.201.15.139   Amazon Linux 2   5.10.233-223.887.amzn2.x86_64   containerd://1.7.25
ip-192-168-2-123.ap-northeast-2.compute.internal   Ready    <none>   34m   v1.31.4-eks-aeac579   192.168.2.123   54.180.83.125   Amazon Linux 2   5.10.233-223.887.amzn2.x86_64   containerd://1.7.25

3. EKS API 서버와 자격증명 확인

EKS API 서버에 질의가 성공하면 IAM 자격증명이 정상적으로 통과됨

1
(eks-user@myeks:default) [root@myeks-host ~]# kubectl get node -v=6

출력 (자격증명 정상 작동 확인)

1
2
3
4
5
I0208 10:34:06.947941   10088 loader.go:395] Config loaded from file:  /root/.kube/config
I0208 10:34:07.854366   10088 round_trippers.go:553] GET https://F5010046882B83E478ED4CDA5EA08828.gr7.ap-northeast-2.eks.amazonaws.com/api/v1/nodes?limit=500 200 OK in 891 milliseconds
NAME                                               STATUS   ROLES    AGE   VERSION
ip-192-168-1-206.ap-northeast-2.compute.internal   Ready    <none>   36m   v1.31.4-eks-aeac579
ip-192-168-2-123.ap-northeast-2.compute.internal   Ready    <none>   36m   v1.31.4-eks-aeac579

자격증명 파일 확인

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
32
33
34
35
36
(eks-user@myeks:default) [root@myeks-host ~]# cat /root/.kube/config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJRy9USVhYbUhGdlF3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TlRBeU1EZ3dNRFEyTURKYUZ3MHpOVEF5TURZd01EVXhNREphTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUURQQ1RXRnZQSFAvdGRuSHVSa2k0L3BQN29iZDJDVXp1OEpoT29rVXhzQmxkcmZEMEE3QUxaSk1WOUIKc1p4QnVHMUthdWprVFZHNU5JdkVYZG1FS0NWSkQ0UFZFRWlNd29CTFA3ZkJaS2dmbjAwQ2JSNEdTbFRoK3krdAp5RWUrWGw1ZnpBSEswdVpFUU9WWWIrdkJhdnJzSFlLSEJYYlhmSitjdTVaU25DQmxsNThXTnVFNis5VzFHdWlWCkpLd2VvMHhlM0NGSHRBWXRGaTlUN1puQ29HTkorcW9xOGgyZjZKeHQ2K2RiZzJZVExiYjJoM20rRC9kODV3WW8KMC9XbDBCbGw0ZmJiZXFrWFNIYU1TYVMwc3p5Q1VsZDhKTmIrSmxTRS9TdlBsblFjR01RRkxSNzRxaW5tSjRZNAoveDZvRUJMbk1VQ0MrcWdkWnlUSXpKNFlmbCtaQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJUVFN4UHMxNWVEY3Eyd2U3RkYwTzlGQkpoNExqQVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQTVoODU0KzBxawpqV24vQWlsZXF6RFk4MHc1VFNEektpQXpqVzR3OEZ4SlZNUVpidEFUQ29KYUU1ZnpUaW5ZbUZTbXRpYTdLRW9iCk80NTkxWC94SlN4cFUxNTdiR2ZvblRPaDRQeWRFd1ZJTzdlOExJU3NqRmE4dFUwWUtwdWdGcDQ5N1ZxWUhqNnoKM3ZPajhVbFAzcVBGVUZVNHBKbzM4b2lzQmRnZmlVb3NpNUxHRVgrUEJhdFd2aWRVSmpaUVkrcGlkRVpEWjJIWApYTDcvQjVsTVBNZlF6V3hXcG9EbklweXQ0anJTS05DczJRVzJWMzExdFRDQXZMVkhUZURLejVpUnhvUEZGcXNvCjQ2RG9NQWIyd2NBTXFJcUxUeGZ5ZmJib052SHVkclNUWCtMamZNQnlzR1pWbWlkd1VUTm1Sck5STGNDNXZZcGsKdnJ3MG1tUnZqM0JKCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
    server: https://F5010046882B83E478ED4CDA5EA08828.gr7.ap-northeast-2.eks.amazonaws.com
  name: myeks.ap-northeast-2.eksctl.io
contexts:
- context:
    cluster: myeks.ap-northeast-2.eksctl.io
    namespace: default
    user: eks-user@myeks.ap-northeast-2.eksctl.io
  name: eks-user@myeks.ap-northeast-2.eksctl.io
current-context: eks-user@myeks.ap-northeast-2.eksctl.io
kind: Config
preferences: {}
users:
- name: eks-user@myeks.ap-northeast-2.eksctl.io
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      args:
      - eks
      - get-token
      - --output
      - json
      - --cluster-name
      - myeks
      - --region
      - ap-northeast-2
      command: aws
      env:
      - name: AWS_STS_REGIONAL_ENDPOINTS
        value: regional
      interactiveMode: IfAvailable
      provideClusterInfo: false

설명

  • Config loaded from file: /root/.kube/config 로그가 보이면 올바른 인증 정보가 로드된 것
  • GET ... 200 OK 응답이 확인되면 EKS API 서버에 정상적으로 접근 가능
  • kubectl 명령어 실행 시 문제가 없다면 IAM 역할이 올바르게 부여됨

📦 14. EKS 클러스터의 Pod 상태 확인

EKS 클러스터 내에서 실행 중인 시스템 Pod 정보 조회

1. kube-system 네임스페이스에서 실행 중인 Pod 확인

1
2
3
4
5
6
7
8
9
10
(eks-user@myeks:default) [root@myeks-host ~]# kubectl get pod -n kube-system
NAME                              READY   STATUS    RESTARTS   AGE
aws-node-84cmt                    2/2     Running   0          46m
aws-node-cbpp9                    2/2     Running   0          46m
coredns-9b5bc9468-p2xc5           1/1     Running   0          50m
coredns-9b5bc9468-w46h7           1/1     Running   0          50m
kube-proxy-8rw86                  1/1     Running   0          46m
kube-proxy-cfqch                  1/1     Running   0          46m
metrics-server-86bbfd75bb-qxsx7   1/1     Running   0          50m
metrics-server-86bbfd75bb-wzchv   1/1     Running   0          50m

2. 모든 네임스페이스에서 실행 중인 Pod 확인

1
2
3
4
5
6
7
8
9
10
(eks-user@myeks:default) [root@myeks-host ~]# kubectl get pod -A
NAMESPACE     NAME                              READY   STATUS    RESTARTS   AGE
kube-system   aws-node-84cmt                    2/2     Running   0          47m
kube-system   aws-node-cbpp9                    2/2     Running   0          47m
kube-system   coredns-9b5bc9468-p2xc5           1/1     Running   0          51m
kube-system   coredns-9b5bc9468-w46h7           1/1     Running   0          51m
kube-system   kube-proxy-8rw86                  1/1     Running   0          47m
kube-system   kube-proxy-cfqch                  1/1     Running   0          47m
kube-system   metrics-server-86bbfd75bb-qxsx7   1/1     Running   0          51m
kube-system   metrics-server-86bbfd75bb-wzchv   1/1     Running   0          51m

🛠️ 15. 배포된 Pod의 컨테이너 이미지 확인

클러스터에서 실행 중인 모든 Pod의 컨테이너 이미지 정보 조회

1
2
3
4
5
6
(eks-user@myeks:default) [root@myeks-host ~]# kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon/aws-network-policy-agent:v1.1.5-eksbuild.1
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/amazon-k8s-cni:v1.19.0-eksbuild.1
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/coredns:v1.11.3-eksbuild.1
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/kube-proxy:v1.31.2-minimal-eksbuild.3
2 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/metrics-server:v0.7.2-eksbuild.1

🌍 16. 워커 노드 접근 및 네트워크 정보 확인

EKS 클러스터의 워크 노드(Worker Node) IP를 확인하고 환경 변수로 설정

1. 실행 중인 EC2 인스턴스 및 IP 확인

EKS 노드 그룹에 포함된 인스턴스의 공인 IP(Public IP) 및 사설 IP(Private IP) 조회

1
(eks-user@myeks:default) [root@myeks-host ~]# aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table

출력

1
2
3
4
5
6
7
8
9
-----------------------------------------------------------------------------
|                             DescribeInstances                             |
+-----------------------------+----------------+----------------+-----------+
|        InstanceName         | PrivateIPAdd   |  PublicIPAdd   |  Status   |
+-----------------------------+----------------+----------------+-----------+
|  myeks-myeks-nodegroup-Node |  192.168.2.123 |  54.180.83.125 |  running  |
|  myeks-host                 |  192.168.1.100 |  52.78.0.68    |  running  |
|  myeks-myeks-nodegroup-Node |  192.168.1.206 |  43.201.15.139 |  running  |
+-----------------------------+----------------+----------------+-----------+

2. 노드의 Private IP를 환경 변수로 저장

각 노드의 사설 IP(Private IP)를 변수로 저장

1
2
(eks-user@myeks:default) [root@myeks-host ~]# N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address})
(eks-user@myeks:default) [root@myeks-host ~]# N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address})

출력

1
2
(eks-user@myeks:default) [root@myeks-host ~]# echo $N1, $N2
192.168.1.206, 192.168.2.123

변수를 시스템에 영구적으로 저장

1
2
(eks-user@myeks:default) [root@myeks-host ~]# echo "export N1=$N1" >> /etc/profile
(eks-user@myeks:default) [root@myeks-host ~]# echo "export N2=$N2" >> /etc/profile

✅ 노드 그룹 인스턴스의 네트워크 탭에서 각 노드의 Private IPv4 주소(192.168.1.206, 192.168.2.123) 확인 가능

Image

Image

🔄 17. 워커 노드 네트워크 설정 및 SSH 접속

EKS 워커 노드에 접근하여 네트워크 설정을 확인하고 SSH 접속을 테스트

1. 워커 노드에 Ping 테스트

EKS의 워커 노드는 기본 보안 그룹 설정에 의해 Ping 요청이 차단됨

1
2
(eks-user@myeks:default) [root@myeks-host ~]# ping -c 1 $N1
(eks-user@myeks:default) [root@myeks-host ~]# ping -c 1 $N2

출력

1
2
3
4
5
6
7
# ping -c 1 $N1 출력
--- 192.168.1.206 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

# ping -c 1 $N2 출력
--- 192.168.2.123 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms

2. 노드 보안 그룹 ID 확인 및 저장

노드가 속한 보안 그룹 ID(SG ID) 조회 및 환경 변수 저장

1
2
(eks-user@myeks:default) [root@myeks-host ~]# aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text
sg-0aa71fc3e9206738b
1
2
3
4
5
(eks-user@myeks:default) [root@myeks-host ~]# NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text)
(eks-user@myeks:default) [root@myeks-host ~]# echo $NGSGID
sg-0aa71fc3e9206738b
(eks-user@myeks:default) [root@myeks-host ~]# echo "export NGSGID=$NGSGID" >> /etc/profile

3. 보안 그룹에 Ping 허용 규칙 추가

EKS 워커 노드에 myeks-host (192.168.1.100)에서의 접근 허용

1
(eks-user@myeks:default) [root@myeks-host ~]# aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32

출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-0a4bdce9db2440e6a",
            "GroupId": "sg-0aa71fc3e9206738b",
            "GroupOwnerId": "378102432899",
            "IsEgress": false,
            "IpProtocol": "-1",
            "FromPort": -1,
            "ToPort": -1,
            "CidrIpv4": "192.168.1.100/32",
            "SecurityGroupRuleArn": "arn:aws:ec2:ap-northeast-2:378102432899:security-group-rule/sgr-0a4bdce9db2440e6a"
        }
    ]
}

4. Ping 테스트 (보안 그룹 수정 후 허용됨)

보안 그룹에서 ICMP가 허용되었으므로 Ping이 정상적으로 응답함

1
2
3
4
5
6
7
8
(eks-user@myeks:default) [root@myeks-host ~]# ping -c 2 $N1
PING 192.168.1.206 (192.168.1.206) 56(84) bytes of data.
64 bytes from 192.168.1.206: icmp_seq=1 ttl=255 time=0.416 ms
64 bytes from 192.168.1.206: icmp_seq=2 ttl=255 time=0.453 ms

--- 192.168.1.206 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1017ms
rtt min/avg/max/mdev = 0.416/0.434/0.453/0.027 ms
1
2
3
4
5
6
7
8
(eks-user@myeks:default) [root@myeks-host ~]# ping -c 2 $N2
PING 192.168.2.123 (192.168.2.123) 56(84) bytes of data.
64 bytes from 192.168.2.123: icmp_seq=1 ttl=255 time=1.09 ms
64 bytes from 192.168.2.123: icmp_seq=2 ttl=255 time=1.03 ms

--- 192.168.2.123 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 1.035/1.064/1.093/0.029 ms

5. SSH를 통한 워커 노드 접속

1
2
3
(eks-user@myeks:default) [root@myeks-host ~]# ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no ec2-user@$N1 hostname
Warning: Permanently added '192.168.1.206' (ECDSA) to the list of known hosts.
ip-192-168-1-206.ap-northeast-2.compute.internal
1
2
3
(eks-user@myeks:default) [root@myeks-host ~]# ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no ec2-user@$N2 hostname
Warning: Permanently added '192.168.2.123' (ECDSA) to the list of known hosts.
ip-192-168-2-123.ap-northeast-2.compute.internal

설명

  • i ~/.ssh/id_rsa → SSH 키 파일을 사용하여 접속
  • StrictHostKeyChecking=no → 첫 접속 시 Host Key 경고 방지

6. SSH로 직접 접속하여 워커 노드 로그인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(eks-user@myeks:default) [root@myeks-host ~]# ssh ec2-user@$N1
Last login: Mon Feb  3 23:56:27 2025 from 52.94.123.246
   ,     #_
   ~\_  ####_        Amazon Linux 2
  ~~  \_#####\
  ~~     \###|       AL2 End of Life is 2026-06-30.
  ~~       \#/ ___
   ~~       V~' '->
    ~~~         /    A newer version of Amazon Linux is available!
      ~~._.   _/
         _/ _/       Amazon Linux 2023, GA and supported until 2028-03-15.
       _/m/'           https://aws.amazon.com/linux/amazon-linux-2023/

8 package(s) needed for security, out of 8 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-192-168-1-206 ~]$ 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(eks-user@myeks:default) [root@myeks-host ~]# ssh ec2-user@$N2
Last login: Mon Feb  3 23:56:27 2025 from 52.94.123.246
   ,     #_
   ~\_  ####_        Amazon Linux 2
  ~~  \_#####\
  ~~     \###|       AL2 End of Life is 2026-06-30.
  ~~       \#/ ___
   ~~       V~' '->
    ~~~         /    A newer version of Amazon Linux is available!
      ~~._.   _/
         _/ _/       Amazon Linux 2023, GA and supported until 2028-03-15.
       _/m/'           https://aws.amazon.com/linux/amazon-linux-2023/

8 package(s) needed for security, out of 8 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-192-168-2-123 ~]$ 

관리형 Bastion 서버(192.168.1.100) 네트워크 정보 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(eks-user@myeks:default) [root@myeks-host ~]# ip -c a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 02:2e:b0:2f:d6:03 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.100/24 brd 192.168.1.255 scope global dynamic eth0
       valid_lft 2859sec preferred_lft 2859sec
    inet6 fe80::2e:b0ff:fe2f:d603/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:c1:03:5b:35 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

설명

  • eth0 (192.168.1.100) → 관리형 Bastion 서버의 내부 IP
  • docker0 (172.17.0.1) → Docker 네트워크 인터페이스
  • Bastion 서버를 통해 EKS 노드에 접근 가능

🕵️‍♂️ 18. 워커 노드 원격 명령 실행

1. SSH를 통한 원격 명령 실행 - 호스트 이름 확인

각 워커 노드에서 호스트 이름을 출력

1
(eks-user@myeks:default) [root@myeks-host ~]# for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i hostname; echo; done

출력

1
2
3
4
5
>> node 192.168.1.206 <<
ip-192-168-1-206.ap-northeast-2.compute.internal

>> node 192.168.2.123 <<
ip-192-168-2-123.ap-northeast-2.compute.internal

2. 네트워크 인터페이스 정보 확인

각 워커 노드에서 네트워크 인터페이스 및 IP 주소 정보 확인

1
(eks-user@myeks:default) [root@myeks-host ~]# for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c addr; echo; done

출력

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
>> node 192.168.1.206 <<
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 02:35:bc:e8:8b:b9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.206/24 brd 192.168.1.255 scope global dynamic eth0
       valid_lft 3122sec preferred_lft 3122sec
    inet6 fe80::35:bcff:fee8:8bb9/64 scope link 
       valid_lft forever preferred_lft forever
3: eni22d7019dbe2@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default 
    link/ether b2:53:43:26:9e:a7 brd ff:ff:ff:ff:ff:ff link-netns cni-99b00711-77a7-eb8b-591b-b21cdb7a10bd
    inet6 fe80::b053:43ff:fe26:9ea7/64 scope link 
       valid_lft forever preferred_lft forever
4: eni35d9a494c70@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default 
    link/ether 42:e9:58:0b:5f:65 brd ff:ff:ff:ff:ff:ff link-netns cni-fda91708-8d7a-41c7-913b-33a8408907ac
    inet6 fe80::40e9:58ff:fe0b:5f65/64 scope link 
       valid_lft forever preferred_lft forever
5: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 02:4b:ed:a7:73:5f brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.136/24 brd 192.168.1.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::4b:edff:fea7:735f/64 scope link 
       valid_lft forever preferred_lft forever

>> node 192.168.2.123 <<
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 0a:15:fc:9b:15:97 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.123/24 brd 192.168.2.255 scope global dynamic eth0
       valid_lft 3562sec preferred_lft 3562sec
    inet6 fe80::815:fcff:fe9b:1597/64 scope link 
       valid_lft forever preferred_lft forever
3: eni011365725ba@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default 
    link/ether 86:a6:7b:32:54:04 brd ff:ff:ff:ff:ff:ff link-netns cni-b3c96071-26ff-ad52-123c-dde85398a471
    inet6 fe80::84a6:7bff:fe32:5404/64 scope link 
       valid_lft forever preferred_lft forever
4: eni80387e350f8@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default 
    link/ether f2:fd:39:93:a1:15 brd ff:ff:ff:ff:ff:ff link-netns cni-9797bb40-a9e7-d43c-fe6c-9335d51bcb6e
    inet6 fe80::f0fd:39ff:fe93:a115/64 scope link 
       valid_lft forever preferred_lft forever
5: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 0a:58:fc:6a:2d:07 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.251/24 brd 192.168.2.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::858:fcff:fe6a:2d07/64 scope link 
       valid_lft forever preferred_lft forever

🔗 19. 워커 노드의 TCP 연결 상태 및 API 서버 연결 확인

EKS 워커 노드에서 현재 활성화된 TCP 연결을 확인하고, kubelet 및 kube-proxy가 API 서버와 어떻게 연결되는지 분석

1. 워커 노드에서 TCP 연결 상태 확인

각 워커 노드에서 현재 활성화된 TCP 연결 및 프로세스 정보 조회

1
(eks-user@myeks:default) [root@myeks-host ~]# for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ss -tnp; echo; done

출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>> node 192.168.1.206 <<
State Recv-Q Send-Q          Local Address:Port           Peer Address:Port Process                                                 
ESTAB 0      0               192.168.1.206:38756         52.95.195.109:443   users:(("ssm-agent-worke",pid=2462,fd=14))             
ESTAB 0      0               192.168.1.206:42540           3.37.179.56:443   users:(("aws-k8s-agent",pid=3366,fd=7))                
ESTAB 0      56              192.168.1.206:22            192.168.1.100:43702 users:(("sshd",pid=61805,fd=3),("sshd",pid=61773,fd=3))
ESTAB 0      0               192.168.1.206:53470           3.37.34.120:443   users:(("kube-proxy",pid=3109,fd=9))                   
ESTAB 0      0               192.168.1.206:48848            10.100.0.1:443   users:(("controller",pid=3482,fd=12))                  
ESTAB 0      0               192.168.1.206:57918           3.37.179.56:443   users:(("kubelet",pid=2889,fd=28))                     
ESTAB 0      0      [::ffff:192.168.1.206]:10250 [::ffff:192.168.1.21]:41106 users:(("kubelet",pid=2889,fd=13))                     
ESTAB 0      0      [::ffff:192.168.1.206]:10250 [::ffff:192.168.2.91]:45266 users:(("kubelet",pid=2889,fd=22))                     

>> node 192.168.2.123 <<
State Recv-Q Send-Q          Local Address:Port           Peer Address:Port Process                                                 
ESTAB 0      56              192.168.2.123:22            192.168.1.100:47978 users:(("sshd",pid=61493,fd=3),("sshd",pid=61461,fd=3))
ESTAB 0      0               192.168.2.123:32834            10.100.0.1:443   users:(("controller",pid=3499,fd=12))                  
ESTAB 0      0               192.168.2.123:60346           3.37.179.56:443   users:(("kube-proxy",pid=3113,fd=9))                   
ESTAB 0      0               192.168.2.123:47652           3.37.34.120:443   users:(("aws-k8s-agent",pid=3376,fd=7))                
ESTAB 0      0               192.168.2.123:40712          52.95.195.99:443   users:(("ssm-agent-worke",pid=2482,fd=14))             
ESTAB 0      0               192.168.2.123:35944           3.37.34.120:443   users:(("kubelet",pid=2896,fd=12))                     
ESTAB 0      0      [::ffff:192.168.2.123]:10250 [::ffff:192.168.1.21]:39610 users:(("kubelet",pid=2896,fd=13))                     
ESTAB 0      0      [::ffff:192.168.2.123]:10250 [::ffff:192.168.2.91]:49546 users:(("kubelet",pid=2896,fd=24))                     

2. 워커 노드의 API 서버 연결 분석

워커 노드 1 (Node1: 192.168.1.206)의 API 서버 연결

로컬 주소대상 (API 서버)연결된 프로세스설명
192.168.1.206:534703.37.179.56:443kube-proxykube-proxy가 API 서버와 연결
192.168.1.206:579183.37.34.120:443kubeletkubelet이 API 서버와 연결
  • Public 클러스터이므로 인터넷을 통해 API 서버와 통신
  • API 서버와의 연결이 외부 트래픽으로 나갔다가 다시 들어오는 구조

워커 노드 2 (Node2: 192.168.2.123)의 API 서버 연결

로컬 주소대상 (API 서버)연결된 프로세스설명
192.168.2.123:603463.37.179.56:443kube-proxykube-proxy가 API 서버와 연결
192.168.2.123:359443.37.34.120:443kubeletkubelet이 API 서버와 연결
  • Node1과 동일하게 Public 클러스터 방식으로 API 서버와 통신
  • 외부 네트워크를 통해 API 서버에 접근하는 구조

3. API 서버의 공인 IP 주소 확인

1
2
(eks-user@myeks:default) [root@myeks-host ~]# APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
(eks-user@myeks:default) [root@myeks-host ~]# dig +short $APIDNS

출력

1
2
3.37.34.120
3.37.179.56

설명

  • API 서버는 퍼블릭 네트워크를 통해 접근 가능
  • kube-proxy, kubeletEKS API 서버와 연결을 유지하며 상태를 동기화

Image

🛜 20. Netshoot 컨테이너를 이용한 네트워크 디버깅 및 API 서버 연결 확인

EKS 클러스터에서 Netshoot 컨테이너를 활용하여 네트워크 디버깅을 수행하고, API 서버와 kubelet 간의 연결 흐름을 분석

1. Netshoot 컨테이너 실행 및 네트워크 인터페이스 확인

Netshoot는 네트워크 디버깅 도구가 포함된 컨테이너 이미지

1.1 Netshoot 컨테이너 실행

1
2
3
4
5
6
7
8
9
10
11
(eks-user@myeks:default) [root@myeks-host ~]# kubectl run -it --rm netdebug --image=nicolaka/netshoot --restart=Never -- zsh
If you don't see a command prompt, try pressing enter.
                    dP            dP                           dP   
                    88            88                           88   
88d888b. .d8888b. d8888P .d8888b. 88d888b. .d8888b. .d8888b. d8888P 
88'  `88 88ooood8   88   Y8ooooo. 88'  `88 88'  `88 88'  `88   88   
88    88 88.  ...   88         88 88    88 88.  .88 88.  .88   88   
dP    dP `88888P'   dP   `88888P' dP    dP `88888P' `88888P'   dP   
                                                                    
Welcome to Netshoot! (github.com/nicolaka/netshoot)
Version: 0.13

1.2 Netshoot 컨테이너의 네트워크 인터페이스 확인

1
ip -c a

출력

1
2
3
4
5
6
7
8
9
10
11
12
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
3: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc noqueue state UP group default 
    link/ether 0e:d0:75:ed:87:3f brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.2.179/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::cd0:75ff:feed:873f/64 scope link 
       valid_lft forever preferred_lft forever

2. API 서버와 kubelet 연결 확인

2.1 Netshoot 컨테이너에서 kubelet 연결 감지

1
watch uptime

✅ 설명

  • 지속적인 API 호출을 발생시켜 네트워크 연결 변화를 감지 가능

2.2 워커 노드에서 TCP 연결 상태 확인

1
(eks-user@myeks:default) [root@myeks-host ~]# for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ss -tnp; echo; done

출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
>> node 192.168.1.206 <<
State Recv-Q Send-Q          Local Address:Port           Peer Address:Port Process                                                 
ESTAB 0      0               192.168.1.206:38756         52.95.195.109:443   users:(("ssm-agent-worke",pid=2462,fd=14))             
ESTAB 0      0               192.168.1.206:42540           3.37.179.56:443   users:(("aws-k8s-agent",pid=3366,fd=7))                
ESTAB 0      56              192.168.1.206:22            192.168.1.100:51074 users:(("sshd",pid=71668,fd=3),("sshd",pid=71636,fd=3))
ESTAB 0      0               192.168.1.206:53470           3.37.34.120:443   users:(("kube-proxy",pid=3109,fd=9))                   
ESTAB 0      0               192.168.1.206:48848            10.100.0.1:443   users:(("controller",pid=3482,fd=12))                  
ESTAB 0      0               192.168.1.206:57918           3.37.179.56:443   users:(("kubelet",pid=2889,fd=28))                     
ESTAB 0      0      [::ffff:192.168.1.206]:10250 [::ffff:192.168.1.21]:41106 users:(("kubelet",pid=2889,fd=13))                     
ESTAB 0      0      [::ffff:192.168.1.206]:10250 [::ffff:192.168.2.91]:45266 users:(("kubelet",pid=2889,fd=22))                     

>> node 192.168.2.123 <<
State Recv-Q Send-Q          Local Address:Port            Peer Address:Port Process                                                 
ESTAB 0      56              192.168.2.123:22             192.168.1.100:34654 users:(("sshd",pid=72153,fd=3),("sshd",pid=72121,fd=3))
ESTAB 0      0                   127.0.0.1:52426              127.0.0.1:34123 users:(("kubelet",pid=2896,fd=27))                     
ESTAB 0      0               192.168.2.123:32834             10.100.0.1:443   users:(("controller",pid=3499,fd=12))                  
ESTAB 0      0               192.168.2.123:60346            3.37.179.56:443   users:(("kube-proxy",pid=3113,fd=9))                   
ESTAB 0      0               192.168.2.123:47652            3.37.34.120:443   users:(("aws-k8s-agent",pid=3376,fd=7))                
ESTAB 0      0                   127.0.0.1:34123              127.0.0.1:52426 users:(("containerd",pid=2770,fd=88))                  
ESTAB 0      0               192.168.2.123:40712           52.95.195.99:443   users:(("ssm-agent-worke",pid=2482,fd=14))             
ESTAB 0      0               192.168.2.123:35944            3.37.34.120:443   users:(("kubelet",pid=2896,fd=12))                     
ESTAB 0      0      [::ffff:192.168.2.123]:10250  [::ffff:192.168.1.21]:39610 users:(("kubelet",pid=2896,fd=13))                     
ESTAB 0      0      [::ffff:192.168.2.123]:10250 [::ffff:192.168.2.163]:47628 users:(("kubelet",pid=2896,fd=26))                     
ESTAB 0      0      [::ffff:192.168.2.123]:10250  [::ffff:192.168.2.91]:49546 users:(("kubelet",pid=2896,fd=24)) 

kubelet 프로세스(PID 2896)가 EKS Owned ENI(192.168.2.163)와 연결됨

1
ESTAB 0      0      [::ffff:192.168.2.123]:10250 [::ffff:192.168.2.163]:47628 users:(("kubelet",pid=2896,fd=26))

Image

✅ 설명

  • 192.168.2.123:10250 → Worker Node 2의 kubelet API 포트
  • 192.168.2.163:47628 → EKS Owned ENI (API 서버가 사용하는 ENI)
  • kubelet이 EKS Owned ENI를 통해 API 서버와 연결됨

3. Netshoot 컨테이너 종료 후 연결 변화 확인

1
2
3
exit
pod "netdebug" deleted
pod default/netdebug terminated (Error)

✅ 종료 후 TCP 연결 확인

1
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ss -tnp; echo; done
1
ESTAB 0      0      [::ffff:192.168.2.123]:10250 [::ffff:192.168.2.163]:47628 users:(("kubelet",pid=2896,fd=26))

🚀 Netshoot 종료 후, API 서버와 kubelet 간의 연결이 사라짐

4. API 서버와 EKS Owned ENI 연결 흐름

연결 흐름 요약

kubectl 실행 → API 서버 호출 (공인 IP) → EKS Owned ENI 경유 → 워커 노드 kubelet

✅ 설명

  • Public Cluster Endpoint Access 환경에서도 API 서버는 내부 네트워크를 통해 kubelet과 연결됨
  • kubelet은 EKS Owned ENI를 통해 API 서버와 통신

🚀 퍼블릭 엔드포인트를 사용해도 내부적으로 kubelet과 통신할 때는 Private 네트워크를 사용

5. EKS Owned ENI의 소유권 분석

ImageEKS Owned ENI는 내 AWS 계정(378102432899) 소유이지만, 연결된 EC2 인스턴스의 소유자는 AWS(514342867336)

소유권 차이 분석

  • ENI(네트워크 인터페이스)는 AWS 계정(378102432899) 소유
  • 해당 ENI가 연결된 EC2 인스턴스는 AWS 관리형 리소스

🚀 즉, API 서버는 퍼블릭 엔드포인트를 제공하지만 내부적으로 kubelet과 통신할 때는 Private 네트워크를 사용하며 보안성과 관리 편의성을 유지함


🔧 EKS Cluster Endpoint를 Public(IP제한)+Private 로 변경

EKS 클러스터의 API Server Endpoint 설정을 Public(제한된 IP만 접근 가능) + Private로 변경하여, 내부 트래픽은 Private Endpoint를 사용하고 외부 트래픽은 특정 IP에서만 접근할 수 있도록 설정

1. 현재 설정 확인

현재 API Server Endpoint 상태

  • Public Endpoint 활성화 (0.0.0.0/0 허용)
  • Private Endpoint 비활성화

Image

클러스터 도메인 주소 (F5010046882B83E478ED4CDA5EA08828.gr7.ap-northeast-2.eks.amazonaws.com) 확인

Image

API 서버 도메인 조회

1
while true; do dig +short F5010046882B83E478ED4CDA5EA08828.gr7.ap-northeast-2.eks.amazonaws.com ; echo "------------------------------" ; date; sleep 1; done

출력

1
2
3
4
3.37.34.120
3.37.179.56
------------------------------
Sat Feb  8 04:28:56 PM KST 2025
  • 현재 API 서버 도메인이 공인 IP를 응답하는 상태

2. 노드와 Control Plane 간의 통신 상태 모니터링

kube-proxy, kubelet이 어떤 IP와 연결되는지 모니터링

1
2
3
N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address})
N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address})
while true; do ssh ec2-user@$N1 sudo ss -tnp | egrep 'kubelet|kube-proxy' ; echo ; ssh ec2-user@$N2 sudo ss -tnp | egrep 'kubelet|kube-proxy' ; echo "------------------------------" ; date; sleep 1; done

설명

  • kube-proxy, kubelet이 현재 공인 IP를 통해 API 서버와 통신 중
  • 변경 후, 내부 네트워크에서는 Private IP를 사용하도록 확인할 예정

3. EKS 클러스터 Endpoint 설정 변경

Public Endpoint를 특정 IP(50.1.1.1)만 접근 가능하도록 제한, Private Endpoint 활성화

1
aws eks update-cluster-config --region $AWS_DEFAULT_REGION --name $CLUSTER_NAME --resources-vpc-config endpointPublicAccess=true,publicAccessCidrs="50.1.1.1/32",endpointPrivateAccess=true

설명

  • endpointPublicAccess=true → Public Endpoint 유지
  • publicAccessCidrs="50.1.1.1/32"외부에서 50.1.1.1 IP에서만 접근 가능 (강의와 동일하게 설정함.. 테스트 꼬임방지)
  • endpointPrivateAccess=trueVPC 내부에서 Private Endpoint 사용 가능

업데이트 진행 중인 상태 확인

Image

4. 변경된 API 서버 도메인 정보 확인

API 서버 엔드포인트 조회

1
2
3
4
(eks-user@myeks:default) [root@myeks-host ~]# APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
(eks-user@myeks:default) [root@myeks-host ~]# dig +short $APIDNS
3.37.179.56
3.37.34.120

변경 후 지속적인 확인

1
2
3
4
5
(eks-user@myeks:default) [root@myeks-host ~]# while true; do dig +short $APIDNS ; echo "------------------------------" ; date; sleep 1; done
3.37.34.120
3.37.179.56
------------------------------
Sat Feb  8 16:38:45 KST 2025

업데이트 완료

Public과 Private Endpoint가 적용되어, 내부에서는 Private IP를, 외부에서는 Public IP를 반환하는 것을 확인할 수 있다.

Image

5. 도메인 질의 응답 결과 비교

VPC 내부에서 실행한 도메인 질의 결과 (Private Endpoint 확인) - 오른쪽 상단

  • 내부에서는 EKS Owned ENI의 Private IP가 반환됨
  • 내부 네트워크에서 API 서버에 직접 연결 가능

외부에서 실행한 도메인 질의 결과 (Public Endpoint 확인) - 오른쪽 하단

  • 외부에서는 Public IP가 반환됨
  • 설정한 Public Access CIDR(허용된 IP 범위 내)에서만 접근 가능

Image

✅ 결과 분석

  • 내부 VPC 환경에서는 Private IP를 사용하여 API 서버에 접근 가능
  • 외부에서는 Public IP를 통해 제한된 접근만 가능
  • Private Endpoint 활성화 후 kubeletkube-proxy가 내부 네트워크를 통해 통신하도록 설정 완료

6. EKS Owned ENI 적용 및 보안 그룹 설정

EKS API 서버가 Owned ENI를 사용하도록 변경됨

  • 내부 VPC에서 API 서버에 접근할 때 EKS Owned ENI의 Private IP가 반환됨
  • VPC 내 Bastion Host가 EKS Owned ENI로 접근해야 함
  • 하지만 현재 외부에서는 여전히 Public IP를 반환 중

6-1. EKS Control Plane 보안 그룹에 작업용 EC2 접근 허용

EKS Owned ENI를 통해 내부 네트워크에서 API 서버에 접근하기 위해, Control Plane 보안 그룹에 접근 허용 룰을 추가

Control Plane 보안 그룹 ID 확인

1
2
3
4
# EKS ControlPlane 보안그룹 ID 확인
(eks-user@myeks:default) [root@myeks-host ~]# CPSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*ControlPlaneSecurityGroup* --query "SecurityGroups[*].[GroupId]" --output text)
(eks-user@myeks:default) [root@myeks-host ~]# echo $CPSGID
sg-0b8417747083986a6

Bastion Host(192.168.1.100)에서 API 서버 접근 허용 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 노드 보안그룹에 eksctl-host 에서 노드(파드)에 접속 가능하게 룰(Rule) 추가 설정
(eks-user@myeks:default) [root@myeks-host ~]# aws ec2 authorize-security-group-ingress --group-id $CPSGID --protocol '-1' --cidr 192.168.1.100/32
{
    "Return": true,
    "SecurityGroupRules": [
        {
            "SecurityGroupRuleId": "sgr-0e1cbc756c940c815",
            "GroupId": "sg-0b8417747083986a6",
            "GroupOwnerId": "378102432899",
            "IsEgress": false,
            "IpProtocol": "-1",
            "FromPort": -1,
            "ToPort": -1,
            "CidrIpv4": "192.168.1.100/32",
            "SecurityGroupRuleArn": "arn:aws:ec2:ap-northeast-2:378102432899:security-group-rule/sgr-0e1cbc756c940c815"
        }
    ]
}

6-2. 업데이트 후 다시 도메인 질의

1
2
3
APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
dig +short $APIDNS
while true; do dig +short $APIDNS ; echo "------------------------------" ; date; sleep 1; done

이제 VPC 내부에서 API 서버 도메인을 질의하면, EKS Owned ENI의 Private IP가 반환됨

✅ 내부 트래픽이 Public IP를 거치지 않고 Private 네트워크에서 처리됨

Image

EKS API 서버의 도메인 질의 결과가 EKS Owned ENI로 변경된 것을 확인할 수 있음

VPC 내부에서 API 서버 도메인을 질의하면,

  • 동일한 도메인이지만 EKS Owned ENI의 Private IP를 반환
  • 내부 네트워크에서 API 서버와 Private 통신 가능

🚀 즉, 내부 트래픽은 Public IP를 거치지 않고 Private 네트워크에서 처리됨

Image

7. kube-proxykubelet의 API 서버 연결 방식 변경

기존 상태

  • kube-proxykubelet공인 IP(예: 3.37.34.120, 3.37.179.56) 를 통해 API 서버와 통신
  • 내부 네트워크에서도 트래픽이 외부로 나갔다가 다시 API 서버로 전달되는 구조

출력 (변경 전 상태)

1
2
3
4
5
6
7
8
9
10
11
12
------------------------------
Sat Feb  8 16:56:19 KST 2025
ESTAB 0      0               192.168.1.206:53470           3.37.34.120:443   users:(("kube-proxy",pid=3109,fd=9))                     
ESTAB 0      0               192.168.1.206:57918           3.37.179.56:443   users:(("kubelet",pid=2889,fd=28))                       
ESTAB 0      0      [::ffff:192.168.1.206]:10250 [::ffff:192.168.1.21]:41106 users:(("kubelet",pid=2889,fd=13))                       
ESTAB 0      0      [::ffff:192.168.1.206]:10250 [::ffff:192.168.2.91]:45266 users:(("kubelet",pid=2889,fd=22))                       

ESTAB 0      0               192.168.2.119:41294           3.37.34.120:443   users:(("kubelet",pid=2892,fd=26))                       
ESTAB 0      0               192.168.2.119:34822           3.37.179.56:443   users:(("kube-proxy",pid=3170,fd=9))                     
ESTAB 0      0      [::ffff:192.168.2.119]:10250 [::ffff:192.168.1.21]:52840 users:(("kubelet",pid=2892,fd=12))                       
ESTAB 0      0      [::ffff:192.168.2.119]:10250 [::ffff:192.168.2.91]:33510 users:(("kubelet",pid=2892,fd=15))                       
------------------------------

설정 변경 적용 (kube-proxy가 내부 네트워크를 통해 API 서버와 연결되도록 수정)

kube-proxy 데몬셋 재시작

1
2
(eks-user@myeks:default) [root@myeks-host ~]# kubectl rollout restart ds/kube-proxy -n kube-system
daemonset.apps/kube-proxy restarted

✅ 변경 후 kube-proxy의 API 서버 접근 방식 확인

kube-proxyPublic IP(3.37.34.120:443)가 아닌 EKS Owned ENI의 Private IP(192.168.1.219)로 API 서버에 연결됨

1
2
3
4
5
6
7
8
9
10
11
12
------------------------------
Sat Feb  8 17:05:07 KST 2025
ESTAB 0      0               192.168.1.206:35464         192.168.1.219:443   users:(("kube-proxy",pid=243935,fd=9))                   
ESTAB 0      0               192.168.1.206:57918           3.37.179.56:443   users:(("kubelet",pid=2889,fd=28))                       
ESTAB 0      0      [::ffff:192.168.1.206]:10250 [::ffff:192.168.1.21]:41106 users:(("kubelet",pid=2889,fd=13))                       
ESTAB 0      0      [::ffff:192.168.1.206]:10250 [::ffff:192.168.2.91]:45266 users:(("kubelet",pid=2889,fd=22))                       

ESTAB 0      0               192.168.2.119:49312         192.168.1.219:443   users:(("kube-proxy",pid=144393,fd=9))                   
ESTAB 0      0               192.168.2.119:41294           3.37.34.120:443   users:(("kubelet",pid=2892,fd=26))                       
ESTAB 0      0      [::ffff:192.168.2.119]:10250 [::ffff:192.168.1.21]:52840 users:(("kubelet",pid=2892,fd=12))                       
ESTAB 0      0      [::ffff:192.168.2.119]:10250 [::ffff:192.168.2.91]:33510 users:(("kubelet",pid=2892,fd=15))                       
------------------------------

kubelet도 동일하게 변경 적용

각 노드에서 kubelet을 재시작하여 설정 반영

1
2
3
4
(eks-user@myeks:default) [root@myeks-host ~]# for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo systemctl restart kubelet; echo; done
>> node 192.168.1.206 <<

>> node 192.168.2.123 <<

변경 후 kubelet의 API 서버 접근 방식 확인

  • 변경 전: 3.37.179.56:443 (Public IP)
  • 변경 후: 192.168.2.163:443 (EKS Owned ENI의 Private IP)
1
2
3
4
5
6
7
8
9
10
11
12
------------------------------
Sat Feb  8 17:09:05 KST 2025
ESTAB 0      0               192.168.1.206:35464         192.168.1.219:443   users:(("kube-proxy",pid=243935,fd=9))                   
ESTAB 0      0               192.168.1.206:51064         192.168.2.163:443   users:(("kubelet",pid=252609,fd=18))                     
ESTAB 0      0      [::ffff:192.168.1.206]:10250 [::ffff:192.168.1.21]:48944 users:(("kubelet",pid=252609,fd=23))                     
ESTAB 0      0      [::ffff:192.168.1.206]:10250 [::ffff:192.168.2.91]:37384 users:(("kubelet",pid=252609,fd=24))                     

ESTAB 0      0               192.168.2.119:49312         192.168.1.219:443   users:(("kube-proxy",pid=144393,fd=9))                   
ESTAB 0      0               192.168.2.119:41294           3.37.34.120:443   users:(("kubelet",pid=2892,fd=26))                       
ESTAB 0      0      [::ffff:192.168.2.119]:10250 [::ffff:192.168.1.21]:52840 users:(("kubelet",pid=2892,fd=12))                       
ESTAB 0      0      [::ffff:192.168.2.119]:10250 [::ffff:192.168.2.91]:33510 users:(("kubelet",pid=2892,fd=15))                       
------------------------------

결과

  • 내부 네트워크에서 kubeletkube-proxy가 Public IP를 거치지 않고 API 서버에 직접 연결
  • EKS Owned ENI를 활용하여 내부 트래픽이 Private 네트워크에서 처리됨
  • API 서버 보안 강화 및 네트워크 성능 최적화 완료

선언형 (멱등성) 알아보기

1. 파드 생성 및 모니터링

터미널 1: 실시간으로 파드 상태를 모니터링

1
watch -d 'kubectl get pod'

터미널 2: Deployment를 생성하고 레플리카(3개) 설정

1
kubectl create deployment my-webs --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --replicas=3

Image

2. 파드 개수 조정 (확장 & 축소)

파드 개수 증가 (3개 → 6개)

1
kubectl scale deployment my-webs --replicas=6 && kubectl get pod -w

Image

파드 개수 감소 (6개 → 3개)

1
2
# 파드 감소
kubectl scale deployment my-webs --replicas=3

Image

Image

3. 강제 삭제 후 자동 복구 확인

모든 파드 삭제 (강제 제거)

1
2
3
```bash
kubectl delete pod --all && kubectl get pod -w

Image

삭제 후에도 Deployment 설정에 따라 자동으로 3개가 다시 생성됨

Image

결과: Kubernetes는 선언형 방식으로 관리되므로,

  • Deployment에서 설정한 replicas=3에 맞춰 자동으로 파드를 복구
  • 이를 통해 멱등성(Idempotency) 개념을 실습 가능

실습 완료 후 Deployment 삭제

1
kubectl delete deploy my-webs

EC2 및 EKS 노드 그룹 모니터링 & 확장 실습

1. EC2 인스턴스 실시간 모니터링

현재 실행 중인 EC2 인스턴스 상태를 지속적으로 확인

1
while true; do aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text ; echo "------------------------------" ; sleep 1; done

결과

  • EC2 인스턴스의 Public/Private IP, 이름, 상태를 실시간으로 출력
  • 클러스터 노드의 증가/감소 상태를 모니터링 가능

2. 현재 EKS 노드 그룹 정보 확인

1
eksctl get nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup

3. EKS 노드 그룹 크기 확장 (2개 → 3개로 증가)

기존 노드 개수(2개)를 3개로 확장

1
2
# 노드 2개 → 3개 증가
eksctl scale nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup --nodes 3 --nodes-min 3 --nodes-max 6

결과

  • 새로운 노드 (192.168.2.119)가 추가됨
  • 기존 2개 → 3개로 확장 완료
  • 클러스터 노드 개수 조정
    • 최소 3개 (-nodes-min=3)
    • 최대 6개 (-nodes-max=6)
    • 현재 3개 (-nodes=3)

🚀 확장 후, 192.168.2.119 노드가 추가되어 클러스터 용량 증가

Image

This post is licensed under CC BY 4.0 by the author.