관리 메뉴

피터의 개발이야기

[Kubernetes] 네트워크 이해 본문

Kubernetes/기초공부

[Kubernetes] 네트워크 이해

기록하는 백앤드개발자 2023. 5. 4. 07:52
반응형

[kubernetes] 쿠버네티스 목차

ㅁ 들어가며

[kubernetes] 쿠버네티스 컨트롤러에서 컨트롤러의 역할과 다양한 목적에 따른 배포과 관리 방식에 대해서 알아보았다. 이번 글에서는 리소스 들 간의 통신을 위한 Network에 대해서, 쿠버네티스 입문 책(7,8,15,16장)쿠버네티스 문서 > 개념 >서비스, 로드밸런싱, 네트워킹을 읽고 공부한 내용을 정리하였다.

 

쿠버네티스 네트워크 모델
 ㄴ Service
 ㄴ Ingress
 ㄴ kube-proxy
클러스터 네트워킹 구성
 ㄴ 도커 컨테이너의 네트워킹
 ㄴ 멀티노드의 네트워크 구조
CNI란?
 ㄴ CNI 플러그인
쿠버네티스 DNS
 ㄴ kube-dns 질의 구조
 ㄴ CoreDNS의 질의 구조
 ㄴ 파드의 DNS 설정

 

ㅁ 쿠버네티스 네트워크 모델

 클러스터의 모든 Pod는 고유한 IP주소를 갖는다. 쿠버네티스 IP주소는 Pod범주에 존재하며, Pod내의 컨테이너들은 IP주소, MAC주소를 포함하는 네트워크 네임스페이스를 공유한다. 그래서 Pod내의 컨테이너는 각 포트로 접속할 수 있다.

 

쿠버네티스 네트워킹은 다음의 네 가지 문제를 해결한다.

참조쿠버네티스 네트워크 모델의 내용을 보고 정리

 

 

ㅁ Service

서비스는 여러 개 파드의 로드벨런서 역할을 한다. 서비스에 접근할 수 있는 IP 하나를 통해 인입된 트래픽은 균등하게 파드에게 전달된다. 

 

ㅇ 서비스 타입

 - ClusterIP: 클러스터 안의 노드나 파드에 접속할 때에 사용한다.  클러스터 IP를 이용해서 서비스에 연결된 파드나 노드에 접근한다. 클러스터 외부에서는 접근할 수 없다.

 - NodePort: 서비스 하나에 모든 노드의 지정 포트를 할당한다. 노드에 상관없이 서비스에 지정된 포트 번호만 사용하면 파드에 접근할 수 있다. 노트포트를 이용하여 클러스터 외부에서도 접근이 가능하다. 

 - LoadBalancer: 퍼블릭 클라우드 서비스 혹은 오픈스팩 같은 프라이빗 클라우드에서 쿠버네티스를 지원하는 로드밸런서 장비에서 사용된다. kubectl get service 명령에서 EXTERNAL-IP 항목에 로드밸런서 IP를 확인할 수 있다. 

 - ExternalName: .spec.externalName 필드에 설정한 값과 서비스를 연결한다. 클러스터 안에서 외부에 접근할 때 주로 사용한다. 이 서비스로 클러스터 외부에 접근하면 설정해둔 CNAME값을 이용해 클러스터 외부에 접근할 수 있다.  

 

ㅇ 헤드리스 서비스

 .spec.clusterIP필드 값을 None으로 설정하면 클러스터 IP가 없는 서비스를 만들 수 있다. 로드밸런싱이 필요 없거나 단일 서비스 IP가 필요 없을 때 사용한다. 

 

ㅁ Ingress

인그레스는 클러스터 외부와 통신을 가능하게 한다. 서비스와의 차이점은 주로 L7영역의 통신을 담당해서 처리한다는 점이다. 인그레스는 클러스터 외부에서 안으로 접근하는 요청들 정의된 URL 패턴에 따라 분기처리한다. 이 뿐만 아니라 트래픽 로드밸런싱, SSL 인증서 처리, 도메인 기반 가상 호스팅도 제공한다. 인그레스 자체는 이런 규칙들을 정의한 곳이고, 실제 동작은 인그레스 컨트롤러에서 이루어준다. 

  클라우드를 사용하면 자체 로드밸런서 서비시와 연동해서 인그레스를 사용할 수 있다. 클라우드를 사용하지 않는 경우 인그레스 컨트롤러를 직접 인그레스와 연동해야한다. 쿠버네티스에서는 ingress-nginx를 제공하며 ingress-ngix 컨트롤러는 인그레스에 설정한 내용을 nginx 환경 설정으로 변경해서 nginx에 적용한다.

 

  무중단 배포를 할 때 주의할 점

