쿠버네티스 스터디 (PKOS 2기) - 2주차

김준영·2023년 3월 14일
0

CloudNet PKOS2기

목록 보기
2/5
post-thumbnail

글에 중간 중간에 첨부된 다이어그램은 스터디에서 사용하는 다이어그램을 캡처하였습니다.
CloudNet팀의 가시다님 스터디로 진행됩니다.

Basic Concept

쿠버네티스 서비스

기존 가상머신 환경처럼 파드간 연결에 고정된 IP 주소를 이용하면 쿠버네티스 환경에서 새롭게 생성되는 파드는 기존 파드와 IP 주소가 다르므로 IP주소를 다시 환경변수 파일 등에서 수정해야 하므로 추가 시간이 소요됨. 쿠버네티스는 클러스터 내부 혹은 외부 연결에 따라 ClusterIP, Headless와 NodePort, LoadBalancer로 나뉜다.

특징

노드 내 실행중인 여러 파드로 부하를 분산하는 로드밸런싱 기능을 자체적으로 지원

CoreDNS 및 LocalDNS 설정

쿠버네티스는 서비스 이름을 기준으로 도메인 이름(DNS)으로 관리한다. 쿠버네티스는 DNS 기능을 코어 DNS와 로컬 DNS 두가지로 나눠서 사용함. 이러한 두가지 DNS 모두 마스터 노드의 파드로 관리한다 해당 파드는 kube-system 네임스페이스에서 확인할 수 있다.

k get pod -o wide -n kube-system
k get deployment -n kube-system
k get daemonsets -n kube-system

코어 DNS는 이중화를 위해 2개의 파드가 디플로이먼트로 실행되고 로컬 DNS는 쿠버네티스 전체 노드에 데몬셋(DemonSet)으로 실행된다. 만약 DNS 조회 및 응답에 문제가 생겼을 때 위 파드를 재 시작하면 문제가 해결되는 경우가 많다.

데몬셋은 쿠버네티스가 실행되는 모드 노드에서 자동으로 실행하는 파드이다. 기존 클러스터에 노드가 추가되면 해당 노드에 데몬셋으로 등록된 파드가 자동으로 실행된다. 스토리지, 로깅, 모니터링 용도의 파드가 주로 데몬셋으로 실행된다.

웹서버에서 데이터베이스 파드를 연결하기 위한설정 파일에 데이터베이스 연결은 {서비스이름}.{네임스페이스이름} 형식으로 네임스페이스 이름까지 등록해서 사용함.

부하 분산 설정

모든 쿠버네티스 서비스는 기본 설정으로 부하 분산을 지원한다. 쿠버네티스 모든 노드에서 실행중인 kube-proxy 파드는 노드 내에서 실행 중인 모든 파드의 네트워크 트래픽을 처리한다. 여기서 proxy는 대리라는 의미로 일반적으로 프락시 서버는 모든 네트워크 트래픽을 자신을 통해 처리한다. 유사하게 kube-proxy는 쿠버네티스 서비스와 연동해서 파드의 모든 잉그레스, 이그레스 통신을 처리함.

Study 실습

가시다님이 무료로 제공하는 kops 원클릭 cloudformation 링크를 통해 kops 원클릭 배포를 진행하자.

CNI란

컨테이너 간의 네트워킹을 제어할 수 있는 플러그인을 만들기 위한 표준. 쿠버네티스에서는 Pod간의 통신을 위해 CNI를 사용함.

AWS VPC CNI란

K8S CNI - Container Network Interface는 k8s의 네트워크 환경을 구성해준다.
AWS VPC CNI - 파드의 IP를 할당해준다. 파드의 IP 네트워크 대역과 노드(워커)의 IP대역이 같아서 직접 통신이 가능하다.

Calico CNI란

오픈소스 프로젝트, k8s의 각 노드에 설치되어 각 파드간 네트워크 통신이 가능하도록 도와주는 역할을 한다.

K8s Calico CNI와 AWS VPC CNI 차이

  • AWS CNI: 네트워크 통신의 최적화를 위해서 노드와 파드의 네트워크 대역을 동일하게 설정함
  • AWS CNI: 파드간 통신시 동일 대역으로 직접 통신
  • Calico CNI: 오버레이 통신을 한다


aws vpc cli을 사용하면 오버레이를 사용 하지 않고 동작이 단순 해 진다.

여기서 잠깐

