Udemy CKA course 9. Networking (네트워킹): 네트워크 선행개념 (스위칭, 라우팅, DNS, 네트워크 네임스페이스, 도커, CNI) 및 쿠버네티스 네트워킹 (노드, 파드, 서비스, DNS, 인그레스)

jihyelee·2024년 2월 5일
0

kubernetes

목록 보기
11/15

Certified Kubernetes Administrator (CKA) with Practice Tests (강의 링크, 레퍼런스 노트)

  • 평소 강의 할인도 많이 하고, 연습문제도 풀어볼 수 있으니 실제 강의 수강을 추천
  • 아래는 강의 내용 번역 및 정리본 (문제 시 댓글로 알려주세요)

네트워크 기본 (선행 개념)

스위칭과 라우팅

스위칭 (Switching)

  • 2 개의 시스템을 연결할 때 스위치 사용
    • 스위치가 네트워크를 생성해 두 시스템을 연결
    • 스위치와 연결하기 위해서는 각 호스트마다 인터페이스 필요
      • ip link : 인터페이스 확인 명령어
      • ip addr add [호스트 ip 주소] dev eth0 : 각 시스템에 ip 주소 할당
    • ip 주소가 할당되고 네트워크로 연결된다면 스위치를 통해 두 시스템이 통신 가능
      • ping [호스트 ip 주소] : 통신 가능 여부 확인
  • 스위치는 네트워크 내에서만 통신을 가능하게 할 수 있음
    • 한 호스트로부터 패킷을 받아 같은 네트워크에 있는 다른 시스템에 전달

라우팅 (Routing)

  • 다른 네트워크들을 연결하는 장치
  • 여러 네트워크 포트를 가진 별개의 서버라고 생각할 수 있음
    • 라우터는 연결된 네트워크마다 다른 IP를 가짐 (게이트웨이)
  • 라우팅 테이블에 정의된 내용을 통해 다른 네트워크에 존재하는 시스템끼리 통신 가능
    • route : 라우팅 테이블 확인
    • ip route add [스위치 ip 주소] via [라우터 게이트웨이 ip 주소] : 다른 네트워크 연결, 라우팅 테이블에 해당 내용 작성됨
      • 모든 시스템에 대해 이러한 설정(configuration) 이루어져야 함
        • e.g. 인터넷과 연결하고자 한다면 스위치 ip 주소에 인터넷 ip 주소 사용할 수 있음
      • 라우터가 없이 세 개의 호스트가 있고 두 개의 호스트가 다른 하나로 연결되어 있을 때, 네트워크 IP와 호스트 인터페이스 ip 주소를 연결할 수 있음
        • 일반적으로 받은 패킷을 다른 호스트로 포워드하지 못하지만, 설정을 바꿔주면 가능
          1. echo 1 > /proc/sys/net/ipv4/ip_forward : 기본값 0
          1. /etc/sysctl.conf의 net.ipv4.ip_forward 값 변경
  • 기본 게이트웨이 (Default gateway)
    • 외부의 어떠한 네트워크로부터 오는 요청이라도 라우터를 통과할 수 있게 함 (일일이 지정할 필요 없음)
    • ip route add default via [라우터 게이트웨이 ip 주소]
      • default 대신 0.0.0.0으로 표현할 수 있음

명령어

  • ip link : 호스트의 인터페이스를 나열하고 수정
  • ip addr : 인터페이스에 할당된 ip 주소 확인
  • ip addr add 192.168.1.10/24 dev eth0 : 인터페이스에 ip 주소 할당
    • 해당 명령어들은 재시작 전까지만 효력을 발휘
    • 영구적 변경을 원한다면 etc/network/interface 수정 필요
  • ip route 혹은 route : 라우팅 테이블 확인
  • ip route add 192.168.1.0/24 via 192.168.2.1 : 라우팅 테이블에 엔트리 추가
  • cat /proc/sys/net/ipv4/ip_forward : 라우터처럼 설정된 호스트가 있을 때 ip 포워딩이 가능한지 여부 확인 (0일 경우 불가능)