인그레스 설정을 통해 무중단 배포를 할 수 있다. RollingUpdate로 설정했을 때, .maxSurge 필드는 기본 파드 개수에 여분의 파드를 몇 개 추가할지 설정한다. maxUnavailable 필드에는 디플로이번트를 업데이트하는 동안 몇 개의 파드를 이용할 수 없어도 되는지 설정한다. readinessPorbe는 실제로 컨테이너가 서비스 요청을 처리할 수 있는 상태인지 진단한다.

  GracefulShutdown 설정이 필요하다. GracefulShutdown은 컨테이너에서 SIGTERM 신호를 받았을 때 기존 요청은 처리 완료하고 신규 요청을 받지 않다. 기존 처리가 지연이 되면 컨테이너는 SIGKILL 처리를 하는데 이를 유회하려면 .terminationGracePeriodSeconds 필드에 시간을 설정할 수 있고 기본 대기시간은 30초이다.

 

NGINX 인그레스(Ingress) 컨트롤러로 Minikube에서 인그레스 설정하기

블루/그린 배포, 카나리아 배포 및 A/B 테스트를 위해 AWS Load Balancer Controller 사용

 

ㅁ kube-proxy

kube-proxy는 쿠버네티스에서 서비스를 만들었을 때 클러스터 IP나 포트로 접근할 수 있게 만들어 준다. 노드마다 실행되면서 클러스터 내부 IP로 연결하려는 요청을 파드로 전달한다. kube-proxy는 userspace, iptables, IPVS를 사용하여 네트워크를 관리한다. 

ㅇ userspace 모드
userspace모드로 설정하면 클라이언트에서 서비스IP를 통해서 요청을 하게 되면 iptables을 거쳐서 큐브프록시가 요청을 받은 다음에 그 서비스IP가 연결되야하는 적절한 포드로 연결을 해 준다. 이때 요청을 포드들에 나눠주는 방식은 라운드로빈(round robin)이다.
ㅇ iptables 모드
  iptables 모드가 userspace모드와 다른점은 큐브프록시는 iptable을 관리하는 역할만 하고 직접 클라이언트로 부터 트래픽을 받지는 않다. 클라이언트로부터 오는 모든 요청은 iptables을 거쳐서 직접 포드로 전달된다. 그래서 userspace모드보다 빠른 성능을 가지게 된다. userspace모드에서는 포드 하나로의 요청이 실패하면 자동으로 다른 포드로 연결을 재시도 하지만 iptables모드에서는 포드하나로 가는 요청이 실패하면 재시도를 하지 않고 그냥 요청이 실패한다. 그래서 이런걸 방지하기 위해서 readiness probe 설정이 잘 되어 있어야 한다.
 
ㅇ ipvs 모드
ipvs(IP Virtual Server) 모드는 리눅스 커널에 있는 L4 로드밸런싱 기술로 Netfilter에 포함되어 있다. 그래서 IPVS 커널모듈이 설치되어 있어야 한다. ipvs는 커널스페이스에서 작동하고 데이터 구조를 해시테이블로 저장해서 가지고 있기 때문에 iptables보다 빠르고 좋은 성능을 낸다. 그리고 ipvs는 더 많은 로드밸런싱 알고리즘을 가지고 있어서 이걸 이용할 수 있다. rr(round-robin), lc(least connection), dh(destination hashing), sh(source hashing), sed(shortest expected delay), nq(never queue)등의 다양한 로드밸런싱 알고리즘을 제공해 준다. 

 

  NAT 영역의 설정은 kube-proxy가 담당한다. 파드에 변경 사항이 발생하면 kube-proxy가 NAT 규칙을 업데이트한다.  쿠버네티스 초기에는 kube-proxy가 직접 패킷을 받아서 IP를 변환했으므로 성능 이슈가 있었지만, 현재는 Netfilter 기반의 iptables를 이용하는 것이 기본 옵션이다. kube-proxy는 직접 패킷을 변환하는 것이 아니라 iptables에 규칙만 업데이트 한다. iptables에 수천 개 단위로 업데이트 하면 성능 이슈가 있어 요즘은 IPVS(IP Virtural Server)를 사용하고 있다.

 