오버레이란? -> 물리적인 인프라를 기반으로 네트워크 가상화 기술을 사용하여 End-to-End 통신을 수행하는 기술을 정의하는 단어이다.
secondary IP란? -> 현재 서브넷에 의해 나뉘어져 있는 네트워크 대역에 추가적인 호스트가 필요할 때 전체적인 구성을 변경하지 않고도 확장 가능하게 하는 기술
ENI란? -> Elastic Network Interface는 인스턴스가 AWS 서비스, 다른 인스턴스 등 다른 네트워크 리소스와 통신 할 수 있도록 한다.
모든 인스턴스는 기본 네트워크 인터페이스(ENI)가 있어야 하며 이 인터페이스는 하나의 서브넷에만 연결된다.
각 인스턴스는 서비스넷으로 지정한 범위 내의 기본 프라이빗 IP 주소를 지녀야 하며 기본 프라이빗 IP 주소는 인스턴스의 기본 ENI와 연결된다. 이 주소는 변경, 삭제 할 수 없지만 기본 ENI에 Secondary Private IP 주소를 할당하여 사용할 수 있다.
veth란? -> veth는 리눅스의 버추얼 이더넷 인터페이스를 의미한다. veth는 쌍으로 만들어지며 네트워크 네임스페이스들을 터널로서 연결하거나, 물리 디바이스와 다른 네트워크 네임스페이스의 장비를 연결하는 용도로 사용할 수 있다.
L3 Lookup 이란? -> Destination IP 주소를 key로 IP Forwarding Table을 LPM(Longest Prefix Match) 방식으로 search하여 Next Hop IP 주소와 출력 포트 정보를 얻어 온다.
SNAT -> 내부에서 외부로, 패킷의 source 주소를 변경하는 것으로 인터넷으로 나가는 패킷의 SourceIP를 G/W의 public ip 로 바꾼다
DNAT -> 외부에서 내부로, Destination ip 주소를 변경하여 내부에 접근할 수 있도록 패킷을 변경한다.
대표적인 것은 LoadBalancer이다.

워커 노드에 생성 가능한 최대 파드 갯수


1. Secondary IPv4 addresses : 인스턴스 유형에 최대 ENI 갯수와 할당 가능 IP 수를 조합하여 선정
2. IPv4 Prefix Delegation : IPv4 28bit 서브넷(prefix)를 위임하여 할당 가능 IP 수와 인스턴스 유형에 권장하는 최대 갯수로 선정

t3.medim(예시) 노드의 네트워크 구성

  • 네트워크 네임스페이스는 호스트(Root)와 파드(per pod)로 구분된다
  • 특정한 파드(kube-proxy, aws-node)는 호스트(root)의 IP를 그대로 사용한다
  • t3.medium의 경우 ENI에 최대 6개의 IP를 가질 수 있다.
  • ENI0, ENI1으로 2개의 ENI는 자신의 IP 이외에 추가적으로 5개 보조 프라이빗 IP를 가질 수 있다.
  • coredns 파드는 veth 으로 호스트에는 eniY@ifN 인터페이스와 파드에 eth0 과 연결되어 있다

노드 간 파드 통신

  1. pod1에서 pod2로 통신 시작
  2. 목적지 IP주소 (192.168.2.63), 목적지 MAC주소 (192.168.1.249)로 가겠다고 veth로 발송
  3. veth(192.168.1.249)에 도착해서 L3 룩업 수행 eth0(192.168.1.64)로 발송
  4. eth0에서 다른 노드로 발송
  5. 다른 노드의 eth0 -> veth로 발송
  6. 목적지 192.168.2.63 도착

파드에서 외부 통신

  • iptable 에 SNAT 을 통하여 노드의 eth0 IP로 변경되어서 외부와 통신됨

파드에서 외부로 연결할때는 iptable에서 정책이 걸려있다
실습에서 파드안에서 외부랑 통신할때 어떤 ip로 변하게 되나면 해당하는 워커 노드의 ENI의 매핑된 유동적 ip이다.
AWS VPC CNI를 쓰면 IPTable을 안쓴는 것은 아니고 좀 덜 쓸 수 있다라고 보면 되고 장애처리라던가 효율이 더 좀 더 좋다.

파드가 외부와 통신시에는 'AWS-SNAT-CHAIN-0, AWS-SNAT-CHAIN-1' 룰(rule)에 의해서 SNAT 되어서 외부와 통신!
참고로 뒤 IP는 eth0(ENI 첫번째)의 IP 주소이다

Service & AWS Loadbalacer Controller

