[AEWS 2기] EKS 설치및 셋팅 + 클러스터 엔드포인트

EKS 스터디 CloudNet@팀의 AEWS 2기에 작성된 자료를 베이스로 작성된 블로깅입니다. 

저는 쿠버네티스를 접하고 사용안하고, 공부안한지 너무 오래되어서 개념을 익힐겸 핸즈온처럼 하나하나 해보았습니다. 

 

기본 아키텍쳐 

CloudFormation을 사용해서 위 구성요소들을 만들어줍니다.

(버튼만 클릭하면 위 아키텍쳐처럼 수성되는 되게 쉬운 일인 것 같지만 조금 팁을 드리자면)

보통은 요즘 테라폼으로 구성을 많이하지, 클라우드 포메이션에 안 익숙한 사람들은 권한에 안 익숙해서 막히는 경우가 있다고 생각합니다. 

위 부분인데, 실습이니까 되게 하기 위해서 (생성을 위해서) IAM에서 Cloudformation 용도로 역할을 하나 만들고, 그 역할에 admin 권한을 주면 자잘한 권한 이슈없이 건너올 수 있습니다 . 

 

CloudFormation 

CloudFormation 스택 배포가 완료되면, 생성되는 리소스들이 보인다. 

주요한것들은VPC, Subnet4개, EC2 1대 + 보안그룹이다. 보안그룹의 경우 만들때 넣었던 나의 IP만을 가지고 있다. 

 

 보안그룹에서 Myeks-HOST-SG를 확인해서 내 아이피만 인바운드에 추가된 것을 확인할 수 있다. 

- 모든 ip에 대해서 허용이 된다면 보안적으로 위험하기 때문이다. 

 

EC2에 접속 

# CloudFormation 스택 배포 완료 후 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[*].OutputValue' --output text
예시) 43.202.53.3

다음 명령어를 사용해서 스택으로 생성된 EC2의 IP를 획득할 수 있다. 

 

# ec2 에 SSH 접속 : root / qwe123
예시) ssh root@ 43.202.53.3
ssh root@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)
root@@X.Y.Z.A's password: qwe123

 

다음 명령어를 사용해서 획득한 ip 주소를 가지고, 스택으로 배포된 인스턴스에 ssh 접속을 할 수 있다.

미리 설정되어있는 비밀번호인 qwe123을 넣으면 이렇게 접속이 가능하다. 

 

Host EKS
	HostName 43.202.53.3
	User ec2-user
	IdentityFile /Your/key/path/your.pem

혹은 이렇게 .ssh경로에 config파일에 해당 정보를 입력하고 연결을 하면

비밀번호 입력하는 과정없이 바로 접속이 가능하다. 

 

기초 환경 확인

kubectl version --client=true -o yaml | yh
eksctl version
aws --version
ls /root/.ssh/id_rsa*

위 명령으로 설치되어있어야할 툴의 설치 유무를 확인해줍니다. 

다 설치되어 있으므로 모든 정보가 출력 되는 것을 확인할 수 있습니다. 

 

자격증명 확인 

aws ec2 describe-instances

다음 명령어로 해당 인스턴스에 설정되어있는 인증 정보를 확인합니다. 

root@myeks-host ~]# aws ec2 describe-instances
Unable to locate credentials. You can configure credentials by running "aws configure".

다음과 같은 로그가 표시된다면 크레덴셜이 설정이 안되어있다는 의미입니다. 

 

aws configure list

다음과 같은 로그가 표시된다면 크레덴셜이 설정이 안되어있다는 의미입니다. 

다음 명령으로 더 확실하게 확인할 수 있습니다. 

aws configure

다음 명령으로 

- AWS Access Key ID

- AWS Secret Access Key

- Default region name

- Default output format

위 네개 항목에 대해 설정 해줄 수 있습니다. 

aws configure list

설정을 다 한 후 다음 명령으로 자격증명이 제대로 되었는지 확인할 수 있습니다. 

aws ec2 describe-instances

그리고 다시 위 명령을 하면 아까는 크레덴셜이 설정 안되어있어서 못봤던 인스턴스의 정보들을 확인할 수 있게 됩니다. 

 

VPC의 세부정보 

aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq

이 명령은 VPC의 태그 중 이름이 $CLUSTER_NAME-VPC인 것을 검색의 세부 정보를 보여줍니다.

 

export VPCID=$(aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq -r .Vpcs[].VpcId)

다음 명령은 

- aws ec2 describe-vpcs 명령을 사용하여 특정 이름을 가진 VPC의 정보를 조회합니다.