ㅁ 클러스터 네트워킹 구성

쿠버네티스 입문 책, 15장의 내용을 보고 정리한 내용이다. 이 장을 읽으면서 네트워크의 부족한 개념들을 별도로 공부하였는데, 어려운 네트워크를 통합적으로 이해할 수 있었던 계기가 되었다. 어렵지만 시간을 가지고 한번을 정독하면 큰 도움이 된다. 

 

도커 컨테이너의 네트워킹

 쿠버네티스의 파드 네트워킹을 이해하기 위해서는 도커 컨테이너의 네트워킹을 이해해야한다. 도커 브리지 타입 네트워크는 호스트 안에 docker0이라는 브리지를 추가해 컨테이너와 호스트 사이를 연결한다. 네트워크 네임스페이스는 별도의 ARP(Address Resolution Protocol, IP를 MAC으로 변경), 라우팅, iptables가 있다. 네트워크 네임스페이스는 서로 연결되기 전까지는 독립적으로 동작한다. 베스(vartual ethernet, veth)는 컨테이너와 호스트 브리지(docker0)에 연결해서 호스트 네임스페이스와 컨테이너 네트워크 사이를 통신한다.

 

파드 네트워킹

  쿠버네티스는 도커와는 달리 파드 단위로 컨테이너를 관리한다. 파드의 veth0은 pause 컨테이너 네트워크 네임스페이스에 속한 장치이다. 같은 파드 안에서 pause 컨테이너 네트워크 네임스페이스를 공유해 사용한다. 그래서 pause 컨테이너가 변하지 않으면 사용자 컨테이너들은 재시작을 하더라도 veth0에 할당된 IP를 사용한다. 파드 하나에 여러개 컨테이너를 생성되더라도 컨테이너 각각에 할당된 IP는 변하지 않다. pause가 문제가 생기면 네트워크 통신을 할 수 없다.

 

 

멀티노드의 네트워크 구조

멀티노드의 네트워크 구조에서는 CNI(Container Network Interface)를 사용하여 PID에 개별 IP를 할당하게 해 준다. 

쿠버네티스는 클러스터 내부에서 사용하는 DNS를 설정할 수 있다. 그래서 파드끼리 통신을 할 때에 IP가 아닌 도메인을 사용할 수 있다. DNS를 사용하기 위해서는 CoreDNS가 필요하다. CNI는 표준을 의미하기도 하고 플러그인 이름이기도 하다. 

 

 

CNI란?

 

 

CNI(Container Network Interface)는 컨테이너 간의 네트워킹을 제어할 수 있는 기술적인 표준이다.
내용이 길어져서 [AWS VPN] CNI란에 정리하였다.

 

CNI 플러그인

 네트워크 모델은 각 노드의 컨테이너 런타임에 의해 구현된다. 가장 일반적인 컨테이너 런타임은 컨테이너 네트워크 인터페이스(CNI) 플러그인을 사용하여 네트워크 및 보안 기능을 관리한다. 상용클라우드는 CNI를 지원하고 있어 별도의 플러그인을 직접 설정할 필요가 없지만, 사설인 경우 쿠버네티스 클러스터 네트워크도 직접 구성해야한다. 플라넬, 칼리코, 캐널, kube-router, 로마나, 위브넷, 실리엄, 컨티브, 멀터스 등 다양한 네트워크 플러그인을 사용할 수 있다.  쿠버네티스에서 지원하는 네트워킹 애드온의 일부 목록은 쿠버네티스 공식문서 페이지를 참조.

 

 

ㅁ 쿠버네티스 DNS