DNS

  • 호스트를 호출할 때 ip 주소 대신 이름을 사용
    • /etc/hosts에 ip 주소와 이름을 엔트리로 작성함으로써 이름 사용 가능
    • 하나의 ip 주소에 여러 개의 이름을 사용할 수 있음 (별도의 엔트리로 작성)
  • 호스트마다 별개의 /etc/hosts 파일을 관리하는 대신 DNS 서버를 두어 한꺼번에 관리
    • 모든 호스트의 /etc/resolv.conf에 DNS 변환 설정 (resolution configuration) 파일 추가
    • e.g. nameserver [DNS 서버 ip 주소] 와 같이 엔트리 작성
  • 호스트의 /etc/hosts와 DNS에 동일한 이름 있을 경우
    • 로컬 파일을 먼저 확인, 엔트리 찾으면 해당 엔트리를 이용 (없을 시 DNS 확인)
    • 순서는 /etc/nsswitch.conf 파일에서 수정 가능 (hosts 항목 확인)
  • 호스트와 DNS에 모두 없는 이름일 경우
    • 호스트의 /etc/resolv.conf에서 nameserver 8.8.8.8 엔트리 등록 가능
      • 8.8.8.8은 구글에서 제공하는, 인터넷 상 모든 웹사이트를 알고 있는 공공 네임서버
    • 혹은 DNS에서 Forward All to 8.8.8.8을 파일의 가장 하단에 작성할 수도 있음

도메인 이름

  • e.g. www.facebook.com
  • 공공 인터넷에서 우리가 기억할 수 있도록 ip 주소가 이름으로 변환된 것
  • 상위 단계 도메인
    • .com: 상업적 혹은 일반적 이용
    • .net: 네트워크
    • .edu: 교육기관
    • .org: 비영리 기관
    • .io
  • 서브 도메인
    • 추가적인 그룹핑을 도와줌
    • e.g. www, drive, maps, apps, mail, ...

도메인 탐색

  • 상위 단계에서부터 서브 도메인까지 각기 다른 DNS 서버를 지나오면서 올바른 IP 주소를 찾음
    • e.g. com -> google -> app 순서
    • 찾은 결과를 짧은 시간동안 캐시에 저장하고 사용하기도 함
  • 내부 도메인 서버에서 192.168.1.10의 도메인을 web.mycompany.com으로 지정했지만 web이라는 간단한 이름으로 찾고 싶을 때
    • 호스트의 /etc/resolv.conf에서 search mycompany.com 엔트리를 작성해줄 수 있음
    • mycompany.com은 추가적으로 붙이고 싶은 도메인 이름을 의미
    • 붙이고 싶은 도메인 이름은 여러 개를 작성해줄 수도 있음

레코드 타입

  • A
    • 이름과 IP 주소 (e.g. 192.168.1.1) 매핑
  • AAAA
    • 이름과 IPv6 매핑
  • CNAME
    • 이름과 다른 이름 매핑

nslookup, dig

  • nslookup www.google.com : DNS 서버에서 호스트 이름을 검색할 때 사용
  • nslookup은 로컬 /etc/hosts 파일은 검색하지 못함
  • dig www.google.com : DNS 서버에서 호스트 이름 검색, 더욱 자세한 내용 조회

CoreDNS

  • 호스트를 DNS 서버로 설정하는 것을 도와주는 여러 솔루션 중 하나
  • 깃허브 페이지 혹은 도커 이미지 형식으로 CoreDNS 바이너리 파일 다운로드 가능

네트워크 네임스페이스

  • 네임스페이스
    • 호스트가 집이라면, 네임스페이스는 집 안의 격리된 방
    • 각 네임스페이스는 자신이 수행하는 프로세스만 확인할 수 있음 (ps aux)
      • 호스트에서 동일 명령어를 사용하면 모든 네임스페이스의 프로세스 확인 가능
  • 네트워크 네임스페이스
    • 호스트는 로컬 네트워크와 연결하는 인터페이스, 라우팅 테이블, ARP 테이블을 가짐
    • 컨테이너가 생성되면 네트워크 네임스페이스를 만들어 호스트의 네트워크 관련 정보를 컨테이너가 볼 수 없게 함
      • 컨테이너는 가상 인터페이스, 라우팅 테이블, ARP 테이블을 별도로 가짐

명령어

  • ip nets add [네임스페이스명] : 네트워크 네임스페이스 생성
  • ip netns exec [네임스페이스명] ip link : 네임스페이스 내에서 인터페이스 정보 확인
    • ip -n [네임스페이스명] ip link 또한 동일한 명령어
  • ip netns exec [네임스페이스명] arp/route : 네임스페이스 내에서 ARP 테이블, 라우팅 테이블 정보 확인