- jq -r .Vpcs[].VpcId는 이 결과에서 VPC의 ID만을 추출합니다. 여기서 -r 옵션은 결과를 raw output으로 출력하라는 것을 나타냅니다.

- 이렇게 추출된 VPC ID를 VPCID라는 환경 변수에 할당합니다.

 

echo "export VPCID=$VPCID" >> /etc/profile

export VPCID=$VPCID /etc/profile 파일에 추가합니다. 이렇게 하면 사용자가 로그인할 때마다 VPCID 변수가 설정됩니다. 따라서 VPC ID를 영구적으로 사용할 수 있게 됩니다.

 

echo $VPCID

환경 변수 VPCID의 값을 출력합니다. 이렇게 하면 현재 쉘에서 VPC ID를 확인할 수 있습니다.

실행된 터미널의 로그는 다음과 같습니다. 

 

subnet 정보 확인 

aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --output json | jq

환경 변수 VPCID의 값을 출력합니다. 이렇게 하면 현재 쉘에서 VPC ID를 확인할 수 있습니다.

# CloudFormation 스택 배포 완료 후 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[*].OutputValue' --output text
예시) 3.35.137.31

다음 명령을 사용해서 해당 vpc에 속한 subnet의 정보를 json으로 출력합니다. 

export PubSubnet1=$(aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet1" --query "Subnets[0].[SubnetId]" --output text)
export PubSubnet2=$(aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet2" --query "Subnets[0].[SubnetId]" --output text)
echo "export PubSubnet1=$PubSubnet1" >> /etc/profile
echo "export PubSubnet2=$PubSubnet2" >> /etc/profile
echo $PubSubnet1
echo $PubSubnet2

다음 명령어들을 사용해서 첫번째와 두번째 서브넷의 ID를 각각 환경변수로 만들어서 저장해줍니다. 

echo 명령어를 사용해서 두 서브넷들에 대해서 ID값들이 잘 저장되었는지 확인해줍니다. 로그에서는 잘 나와준것을 확인할 수 있습니다. 

 

EKS 배포전 EKS 기본 명령어와 --dry-run 옵션

현재 지원하는 eks 버전을 확인하는  명령어 파이프라인

eksctl create cluster -h | grep version

모든 지원하는 버전들이 명시되어있고,  그 중 1.29가 디폴트이다. 

하지만 안정성을 위해서 하나 낮은 버전을 추천한다고 한다. 

 

--dry-run을 사용한 명령어 시뮬레이션

노드 그룹없이 eks 클러스터를 생성하는 명령어

eksctl create cluster --name myeks --region=ap-northeast-2 --without-nodegroup --dry-run | yh

위 명령어는 "myeks"라는 이름의 새로운 Amazon EKS 클러스터를 아시아 태평양(서울) 리전에 생성하되, 노드 그룹 없이 생성하고, 실제 작업을 수행하지 않고 미리 보여준다.

--without-nodegroup

노드 그룹을 생성하지 않고 클러스터를 생성하는 옵션입니다.  이 옵션을 사용하면 클러스터는 노드가 없는 상태로 생성됩니다.

--dry-run 옵션에 대하여

실제로 작업을 수행하지 않고 명령이 어떻게 실행될지 미리 보여줍니다. 이 옵션을 사용하여 작업을 미리 검토할 수 있습니다.

이렇게 어떤 작업을 할지 로그로 미리 보여준다. 

# CloudFormation 스택 배포 완료 후 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[*].OutputValue' --output text
예시) 3.35.137.31

 

배포하기 전 갖춰져야 할 환경변수들 

 
echo $AWS_DEFAULT_REGION
echo $CLUSTER_NAME
echo $VPCID
echo $PubSubnet1,$PubSubnet2

위 명령어들에 대해서 갖추어져 있어야 eks 배포를 할때 실패가 안납니다. 

위 명령어들을 사용해서 확인 해보았는데, 잘 갖추어진것으로 확인했습니다. 

EKS 배포

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.28 --ssh-access --external-dns-access --verbose 4

dry run을 빼고 명령을 실행하여 eks 배포를 시작합니다. (--verbose 4 옵션을 사용하여 자세하게 로그를 출력하여 배포과정을 확인합니다.)

그럼 이제 이렇게 eks 배포가 시작이 됩니다. --verbose 4 옵션 덕분에 배포 과정 로그들이 주르륵 잘 나옵니다 .

 

EKS 배포 후 CloudFormation

위 명령을 사용해서 Eks 배포를 실행했는데, cloudformation에서 스택으로 생성된것을 볼 수 있었습니다.

어떤 연관성을 가지고 있는 걸까요?

eksctl은 Amazon EKS 클러스터를 생성할 때, 내부적으로 AWS의 클라우드 서비스인 CloudFormation을 사용합니다. 

CloudFormation은 인프라스트럭처를 코드로 관리하는 서비스입니다. 따라서 eksctl을 사용하여 클러스터를 생성하면, 실제로는 CloudFormation 스택이 생성되고 관리되며, 이를 통해 클러스터가 구성됩니다. 

이렇게 하면 클러스터의 배포 및 관리가 단순화되고, 인프라스트럭처를 코드로 관리할 수 있게 됩니다.

배포가 완료 된 후 노드 그룹에서 명령한대로 최소 두개의 인스턴스가 생성되었는지 확인해봅시다 .

 

노드 그룹?

Autoscaling group이라고 생각하면 됩니다 .

- 노드 = ec2

- 노드 그룹 = ec2 묶음 = Auto Scaling 그룹

이렇게 오토스케일링그룹에서 최소2 최대 2 확인했습니다. 

eks 배포로 생성된 노드그룹으로 인해 생성된 ec2 인스턴스들입니다. 

둘 다 myeks-myeks-nodegroup-Node 이름을 가지고있고, t3.medium 타입으로 생성되었습니다. 

 

kubectl 명령어

kubectl krew list
kubectl ctx
kubectl ns
kubectl ns default
kubectl get-all    # 모든 네임스페이스에서 모든 리소스 확인

이 명령어들은 Kubernetes 클러스터에서 리소스를 관리하고 작업하기 위해 사용되는 kubectl의 확장 기능과 일부 유용한 명령어들입니다. 

kubectl krew list: kubectl 플러그인(확장 기능)의 목록을 표시합니다. krew는 kubectl 플러그인 매니저로, 다양한 유용한 확장 기능을 설치하고 관리하는 데 사용됩니다.

 

kubectl ctx: 현재 사용 중인 Kubernetes 컨텍스트(클러스터, 사용자, 네임스페이스 등의 설정 집합)를 표시하거나 변경합니다.

 

kubectl ns: 현재 선택된 네임스페이스를 표시하거나 변경합니다.

 

kubectl ns default: 기본 네임스페이스를 선택합니다. 이 명령은 현재 활성화된 네임스페이스를 'default'로 변경합니다.

kubectl ns kube-public

위와같이 kubectl ns 뒤에 다른 네임스페이스를 넣어서 바꿀 수 있습니다. 

# CloudFormation 스택 배포 완료 후 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[*].OutputValue' --output text
예시) 3.35.137.31

 

