본문 바로가기
EKS Study

2주차 - EKS Networking

by 줄스토리 2024. 3. 10.

#스터디 시작

EKS 스터디를 하면서 가장 배우고 싶었던 부분이 eks networking 이였습니다. 네트워크는 통신구조 및 방화벽과도 연관이 있어서 처음 접하기에는 굉장히 어려웠습니다. 이번 스터디를 통해서 eks network 구조와 응용사례들을 배웠으면 좋겠습니다.

 

#사전준비

  • CloudFormation 으로 자동 배포 - 서울리전클릭 후 아래 파라미터 입력 후 스택 생성되며, 스택 이름은 기본 myeks 클러스터로 생성

# SSH 접속
ssh -i ~/.ssh/kp-gasida.pem ec2-user@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)

# cloud-init 실행 과정 로그 확인
tail -f /var/log/cloud-init-output.log

# cloud-init 정상 완료 후 eksctl 실행 과정 로그 확인
tail -f /root/create-eks.log

# default 네임스페이스 적용
kubectl ns default

# 설치 확인
kubectl cluster-info
eksctl get cluster
eksctl get nodegroup --cluster $CLUSTER_NAME

# 환경변수 정보 확인
export | egrep 'ACCOUNT|AWS_|CLUSTER|KUBERNETES|VPC|Subnet'
export | egrep 'ACCOUNT|AWS_|CLUSTER|KUBERNETES|VPC|Subnet' | egrep -v 'SECRET|KEY'

 

- 노드 정보 확인 및 SSH 접속

 

- 다른 터미널에서 환경변수 적용

 

 

#EKS Networking

 

Amazon EKS에서 관리하는 Kubernetes 클러스터에 대해 EC2 작업자 노드를 실행하도록 Amazon VPC를 구성하는 다양한 방법을 다룹니다. AWS의 네트워킹 구성과 Kubernetes의 네트워킹 요구 사항을 모두 이해해야 하며, 기본 AWS CloudFormation 템플릿을 사용하여 Amazon VPC와 Amazon EC2 작업자 노드를 배포하면 일반적으로 모든 것이 정상적으로 작동합니다. 그러나 구성의 작은 문제로 인해 오류가 발생할 수 있으므로 주의가 필요합니다. 특히, 노드가 클러스터 제어 영역에 연결할 수 있도록 서브넷이 올바르게 구성되었는지 확인하는 것이 중요합니다.

 

EKS 클러스터 아키텍처

EKS 클러스터는 AWS에서 관리하는 VPC와 고객이 관리하는 두 번째 VPC로 구성됩니다. 두 번째 VPC는 컨테이너가 실행되는 Kubernetes 작업자 노드와 기타 AWS 인프라를 호스팅합니다. 작업자 노드는 관리형 API 서버 엔드포인트에 연결해야 하며, 이 연결을 통해 Kubernetes 제어 플레인에 자신을 등록하고 애플리케이션 Pod 실행 요청을 수신합니다.

작업자 노드는 퍼블릭 엔드포인트에 연결하거나 서브넷에 배치된 EKS 관리 탄력적 네트워크 인터페이스(ENI)를 통해 연결됩니다. 클러스터의 프라이빗 엔드포인트를 활성화 여부에 따라 연결 경로가 결정됩니다. 프라이빗 엔드포인트가 비활성화된 경우에도 EKS는 kubectl exec 및 로그와 같이 Kubernetes API 서버에서 시작되는 작업을 허용하도록 ENI를 계속 프로비저닝합니다.

 

워커 노드가 온라인 상태가 되었을 경우, 컨트롤 플레인에서의 수행 순서는 다음과 같습니다.

  • EC2 인스턴스가 시작됩니다. Kubelet과 Kubernetes 노드 에이전트는 각 인스턴스에서 부팅 프로세스의 일부로 시작됩니다.
  • Kubelet은 노드를 등록하기 위해 Kubernetes 클러스터 엔드포인트에 접근합니다. VPC 외부의 퍼블릭 엔드포인트 또는 VPC 내의 프라이빗 엔드포인트에 연결됩니다.
  • Kubelet은 API 명령을 수신하고 엔드포인트로 보냅니다. API 서버(kubectl get nodes)에 쿼리하면 각 노드의 Kubelet이 API 서버에 다시 보고한 최신 상태가 표시됩니다.

노드가 클러스터 엔드포인트에 도달할 수 없는 경우 제어 플레인에 등록할 수 없으므로 포드를 시작하거나 중지하는 명령을 수신할 수 없습니다. 또한, 새 노드를 연결할 수 없으면 해당 노드를 클러스터의 일부로 사용할 수 없습니다.

 