네임스페이스 연결 (2개)

  • 가상의 이더넷 쌍 혹은 케이블 사용해 연결 가능 (파이프라고 일컬어짐)
  • ip link add [인터페이스명1] type veth peer name [인터페이스명2] : 두 개의 인터페이스 연결
  • ip link set [인터페이스명] netns [네임스페이스명] : 인터페이스를 각각 해당되는 네임스페이스에 연결
  • ip -n [네임스페이스명] addr add [ip주소] dev [인터페이스명] : ip 주소 할당
  • ip -n [네임스페이스명] link set [인터페이스명] up : 링크 업, 네임스페이스가 서로 통신 가능
  • ip -n [네임스페이스명] link del [인터페이스명] : 브릿지를 활용할 때 케이블 필요없어 삭제

네임스페이스 연결 (n개)

  • 리눅스 브릿지를 활용해 여러 개의 네임스페이스를 연결할 수 있음
  • ip link add [브릿지명] type bridge
  • ip link set dev [브릿지명] up
    • 네임스페이스에게는 스위치 역할, 호스트에게는 인터페이스 역할
  • ip link add [인터페이스명1] type veth peer name [브릿지 인터페이스명1] : 네임스페이스마다 지정
  • ip link set [인터페이스명] netns [네임스페이스명]
  • ip link set [브릿지 인터페이스명] master [브릿지명]
  • ip -n [네임스페이스명] addr add [ip주소] dev [인터페이스명]
  • ip -n [네임스페이스명] link set [인터페이스명] up
  • ip addr add [브릿지 ip주소] dev [브릿지명] : 호스트와 모든 네임스페이스 연결 (브릿지 이용)

네임스페이스와 외부의 LAN 네트워크 연결

  • 호스트와 브릿지를 연결해놓았다면 호스트가 일종의 게이트웨이 역할을 수행
  • ip netns exec [네임스페이스명] ip route add [외부 LAN ip 주소] via [브릿지와 로컬 호스트 인터페이스 ip 주소]
    • 로컬 호스트는 브릿지와 연결된 인터페이스와 외부 네트워크와 연결된 인터페이스를 가짐 (총 2개)
    • 명령어 수행 시 네임스페이스에서 외부 LAN 네트워크로 ping은 보낼 수 있으나 NAT 기능 수행 불가
  • iptables -t nat -A POSTROUTING -s [브릿지 ip 주소] -j MASQUERADE
    • NAT IP 테이블에 새로운 규칙 추가
    • 소스 네트워크로부터 오는 모든 패킷의 from address를 교체
    • 이를 통해 외부 네트워크와 통신 가능
  • ip netns exec [네임스페이스명] ip route add default via [브릿지와 로컬 호스트 인터페이스 ip 주소]
    • 호스트를 기본 게이트웨이로 설정함으로써 외부 인터넷 또한 접속 가능함
  • iptables -t nat -A PREROUTING --dport 80 --to-destination [네임스페이스 ip주소:80] -j DNAT
    • 외부의 호스트가 다른 호스트에 있는 네임스페이스와 통신하고 싶은 경우 해당 규칙을 지정해줄 수 있음
    • 로컬 호스트에서 포트 80으로 들어오는 트래픽은 모두 해당 네임스페이스로 포워드한다는 뜻

도커 네트워킹

  • docker run --network none [이름]
    • 컨테이너는 외부 네트워크 및 다른 컨테이너와 통신 불가
  • docker run --network host [이름]
    • 포트 80을 사용하는 컨테이너를 실행할 경우, 호스트에서 추가적인 포트 매핑 없이 사용 가능
    • 두 개의 프로세스가 동시에 같은 포트를 사용할 수는 없음 (컨테이너의 인스턴스 하나만 가능)
  • docker run [이름]
    • 호스트와 컨테이너가 붙어있는 내부적인 프라이빗 네트워크(브릿지)가 생성됨
    • 브릿지는 기본적으로 172.17.0.0 주소를 가짐

브릿지

  • docker network ls : bridge라는 이름으로 조회됨
  • ip link : docker0이라는 이름으로 조회됨
    • docker0는 기본적으로 172.17.0.1를 ip 주소로 부여받음 (ip addr)
  • ip netns : 도커는 컨테이너 실행 시 네트워크 네임스페이스를 생성
  • docker inspect [컨테이너 ID] : 네트워크 네임스페이스 확인 가능

브릿지와 컨테이너의 네임스페이스 연결하기

  • ip link : 브릿지의 인터페이스 엔드 확인 가능
  • ip -n [네트워크 네임스페이스명] link : 네트워크 네임스페이스의 엔드 확인 가능