kubectl get-all: 모든 네임스페이스에서 클러스터 내의 모든 리소스를 표시합니다. 일반적으로는 kubectl get all --all-namespaces와 같은 기능을 수행합니다. 하지만 get-all all 명령과 달리 all이 지원하지 않는 자원도 포함하여 모든 자원을 표시합니다.

 

kubectl cluster-info

kubectl cluster-info는 현재 작업 중인 Kubernetes 클러스터의 정보를 표시합니다.

Kubernetes control plane URL: 이 URL은 Kubernetes 마스터 노드의 엔드포인트를 나타냅니다. 즉, 클러스터를 제어하고 관리하기 위한 API 서버의 위치입니다. 

 https://8CF9012F5B759D908B6847C3214C799B.gr7.ap-northeast-2.eks.amazonaws.com로 표시되고 있습니다. 

해당 엔드포인트는 AWS 콘솔에 eks 섹션에서 서버 엔드포인트에서 동일한 것을 확인할 수 있습니다.

CoreDNS URL

CoreDNS는 Kubernetes 클러스터 내의 DNS 서비스입니다. 이 URL은 CoreDNS 서비스의 엔드포인트를 나타내며, 클러스터 내부에서 DNS 쿼리를 처리하기 위해 사용됩니다. 이 예시에서는 https://8CF9012F5B759D908B6847C3214C799B.gr7.ap-northeast-2.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy로 표시됩니다.

CoreDNS?

클러스터 내부의 DNS 쿼리를 처리하고, 이를 바탕으로 서비스 디스커버리(Service Discovery)를 제공합니다. 예를 들어, 클러스터 내부에서 서비스 A의 DNS 이름을 사용하여 해당 서비스의 IP 주소를 검색하고 통신할 수 있습니다.

 

eksctl get cluster

eksctl get cluster 명령어는 현재 AWS 계정에 있는 모든 Amazon EKS 클러스터의 목록을 가져옵니다. 

aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint

 

dig 조회 

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

