AEWS 1주차 정리
Arch Linux에서 AWS CLI 설치 및 EKS 구축 구축 과정 기록
🔑 1. IAM User 생성
AWS IAM에서 관리 권한이 있는 사용자를 생성
IAM 콘솔 접속
AWS 콘솔에서 IAM 서비스로 이동
- 사용자 추가
- 사용자 이름:
eks-user
(예시) - 권한 설정:
AdministratorAccess
(모든 권한 부여)
- 사용자 이름:
생성 완료
생성된 IAM 사용자의 액세스 키를 안전하게 보관
🔐 2. Access Key 발급
IAM 사용자(eks-user
)의 Access Key를 생성하여 인증 정보 확보
- IAM 콘솔에서 사용자 선택
- IAM → Users →
eks-user
선택
- IAM → Users →
- Access Key 생성
- Security credentials(보안 자격 증명) 탭 이동
- Create access key 클릭
- Access Key 저장
- 생성된 Access Key ID와 Secret Access Key를 안전한 곳에 보관
- Secret Access Key는 이후 다시 확인할 수 없으므로 주의
📥 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 템플릿 파일에서 설정된 값
🛡️ 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
🏗️ 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
🚀 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. 배포 상태
배포중 (인스턴스가 생성되고 부팅 중)
🏢 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
✅ 현재 API Server endpoint access는 Public으로 설정됨
✅ Auto Scaling groups 두 개가 배포됨
✅ 설정한 값이 올바르게 반영됨
🔍 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) 확인 가능
🔄 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:53470 | 3.37.179.56:443 | kube-proxy | kube-proxy가 API 서버와 연결 |
192.168.1.206:57918 | 3.37.34.120:443 | kubelet | kubelet이 API 서버와 연결 |
- Public 클러스터이므로 인터넷을 통해 API 서버와 통신
- API 서버와의 연결이 외부 트래픽으로 나갔다가 다시 들어오는 구조
워커 노드 2 (Node2: 192.168.2.123)의 API 서버 연결
로컬 주소 | 대상 (API 서버) | 연결된 프로세스 | 설명 |
---|---|---|---|
192.168.2.123:60346 | 3.37.179.56:443 | kube-proxy | kube-proxy가 API 서버와 연결 |
192.168.2.123:35944 | 3.37.34.120:443 | kubelet | kubelet이 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
,kubelet
이 EKS API 서버와 연결을 유지하며 상태를 동기화
🛜 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))
✅ 설명
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의 소유권 분석
✅ EKS 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 비활성화
✅ 클러스터 도메인 주소 (F5010046882B83E478ED4CDA5EA08828.gr7.ap-northeast-2.eks.amazonaws.com) 확인
✅ 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=true
→ VPC 내부에서 Private Endpoint 사용 가능
✅ 업데이트 진행 중인 상태 확인
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를 반환하는 것을 확인할 수 있다.
5. 도메인 질의 응답 결과 비교
✅ VPC 내부에서 실행한 도메인 질의 결과 (Private Endpoint 확인) - 오른쪽 상단
- 내부에서는 EKS Owned ENI의 Private IP가 반환됨
- 내부 네트워크에서 API 서버에 직접 연결 가능
✅ 외부에서 실행한 도메인 질의 결과 (Public Endpoint 확인) - 오른쪽 하단
- 외부에서는 Public IP가 반환됨
- 설정한 Public Access CIDR(허용된 IP 범위 내)에서만 접근 가능
✅ 결과 분석
- 내부 VPC 환경에서는 Private IP를 사용하여 API 서버에 접근 가능
- 외부에서는 Public IP를 통해 제한된 접근만 가능
- Private Endpoint 활성화 후
kubelet
및kube-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 네트워크에서 처리됨
EKS API 서버의 도메인 질의 결과가 EKS Owned ENI로 변경된 것을 확인할 수 있음
✅ VPC 내부에서 API 서버 도메인을 질의하면,
- 동일한 도메인이지만 EKS Owned ENI의 Private IP를 반환
- 내부 네트워크에서 API 서버와 Private 통신 가능
🚀 즉, 내부 트래픽은 Public IP를 거치지 않고 Private 네트워크에서 처리됨
7. kube-proxy
및 kubelet
의 API 서버 연결 방식 변경
✅ 기존 상태
kube-proxy
와kubelet
이 공인 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-proxy
가 Public 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))
------------------------------
✅ 결과
- 내부 네트워크에서
kubelet
과kube-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
2. 파드 개수 조정 (확장 & 축소)
파드 개수 증가 (3개 → 6개)
1
kubectl scale deployment my-webs --replicas=6 && kubectl get pod -w
파드 개수 감소 (6개 → 3개)
1
2
# 파드 감소
kubectl scale deployment my-webs --replicas=3
3. 강제 삭제 후 자동 복구 확인
모든 파드 삭제 (강제 제거)
1
2
3
```bash
kubectl delete pod --all && kubectl get pod -w
삭제 후에도 Deployment
설정에 따라 자동으로 3개가 다시 생성됨
✅ 결과: 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
)
- 최소 3개 (
🚀 확장 후, 192.168.2.119
노드가 추가되어 클러스터 용량 증가