외부 사용자와 컨테이너 연결하기

  • docker run -p 8080:80 [컨테이너명] : 도커 호스트 8080과 컨테이너의 포트(80)를 연결
  • curl http://[도커 호스트 IP]:8080 : 외부 사용자 또한 컨테이너의 어플리케이션 접근 가능

CNI

네트워크 네임스페이스 동작순서

    1. 네트워크 네임스페이스 생성
    1. 브릿지 네트워크/인터페이스 생성
    1. VETH 쌍 생성 (파이프, 가상 케이블)
    1. vEth를 네임스페이스에 연결
    1. 다른 vEth를 브릿지에 연결
    1. IP 주소 할당
    1. 인터페이스를 사용중(up)으로 변경
    1. NAT -IP Masquerade 사용 가능하도록 변경

CNI

  • 위의 2-8 과정을 브릿지 네트워크 생성 과정으로 묶고 프로그램화할 수 있음 (프로그램 = 플러그인)
    • bridge add [컨테이너 ID] [네임스페이스명]
  • CNI는 프로그램이 컨테이너 런타임 엔진에서 네트워킹을 잘 수행하도록 일련의 기준을 제시
    • 플러그인이 어떻게 개발되어야 하고 컨테이너 런타임이 어떻게 그것을 수행해야 하는지를 정의
  • CNI를 지원하는 컨테이너 런타임 엔진
    • rkt, mesos, ...
  • CNI를 지원하는 플러그인 종류
    • BRIDGE, VLAN, IPVLAN, MACVLAN, WINDOWS
    • DHCP, host-local (IPAM 플러그인)
    • weaveworks, flannel, cilium, NSX, ...(제 3 기관)
  • 도커는 CNI를 지원하지 않음 (Container Network Model; CNM 지원)
    • docker run --network=cni-bridge [컨테이너명] : 네트워크 플러그인 이런 방식으로 사용 불가
    • docker run --network=none [컨테이너명] 후 수동으로 bridge add [컨테이너ID] [네임스페이스명] 진행해줘야 함
      • 쿠버네티스 또한 도커 컨테이너를 만들 때 이런 순서를 따름

쿠버네티스

클러스터 노드 네트워킹

  • 마스터 노드, 워커 노드는 네트워크에 연결된 1개 이상의 인터페이스를 가짐
    • 인터페이스는 IP를 가짐
    • 호스트는 유일한 호스트명과 MAC 주소를 가짐
  • 오픈하는 포트
    • kube-api: 6443
      • 해당 포트로 외부 사용자, kubectl, kubelet, kube-scheduler, kube-controller-manager 등의 요청을 받음
    • kubelet: 10250
    • kube-scheduler: 10259
    • kube-controller-manager: 10257
    • ETCD: 2379
      • 마스터 노드가 여러 개일 때 2380 또한 사용
      • ETCD 클라이언트가 서로 통신하기 위한 목적
    • Services (워커 노드): 30000-32767
      • 해당 포트로 외부 접근에 서비스를 노출

명령어

  • ip link
  • ip address 혹은 ip addr 혹은 ip a
    • 인터페이스의 IP 주소 확인 가능
    • 인터페이스의 MAC 주소 확인 가능 (show 옵션)
    • controlplane이 아닌 다른 노드를 확인하고 싶다면 ssh 필요
  • ip address show type bridge
    • 브릿지 인터페이스 정보 확인 가능
  • ip addr add [ip주소] dev [인터페이스]
    • 인터페이스에 IP 주소 할당
  • ip route 혹은 route
    • 라우팅 정보 확인 가능 (기본 게이트웨이 포함)
  • netstat
    • -l 옵션: 듣고 있는 포트 정보 확인 가능
    • -p 옵션: 프로그램 이름 혹은 PID 정보 확인 가능
    • -n 옵션: don't resolve names (numeric)
    • e.g. netstat -npl | grep -i scheduler
      • -i는 대소문자 구분 없음을 의미
      • 스케줄러가 어떤 포트를 듣고 있는지 확인 가능

파드 네트워킹

  • 노드를 연결하는 네트워크 말고도 파드를 연결하는 네트워크 또한 필요
  • 네트워킹 모델
    • 모든 파드는 IP 주소를 가져야 함
    • 모든 파드는 같은 노드에 위치한 다른 파드와 통신 가능해야 함
    • 모든 파드는 NAT 없이 다른 노드에 있는 다른 파드와 통신 가능해야 함
    • flannel, NSX, weaveworks 등 네트워킹 솔루션 사용 가능