Amazon EKS 클러스터의 API 엔드포인트를 조회하고, 해당 엔드포인트의 DNS 주소를 추출한 다음, dig 명령어를 사용하여 해당 DNS 주소의 IP 주소를 확인합니다.

- EKS 클러스터의 정보를 조회하고, jq를 사용하여 엔드포인트를 추출한 다음, cut 명령어를 사용하여 URL에서 호스트 부분을 추출하여 APIDNS 변수에 할당

- dig 명령어를 사용하여 DNS 쿼리를 수행하여 클러스터의 API 서버의 IP 주소를 확인합니다. $APIDNS 변수에 저장된 DNS 주소를 사용하여 클러스터의 API 서버의 IP 주소를 확인합니다. +short 옵션은 결과를 간결하게 출력

 

eks API 접속 시도 : 도메인 or 출력되는 ip 주소로 https:///version 외부에서도 접속 가능!

curl -k -s $(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint)

첫 번째 curl 명령어는 클러스터 엔드포인트에 대한 요청을 수행합니다. 그러나 응답으로 "403 Forbidden" 오류가 반환되었습니다. 

curl -k -s $(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint)/vrsion | jq

두 번째 curl 명령어는 클러스터 엔드포인트에 "/version" 엔드포인트에 대한 요청을 수행합니다. 이번에는 요청이 성공하여 Kubernetes 클러스터의 버전 정보를 반환합니다. 

이 정보에는 Kubernetes의 주요 버전(major), 마이너 버전(minor), Git 버전(gitVersion), Git 커밋(gitCommit) 등이 포함되어 있습니다.

 

 

노드 정보 상세 확인

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

- 현재 "실행 중"(running) 상태인 EC2 인스턴스에 대해 공용 IP 주소, 사설 IP 주소, 인스턴스 이름(태그 중 'Name' 키를 가진 태그의 값), 그리고 인스턴스 상태를 추출합니다.

 

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})

이 명령어는 ap-northeast-2a 지역(zone)에 위치한 노드 중 첫 번째 노드의 IP 주소를 조회합니다. 결과는 변수 N1에 저장됩니다.

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})

이 명령어는 ap-northeast-2c 지역(zone)에 위치한 노드 중 첫 번째 노드의 IP 주소를 조회합니다. 결과는 변수 N2에 저장됩니다.

echo $N1, $N2

echo $N1, $N2 명령어를 사용하여 N1 N2 변수에 저장된 두 노드의 IP 주소를 출력합니다.

환경변수에 넣어줍니다. 

 

ping test

ping -c 1 $N1

패킷 손실이 일어났다. 

 

노드 보안그룹에 eksctl-host 에서 노드(파드)에 접속 가능하게 룰(Rule) 추가 설정

aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text

 그룹 이름에 'nodegroup'이 포함된 보안 그룹만을 대상으로 조회하도록 지정후 보안 그룹의 식별자(Group ID)만을 추출하여 출력하도록 지정

NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text)

변수 할당 NGSGID=$(...): 첫 번째 명령어의 실행 결과, 즉 특정 이름 패턴을 포함하는 보안 그룹의 GroupId들을 텍스트 형식으로 출력하고, 이를 NGSGID라는 환경 변수에 저장

echo $NGSGID
echo "export NGSGID=$NGSGID" >> /etc/profile

이 명령어는 NGSGID 환경 변수를 내보내는 (export) 쉘 명령을 /etc/profile 파일의 끝에 추가합니다. 이렇게 하면 시스템에 로그인하는 모든 사용자와 모든 새 쉘 세션에서 NGSGID 환경 변수가 자동으로 설정됩니다.

aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32

 

# CloudFormation 스택 배포 완료 후 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[*].OutputValue' --output text
예시) 3.35.137.31

EC2 보안 그룹에 대한 인바운드(ingress) 규칙을 추가하는 작업을 수행

 명령어를 사용하면 지정된 보안 그룹에 모든 프로토콜과 포트에 대해 192.168.1.100 IP 주소에서 오는 트래픽을 허용하는 규칙이 추가됩니다.

 

다시 ping 명령 

ping -c 2 $N1
ping -c 1 $N2

인바운드에 ip주소를 넣어준 뒤 패킷이 정상적으로 반환되는것을 확인할 수 있다. 

 

AWS VPC CNI 사용 확인

kubectl -n kube-system get ds aws-node

이 명령어의 실행 결과는 aws-node DaemonSet의 기본 정보를 보여줍니다. 

이 정보에는 DaemonSet의 이름, desired(원하는) 파드 수, 현재 파드 수, 사용 중인 이미지 등이 포함될 수 있습니다.

 

kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2

결과적으로, 이 명령어의 실행은 aws-node DaemonSet이 사용하는 컨테이너 이미지의 이름을 도메인 이름 없이 출력합니다. 

이 정보는 특정 버전의 aws-node 이미지를 사용하고 있는지 확인하거나 문제 해결 시 유용하게 쓰일 수 있습니다. 

 

파드 IP 확인

kubectl get pod -n kube-system -o wide

kube-system 네임스페이스 내의 모든 파드들의 상세 정보를 조회합니다. -o wide 옵션은 추가적인 정보(예: 노드 이름, 파드의 IP 주소, 실행 중인 컨테이너 이미지)를 포함하여 출력합니다.

 

kubectl get pod -n kube-system -l k8s-app=kube-dns -owide

kube-system 네임스페이스 내에서 k8s-app=kube-dns 라벨이 할당된 파드들만을 대상으로 상세 정보를 조회합니다. kube-dns는 클러스터 내의 DNS 서비스 관련 파드입니다. 

 

for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i hostname; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c addr; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c route; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo iptables -t nat -S; echo; done

각 인스턴스의 IP 주소(192.168.1.120 192.168.2.124)를 사용하여 ec2-user로 로그인 후, 각 인스턴스의 호스트 이름(ip-192-168-1-120.ap-northeast-2.compute.internal ip-192-168-2-124.ap-northeast-2.compute.internal)을 조회했습니다. 

Node Cgroup version 

for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i stat -fc %T /sys/fs/cgroup/; echo; done

두 개의 EC2 인스턴스에 대해 SSH를 사용하여 /sys/fs/cgroup/ 디렉터리의 파일 시스템 유형을 조회하는 것을 목적으로 합니다.

두 EC2 인스턴스의 /sys/fs/cgroup/ 디렉터리가 tmpfs, 즉 메모리 기반의 임시 파일 시스템을 사용하고 있음을 확인했습니다. 

tmpfs 사용은 파일 처리 속도를 향상시켜 성능 이점을 제공합니다. 이 디렉터리는 리눅스의 cgroups 기능을 통해 시스템 리소스(예: CPU, 메모리)의 할당과 제한을 관리하는 데 사용됩니다. 

cgroups의 이러한 관리는 시스템의 효율성과 안정성을 높이는 데 중요합니다. Kubernetes 환경에서는 cgroups가 컨테이너 리소스 사용을 제어하는 데 핵심적 역할을 하며, tmpfs 사용은 이 리소스 관리를 더욱 효율적으로 만듭니다.

 

for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i df -hT /; echo; done

두 EC2 인스턴스의 루트 파일 시스템(/)에 대한 디스크 사용량 정보를 보여줍니다. 여기서 df -hT 명령어는 연결된 파일 시스템의 용량, 사용량, 사용 가능한 공간 및 사용 비율을 포함한 정보를 가독성 좋은 형식으로 출력합니다.


EKS owned ENI 확인

 

Kubernetes 클러스터에서 kubelet kube-proxy의 통신, 그리고 API 서버의 주소를 파악하기 위한 단계

# kubelet, kube-proxy 통신 Peer Address는 어딘인가요?
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ss -tnp; echo; done

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

# [터미널] aws-node 데몬셋 파드 1곳에 bash 실행해두기 
kubectl exec daemonsets/aws-node -it -n kube-system -c aws-eks-nodeagent -- bash

# exec 실행으로 추가된 연결 정보의 Peer Address는 어딘인가요? >> AWS 네트워크 인터페이스 ENI에서 해당 IP 정보 확인
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ss -tnp; echo; done

이 작업의 순서와 그 결과를 통해, Kubernetes 클러스터 내 kubelet, kube-proxy의 통신 상대(peer) 주소와 그 연결들을 파악할 수 있습니다. 이는 클러스터의 노드 간 및 AWS EKS API 서버와의 통신을 이해하는 데 중요합니다.

 

1. kubelet, kube-proxy 통신 Peer Address 파악 (노드 간 및 외부 연결 확인)

for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i sudo ss -tnp; echo; done

kubelet kube-proxy는 각 노드에서 Kubernetes 클러스터의 다른 컴포넌트들과 통신하는 데 사용됩니다. 이들의 통신 정보를 확인하기 위해 각 노드에 SSH로 접하여 ss -tnp 명령어를 실행하는 것이 일반적입니다. 

이 명령어는 네트워크 연결, 사용 중인 포트, 관련된 프로세스 등에 대한 정보를 제공합니다.