#EKS 실습

 

1. 준비 단계

 

1.1. AWS 계정 및 리전 설정

  • AWS 계정을 생성하고 EKS를 지원하는 리전을 선택합니다.
  • 기본적으로 모든 리전에서 EKS를 사용할 수 있지만, 일부 기능은 특정 리전에서만 사용 가능할 수 있습니다.

1.2. VPC 및 서브넷 생성

  • EKS 클러스터를 위한 VPC(Virtual Private Cloud)를 생성합니다.
  • VPC는 클러스터의 네트워크 환경을 격리하는 데 사용됩니다.
  • 클러스터 내 워크로드에 따라 여러 개의 서브넷을 생성할 수 있습니다.

1.3. 보안 그룹 설정

  • EKS 클러스터, 워크로드, 노드에 대한 보안 그룹을 설정합니다.
  • 보안 그룹은 네트워크 트래픽을 제어하는 데 사용됩니다.
  • 기본적으로 EKS에서 관리하는 보안 그룹이 제공되지만, 추가적인 규칙을 설정할 수 있습니다.

1.4. IAM 역할 및 권한 설정

  • EKS 클러스터 관리 및 워크로드 실행에 필요한 IAM 역할 및 권한을 설정합니다.
  • IAM 역할은 AWS 리소스에 대한 액세스를 제어하는 데 사용됩니다.
  • EKS에서 관리하는 기본 역할이 제공되지만, 사용자 정의 역할을 생성할 수 있습니다.

2. EKS 클러스터 생성

 

2.1. eksctl 또는 AWS 콘솔 사용

  • eksctl CLI 또는 AWS 콘솔을 사용하여 EKS 클러스터를 생성합니다.
  • eksctl은 EKS 클러스터를 관리하는 CLI 도구입니다.
  • AWS 콘솔은 웹 기반 인터페이스를 제공합니다.

2.2. 클러스터 구성 옵션 설정

  • 클러스터 이름, 노드 유형, 노드 수, Kubernetes 버전 등 클러스터 구성 옵션을 설정합니다.
  • 노드 유형은 EC2 인스턴스 유형을 의미하며, 클러스터의 성능 및 비용에 영향을 미칩니다.
  • Kubernetes 버전은 클러스터에서 실행할 Kubernetes 버전을 의미합니다.

3. 네트워크 인프라 설정

 

3.1. 기본 네트워크 구성

  • EKS 클러스터 생성 시 기본적인 네트워크 인프라가 자동으로 생성됩니다.
  • 여기에는 VPC, 서브넷, 라우팅 테이블, 보안 그룹 등이 포함됩니다.

3.2. 추가 네트워크 구성

  • 클러스터에 따라 추가적인 네트워크 구성이 필요할 수 있습니다.
  • 예를 들어, 외부 네트워크와의 연결, VPN 연결, LoadBalancer 설정 등이 필요할 수 있습니다.
# CNI 정보 확인
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i tree /var/log/aws-routed-eni; echo; done
ssh ec2-user@$N1 sudo cat /var/log/aws-routed-eni/plugin.log | jq
ssh ec2-user@$N1 sudo cat /var/log/aws-routed-eni/ipamd.log | jq
ssh ec2-user@$N1 sudo cat /var/log/aws-routed-eni/egress-v6-plugin.log | jq
ssh ec2-user@$N1 sudo cat /var/log/aws-routed-eni/ebpf-sdk.log | jq
ssh ec2-user@$N1 sudo cat /var/log/aws-routed-eni/network-policy-agent.log | jq

# 네트워크 정보 확인 : eniY는 pod network 네임스페이스와 veth pair
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -br -c addr; echo; done
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c addr; echo; done
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c route; echo; done
ssh ec2-user@$N1 sudo iptables -t nat -S
ssh ec2-user@$N1 sudo iptables -t nat -L -n -v

 

-iptables

iptables는 리눅스 운영 체제에서 네트워크 트래픽을 필터링하고 제어하는 데 사용되는 기본 방화벽 도구입니다. iptables 명령어를 사용하여 규칙을 추가, 삭제, 수정하고, 네트워크 트래픽을 관리할 수 있습니다.

1. iptables 명령어 구조

iptables 명령어는 다음과 같은 기본 구조를 따릅니다.