네트워킹 모델 구성 및 명령어

  • 노드를 연결하는 LAN 네트워크
    • 192.168.1.0
  • 세 개의 노드
    • node1 (192.168.1.11) 에 컨테이너 2개 (10.244.1.2, 10.244.1.3)
    • node2 (192.168.1.12) 에 컨테이너 1개 (10.244.2.2)
    • node3 (192.168.1.13) 에 컨테이너 1개 (10.244.3.2)
  • 노드마다 브릿지 네트워크 생성 및 활성화
    • ip link add v-net-0 type bridge
    • ip link set dev v-net-0 up
  • 브릿지 인터페이스에 IP 주소 설정 (노드마다)
    • ip addr add 10.244.1.1/24 dev v-net-0
    • ip addr add 10.244.2.1/24 dev v-net-0
    • ip addr add 10.244.3.1/24 dev v-net-0
  • 파이프 혹은 가상 네트워크 케이블로 컨테이너를 브릿지에 연결
    • 노드마다 스크립트로 만들어 사용 가능
    • ip link add ... : veth 쌍 생성
    • ip link set ... : veth를 각각의 인터페이스에 붙이기
    • ip -n [네임스페이스] addr add ... : ip 주소 할당
    • ip -n [네임스페이스] route add ... : ip 주소 할당
    • ip -n [네임스페이스] link set ... : 인터페이스 활성화
  • 다른 노드의 컨테이너 접근 가능하도록 라우팅 설정 (방법 1, 비추천)
    • node1$ ip route add 10.244.2.2 via 192.168.1.12
    • node1$ ip route add 10.244.3.2 via 192.168.1.13
    • node2$ ip route add 10.244.1.2 via 192.168.1.11
    • node2$ ip route add 10.244.3.2 via 192.168.1.13
    • ...
  • 각 서버에서 라우팅을 설정하는 것보다 라우터의 라우팅 테이블 활용하는 것이 편리 (방법 2, 추천)
    • 모든 호스트는 기본 게이트웨이를 사용하도록 지정
    • e.g. 네트워크 10.244.1.0/24 (브릿지)의 게이트웨이는 192.168.1.1 (노드)
    • 10.244.0.0/16 이라는 하나의 거대한 네트워크를 생성하게 됨

CNI

  • 컨테이너 혹은 파드 생성 시 CNI 표준에 맞춰서 위와 같은 명령어를 가진 스크립트를 생성할 수 있음
    • ADD 섹션에 파이프 생성, 파이프 인터페이스에 붙임, IP 주소 할당, 인터페이스 활성화 등 포함
    • DEL 섹션에 파이프 삭제 포함
  • 컨테이너 런타임이 컨테이너를 생성 시
      1. /etc/cni/net.d/net-script/conflist에서 스크립트 이름을 확인
      1. /opt/cni/bin에서 스크립트 확인
      1. ./[스크립트명].sh add [컨테이너][네임스페이스]로 컨테이너 생성

쿠버네티스에서의 CNI

  • CNI
    • 컨테이너 런타임은 네트워크 네임스페이스를 만들어야 함
    • 컨테이너가 붙는 네트워크를 확인해야 함
    • 컨테이너 런타임은 컨테이너가 추가 혹은 삭제될 때 네트워크 플러그인 (브릿지)를 작동시켜야 함
    • 네트워크 환경설정(configuration)은 JSON 형태여야 함
  • CNI 설정 확인
    • kubelet.service 파일의 --network-plugin에서 확인 가능
    • ps -aux | grep kubelet 에서도 확인 가능
    • 바이너리 파일은 기본적으로 /opt/cni/bin에 저장
    • 어떤 플러그인이 설정되어 있는지는 /etc/cni/net.d에서 확인 가능

Weaveworks

CNI

  • 각 노드마다 에이전트를 배치, 각 에이전트는 서로 통신 가능
    • 다른 노드의 파드와 IP 정보 등 셋업의 토폴로지 갖고 있음
  • 패킷을 인터셉팅해 새로운 주소로 갈음 및 캡슐화, 다른 노드로 전송
    • 다른 노드에 있는 에이전트가 비캡슐화 진행

Weave 배포

  • pod 형태로 배포하는 것이 편리
    • kubectl apply -f https://github.com/weaveworks/weave/releases/download/v2.8.1/weave-daemonset-k8s.yaml
    • daemonset으로 배포되어 클러스터의 모든 노드에 각각 하나의 파드가 배포되도록 함
  • weave peers
    • kubectl get pods -n kube-system
      • weavenet에서 배포한 파드들을 확인할 수 있음 (weave peers)
    • kubectl logs [pod명] weave -n kube-system
      • 로그 확인 또한 가능 (e.g. IP 주소 범위 등)