- ss -tnp: 활성 TCP 연결을 보여주며, -n은 주소와 포트 번호를 숫자로 표시하도록 합니다. -p는 연결된 프로세스의 ID와 이름을 보여줍니다.

- ss -tnp 명령어 실행 결과, 각 노드에서 다양한 외부 주소와의 ESTAB(established) 상태 TCP 연결을 확할 수 있습니다. 특히, kube-proxy kubelet 프로세스의 연결이 눈에 띕니다. 예를 들어, kube-proxy3.39.3.89:443, kubelet3.37.136.118:443와 연결되어 있음을 알 수 있습니다.

- 실행 결과에서, kubelet kube-proxy와 관련된 연결의 "Peer Address"를 찾습니다. 이는 해당 서비스들이 클러스터의 다른 컴포넌트나 서비스와 통신하는 데 사용하는 주입니다.

- 이는 Kubernetes 클러스터의 컴포넌트들이 클러스터 외부의 특정 주소(예: AWS EKS API 서버)와 통신하고 있을 나타냅니다.

 

Kubernetes API 서버 주소 확인

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

Kubernetes API 서버의 주소를 확하기 위해 AWS CLI와 jq 도구를 사용하여 EKS 클러스터의 정보를 조회하고, API 서버의 엔드포인트 주소를 추합니다.

- dig +short $APIDNS: 추출된 API 서버의 DNS 이름을 dig 명령어로 조회하여 IP 주소를 확합니다.

- aws eks describe-cluster 명령과 dig를 통해 얻은 API 서버의 DNS 주소(3.39.3.89, 3.37.136.118)는 ss -tnp 명령어 결과에서 확인된 주소와 일합니다. 이는 kubelet, kube-proxy AWS EKS 클러스터의 API 서버와 통신하고 있음을 확시켜 줍니다.

 

aws-node 데몬셋 파드에 bash 실행

kubectl exec daemonsets/aws-node -it -n kube-system -c aws-eks-nodeagent -- bash

특정 aws-node 데몬셋 파드에 대한 bash 쉘을 열어 직접 접근할 수 있습니다.

- kubectl exec daemonsets/aws-node -it -n kube-system -c aws-eks-nodeagent -- bash

- kube-system 네임스페이스의 aws-node 데몬셋에 속한 파드 중 하나에 대해 대화형(-it) bash 쉘을 엽니다. 

- docker exec으로 컨테이너에서 bash를 여는 것이랑 같습니다. 

 

EKS owned ENI 

관리형 노드 그룹의 워커 노드는 내 소지만, 연결된 ENI(NIC)의 인스턴스(관리형 노드)는 AWS 소이다

EKS Owned ENI란?

1. ENI (Elastic Network Interface) 정의: ENI는 AWS EC2 인스턴스에 연결되어 네트워크 통신을 가능하게 하는 가상 네트워크 카입니다. 각 ENI는 보안 그룹, 프라이빗 IP 주소, 퍼블릭 IP 주소, MAC 주소 등의 정를 가질 수 있습니다.

2. EKS 소유의 ENI: EKS 클러스터에서, 특정 기능이나 서비스(예: VPC CNI, Load Balancer, NAT Gateway 등)를 위해 생성되는 ENI는 논리적으로는 사용자의 AWS 계정에 속하지만, 실제로는 EKS 서비스에 의해 관됩니다. 이러한 ENI들은 EKS 클러스터의 네트워킹을 원활하게 하기 위해 필하며, 이 ENI들은 AWS 측에서 자동으로 생성하고 삭합니다.

3. 관리형 노드 그룹의 컨텍스트에서의 의: 사용자가 관리형 노드 그룹을 생성하면, 워커 노드를 호스팅하는 EC2 인스턴스는 사용자의 계정에 속하게 됩니. 하지만, 이 인스턴스들에 연결된 일부 ENI는 EKS 클러스터의 네트워크 기능을 지원하기 위해 EKS 서비스에 의해 관됩니다. 이 경우, ENI는 "EKS owned"라고 간됩니다.

 

이 개념의 중요성

- 네트워크 관리와 운영의 단순화: EKS 서비스에 의해 ENI가 관되면, 사용자는 네트워크 구성과 관리의 복잡성을 줄일 수 있습니. AWS가 이러한 리소스의 생성과 삭제를 자동으로 처하기 때문입니다.

- 보안 및 격리: EKS owned ENI를 통해 특정 네트워크 트래픽과 통신 경로를 보안적으로 관리하고, 필요한 경우 격리할 수 있습니다.