iptables [옵션] <테이블> <체인> <규칙>
  • 옵션: iptables 명령어의 작동 방식을 변경하는 데 사용됩니다.
  • 테이블: 규칙이 저장되는 테이블을 지정합니다. 주요 테이블로는 filter, nat, mangle, raw 등이 있습니다.
  • 체인: 테이블 내에 존재하는 규칙 집합을 지정합니다. 주요 체인으로는 INPUT, OUTPUT, FORWARD 등이 있습니다.
  • 규칙: 패킷 필터링 조건과 조치를 정의합니다.

2. 주요 옵션

  • -A: 규칙을 체인에 추가합니다.
  • -D: 규칙을 체인에서 삭제합니다.
  • -I: 규칙을 체인에 삽입합니다.
  • -L: 규칙 목록을 출력합니다.
  • -F: 체인의 모든 규칙을 삭제합니다.
  • -t: 테이블을 지정합니다.
  • -p: 프로토콜을 지정합니다.
  • -s: 출발지 IP 주소를 지정합니다.
  • -d: 목적지 IP 주소를 지정합니다.
  • --sport: 출발지 포트 번호를 지정합니다.
  • --dport: 목적지 포트 번호를 지정합니다.
  • -j: 규칙과 일치하는 패킷에 적용할 조치를 지정합니다.

 

테스트용 파드 생성 및 파드확인

더보기
# 테스트용 파드 netshoot-pod 생성
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: netshoot-pod
spec:
  replicas: 3
  selector:
    matchLabels:
      app: netshoot-pod
  template:
    metadata:
      labels:
        app: netshoot-pod
    spec:
      containers:
      - name: netshoot-pod
        image: nicolaka/netshoot
        command: ["tail"]
        args: ["-f", "/dev/null"]
      terminationGracePeriodSeconds: 0
EOF

# 파드 이름 변수 지정
PODNAME1=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[0].metadata.name})
PODNAME2=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[1].metadata.name})
PODNAME3=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[2].metadata.name})

# 파드 확인
kubectl get pod -o wide
kubectl get pod -o=custom-columns=NAME:.metadata.name,IP:.status.podIP

# 노드에 라우팅 정보 확인
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c route; echo; done

 

2. 파드에서 외부 통신 테스트 및 확인

  • 파드 shell 실행 후 외부로 ping 테스트 & 워커 노드에서 tcpdump 및 iptables 정보 확인
더보기
더보기
# 작업용 EC2 : pod-1 Shell 에서 외부로 ping
kubectl exec -it $PODNAME1 -- ping -c 1 www.google.com
kubectl exec -it $PODNAME1 -- ping -i 0.1 www.google.com

# 워커 노드 EC2 : TCPDUMP 확인
sudo tcpdump -i any -nn icmp
sudo tcpdump -i eth0 -nn icmp

# 워커 노드 EC2 : 퍼블릭IP 확인
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i curl -s ipinfo.io/ip; echo; echo; done

# 작업용 EC2 : pod-1 Shell 에서 외부 접속 확인 - 공인IP는 어떤 주소인가?
## The right way to check the weather - 링크
for i in $PODNAME1 $PODNAME2 $PODNAME3; do echo ">> Pod : $i <<"; kubectl exec -it $i -- curl -s ipinfo.io/ip; echo; echo; done
kubectl exec -it $PODNAME1 -- curl -s wttr.in/seoul
kubectl exec -it $PODNAME1 -- curl -s wttr.in/seoul?format=3
kubectl exec -it $PODNAME1 -- curl -s wttr.in/Moon
kubectl exec -it $PODNAME1 -- curl -s wttr.in/:help

 

- lsns

리눅스에서는 특정 프로세스를 네임스페이스에 넣게되면 그 네임스페이스에서 허용하는 것만 볼 수 있고 namespace 기능을 지원. 리눅스에서 현재 동작중인 네임스페이스를 보고싶으면 lsns 명령어를 통해 확인 가능

 

- nsenter

다른 네임스페이스에서 프로그램을 실행시킬 때 사용하는 명령어. 즉, 해당 명령어를 사용하면, docker 환경에서 , 특정 컨테이너가 열고 있는 LISTEN port 를 확인가능

 

# t3 타입의 정보(필터) 확인
aws ec2 describe-instance-types --filters Name=instance-type,Values=t3.* \
 --query "InstanceTypes[].{Type: InstanceType, MaxENI: NetworkInfo.MaximumNetworkInterfaces, IPv4addr: NetworkInfo.Ipv4AddressesPerInterface}" \
 --output table

cf)컴퓨팅 - Amazon EC2 인스턴스 유형 - AWS

https://aws.amazon.com/ko/ec2/instance-types/

3. 최대 파드 생성 및 확인

  • t3의경우 노드당 파드 수 최대 17개 생성가능 . 현재 워커노드는 3개이므로 총 51개 생성