IP 주소 관리

  • CNI는 수동이 아니라 자동으로 IP 주소를 관리할 수 있는 2개의 빌트인 플러그인 제공
    • DHCP, host-local
      1. 스크립트에 ip = get_free_ip_from_host_local()처럼 플러그인을 실행하는 코드 작성해 사용할 수 있음
      1. 혹은 cat /etc/cni/net.d/[스크립트명].conf의 IPAM에서 플러그인 종류를 정의할 수 있음
      • e.g. ipam > type, subnet, routes, ..
  • weaveworks의 경우 기본적으로 10.32.0.0/12 범위의 네트워크를 사용
    • 10.32.0.1 > 10.47.255.254
    • 피어가 각 노드에 해당 IP의 범위를 나누어 사용
  • 참고: node01에 pod를 스케줄링하고 기본 게이트웨이를 확인하고 싶다면
    • kubectl run [pod명] --image=[image명] --dry-run=client -o yaml > [파일명].yaml 처럼 yaml 파일 생성
    • spec > nodeName: node01 작성
    • kubectl apply -f [파일명].yaml 으로 pod 생성
    • kubectl exec [pod명] -- ip route 로 기본 게이트웨이 확인 가능

서비스 네트워킹

  • 파드가 다른 파드가 호스팅하는 서비스에 접근하고 싶다면, 서비스(Service) 활용 가능
    • 서비스 IP 혹은 서비스명으로 접근 가능
    • e.g. 블루 파드가 오렌지 파드에 접근하고 싶다면, 오렌지 서비스의 IP 혹은 이름으로 접근 가능
  • ClusterIP
    • 클러스터 내부에 존재하는 파드라면 ClusterIP 서비스에 어디서든 접근 가능
    • 파드가 어떤 노드에 위치해있는지와 무관
  • NodePort
    • ClusterIP와 마찬가지로 클러스터 내의 파드라면 어디서든 접근 가능
    • 이에 더하여, 모든 노드의 포트를 통해 서비스를 노출시켜 외부 사용자 또한 접근 가능
  • 파드 vs. 서비스
    • 파드의 컨테이너는 IP를 할당한 인터페이스와 네임스페이스를 가짐
    • 서비스는 클러스터 전체에서 사용되기 때문에 인터페이스, 네임스페이스 등이 없음

Kube-proxy, IP 주소 범위

  • 각 노드의 kube-proxy가 서비스의 IP:Port로 들어오는 요청을 파드의 IP로 포워드 (규칙 생성)
  • kube-proxy --proxy-mode [userspace | iptables | ipvs]
    • 프록시 모드를 정의하지 않는다면 기본값은 iptable
  • kubectl logs [pod명] -n kube-system
    • 어떤 타입의 프록시를 사용하는지 확인 가능
  • iptables -L -t nat | grep [서비스명]
    • 서비스의 IP:port로 들어오는 요청을 어떤 IP(pod)로 포워드하는지 확인 가능 (DNAT 규칙)
  • 서비스가 생성될 때 부여받는 IP 주소의 범위 확인
    • kube-api-server --service-cluster-ip-range ipNet
    • ps aux | grep kube-api-server
    • cd /etc/kubernetes/manifests/kube-api-server.yaml
    • 기본값: 10.0.0.0/24
  • kubectl get all --all-namespaces
    • pod, daemonset, deployment, service, replicaset 등의 정보를 모두 조회 가능

쿠버네티스에서의 DNS

  • 쿠버네티스는 클러스터 구성 시 자동으로 빌트인 DNS 서버를 배포
  • DNS를 생각할 때 Pod와 Service만 염두에 두면 됨 (노드에 대해 고려할 필요 없음)
    • 모든 pod와 service가 서로 통신 가능하기 때문
  • DNS 서버에 호스트명(web-service), ip 주소(10.107.37.188) 정보가 있다고 가정
    • 네임스페이스가 같을 경우 호스트 이름으로 호출 가능
      • curl http://web-service
      • pod의 경우 호스트 이름은 IP 주소에서 .을 -로 변경한 버전이 사용됨 (e.g. 10-244-1-5)
    • 네임스페이스가 다를 경우 호스트 이름.네임스페이스로 호출 가능
      • curl http://web-service.apps
  • DNS 서버는 호스트명, IP 주소 외에도 여러 서브 도메인 정보를 가질 수 있음
    • 네임스페이스, 타입(e.g. svc, pod) 등
    • curl http://web-service.apps.svc
  • DNS 서버는 기본적으로 cluster.local이라는 루트 도메인 정보를 가짐
    • curl http://web-service.apps.svc.cluster.local