- 비용 관리: EKS owned ENI를 통해 클러스터의 네트워크 리소스 사용량을 보다 효과적으로 모니터링하고 관리할 수 있으멀로, 비용 최적화에 도움이 됩니다.

결론적으로, "EKS owned ENI"는 EKS 클러스터의 네트워킹을 효율적이고 안전하게 관리하기 위한 AWS의 방법입니다. 사용자는 인프라의 세부적인 네트워크 구성 대신 클러스터의 애플리케이션 로직과 비즈니스 요구사

 

EKS Managed Node Groups and ENIs

- 관리형 노드 그룹의 워커 노드는 사용자의 AWS 계정에 속하지만, AWS EKS 서비스에 의해 자동으로 관됩니다. 이러한 노드 그룹 내의 인스턴스(워커 노드)는 사용자가 설정한 사양에 따라 AWS가 생성하고, 사용자의 계정 내에서 실행됩니다.

- EKS owned ENI는 이러한 워커 노드에 연결되어 있으며, EKS 클러스터의 네트워킹 및 커뮤니케이션을 위해 필수적인 구성 요소입니다. EKS 서비스는 이러한 ENI를 생성하고 관리하여 클러스터 내의 파드 간 통신이나 클러스터와 외부 세계 간의 네트워킹을 가능하게 합니다.

 

소유자 및 요청자 ID 설명

소유자 ID (018768293104)

이 ID는 네트워크 인터페이스를 소유하고 있는 AWS 계정의 ID를 나타냅니다. 여기서는 당신의 AWS 계정 ID입니다. EKS 클러스터를 생성할 때 AWS 리소스를 관리하는 계정의 ID이며, 클러스터와 관련된 모든 AWS 리소스(예: EC2 인스턴스, ENI 등)의 기본 소유자입니다.

 

요청자 ID와 인스턴스 소유자 ID가 나의 AWS 계정 ID와 다르다

이는 일반적으로 관리형 서비스(예: EKS 관리형 노드 그룹) 또는 AWS가 대신 작업을 실행하는 다른 시나리오에서 발생합니다. 예를 들어, EKS 클러스터에서 자동으로 관리되는 리소스는 AWS가 대신 생성하고 관

 

EKS 환경에서의 ID

EKS 클러스터 내에서 생성된 리소스(예: ENI)의 경우, 요청자 ID인스턴스 소유자 ID가 동할 수 있습니다. 이는 EKS 클러스터를 관리하기 위해 AWS가 제공하는 자동화된 프로세스(예: 노드 그룹 관리)에 의해 리소스가 생되었지만, 해당 리소스들은 사용자의 AWS 계정 내에서 생성되고 관리되기 때문입니다.

 

EKS와 ENI의 관계

- EKS 관리형 노드 그룹 내의 워커 노드와 ENI 사이의 관계는 EKS 서비스가 클러스터의 운영을 간소화하고 자동화하는 방식의 일부입니다. EKS 서비스는 네트워킹을 포함한 다양한 인프라 요소를 관리함으로써 사용자가 클러스터의 애플리케이션 배포와 운영에 더 집중할 수 있게 합니다.

- ENI의 관리는 EKS 클러스터의 원활한 운영을 위해 중요합니다. EKS가 ENI를 관리함으로써, 파드 간의 네트워킹, 서비스의 노출, 그리고 클러스터 외부 리소스와의 통신이 가능해집니다.

요약하자면, "EKS owned ENI"와 관련된 소유자 및 요청자 ID 정보는 EKS 클러스터와 그 구성요소가 어떻게 AWS 계정과 연관되어 있는지를 나타냅니다. EKS 서비스는 이러한 인프라 구성요소를 효율적으로 관리하여 사용자가 Kubernetes 클러스터를 보다 쉽게 운영할 수 있도록 지원합니다.


EKS Cluster Endpoint 를 Public(IP제한)+Private 로 변경 및 확인

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

Amazon EKS 클러스터의 API 서버 엔드포인트 DNS 주소를 조하고, 그 주소에 대해 지속적으로 DNS 조회(dig +short)를 실행한 후, 결과와 현재 시간을 출력하는 과정을 무한 반합니다.

 

노드에서 ControlPlane과 통신 연결 확인

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

kubeletkube-proxy 프로세스의 네트워크 연결 상태를 지속적으로 모니터링하는 작업을 자동합니다.

이 방법을 통해 관리자는 kubelet kube-proxy의 연결 상태를 실시간으로 모니터링할 수 있으며, 클러스터의 네트워크 상태와 이들 핵심 컴포넌트의 건강 상태를 주기적으로 확인할 수 있습니다.

 