MetalLb를 이용한 로드밸런서 타입 서비스 구축

노드 타입 서비스는 외부 클라이언트에서 접속했을 때 특정 도메인이 아닌 특정 노드가 실제로 사용하는 IP 주소를 지정해서 접속함. EKS, AKS 등 퍼블릭 클라우드 업체가 제공하는 매니지드 쿠버네티스 서비스는 로드밸런서 타입의 서비스를 자체적으로 제공하지만 온프레미스 환경은 외부 업체가 제공하는 별도의 솔루션이 필요하다.

MetalLb 설치에 앞서 로드밸런서 용도로 사용할 IP 대역이 필요하다. 할당할 로드밸런서 IP 대역이 다른 서버 등에서 사용하지 않는지 검증하기 위해 'ping + for반복문' 명령어로 사용해 확인

for i in {0..9};do ping -c <ip>$i

헬름으로 설치한다

helm repo add metallb https://metallb.github.io/metallb
helm pull metallb/metallb --version -v0.12.1
tar xvfz metallb-0.12.1.tgz
rm -rf metallb-0.12.1.tgz
mv metallb/ metallb-0.12.1
cd metallb-0.12.1/
cp values.yaml my-values.yaml
# 헬름의 설정값을 바꿔주기위하여 yaml을 나의 yaml으로 복사하여 설정

my-value.yaml 파일의 address 대역을 사전에 준비한 IP 대역으로 입력

k create ns metallb
helm install metallb -f my-values.yaml .

서비스 종류

  1. Cluster IP
  2. NodePort

    iptables 규칙은 스마트한 규칙 세트로 이루어짐

  3. LoadBalancer
  4. Service(LoadBalancer Controller): AWS Load Balancer Controller + NLB IP 모드 동작 with AWS VPC CNI

NLB 모드 인스턴스 유형

  1. externalTrafficPolicy: ClusterIP -> 2번 분산 (Loadbalancer 타입 기본모드)
  2. externalTrafficPolicy: Local -> 1번 분산, 워커 노드의 iptables 사용

로드밸런서가 부하분산하여 파드가 존재하는 노드들에게 전달한다 -> iptables에서 노드에 있는 파드만 연결
DNAT 2번 동작: 첫번째 (로드밸런스 접속 후 빠져나갈 때), 두번째 (노드의 iptables 룰에서 파드IP 전달)

IP유형 -> AWS LoadBalancer 컨트롤러 파드 및 정책 설정 필요
1. Proxy Protocol v2 비활성화: NLB에서 바로 파드로 인입, ClientIP가 NLB로 SNAT 되어 client ip 확인 불가능
2. Proxy Protocol v2 활성화: NLB에서 바로 파드로 인입 및 ClientIP 확인 가능

인그레스

로드밸런스 타입 서비스는 네트워크 레이어4 기능까지만 지원하므로 몇 가지 한계가 있다. 쿠버네티스는 인그레스라는 별도의 오브젝트로 네트워크 레이어7 기능을 제공

  • URL 및 경로별 백엔드 서비스 분리
  • SSL/TLS 인증서 연동
  • 애플리케이션 관리 효율을 위해 외부 접속에 관한 상세 규칙을 별도 인그레스 리소스로 분리

쿠버네티스 인그레스는 많이 사용하는 네트워크 7계층을 지원하는 스위치(L7 스위치)와 유사한 기능을 제공한다. 쿠버네티스 인그레스는 설정에 관련된 부분만 포함하고 실제 네트워크 트래픽 처리는 인그레스 컨트롤러가 관리한다. 인그레스 컨트롤러는 쿠버네티스 자체에서 제공하지 않고 nginx, haproxy, traefik 등 솔루션인데 가장 많이 사용하는 솔루션은 nginx 인그레스 컨트롤러이다.
외부에서 사용자가 특정 경로로 접속하게 되면 인그레스를 통해 정의해둔 규칙에 따라 인그레스 컨트롤러가 동작하여 서비스에 맞는 파드로 연결해준다.

: web proxy 역할을 한다

AWS Load Balancer Controller + Ingress (ALB) IP 모드 동작 with AWS VPC CNI

궁금한 점: 간간히 특정 파드에 트래픽이 몰리는 현상이 있는데 이거는 AWS LoadBalancer Controller + NLB|ALB 로 해결이 가능할까? -> 나중에 조사해보기

마치며

좀 더 깊숙한 지식을 얻기 위해서는 책 읽기와 스터디가 중요하다는 걸 깨달았다

0개의 댓글