CoreDNS

  • 호스트마다 /etc/hosts로 DNS를 관리하는 것은 어려움
  • 이를 해결하기 위해 중앙 DNS 서버를 사용
    • 각 호스트의 /etc/resolv.conf에 namerserver 정보 (DNS 서버) 제공
  • CoreDNS는 pod의 형태로 배포됨 (2개의 replicaset)
    • /etc/coredns/Corefile에 플러그인 정보들 포함
      • kubernetes cluster.local ... { # CoreDNS가 쿠버네티스에서 잘 작동하도록 함
        • pods insecure ...} # pod를 DNS 서버 레코드에 추가할 때 이름을 IP 주소의 .을 -로 변경한 값 사용
      • proxy . /etc/resolve.conf # 모르는 주소를 호출할 때 resolve.conf에 있는 na meserver에 넘겨줌
    • 해당 파일은 configmap 객체의 형태로 pod에서 사용됨
      • 수정이 필요할 시 configmap을 수정하면 됨
  • CoreDNS는 다른 요소들이 접근 가능하도록 kube-dns라는 이름을 가진 서비스를 배포
    • 각 호스트의 /etc/resolv.conf에 nameserver IP 주소로 해당 서비스의 IP 주면 됨
    • /etc/resolv.conf에 search 엔트리를 등록할 수 있음
      • e.g. search default.svc.cluster.local svc.cluster.local cluster.local

인그레스

서비스 vs. 인그레스

  • 두 가지 서비스를 제공하는 홈페이지가 있다고 가정 (wear, video)
  • wear 기능을 담당하는 pod는 deployment로 감싸져 있고, video 기능을 담당하는 pod 또한 별개의 deployment로 배포됨
    • 트래픽이 많아지면 deployment 안의 pod가 많아짐
  • service는 해당 deployment를 외부에 노출 (NodePort), 트래픽이 많아지면 LoadBalancer 역할을 수행
    • 서비스에서는 30000 이상의 높은 숫자의 포트만 사용 가능
    • 별도의 프록시 서버 혹은 로드밸런서를 이용해 사용자의 서비스 접근을 용이하게 함
  • 인그레스란, 사용자로 하여금 단일한 URL을 통해 어플리케이션에 접근 가능하도록 하는 기능
    • SSL 보안 또한 편리하게 적용할 수 있음
    • 일종의 로드밸런서 역할을 하는 서비스 상단의 레이어라고 생각할 수 있음
    • 외부에서 접근 가능하도록 노출시켜야 하기 때문에, NodePort(서비스) 혹은 클라우드 기반의 로드밸런서로 퍼블리시해야 함

Ingress

    1. 지원 가능한 솔루션을 배포 (e.g. traefik, haproxy, nginx, ..)
    • ingress controller
    1. 인그레스를 환경설정하기 위한 규칙을 명세화
    • ingress resources (yaml 파일 이용)