Public(IP제한)+Private 로 변경

aws eks update-cluster-config --region $AWS_DEFAULT_REGION --name $CLUSTER_NAME --resources-vpc-config endpointPublicAccess=true,publicAccessCidrs="$(curl -s ipinfo.io/ip)/32",endpointPrivateAccess=true

이 명령어 Amazon EKS 클러스터의 VPC 구성을 업데이트하여 클러스터 API 서버에 대한 접근 방식을 변합니다. 

구체적으로는 API 서버의 공개 접근(public access)과 사설 접근(private access)을 모두 활성하고, 

공개 접근에 대한 CIDR 범위를 현재 공개 IP 주소로 제합니다.

업데이트가 완료되면, 지정된 CIDR 범위 내의 IP 주소를 가진 사용자만이 EKS 클러스터 API 서버에 공개적으로 접할 수 있게 되며, VPC 내부에서는 사설 접근이 가해집니다. 이 방식은 필요한 경우 클러스터의 보안을 강화하고, 불필요한 외부 접근을 제한하기 위한 좋은 방입니다.

 

EKS에서 기존 퍼블릭만 API 서버 엔드포인트 액세스가 가능했었는데 

 

퍼블릭 및 프라이빗으로 바뀐 것을 확인할 수 있다. 

그리고 api 서버 엔드포인트가 바꼈다. 

출력이 처음에 AWS EKS 클러스터의 API 서버의 공개 IP 주소(43.203.14.5152.79.197.164)를 보여주다 내부 IP 주소(192.168.1.158192.168.2.15)로 바뀌는 을 관찰

aws eks update-cluster-config 명령으로 EKS 클러스터 설정을 변경하고, publicAccessCidrs를 현재 외부 IP 주소로 제한한 후에, dig +short $APIDNS 명령의 출력이 변경된 것을 관찰. 

클러스터의 API 서버 엔드포인트에 대한 공개 접근 설정을 조정합니다.

 

1. publicAccessCidrs 설정의 변경

이 설정을 변경함으로써 클러스터 API 서버에 대한 공개 접근을 현재 사용 중인 외부 IP 주소(/32는 단일 IP 주소를 의미)로 제했습니다. 이는 클러스터의 보안을 강화하기 위한 조치일 수 있습니다. 그러나 명령 실행 시점에서의 외부 IP만 허용하게 되므로, 이외의 IP에서의 접근은 제한됩니다.

 

2. 엔드포인트의 내부 접근 설정 변경

endpointPrivateAccess=true 설정은 클러스터 내부에서 API 서버에 접근할 수 있도록 합니다. 이 설정 변경 후, 클러스터 내부 노드의 IP 주소가 dig 명령의 출력으로 나타나기 시작한 것으로 보입니다. 이는 클러스터 내부에서 API 서버의 내부 엔드포인트 주소를 조회하게 되어, 외부가 아닌 내부 네트워크 주소가 표시되는 것일 수 있습니다.

결론적으로, aws eks update-cluster-config 명령으로 클러스터의 VPC 설정을 조정하면서 API 서버에 대한 접근 제어 방식이 변경되었고, 이로 인해 클러스터 API 엔드포인트에 대한 DNS 조회 결과가 외부 IP 주소에서 내부 IP 주소로 변되었습니다

 

간단하게

클러스터 API 서버 접근 제한: aws eks update-cluster-config 명령을 사용해 클러스터의 API 서버에 대한 접근 설정을 변경했습니다. 이 변경으로 인해 클러스터 API 서버에 접근할 수 있는 IP 주소를 현재 사용자의 외부 IP 주소로 제한했습니다.

내부 접근 활성화: 동시에, 클러스터 내부에서 API 서버에 접근할 수 있도록 설정을 변경했습니다 (endpointPrivateAccess=true).

DNS 조회 결과 변경: 설정 변경 후, dig 명령으로 클러스터 API 서버의 DNS 이름을 조회했을 때, 외부 IP 주소 대신 내부 IP 주소가 반환되기 시작했습니다. 이는 클러스터 내부 네트워크에서 API 서버에 접근하기 위한 경로가 활성화되었기 때문입니다.

 

간단히 말해, 설정 변경으 클러스터의 API 서버에 접근할 수 있는 범위가 조되었고, 이로 인해 클러스터 내부에서는 내부 IP 주소를 통해 API 서버에 접근할 수 있게 되었습니다.

 

JUNE .

20'S LIFE IN SYDNEY and BUSAN

    이미지 맵

    DevOps Study/Kubernetes 다른 글

    이전 글

    다음 글