위와같이 50개가 넘으면 pendig 발생

==>kubectl describe pod <pod명> 실행 후, Too many pod로 인해, 스케쥴링이 실패한것을 볼 수 있음

 

4. [심화] Amazon VPC CNI 플러그인으로 노드당 파드수 제한 늘리기

 

파드(Pod)는 쿠버네티스에서 생성하고 관리할 수 있는 가장 작은 컴퓨팅 단위입니다. 하나의 파드는 쿠버네티스 클러스터 내에서 통신하기 위해 고유한 IP 주소가 필요합니다.

 

Amazon Elastic Kubernetes Service(EKS)는 기본적으로 VPC 컨테이너 네트워킹 인터페이스(CNI) 플러그인을 실행하며, EC2 인스턴스에서 네트워크 인터페이스와 IP 주소를 관리하여 Pod에 IP 주소를 할당합니다. VPC CNI 플러그인은 AWS에서 동작하는 쿠버네티스 클러스터 내의 컨테이너 네트워킹이 높은 성능과 낮은 지연을 제공할 수 있도록 EC2 네트워킹과 직접적으로 통합됩니다. 이 플러그인은 각 Pod에 클러스터가 속한 VPC로부터 하나의 IP 주소를 받아 할당합니다.

기본적으로 Pod에 할당할 수 있는 IP 주소의 수는 EC2 인스턴스 유형에 연결할 수 있는 인터페이스당 보조 IP와 ENI의 최대 수를 기반으로 합니다.

# ENABLE_PREFIX_DELEGATION 파라미터를 사용하여 네트워크 인터페이스에 접두사를 할당하도록 VPC CNI 플러그인을 구성
kubectl set env daemonset aws-node -n kube-system ENABLE_PREFIX_DELEGATION=true

# 환경 변수가 설정되었는지 확인
kubectl describe daemonset -n kube-system aws-node | grep ENABLE_PREFIX_DELEGATION

# 더 빠른 확장, IPv4 주소 보존
kubectl set env ds aws-node -n kube-system WARM_PREFIX_TARGET=1

Amazon VPC CNI는 WARM_PREFIX_TARGET 또는 WARM_IP_TARGET과 MINIMUM_IP_TARGET 중 어느 한쪽이나 둘 모두 설정을 지원한다. 권장되는(설치 매니페스트 내 기본 설정값인) 구성은 WARM_PREFIX_TARGET을 1로 설정하는 것이다. 사용 중인 매니페스트에 아직 설정되어 있지 않다면 아래 명령을 사용하여 수동으로 이 값을 설정할 수 있다.

 

더보기
최대 파드 수 계산

 

(인스턴스 유형에 대한 네트워크 인터페이스 수 × (네트워크 인터페이스 당 슬롯 수 - 1)* 16)

 

m5.large 인스턴스에 대해 Amazon EKS에서 권장되는 최대 파드 수

110

 

관리형 노드 그룹 생성

# AWS eks 생성
eksctl create nodegroup \
    --cluster myeks \ 
    --region ap-northeast-2 \ 
    --name juls-nodegroup \ 
    --node-type m5.large \
    --nodes 1

 

파드 개수 확장

ubectl scale deployment.v1.apps/nginx-deployment --replicas=110

 

노드 당 파드 개수확인

 

 

  • 100개이상의 파드가 전부 running되는 것을 확인

 

5. 실습 완료 후 리소스 삭제

eksctl delete cluster --name $CLUSTER_NAME && aws cloudformation delete-stack --stack-name $CLUSTER_NAME

 

삭제 소요시간은 대략 20분정도 걸리며, 아래와 같이 삭제된 것을 확인가능함.

#스터디 후기

처음에는 eks 실습을 vsc가 아닌 ec2 콘솔에서 수행하였지만, vsc에서 플러그인을 설치하고 세팅한 후 작업속도가 매우 향상되었습니다. 그리고 aws eks를 학습하면서 노드에서 파드 개수 제한이 있다는 것을 처음 알았고, 파드 개수를 확장하면서 새로운 내용을 배우게되어 뜻 깊은 시간이 되었습니다.

'EKS Study' 카테고리의 다른 글

6주차 - EKS Security  (0) 2024.04.13
5주차 - EKS Autoscaling  (0) 2024.04.07
4주차 - EKS Observability  (1) 2024.03.24
3주차 - EKS Storage & Nodegroup  (1) 2024.03.17
1주차 - Amzaon EKS 설치 및 기본 사용  (0) 2024.03.03