쿠버네티스는 파드와 서비스를 위한 DNS 레코드를 생성한다. 사용자는 IP 주소 대신에 일관된 DNS 네임을 통해서 서비스에 접속할 수 있다. 파드마다 .spec.dnsPolicy 필드를 사용하여 도메인 요청하는 순서를 설정할 수 있다.

 

 - Default: Node의 DNS 설정 사용

 - ClusterFirst : clutster.local 같은 클러스터 안의 도메인이 아닌 경우 외부 DNS에 도메인 질의를 한다.

 - ClusterFirstWhithHostNet: 파드를 호스트 모드로 사용하겠다고 설정하는 hostNetwork 옵션으로 파드를 실행할 때 반드시 사용해야 하는 필드 값이다. 

 - Node: 파드가 쿠버네티스 클러스터 안 DNS 설정을 무시한다.  .spec.dnsConfig의 하위 필드로 별도의 DNS 설정을 해야한다. 

 

 

kube-dns 질의 구조

  kube-dns 파드는 kubecns(Matser), dnsmasq(DNS 캐시), sidecar(앞 두 파드 헬스체크)로 구성된다. kube-dns 파드에 도메인 이름을 질의했을 때 원하는 결과를 찾을 수 없으면, 사용자 정의 DNS에 질의한다. 업스트림 DNS에 진의한다. 

 

 

CoreDNS의 질의 구조

https://malwareanalysis.tistory.com/267

  CoreDNS는 모듈 형식이며 kube-dns와 다르게 파드 안에 coredns라는 컨테이너 하나만 존재한다. 쿠버네티스 애드온으로 쿠버네티스 클러스터 실행시 pod로 실행된다. 파드, 서비스 도메인을 관리하고 외부 도메인 서버 연결이 필요한 경우 통로역할을 수행한다. CoreDNS는 deployment로 관리되고 ClusterIP타입 서비스를 가진다. 서비스이름은 kube-dns인데 호환성을 위해 구버전부터 사용했던 DNS서비스 이름을 사용한다.

 플러그인을 통해 새로운 기능을 추가할 수 있는 유연함을 가지고 있다. Corefile이라는 CoreDNS 자체의 설정 파일 형식에 맞춰서 DNS를 설정한다. 

  • 파드 도메인: <파드-ip>.<namespace>.pod.cluster.local
  • 서비스 도메인: <서비스이름>.<namespace>.svc.cluster.local

 

파드의 DNS  설정

  파드 안 DNS를 사용자가 직접 설정할 수도 있다. 쿠버네티스 문서

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - 1.2.3.4
    searches:
      - ns1.svc.cluster-domain.example
      - my.dns.search.suffix
    options:
      - name: ndots
        value: "2"
      - name: edns0

사용자는 dnsConfig 필드에서 다음과 같은 속성들을 지정할 수 있다.

  • nameservers: 파드의 DNS 서버가 사용할 IP 주소들의 목록이다. 파드의 dnsPolicy가 "None" 으로 설정된 경우에는 적어도 하나의 IP 주소가 포함되어야 하며, 그렇지 않으면 이 속성은 생략할 수 있다. nameservers에 나열된 서버는 지정된 DNS 정책을 통해 생성된 기본 네임 서버와 합쳐지며 중복되는 주소는 제거된다.
  • searches: 파드의 호스트네임을 찾기 위한 DNS 검색 도메인의 목록이다. 이 속성은 생략이 가능하며, 값을 지정한 경우 나열된 검색 도메인은 지정된 DNS 정책을 통해 생성된 기본 검색 도메인에 합쳐진다. 병합 시 중복되는 도메인은 제거되며, 쿠버네티스는 최대 6개의 검색 도메인을 허용하고 있다.
  • options: name 속성(필수)과 value 속성(선택)을 가질 수 있는 오브젝트들의 선택적 목록이다. 이 속성의 내용은 지정된 DNS 정책에서 생성된 옵션으로 병합된다. 이 속성의 내용은 지정된 DNS 정책을 통해 생성된 옵션으로 합쳐지며, 병합 시 중복되는 항목은 제거된다.

 

ㅁ 네트워킹 연결방식

네트워크의 연결에 대해서 논할 때에 자주 듣게 되는 단어인 NAT, 브릿지, Virtual Network에 대한 정리는 이곳에 정리하였다.

 

ㅁ 함께보면 좋은 사이트

 ㅇ kubernetes 서비스, 로드밸런싱, 네트워킹

 ㅇ 쿠버네티스입문 책 정보

 ㅇ EKS AWS CNI 분석

반응형
Comments