Ingress Controller

  • 쿠버네티스에서 기본으로 배포해주는 ingress controller 없음
  • e.g. GCE (GCP HTTP(S) Load Balancer), Contour, Haproxy, Nginx, traefik, Istio
    • 쿠버네티스 프로젝트에서 GCE, Nginx 지원 중
  • Nginx-ingress-controller를 deployment로 배포할 수 있음
    • apiVersion: extensions/v1beta1
    • kind: Deployment
    • metadata:
      • name: nginx-ingress-controller
    • spec:
      • replicas: 1
      • selector:
        • matchLabels:
          • name: nginx-ingress
      • template:
        • metadata:
          • labels:
            • name: nginx-ingress
        • spec:
          • containers:
            • -name: nginx-ingress-controller
            • image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.21.0
          • args:
            • -/nginx-ingress-controller # nginx 프로그램이 해당 경로에 위치, 해당 서비스를 시작하려면 명령어로 이 내용 넣어주어야 함
            • --configmap=$(POD_NAMESPACE)/nginx-configuration
          • env: # configuration 데이터를 pod 안에서 읽기 위해 필요한 정보
            • -name: POD_NAME
            • valueFrom:
              • fieldRef:
                • fieldPath: meatadata.name
            • -name: POD_NAMESPACE
              • valueFrom:
                • fieldRef:
                  • fieldPath: meatadata.namespace
          • ports: # ingress-controller에 의해 사용되는 포트 정보
            • -name: http
            • containerPort: 80
            • -name: https
            • containerPort: 443
  • Nginx의 환경설정 데이터를 컨트롤러 이미지와 분리시키기 위해 Configmap 객체 사용
    • Nginx Configuration: err-log-path, keep-alive, ssl-protocols, ...
    • apiVersion: v1
    • kind: ConfigMap
    • metadata:
      • name: nginx-configuration
  • Ingress Controller를 외부에 노출시키기 위한 서비스 필요
    • apiVersion: v1
    • kind: Service
    • metadata:
      • name: nginx-ingress
    • spec:
      • type: NodePort
      • ports:
        • -port: 80
        • targetPort: 80
        • protocol: TCP
        • name: http
        • -port: 443
        • targetPort: 443
        • protocol: TCP
        • name: https
      • selector:
        • name: nginx-ingress
  • Ingress Controller가 리소스를 모니터링하고 변화가 있을 때 서버를 환경설정 하기 위해서는 서비스 계정 필요 (Roles, ClusterRoles, RoleBindings)
    • apiVersion: v1
    • kind: ServiceAccount
    • metadata:
      • name: nginx-ingress-serviceaccount

Ingress Resources

  • 트래픽을 어떻게 라우팅할지 결정할 수 있음
    • 각 호스트 혹은 도메인명에 따라서 별개의 규칙이 존재
      • e.g. www.my-online-store.com은 규칙 1, www.wear.my-online-store.com은 규칙 2, ...
    • 각 규칙 내에서 URL을 기반으로 트래픽을 라우팅
      • e.g. 규칙 1에서 www.my-online-store.com/wear, www.my-online-store.com/watch 등 다른 경로에 따라 라우팅

단순 포워드

  • apiVersion: networking.k8s.io/v1
  • kind: Ingress
  • metadata:
    • name: ingress-wear
  • spec:
    • backend:
      • service:
        • name: wear-service
        • port:
          • number: 80

규칙 기반 라우팅 (규칙 1개)

  • 단일 도메인명, 즉 규칙이 있고 (www.my-online-store.com) /wear, /watch라는 2개의 경로 존재
  • kubectl create ingress [ingress명] --rule="host/path=service:port"
    • 최근 버전에서는 이렇게 ingress resource를 생성할 수도 있음
  • apiVersion: networking.k8s.io/v1
  • kind: Ingress
  • metadata:
    • name: ingress-wear-watch
  • spec:
    • rules:
      • -http:
        • paths:
          • -path: /wear
          • pathType: Prefix
          • backend:
            • service:
              • name: wear-service
              • port:
                • number: 80
          • -path: /watch
          • backend:
            • service:
              • name: watch-service
              • port:
                • number: 80

규칙 기반 라우팅 (규칙 2개)

  • 2개의 도메인명이 있고 (wear.my-online-store.com, watch.my-online-store.com) 각 규칙마다 하나의 경로만 존재
  • apiVersion: networking.k8s.io/v1
  • kind: Ingress
  • metadata:
    • name: ingress-wear-watch
  • spec:
    • rules:
      • -host: wear.my-online-store.com
      • http:
        • paths:
          • -backend:
            • service:
              • name: wear-service
              • port:
                • number: 80
      • -host: watch.my-online-store.com
      • http:
        • paths:
          • -backend:
            • service:
              • name: watch-service
              • port:
                • number: 80

명령어로 ingress resource 만들기

  • 다른 네임스페이스에 새로운 어플리케이션이 생긴다면, 그에 맞춰 해당 네임스페이스에 ingress resource 생성해줘야 함
  • 해당 어플리케이션의 서비스명과 서비스 포트를 알아야 함
    • kubectl get svc [서비스명]
  • kubectl create ingress [ingress명] -n [네임스페이스명] --rule="[path]=[서비스명]:[서비스포트]"
    • e.g. kubectl create ingress ingress-pay -n critical-space --rule="/pay=pay-service:8282"
  • metadata > annotations > nginx.ingress.kubernetes.io/rewrite-target: /
    • 해당 내용을 yaml 파일에 추가해 경로가 제대로 작동하도록 수정할 수 있음
profile
Graduate student at Seoul National University, majoring in Artificial Intelligence (NLP). Currently AI Researcher at LG CNS AI Lab

0개의 댓글